summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-07-16 11:45:35 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-07-17 08:59:23 +0000
commit552906b0f222c5d5dd11b9fd73829d510980461a (patch)
tree3a11e6ed0538a81dd83b20cf3a4783e297f26d91 /chromium/chrome/browser
parent1b05827804eaf047779b597718c03e7d38344261 (diff)
BASELINE: Update Chromium to 83.0.4103.122
Change-Id: Ie3a82f5bb0076eec2a7c6a6162326b4301ee291e Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/chrome/browser')
-rw-r--r--chromium/chrome/browser/BUILD.gn1044
-rw-r--r--chromium/chrome/browser/accessibility/accessibility_extension_api_browsertest.cc5
-rw-r--r--chromium/chrome/browser/accessibility/accessibility_permission_context.cc5
-rw-r--r--chromium/chrome/browser/accessibility/accessibility_permission_context.h8
-rw-r--r--chromium/chrome/browser/accessibility/accessibility_ui.cc10
-rw-r--r--chromium/chrome/browser/accessibility/caption_settings_dialog_win.cc6
-rw-r--r--chromium/chrome/browser/accessibility/image_annotation_browsertest.cc1
-rw-r--r--chromium/chrome/browser/android/crypto/BUILD.gn16
-rw-r--r--chromium/chrome/browser/android/lifecycle/BUILD.gn22
-rw-r--r--chromium/chrome/browser/android/metrics/BUILD.gn16
-rw-r--r--chromium/chrome/browser/android/thin_webview/BUILD.gn13
-rw-r--r--chromium/chrome/browser/android/thin_webview/internal/BUILD.gn6
-rw-r--r--chromium/chrome/browser/android/vr/BUILD.gn53
-rw-r--r--chromium/chrome/browser/android/webapk/BUILD.gn4
-rw-r--r--chromium/chrome/browser/apps/BUILD.gn21
-rw-r--r--chromium/chrome/browser/apps/app_shim/BUILD.gn13
-rw-r--r--chromium/chrome/browser/apps/platform_apps/BUILD.gn9
-rw-r--r--chromium/chrome/browser/apps/platform_apps/api/BUILD.gn5
-rw-r--r--chromium/chrome/browser/browser_resources.grd139
-rw-r--r--chromium/chrome/browser/browser_switcher/bho/BUILD.gn87
-rw-r--r--chromium/chrome/browser/buildflags.gni1
-rw-r--r--chromium/chrome/browser/chrome_notification_types.h5
-rw-r--r--chromium/chrome/browser/chromeos/BUILD.gn391
-rw-r--r--chromium/chrome/browser/chromeos/crostini/BUILD.gn4
-rw-r--r--chromium/chrome/browser/chromeos/crostini/crostini_types.mojom (renamed from chromium/chrome/browser/chromeos/crostini/crostini_installer_types.mojom)8
-rw-r--r--chromium/chrome/browser/chromeos/power/ml/BUILD.gn8
-rw-r--r--chromium/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn14
-rw-r--r--chromium/chrome/browser/chromeos/secure_channel/BUILD.gn4
-rw-r--r--chromium/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc25
-rw-r--r--chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc26
-rw-r--r--chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h17
-rw-r--r--chromium/chrome/browser/dev_ui_browser_resources.grd101
-rw-r--r--chromium/chrome/browser/devtools/BUILD.gn18
-rw-r--r--chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc47
-rw-r--r--chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h20
-rw-r--r--chromium/chrome/browser/devtools/chrome_devtools_session.cc67
-rw-r--r--chromium/chrome/browser/devtools/chrome_devtools_session.h27
-rw-r--r--chromium/chrome/browser/devtools/device/android_device_manager.cc9
-rw-r--r--chromium/chrome/browser/devtools/device/devtools_device_discovery.cc17
-rw-r--r--chromium/chrome/browser/devtools/device/tcp_device_provider.cc49
-rw-r--r--chromium/chrome/browser/devtools/device/tcp_device_provider.h9
-rw-r--r--chromium/chrome/browser/devtools/device/usb/android_usb_browsertest.cc1
-rw-r--r--chromium/chrome/browser/devtools/device/usb/android_usb_device.h2
-rw-r--r--chromium/chrome/browser/devtools/device/usb/usb_device_manager_helper.cc7
-rw-r--r--chromium/chrome/browser/devtools/devtools_auto_opener.cc2
-rw-r--r--chromium/chrome/browser/devtools/devtools_browser_context_manager.cc15
-rw-r--r--chromium/chrome/browser/devtools/devtools_browser_context_manager.h2
-rw-r--r--chromium/chrome/browser/devtools/devtools_eye_dropper.cc29
-rw-r--r--chromium/chrome/browser/devtools/devtools_eye_dropper.h1
-rw-r--r--chromium/chrome/browser/devtools/devtools_file_helper.cc8
-rw-r--r--chromium/chrome/browser/devtools/devtools_file_system_indexer.cc8
-rw-r--r--chromium/chrome/browser/devtools/devtools_file_watcher.cc8
-rw-r--r--chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc88
-rw-r--r--chromium/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc3
-rw-r--r--chromium/chrome/browser/devtools/devtools_ui_bindings.cc214
-rw-r--r--chromium/chrome/browser/devtools/devtools_ui_bindings.h11
-rw-r--r--chromium/chrome/browser/devtools/devtools_ui_bindings_unittest.cc16
-rw-r--r--chromium/chrome/browser/devtools/devtools_window.cc64
-rw-r--r--chromium/chrome/browser/devtools/devtools_window.h4
-rw-r--r--chromium/chrome/browser/devtools/global_confirm_info_bar.cc90
-rw-r--r--chromium/chrome/browser/devtools/global_confirm_info_bar.h4
-rw-r--r--chromium/chrome/browser/devtools/inspector_protocol_config.json4
-rw-r--r--chromium/chrome/browser/devtools/protocol/browser_handler.cc39
-rw-r--r--chromium/chrome/browser/devtools/protocol/cast_handler.cc20
-rw-r--r--chromium/chrome/browser/devtools/protocol/cast_handler_unittest.cc38
-rw-r--r--chromium/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc12
-rw-r--r--chromium/chrome/browser/devtools/protocol/page_handler.cc59
-rw-r--r--chromium/chrome/browser/devtools/protocol/page_handler.h12
-rw-r--r--chromium/chrome/browser/devtools/protocol/target_handler.cc12
-rw-r--r--chromium/chrome/browser/devtools/protocol/target_handler.h2
-rw-r--r--chromium/chrome/browser/devtools/protocol/window_manager_handler.cc8
-rw-r--r--chromium/chrome/browser/downgrade/buildflags.gni9
-rw-r--r--chromium/chrome/browser/download/android/BUILD.gn74
-rw-r--r--chromium/chrome/browser/engagement/BUILD.gn8
-rw-r--r--chromium/chrome/browser/extensions/BUILD.gn65
-rw-r--r--chromium/chrome/browser/extensions/api/BUILD.gn1
-rw-r--r--chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc27
-rw-r--r--chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h6
-rw-r--r--chromium/chrome/browser/extensions/api/alarms/alarms_apitest.cc82
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_assistant_private/OWNERS1
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.cc421
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h248
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_apitest.cc96
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.cc63
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h39
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher_unittest.cc58
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/OWNERS6
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc98
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h18
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.h1
-rw-r--r--chromium/chrome/browser/extensions/api/automation/automation_apitest.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h1
-rw-r--r--chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc23
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc15
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc33
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h5
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_unittest.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/certificate_provider/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc66
-rw-r--r--chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc53
-rw-r--r--chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc32
-rw-r--r--chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h3
-rw-r--r--chromium/chrome/browser/extensions/api/chrome_extensions_api_client_unittest.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/commands/command_service.cc44
-rw-r--r--chromium/chrome/browser/extensions/api/commands/command_service.h12
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc41
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_api.h11
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_store.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_store_unittest.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/cookies/cookies_api.h4
-rw-r--r--chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc72
-rw-r--r--chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h23
-rw-r--r--chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc91
-rw-r--r--chromium/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/debugger/debugger_api.cc209
-rw-r--r--chromium/chrome/browser/extensions/api/debugger/debugger_api.h21
-rw-r--r--chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc21
-rw-r--r--chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc49
-rw-r--r--chromium/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc32
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/content_action.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/content_action_unittest.cc190
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc31
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc309
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc1279
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc538
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc283
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc25
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc20
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h16
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc137
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h13
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc42
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc57
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.h8
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc44
-rw-r--r--chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc19
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api.cc113
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api.h19
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc26
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.cc24
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h15
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc14
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc83
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc67
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc98
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h6
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.cc135
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.h30
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_mac.mm26
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_win.cc15
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc25
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc67
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc547
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/browser_action_browsertest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc496
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/extension_action_api_unittest.cc34
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc34
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/page_action_apitest.cc14
-rw-r--r--chromium/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc21
-rw-r--r--chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h4
-rw-r--r--chromium/chrome/browser/extensions/api/file_system/file_system_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc21
-rw-r--r--chromium/chrome/browser/extensions/api/font_settings/font_settings_api.h8
-rw-r--r--chromium/chrome/browser/extensions/api/font_settings/font_settings_apitest.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/gcm/gcm_api.cc15
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc166
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h88
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_unittest.cc172
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc41
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.h6
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc33
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_api.cc169
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_api.h70
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_api_unittest.cc141
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_apitest.cc317
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_constants.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_constants.h2
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc316
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h26
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc28
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.h6
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_mint_queue.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_private_api.cc28
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_private_api.h29
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_private_apitest.cc70
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h2
-rw-r--r--chromium/chrome/browser/extensions/api/identity/web_auth_flow.cc43
-rw-r--r--chromium/chrome/browser/extensions/api/identity/web_auth_flow.h16
-rw-r--r--chromium/chrome/browser/extensions/api/idltest/idltest_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc89
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.h32
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation.h1
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc15
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h2
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc20
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc67
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc23
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/OWNERS5
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.h1
-rw-r--r--chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc79
-rw-r--r--chromium/chrome/browser/extensions/api/management/management_api_non_persistent_apitest.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/management/management_api_unittest.cc695
-rw-r--r--chromium/chrome/browser/extensions/api/management/management_apitest.cc38
-rw-r--r--chromium/chrome/browser/extensions/api/management/management_browsertest.cc24
-rw-r--r--chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.h4
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/incognito_connectability_infobar_delegate.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.h3
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc25
-rw-r--r--chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/notifications_api.cc112
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/notifications_api.h33
-rw-r--r--chromium/chrome/browser/extensions/api/omnibox/omnibox_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc57
-rw-r--r--chromium/chrome/browser/extensions/api/page_capture/page_capture_api.h10
-rw-r--r--chromium/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/OWNERS6
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc646
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.h194
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc1008
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc375
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.h193
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc334
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h71
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.cc19
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h10
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc222
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h100
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc388
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc34
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h14
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc24
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h63
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc14
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc265
-rw-r--r--chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h124
-rw-r--r--chromium/chrome/browser/extensions/api/permissions/permissions_api.cc17
-rw-r--r--chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.h3
-rw-r--r--chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc24
-rw-r--r--chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc46
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_api.cc73
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_apitest.cc176
-rw-r--r--chromium/chrome/browser/extensions/api/processes/processes_api.cc37
-rw-r--r--chromium/chrome/browser/extensions/api/resources_private/resources_private_api.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api_unittest.cc14
-rw-r--r--chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc127
-rw-r--r--chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h22
-rw-r--r--chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc246
-rw-r--r--chromium/chrome/browser/extensions/api/sessions/sessions_api.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/sessions/sessions_api.h3
-rw-r--r--chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc20
-rw-r--r--chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/OWNERS4
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc58
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/settings_private_api.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc40
-rw-r--r--chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc70
-rw-r--r--chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/storage/managed_value_store_cache.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc24
-rw-r--r--chromium/chrome/browser/extensions/api/storage/sync_storage_backend.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/storage/sync_storage_backend.h2
-rw-r--r--chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc15
-rw-r--r--chromium/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_api.cc23
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc19
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_constants.h2
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc30
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h3
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_test.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/windows_util.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.cc225
-rw-r--r--chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.h47
-rw-r--r--chromium/chrome/browser/extensions/api/terminal/crostini_startup_status_unittest.cc57
-rw-r--r--chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc139
-rw-r--r--chromium/chrome/browser/extensions/api/terminal/terminal_private_api.h41
-rw-r--r--chromium/chrome/browser/extensions/api/terminal/terminal_private_browsertest.cc68
-rw-r--r--chromium/chrome/browser/extensions/api/top_sites/top_sites_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc40
-rw-r--r--chromium/chrome/browser/extensions/api/vpn_provider/OWNERS2
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h5
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc24
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc312
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_event_details_unittest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc19
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc32
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h8
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.cc12
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.h2
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc61
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc235
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h48
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.h4
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc357
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h38
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc213
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc308
-rw-r--r--chromium/chrome/browser/extensions/default_extensions/BUILD.gn8
-rw-r--r--chromium/chrome/browser/flags/BUILD.gn85
-rw-r--r--chromium/chrome/browser/image_decoder/BUILD.gn45
-rw-r--r--chromium/chrome/browser/image_editor/internal/BUILD.gn6
-rw-r--r--chromium/chrome/browser/image_editor/public/BUILD.gn4
-rw-r--r--chromium/chrome/browser/image_fetcher/BUILD.gn10
-rw-r--r--chromium/chrome/browser/media/BUILD.gn6
-rw-r--r--chromium/chrome/browser/media/feeds/BUILD.gn19
-rw-r--r--chromium/chrome/browser/media/feeds/media_feeds_store.mojom286
-rw-r--r--chromium/chrome/browser/media/history/media_history_store.mojom87
-rw-r--r--chromium/chrome/browser/media/router/BUILD.gn53
-rw-r--r--chromium/chrome/browser/media/router/discovery/BUILD.gn4
-rw-r--r--chromium/chrome/browser/media/webrtc/OWNERS5
-rw-r--r--chromium/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc19
-rw-r--r--chromium/chrome/browser/media/webrtc/desktop_capture_access_handler.cc12
-rw-r--r--chromium/chrome/browser/media/webrtc/desktop_media_list_ash.cc4
-rw-r--r--chromium/chrome/browser/media/webrtc/desktop_media_list_base.cc4
-rw-r--r--chromium/chrome/browser/media/webrtc/desktop_media_picker_controller.cc17
-rw-r--r--chromium/chrome/browser/media/webrtc/display_media_access_handler.cc15
-rw-r--r--chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc10
-rw-r--r--chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h2
-rw-r--r--chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher_unittest.cc94
-rw-r--r--chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.cc24
-rw-r--r--chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.h20
-rw-r--r--chromium/chrome/browser/media/webrtc/media_stream_device_permission_context_unittest.cc6
-rw-r--r--chromium/chrome/browser/media/webrtc/media_stream_devices_controller.cc60
-rw-r--r--chromium/chrome/browser/media/webrtc/media_stream_devices_controller.h8
-rw-r--r--chromium/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc185
-rw-r--r--chromium/chrome/browser/media/webrtc/media_stream_infobar_browsertest.cc7
-rw-r--r--chromium/chrome/browser/media/webrtc/native_desktop_media_list.cc7
-rw-r--r--chromium/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc1
-rw-r--r--chromium/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc26
-rw-r--r--chromium/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc1
-rw-r--r--chromium/chrome/browser/media/webrtc/tab_capture_access_handler.cc8
-rw-r--r--chromium/chrome/browser/media/webrtc/tab_desktop_media_list.cc11
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_apprtc_browsertest.cc13
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_browsertest.cc3
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc103
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc3
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc7
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_event_log_manager.cc63
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc44
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.h5
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc96
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc95
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc1
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_getmediadevices_browsertest.cc16
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_internals_integration_browsertest.cc2
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_internals_perf_browsertest.cc3
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_log_uploader.cc6
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_log_util.cc6
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc25
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc29
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer.cc6
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer_unittest.cc9
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_simulcast_browsertest.cc7
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_stats_perf_browsertest.cc1
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc21
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_video_high_bitrate_browsertest.cc1
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc3
-rw-r--r--chromium/chrome/browser/media/webrtc/webrtc_webcam_browsertest.cc1
-rw-r--r--chromium/chrome/browser/metrics/BUILD.gn26
-rw-r--r--chromium/chrome/browser/metrics/perf/BUILD.gn4
-rw-r--r--chromium/chrome/browser/nacl_host/test/BUILD.gn4
-rw-r--r--chromium/chrome/browser/net/BUILD.gn4
-rw-r--r--chromium/chrome/browser/net/cert_verify_proc_browsertest.cc151
-rw-r--r--chromium/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc14
-rw-r--r--chromium/chrome/browser/net/chrome_network_service_restart_browsertest.cc10
-rw-r--r--chromium/chrome/browser/net/cookie_policy_browsertest.cc10
-rw-r--r--chromium/chrome/browser/net/dns_probe_browsertest.cc124
-rw-r--r--chromium/chrome/browser/net/dns_probe_runner.cc3
-rw-r--r--chromium/chrome/browser/net/dns_probe_runner.h6
-rw-r--r--chromium/chrome/browser/net/dns_probe_runner_unittest.cc15
-rw-r--r--chromium/chrome/browser/net/dns_probe_service.h10
-rw-r--r--chromium/chrome/browser/net/dns_probe_service_factory.cc186
-rw-r--r--chromium/chrome/browser/net/dns_probe_service_factory.h2
-rw-r--r--chromium/chrome/browser/net/dns_probe_service_factory_unittest.cc128
-rw-r--r--chromium/chrome/browser/net/dns_probe_test_util.cc20
-rw-r--r--chromium/chrome/browser/net/dns_probe_test_util.h14
-rw-r--r--chromium/chrome/browser/net/dns_util.cc108
-rw-r--r--chromium/chrome/browser/net/dns_util.h48
-rw-r--r--chromium/chrome/browser/net/dns_util_unittest.cc201
-rw-r--r--chromium/chrome/browser/net/file_downloader.cc24
-rw-r--r--chromium/chrome/browser/net/ftp_browsertest.cc5
-rw-r--r--chromium/chrome/browser/net/load_timing_browsertest.cc24
-rw-r--r--chromium/chrome/browser/net/net_error_tab_helper.cc8
-rw-r--r--chromium/chrome/browser/net/network_connection_tracker_browsertest.cc5
-rw-r--r--chromium/chrome/browser/net/network_context_configuration_browsertest.cc145
-rw-r--r--chromium/chrome/browser/net/network_request_metrics_browsertest.cc8
-rw-r--r--chromium/chrome/browser/net/nss_context_chromeos_browsertest.cc1
-rw-r--r--chromium/chrome/browser/net/profile_network_context_service.cc69
-rw-r--r--chromium/chrome/browser/net/profile_network_context_service.h5
-rw-r--r--chromium/chrome/browser/net/profile_network_context_service_browsertest.cc343
-rw-r--r--chromium/chrome/browser/net/profile_network_context_service_test_utils.cc119
-rw-r--r--chromium/chrome/browser/net/profile_network_context_service_test_utils.h45
-rw-r--r--chromium/chrome/browser/net/proxy_service_factory.cc7
-rw-r--r--chromium/chrome/browser/net/samesite_cookies_policy_browsertest.cc99
-rw-r--r--chromium/chrome/browser/net/secure_dns_policy_handler.cc38
-rw-r--r--chromium/chrome/browser/net/secure_dns_policy_handler.h3
-rw-r--r--chromium/chrome/browser/net/secure_dns_policy_handler_unittest.cc77
-rw-r--r--chromium/chrome/browser/net/stub_resolver_config_reader.cc388
-rw-r--r--chromium/chrome/browser/net/stub_resolver_config_reader.h104
-rw-r--r--chromium/chrome/browser/net/stub_resolver_config_reader_unittest.cc356
-rw-r--r--chromium/chrome/browser/net/system_network_context_manager.cc252
-rw-r--r--chromium/chrome/browser/net/system_network_context_manager.h27
-rw-r--r--chromium/chrome/browser/net/system_network_context_manager_browsertest.cc141
-rw-r--r--chromium/chrome/browser/net/trial_comparison_cert_verifier_browsertest.cc2
-rw-r--r--chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.cc16
-rw-r--r--chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.h2
-rw-r--r--chromium/chrome/browser/net/trial_comparison_cert_verifier_controller_unittest.cc62
-rw-r--r--chromium/chrome/browser/net/variations_http_headers_browsertest.cc119
-rw-r--r--chromium/chrome/browser/notifications/BUILD.gn4
-rw-r--r--chromium/chrome/browser/notifications/chime/android/BUILD.gn6
-rw-r--r--chromium/chrome/browser/notifications/scheduler/BUILD.gn8
-rw-r--r--chromium/chrome/browser/notifications/scheduler/public/BUILD.gn10
-rw-r--r--chromium/chrome/browser/notifications/scheduler/test/BUILD.gn2
-rw-r--r--chromium/chrome/browser/offline_pages/prefetch/notifications/BUILD.gn26
-rw-r--r--chromium/chrome/browser/optimization_guide/android/BUILD.gn66
-rw-r--r--chromium/chrome/browser/page_load_metrics/integration_tests/jsdeps.gni8
-rw-r--r--chromium/chrome/browser/page_load_metrics/integration_tests/sources.gni11
-rw-r--r--chromium/chrome/browser/password_manager/android_test_helpers/BUILD.gn32
-rw-r--r--chromium/chrome/browser/payments/BUILD.gn81
-rw-r--r--chromium/chrome/browser/payments/android/BUILD.gn19
-rw-r--r--chromium/chrome/browser/performance_hints/android/BUILD.gn21
-rw-r--r--chromium/chrome/browser/performance_manager/BUILD.gn4
-rw-r--r--chromium/chrome/browser/preferences/BUILD.gn14
-rw-r--r--chromium/chrome/browser/prefs/browser_prefs.cc328
-rw-r--r--chromium/chrome/browser/prefs/chrome_command_line_pref_store.cc4
-rw-r--r--chromium/chrome/browser/prefs/chrome_command_line_pref_store_proxy_unittest.cc44
-rw-r--r--chromium/chrome/browser/prefs/chrome_pref_service_factory.cc2
-rw-r--r--chromium/chrome/browser/prefs/incognito_mode_prefs.cc114
-rw-r--r--chromium/chrome/browser/prefs/incognito_mode_prefs.h7
-rw-r--r--chromium/chrome/browser/prefs/pref_functional_browsertest.cc10
-rw-r--r--chromium/chrome/browser/prefs/pref_metrics_service.cc4
-rw-r--r--chromium/chrome/browser/prefs/pref_metrics_service.h1
-rw-r--r--chromium/chrome/browser/prefs/pref_service_incognito_whitelist.cc54
-rw-r--r--chromium/chrome/browser/prefs/profile_pref_store_manager.h4
-rw-r--r--chromium/chrome/browser/prefs/tracked/pref_hash_browsertest.cc6
-rw-r--r--chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc3
-rw-r--r--chromium/chrome/browser/printing/cloud_print/privet_notifications.cc13
-rw-r--r--chromium/chrome/browser/printing/cloud_print/privet_notifications.h10
-rw-r--r--chromium/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc18
-rw-r--r--chromium/chrome/browser/printing/pdf_to_emf_converter.cc4
-rw-r--r--chromium/chrome/browser/printing/pdf_to_emf_converter_browsertest.cc22
-rw-r--r--chromium/chrome/browser/printing/print_browsertest.cc32
-rw-r--r--chromium/chrome/browser/printing/print_dialog_cloud_win.cc6
-rw-r--r--chromium/chrome/browser/printing/print_job.cc8
-rw-r--r--chromium/chrome/browser/printing/print_job_worker.cc47
-rw-r--r--chromium/chrome/browser/printing/print_job_worker.h8
-rw-r--r--chromium/chrome/browser/printing/print_preview_dialog_controller.cc9
-rw-r--r--chromium/chrome/browser/printing/print_preview_dialog_controller_unittest.cc5
-rw-r--r--chromium/chrome/browser/printing/print_preview_message_handler.cc104
-rw-r--r--chromium/chrome/browser/printing/print_preview_message_handler.h23
-rw-r--r--chromium/chrome/browser/printing/print_preview_sticky_settings.cc3
-rw-r--r--chromium/chrome/browser/printing/print_view_manager.h2
-rw-r--r--chromium/chrome/browser/printing/print_view_manager_base.cc26
-rw-r--r--chromium/chrome/browser/printing/print_view_manager_base.h4
-rw-r--r--chromium/chrome/browser/printing/print_view_manager_common.h2
-rw-r--r--chromium/chrome/browser/printing/printer_manager_dialog_linux.cc6
-rw-r--r--chromium/chrome/browser/printing/printer_manager_dialog_win.cc8
-rw-r--r--chromium/chrome/browser/printing/printing_service.cc5
-rw-r--r--chromium/chrome/browser/profile_resetter/BUILD.gn4
-rw-r--r--chromium/chrome/browser/profiles/android/BUILD.gn37
-rw-r--r--chromium/chrome/browser/profiling_host/BUILD.gn58
-rw-r--r--chromium/chrome/browser/push_messaging/BUILD.gn4
-rw-r--r--chromium/chrome/browser/renderer_host/chrome_extension_message_filter.cc17
-rw-r--r--chromium/chrome/browser/renderer_host/chrome_extension_message_filter.h2
-rw-r--r--chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h4
-rw-r--r--chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm73
-rw-r--r--chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h30
-rw-r--r--chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm135
-rw-r--r--chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm3
-rw-r--r--chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm5
-rw-r--r--chromium/chrome/browser/renderer_host/pepper/device_id_fetcher.cc6
-rw-r--r--chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc2
-rw-r--r--chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h2
-rw-r--r--chromium/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc43
-rw-r--r--chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc19
-rw-r--r--chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h2
-rw-r--r--chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc2
-rw-r--r--chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h2
-rw-r--r--chromium/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc6
-rw-r--r--chromium/chrome/browser/reputation/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resource_coordinator/BUILD.gn20
-rw-r--r--chromium/chrome/browser/resource_coordinator/lifecycle_unit_state.mojom10
-rw-r--r--chromium/chrome/browser/resource_coordinator/tab_ranker/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/BUILD.gn213
-rw-r--r--chromium/chrome/browser/resources/about_nacl/BUILD.gn18
-rw-r--r--chromium/chrome/browser/resources/about_nacl/about_nacl.html7
-rw-r--r--chromium/chrome/browser/resources/about_nacl/about_nacl.js11
-rw-r--r--chromium/chrome/browser/resources/accessibility/accessibility.js17
-rw-r--r--chromium/chrome/browser/resources/app_management/BUILD.gn276
-rw-r--r--chromium/chrome/browser/resources/app_management/OWNERS4
-rw-r--r--chromium/chrome/browser/resources/app_management/app.html65
-rw-r--r--chromium/chrome/browser/resources/app_management/app.js99
-rw-r--r--chromium/chrome/browser/resources/app_management/expandable_app_list.html49
-rw-r--r--chromium/chrome/browser/resources/app_management/expandable_app_list.js136
-rw-r--r--chromium/chrome/browser/resources/app_management/index.html27
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/BUILD.gn15
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js15
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js10
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js8
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/device_collection.js32
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/device_table.js22
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/expandable_list.js18
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/object_fieldset.js8
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/page_manager.js82
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/service_list.js10
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/sidebar.js12
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/snackbar.js12
-rw-r--r--chromium/chrome/browser/resources/bluetooth_internals/value_control.js34
-rw-r--r--chromium/chrome/browser/resources/bookmarks/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/bookmarks/BUILD.gn26
-rw-r--r--chromium/chrome/browser/resources/bookmarks/actions.js8
-rw-r--r--chromium/chrome/browser/resources/bookmarks/app.js24
-rw-r--r--chromium/chrome/browser/resources/bookmarks/command_manager.js123
-rw-r--r--chromium/chrome/browser/resources/bookmarks/dialog_focus_manager.js2
-rw-r--r--chromium/chrome/browser/resources/bookmarks/dnd_manager.js40
-rw-r--r--chromium/chrome/browser/resources/bookmarks/edit_dialog.js14
-rw-r--r--chromium/chrome/browser/resources/bookmarks/folder_node.html2
-rw-r--r--chromium/chrome/browser/resources/bookmarks/folder_node.js92
-rw-r--r--chromium/chrome/browser/resources/bookmarks/item.js44
-rw-r--r--chromium/chrome/browser/resources/bookmarks/list.html6
-rw-r--r--chromium/chrome/browser/resources/bookmarks/list.js63
-rw-r--r--chromium/chrome/browser/resources/bookmarks/mouse_focus_behavior.js8
-rw-r--r--chromium/chrome/browser/resources/bookmarks/reducers.js6
-rw-r--r--chromium/chrome/browser/resources/bookmarks/router.js18
-rw-r--r--chromium/chrome/browser/resources/bookmarks/store_client.js6
-rw-r--r--chromium/chrome/browser/resources/bookmarks/toolbar.js22
-rw-r--r--chromium/chrome/browser/resources/bookmarks/util.js6
-rw-r--r--chromium/chrome/browser/resources/browser_switch/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/browser_switch/app.html17
-rw-r--r--chromium/chrome/browser/resources/browser_switch/app.js14
-rw-r--r--chromium/chrome/browser/resources/browser_switch/internals/BUILD.gn9
-rw-r--r--chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.html6
-rw-r--r--chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.js11
-rw-r--r--chromium/chrome/browser/resources/chrome_urls_disabled_page/app.html20
-rw-r--r--chromium/chrome/browser/resources/chromeos/BUILD.gn6
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/BUILD.gn115
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/autoclick/BUILD.gn24
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn378
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/chromevox/common/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni8
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.gni73
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd3813
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn124
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn133
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/strings/BUILD.gn74
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/strings/select_to_speak_strings.grd221
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.gni71
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.grd150
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp2916
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp75
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/strings/switch_access_strings.grdp93
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn187
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/switch_access/strings/BUILD.gn74
-rw-r--r--chromium/chrome/browser/resources/chromeos/accessibility/switch_access/strings/switch_access_strings.grd236
-rw-r--r--chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/BUILD.gn88
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/camera_resources.grd12
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn35
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn16
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn1
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn6
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/js/lib/BUILD.gn9
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn18
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn1
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn5
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn5
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn2
-rw-r--r--chromium/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd4
-rw-r--r--chromium/chrome/browser/resources/chromeos/crostini_installer/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/chromeos/crostini_upgrader/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/chromeos/edu_login/BUILD.gn191
-rw-r--r--chromium/chrome/browser/resources/chromeos/emulator/BUILD.gn2
-rw-r--r--chromium/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/chromeos/login/BUILD.gn108
-rw-r--r--chromium/chrome/browser/resources/chromeos/login/components/BUILD.gn17
-rw-r--r--chromium/chrome/browser/resources/chromeos/machine_learning/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/chromeos/network_ui/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/chromeos/set_time_dialog/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/chromeos/smb_shares/BUILD.gn39
-rw-r--r--chromium/chrome/browser/resources/chromeos/sys_internals/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/chromeos/sys_internals/line_chart/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn32
-rw-r--r--chromium/chrome/browser/resources/chromeos/zip_archiver/cpp/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/component_extension_resources.grd3
-rw-r--r--chromium/chrome/browser/resources/components/BUILD.gn11
-rw-r--r--chromium/chrome/browser/resources/components/components.html7
-rw-r--r--chromium/chrome/browser/resources/components/components.js26
-rw-r--r--chromium/chrome/browser/resources/conflicts/BUILD.gn18
-rw-r--r--chromium/chrome/browser/resources/conflicts/about_conflicts.html12
-rw-r--r--chromium/chrome/browser/resources/conflicts/about_conflicts.js11
-rw-r--r--chromium/chrome/browser/resources/cryptotoken/cryptotokenbackground.js5
-rw-r--r--chromium/chrome/browser/resources/cryptotoken/enroller.js2
-rw-r--r--chromium/chrome/browser/resources/cryptotoken/signer.js3
-rw-r--r--chromium/chrome/browser/resources/cryptotoken/webrequestsender.js2
-rw-r--r--chromium/chrome/browser/resources/device_log_ui/device_log_ui.css21
-rw-r--r--chromium/chrome/browser/resources/device_log_ui/device_log_ui.html40
-rw-r--r--chromium/chrome/browser/resources/device_log_ui/device_log_ui.js30
-rw-r--r--chromium/chrome/browser/resources/discards/BUILD.gn12
-rw-r--r--chromium/chrome/browser/resources/discards/database_tab.html7
-rw-r--r--chromium/chrome/browser/resources/discards/database_tab.js44
-rw-r--r--chromium/chrome/browser/resources/discards/discards.html9
-rw-r--r--chromium/chrome/browser/resources/discards/discards.js12
-rw-r--r--chromium/chrome/browser/resources/discards/discards_tab.html49
-rw-r--r--chromium/chrome/browser/resources/discards/discards_tab.js107
-rw-r--r--chromium/chrome/browser/resources/discards/graph_tab_template.js6
-rw-r--r--chromium/chrome/browser/resources/discards/mojo_api.js1
-rw-r--r--chromium/chrome/browser/resources/discards/sorted_table_behavior.js4
-rw-r--r--chromium/chrome/browser/resources/download_internals/BUILD.gn15
-rw-r--r--chromium/chrome/browser/resources/download_internals/download_internals.html9
-rw-r--r--chromium/chrome/browser/resources/download_internals/download_internals.js233
-rw-r--r--chromium/chrome/browser/resources/download_internals/download_internals_browser_proxy.js94
-rw-r--r--chromium/chrome/browser/resources/download_internals/download_internals_visuals.js93
-rw-r--r--chromium/chrome/browser/resources/downloads/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/downloads/BUILD.gn9
-rw-r--r--chromium/chrome/browser/resources/downloads/OWNERS2
-rw-r--r--chromium/chrome/browser/resources/downloads/constants.js2
-rw-r--r--chromium/chrome/browser/resources/downloads/icon_loader.js2
-rw-r--r--chromium/chrome/browser/resources/downloads/item.html41
-rw-r--r--chromium/chrome/browser/resources/downloads/item.js190
-rw-r--r--chromium/chrome/browser/resources/downloads/manager.js47
-rw-r--r--chromium/chrome/browser/resources/downloads/search_service.js4
-rw-r--r--chromium/chrome/browser/resources/downloads/toolbar.js24
-rw-r--r--chromium/chrome/browser/resources/engagement/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/explore_sites_internals/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/extensions/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/extensions/BUILD.gn48
-rw-r--r--chromium/chrome/browser/resources/extensions/activity_log/BUILD.gn2
-rw-r--r--chromium/chrome/browser/resources/extensions/activity_log/activity_log.js14
-rw-r--r--chromium/chrome/browser/resources/extensions/activity_log/activity_log_history.js36
-rw-r--r--chromium/chrome/browser/resources/extensions/activity_log/activity_log_history_item.js12
-rw-r--r--chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream.js30
-rw-r--r--chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js16
-rw-r--r--chromium/chrome/browser/resources/extensions/checkup.html65
-rw-r--r--chromium/chrome/browser/resources/extensions/checkup.js15
-rw-r--r--chromium/chrome/browser/resources/extensions/code_section.js14
-rw-r--r--chromium/chrome/browser/resources/extensions/detail_view.html63
-rw-r--r--chromium/chrome/browser/resources/extensions/detail_view.js119
-rw-r--r--chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js2
-rw-r--r--chromium/chrome/browser/resources/extensions/drop_overlay.js4
-rw-r--r--chromium/chrome/browser/resources/extensions/error_page.html3
-rw-r--r--chromium/chrome/browser/resources/extensions/error_page.js80
-rw-r--r--chromium/chrome/browser/resources/extensions/extensions_resources.grd18
-rw-r--r--chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd8
-rw-r--r--chromium/chrome/browser/resources/extensions/host_permissions_toggle_list.js10
-rw-r--r--chromium/chrome/browser/resources/extensions/install_warnings_dialog.js4
-rw-r--r--chromium/chrome/browser/resources/extensions/item.html18
-rw-r--r--chromium/chrome/browser/resources/extensions/item.js91
-rw-r--r--chromium/chrome/browser/resources/extensions/item_behavior.js2
-rw-r--r--chromium/chrome/browser/resources/extensions/item_list.html13
-rw-r--r--chromium/chrome/browser/resources/extensions/item_list.js36
-rw-r--r--chromium/chrome/browser/resources/extensions/item_util.js45
-rw-r--r--chromium/chrome/browser/resources/extensions/keyboard_shortcuts.html2
-rw-r--r--chromium/chrome/browser/resources/extensions/keyboard_shortcuts.js14
-rw-r--r--chromium/chrome/browser/resources/extensions/kiosk_dialog.js34
-rw-r--r--chromium/chrome/browser/resources/extensions/load_error.js8
-rw-r--r--chromium/chrome/browser/resources/extensions/manager.html1
-rw-r--r--chromium/chrome/browser/resources/extensions/manager.js116
-rw-r--r--chromium/chrome/browser/resources/extensions/navigation_helper.js16
-rw-r--r--chromium/chrome/browser/resources/extensions/options_dialog.js12
-rw-r--r--chromium/chrome/browser/resources/extensions/pack_dialog.js18
-rw-r--r--chromium/chrome/browser/resources/extensions/pack_dialog_alert.js10
-rw-r--r--chromium/chrome/browser/resources/extensions/runtime_host_permissions.js34
-rw-r--r--chromium/chrome/browser/resources/extensions/runtime_hosts_dialog.js32
-rw-r--r--chromium/chrome/browser/resources/extensions/service.js40
-rw-r--r--chromium/chrome/browser/resources/extensions/shared_style.html2
-rw-r--r--chromium/chrome/browser/resources/extensions/shared_vars.html1
-rw-r--r--chromium/chrome/browser/resources/extensions/shortcut_input.html8
-rw-r--r--chromium/chrome/browser/resources/extensions/shortcut_input.js61
-rw-r--r--chromium/chrome/browser/resources/extensions/shortcut_util.js4
-rw-r--r--chromium/chrome/browser/resources/extensions/sidebar.js8
-rw-r--r--chromium/chrome/browser/resources/extensions/toggle_row.html2
-rw-r--r--chromium/chrome/browser/resources/extensions/toggle_row.js6
-rw-r--r--chromium/chrome/browser/resources/extensions/toolbar.js52
-rw-r--r--chromium/chrome/browser/resources/feed_internals/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/BUILD.gn133
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/authenticator.js141
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/channel.js17
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd52
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js8
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/post_message_channel.js46
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js167
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/saml_injected.js23
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/saml_password_attributes.js165
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/saml_password_attributes_test.unitjs85
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/saml_timestamps.js140
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/saml_timestamps_test.unitjs138
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/scroll_helper_injected.js51
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/webview_event_manager.js22
-rw-r--r--chromium/chrome/browser/resources/gaia_auth_host/webview_saml_injected.js1
-rw-r--r--chromium/chrome/browser/resources/history/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/history/BUILD.gn206
-rw-r--r--chromium/chrome/browser/resources/history/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/history/app.html29
-rw-r--r--chromium/chrome/browser/resources/history/app.js770
-rw-r--r--chromium/chrome/browser/resources/history/browser_service.html4
-rw-r--r--chromium/chrome/browser/resources/history/browser_service.js44
-rw-r--r--chromium/chrome/browser/resources/history/constants.html1
-rw-r--r--chromium/chrome/browser/resources/history/constants.js15
-rw-r--r--chromium/chrome/browser/resources/history/externs.js24
-rw-r--r--chromium/chrome/browser/resources/history/history.html6
-rw-r--r--chromium/chrome/browser/resources/history/history.js64
-rw-r--r--chromium/chrome/browser/resources/history/history_item.html25
-rw-r--r--chromium/chrome/browser/resources/history/history_item.js568
-rw-r--r--chromium/chrome/browser/resources/history/history_list.html21
-rw-r--r--chromium/chrome/browser/resources/history/history_list.js160
-rw-r--r--chromium/chrome/browser/resources/history/history_resources.grd109
-rw-r--r--chromium/chrome/browser/resources/history/history_resources_vulcanized.grd34
-rw-r--r--chromium/chrome/browser/resources/history/history_toolbar.html14
-rw-r--r--chromium/chrome/browser/resources/history/history_toolbar.js26
-rw-r--r--chromium/chrome/browser/resources/history/lazy_load.html13
-rw-r--r--chromium/chrome/browser/resources/history/lazy_load.js12
-rw-r--r--chromium/chrome/browser/resources/history/query_manager.html2
-rw-r--r--chromium/chrome/browser/resources/history/query_manager.js65
-rw-r--r--chromium/chrome/browser/resources/history/router.html9
-rw-r--r--chromium/chrome/browser/resources/history/router.js23
-rw-r--r--chromium/chrome/browser/resources/history/searched_label.html6
-rw-r--r--chromium/chrome/browser/resources/history/searched_label.js8
-rw-r--r--chromium/chrome/browser/resources/history/shared_style.html6
-rw-r--r--chromium/chrome/browser/resources/history/shared_style.js13
-rw-r--r--chromium/chrome/browser/resources/history/shared_vars.html4
-rw-r--r--chromium/chrome/browser/resources/history/shared_vars.js11
-rw-r--r--chromium/chrome/browser/resources/history/side_bar.html21
-rw-r--r--chromium/chrome/browser/resources/history/side_bar.js42
-rw-r--r--chromium/chrome/browser/resources/history/strings.html3
-rw-r--r--chromium/chrome/browser/resources/history/synced_device_card.html22
-rw-r--r--chromium/chrome/browser/resources/history/synced_device_card.js63
-rw-r--r--chromium/chrome/browser/resources/history/synced_device_manager.html18
-rw-r--r--chromium/chrome/browser/resources/history/synced_device_manager.js83
-rw-r--r--chromium/chrome/browser/resources/identity_internals/identity_internals.js16
-rw-r--r--chromium/chrome/browser/resources/identity_scope_approval_dialog/inject.js18
-rw-r--r--chromium/chrome/browser/resources/identity_scope_approval_dialog/manifest.json5
-rw-r--r--chromium/chrome/browser/resources/identity_scope_approval_dialog/scope_approval_dialog.js22
-rw-r--r--chromium/chrome/browser/resources/inline_login/inline_login.js7
-rw-r--r--chromium/chrome/browser/resources/inspect/inspect.css51
-rw-r--r--chromium/chrome/browser/resources/inspect/inspect.js3
-rw-r--r--chromium/chrome/browser/resources/interventions_internals/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/interventions_internals/index.js14
-rw-r--r--chromium/chrome/browser/resources/local_discovery/local_discovery.js46
-rw-r--r--chromium/chrome/browser/resources/local_ntp/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/local_ntp/customize.js36
-rw-r--r--chromium/chrome/browser/resources/local_ntp/externs.js27
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons.grdp31
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/bookmark.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/calculator.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/clock.svg2
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/drive_docs.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/drive_folder.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/drive_form.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/drive_image.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/drive_logo.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/drive_pdf.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/drive_sheets.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/drive_slides.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/drive_video.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/extension_app.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/icons/page.svg1
-rw-r--r--chromium/chrome/browser/resources/local_ntp/local_ntp.css184
-rw-r--r--chromium/chrome/browser/resources/local_ntp/local_ntp.html4
-rw-r--r--chromium/chrome/browser/resources/local_ntp/local_ntp.js429
-rw-r--r--chromium/chrome/browser/resources/local_ntp/most_visited_single.css4
-rw-r--r--chromium/chrome/browser/resources/local_ntp/voice.css6
-rw-r--r--chromium/chrome/browser/resources/local_ntp/voice.js21
-rw-r--r--chromium/chrome/browser/resources/local_state/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/management/BUILD.gn6
-rw-r--r--chromium/chrome/browser/resources/management/icons.html2
-rw-r--r--chromium/chrome/browser/resources/management/management_browser_proxy.js6
-rw-r--r--chromium/chrome/browser/resources/management/management_ui.html9
-rw-r--r--chromium/chrome/browser/resources/management/management_ui.js10
-rw-r--r--chromium/chrome/browser/resources/media/BUILD.gn39
-rw-r--r--chromium/chrome/browser/resources/media/media_data_table.js124
-rw-r--r--chromium/chrome/browser/resources/media/media_feeds.html206
-rw-r--r--chromium/chrome/browser/resources/media/media_feeds.js396
-rw-r--r--chromium/chrome/browser/resources/media/media_history.html249
-rw-r--r--chromium/chrome/browser/resources/media/media_history.js250
-rw-r--r--chromium/chrome/browser/resources/media/mei_preload/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/media_router/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/BUILD.gn20
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/external_message_listener.js11
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/external_message_listener_test.js18
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/externs.js4
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/files.gni29
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/init.js31
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/init_helper.js3
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/init_test.js1
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener.js7
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener_test.js3
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/log_manager.js28
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/manager/provider.js1
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager.js38
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager_test.js5
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_analytics.js7
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_service.js1
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings.js37
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings_test.js77
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream.js18
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream_test.js3
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/mojo_externs.js26
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils.js11
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils_test.js11
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/common/sink_utils.js11
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity.js22
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity_records.js156
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity_records_test.js100
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_analytics.js119
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_analytics_test.js88
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_app_discovery_service.js480
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_app_discovery_service_test.js362
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_client.js355
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_client_test.js307
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider.js474
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider_callbacks.js65
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider_test.js256
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink.js309
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_discovery_service.js334
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_discovery_service_test.js163
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_test.js127
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/presentation_url.js146
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/presentation_url_test.js75
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/providers/dial/sink_app_status.js23
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/utils/analytics.js4
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics.js4
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics_test.js3
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils.js25
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils_test.js3
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/utils/unit_test_utils.js2
-rw-r--r--chromium/chrome/browser/resources/media_router/extension/src/webrtc/peer_connection_analytics.js4
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router_internals.css7
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router_internals.html6
-rw-r--r--chromium/chrome/browser/resources/media_router/media_router_internals.js10
-rw-r--r--chromium/chrome/browser/resources/net_internals/browser_bridge.js58
-rw-r--r--chromium/chrome/browser/resources/net_internals/domain_security_policy_view.js18
-rw-r--r--chromium/chrome/browser/resources/net_internals/events_view.js4
-rw-r--r--chromium/chrome/browser/resources/net_internals/main.js8
-rw-r--r--chromium/chrome/browser/resources/net_internals/sockets_view.js4
-rw-r--r--chromium/chrome/browser/resources/net_internals/tab_switcher_view.js18
-rw-r--r--chromium/chrome/browser/resources/net_internals/view.js46
-rw-r--r--chromium/chrome/browser/resources/network_speech_synthesis/tts_extension.js12
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/BUILD.gn200
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/app.html225
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/app.js229
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/browser_proxy.js45
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.html60
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.js76
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/customize_dialog.html190
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/customize_dialog.js124
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/customize_shortcuts.html274
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/customize_shortcuts.js130
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/customize_themes.html146
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/customize_themes.js151
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/fakebox.html126
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/fakebox.js125
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/grid.html21
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/grid.js82
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/account_circle.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/backgrounds.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/brush.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/check_circle.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/colorize.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/colors.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/generic_globe.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/googlemic_clr_24px.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/header.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/icon_pencil.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/link.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/mic.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/icons/shortcut_circles.svg1
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/logo.html46
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/logo.js167
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/manager.html0
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/manager.js29
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/mini_page.html35
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/mini_page.js18
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/most_visited.html216
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/most_visited.js756
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/new_tab_page.html9
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd89
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/shared_vars.css40
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/theme_icon.html63
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/theme_icon.js23
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/untrusted/iframe.html24
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/untrusted/image.html20
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html21
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js62
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/untrusted/promo.html96
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/untrusted/promo.js23
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.html13
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.js48
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/utils.js73
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.html246
-rw-r--r--chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.js491
-rw-r--r--chromium/chrome/browser/resources/notifications_internals/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/ntp4/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/ntp4/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/ntp4/apps_page.js78
-rw-r--r--chromium/chrome/browser/resources/ntp4/dot_list.js4
-rw-r--r--chromium/chrome/browser/resources/ntp4/incognito_tab.html5
-rw-r--r--chromium/chrome/browser/resources/ntp4/incognito_tab.js17
-rw-r--r--chromium/chrome/browser/resources/ntp4/incognito_tab_theme.css (renamed from chromium/chrome/browser/resources/ntp4/new_incognito_tab_theme.css)0
-rw-r--r--chromium/chrome/browser/resources/ntp4/nav_dot.js32
-rw-r--r--chromium/chrome/browser/resources/ntp4/page_list_view.js50
-rw-r--r--chromium/chrome/browser/resources/ntp4/page_switcher.js22
-rw-r--r--chromium/chrome/browser/resources/ntp4/tile_page.js112
-rw-r--r--chromium/chrome/browser/resources/ntp4/trash.js12
-rw-r--r--chromium/chrome/browser/resources/offline_pages/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/omnibox/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/omnibox/BUILD.gn30
-rw-r--r--chromium/chrome/browser/resources/omnibox/omnibox.html12
-rw-r--r--chromium/chrome/browser/resources/omnibox/omnibox.js67
-rw-r--r--chromium/chrome/browser/resources/omnibox/omnibox_element.js19
-rw-r--r--chromium/chrome/browser/resources/omnibox/omnibox_input.js178
-rw-r--r--chromium/chrome/browser/resources/omnibox/omnibox_output.js2067
-rw-r--r--chromium/chrome/browser/resources/omnibox/omnibox_popup.html16
-rw-r--r--chromium/chrome/browser/resources/omnibox/omnibox_popup.js37
-rw-r--r--chromium/chrome/browser/resources/omnibox/output_results_group.css8
-rw-r--r--chromium/chrome/browser/resources/omnibox/resources.grd8
-rw-r--r--chromium/chrome/browser/resources/optimize_webui.gni12
-rwxr-xr-xchromium/chrome/browser/resources/optimize_webui.py111
-rwxr-xr-xchromium/chrome/browser/resources/optimize_webui_test.py84
-rw-r--r--chromium/chrome/browser/resources/pdf/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/pdf/BUILD.gn19
-rw-r--r--chromium/chrome/browser/resources/pdf/browser_api.js14
-rw-r--r--chromium/chrome/browser/resources/pdf/constants.js (renamed from chromium/chrome/browser/resources/pdf/pdf_fitting_type.js)11
-rw-r--r--chromium/chrome/browser/resources/pdf/controller.js20
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/BUILD.gn18
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.js16
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js4
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js6
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js56
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.js10
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js12
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js12
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js42
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js18
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js14
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html3
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.js19
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html26
-rw-r--r--chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js82
-rw-r--r--chromium/chrome/browser/resources/pdf/gesture_detector.js2
-rw-r--r--chromium/chrome/browser/resources/pdf/index.html2
-rw-r--r--chromium/chrome/browser/resources/pdf/ink/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/pdf/ink/ink_api.js2
-rw-r--r--chromium/chrome/browser/resources/pdf/metrics.js36
-rw-r--r--chromium/chrome/browser/resources/pdf/navigator.js8
-rw-r--r--chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js16
-rw-r--r--chromium/chrome/browser/resources/pdf/pdf_scripting_api.js34
-rw-r--r--chromium/chrome/browser/resources/pdf/pdf_viewer.js104
-rw-r--r--chromium/chrome/browser/resources/pdf/toolbar_manager.js8
-rw-r--r--chromium/chrome/browser/resources/pdf/viewport.js138
-rw-r--r--chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json6
-rw-r--r--chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json6
-rw-r--r--chromium/chrome/browser/resources/plugin_metadata/plugins_win.json6
-rw-r--r--chromium/chrome/browser/resources/print_preview/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/print_preview/BUILD.gn22
-rw-r--r--chromium/chrome/browser/resources/print_preview/cloud_print_interface.js1
-rw-r--r--chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js55
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/cloud_parsers.js20
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/coordinate2d.js2
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/destination.js63
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/destination_match.js2
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/destination_store.js225
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/document_info.js18
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/invitation_store.js8
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/margins.js4
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/model.js153
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/printable_area.js2
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/size.js4
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/state.js24
-rw-r--r--chromium/chrome/browser/resources/print_preview/data/user_manager.js23
-rw-r--r--chromium/chrome/browser/resources/print_preview/native_layer.js4
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview.html1
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview.js1
-rw-r--r--chromium/chrome/browser/resources/print_preview/print_preview_utils.js6
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/BUILD.gn6
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/advanced_options_settings.js4
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html48
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.js50
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/advanced_settings_item.js57
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/app.js87
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/button_strip.js16
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/color_settings.js8
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/copies_settings.html8
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/copies_settings.js48
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_dialog.html32
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_dialog.js69
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_list.html21
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_list.js125
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_list_item.html2
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_list_item.js31
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_select.html4
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_select.js31
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_settings.html1
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/destination_settings.js138
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/dpi_settings.js12
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/duplex_settings.js14
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/header.js95
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/highlight_utils.js67
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/input_behavior.js20
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/layout_settings.js6
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/link_container.js14
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/margin_control.js63
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/margin_control_container.html3
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/margin_control_container.js83
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/margins_settings.html3
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/margins_settings.js69
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/media_size_settings.js2
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/more_settings.js4
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/number_settings_section.html2
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/number_settings_section.js36
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/other_options_settings.js24
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js5
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/pages_settings.js64
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/pin_settings.html3
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/pin_settings.js35
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/plugin_proxy.js38
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/preview_area.js149
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.html1
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.js23
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/print_preview_shared_css.html2
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html2
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.js34
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/scaling_settings.js20
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/select_behavior.js4
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/settings_behavior.js10
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/settings_select.js14
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/sidebar.html5
-rw-r--r--chromium/chrome/browser/resources/print_preview/ui/sidebar.js35
-rw-r--r--chromium/chrome/browser/resources/protobufs/OWNERS4
-rwxr-xr-xchromium/chrome/browser/resources/protobufs/binary_proto_generator.py207
-rw-r--r--chromium/chrome/browser/resources/quota_internals/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/quota_internals/event_handler.js4
-rw-r--r--chromium/chrome/browser/resources/quota_internals/main.css7
-rw-r--r--chromium/chrome/browser/resources/quota_internals/main.html11
-rw-r--r--chromium/chrome/browser/resources/quota_internals/message_dispatcher.js8
-rw-r--r--chromium/chrome/browser/resources/reset_password/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/BUILD.gn106
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/PRESUBMIT.py37
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/README.md2
-rw-r--r--chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb3599
-rwxr-xr-xchromium/chrome/browser/resources/safe_browsing/gen_file_type_proto.py196
-rwxr-xr-xchromium/chrome/browser/resources/safe_browsing/push_file_type_proto.py82
-rw-r--r--chromium/chrome/browser/resources/sandbox_internals/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/sandbox_internals/sandbox_internals_win.js21
-rw-r--r--chromium/chrome/browser/resources/settings/BUILD.gn386
-rw-r--r--chromium/chrome/browser/resources/settings/a11y_page/BUILD.gn110
-rw-r--r--chromium/chrome/browser/resources/settings/about_page/BUILD.gn74
-rw-r--r--chromium/chrome/browser/resources/settings/android_apps_page/BUILD.gn41
-rw-r--r--chromium/chrome/browser/resources/settings/appearance_page/BUILD.gn140
-rw-r--r--chromium/chrome/browser/resources/settings/autofill_page/BUILD.gn575
-rw-r--r--chromium/chrome/browser/resources/settings/basic_page/BUILD.gn50
-rw-r--r--chromium/chrome/browser/resources/settings/change_password_page/BUILD.gn30
-rw-r--r--chromium/chrome/browser/resources/settings/chrome_cleanup_page/BUILD.gn77
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/BUILD.gn81
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn27
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/bluetooth_page/BUILD.gn (renamed from chromium/chrome/browser/resources/settings/bluetooth_page/BUILD.gn)17
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/crostini_page/BUILD.gn (renamed from chromium/chrome/browser/resources/settings/crostini_page/BUILD.gn)45
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/date_time_page/BUILD.gn (renamed from chromium/chrome/browser/resources/settings/date_time_page/BUILD.gn)15
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/device_page/BUILD.gn (renamed from chromium/chrome/browser/resources/settings/device_page/BUILD.gn)45
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/google_assistant_page/BUILD.gn (renamed from chromium/chrome/browser/resources/settings/google_assistant_page/BUILD.gn)9
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn (renamed from chromium/chrome/browser/resources/settings/internet_page/BUILD.gn)30
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn13
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn115
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_a11y_page/BUILD.gn50
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_about_page/BUILD.gn25
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn26
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn12
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_files_page/BUILD.gn7
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn20
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn193
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_printing_page/BUILD.gn121
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn9
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn6
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_search_page/BUILD.gn7
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_settings_menu/BUILD.gn7
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn12
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_settings_search_box/BUILD.gn32
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_settings_ui/BUILD.gn9
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn5
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/parental_controls_page/BUILD.gn (renamed from chromium/chrome/browser/resources/settings/parental_controls_page/BUILD.gn)10
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/personalization_page/BUILD.gn34
-rw-r--r--chromium/chrome/browser/resources/settings/chromeos/plugin_vm_page/BUILD.gn (renamed from chromium/chrome/browser/resources/settings/plugin_vm_page/BUILD.gn)20
-rw-r--r--chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn107
-rw-r--r--chromium/chrome/browser/resources/settings/controls/BUILD.gn303
-rw-r--r--chromium/chrome/browser/resources/settings/default_browser_page/BUILD.gn51
-rw-r--r--chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn67
-rw-r--r--chromium/chrome/browser/resources/settings/incompatible_applications_page/BUILD.gn82
-rw-r--r--chromium/chrome/browser/resources/settings/languages_page/BUILD.gn201
-rw-r--r--chromium/chrome/browser/resources/settings/multidevice_page/BUILD.gn118
-rw-r--r--chromium/chrome/browser/resources/settings/on_startup_page/BUILD.gn140
-rw-r--r--chromium/chrome/browser/resources/settings/os_settings_resources.grd996
-rw-r--r--chromium/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd49
-rw-r--r--chromium/chrome/browser/resources/settings/people_page/BUILD.gn531
-rw-r--r--chromium/chrome/browser/resources/settings/prefs/BUILD.gn80
-rw-r--r--chromium/chrome/browser/resources/settings/printing_page/BUILD.gn198
-rw-r--r--chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn568
-rw-r--r--chromium/chrome/browser/resources/settings/reset_page/BUILD.gn138
-rw-r--r--chromium/chrome/browser/resources/settings/safety_check_page/BUILD.gn105
-rw-r--r--chromium/chrome/browser/resources/settings/search_engines_page/BUILD.gn159
-rw-r--r--chromium/chrome/browser/resources/settings/search_page/BUILD.gn43
-rw-r--r--chromium/chrome/browser/resources/settings/settings.gni136
-rw-r--r--chromium/chrome/browser/resources/settings/settings_main/BUILD.gn48
-rw-r--r--chromium/chrome/browser/resources/settings/settings_menu/BUILD.gn41
-rw-r--r--chromium/chrome/browser/resources/settings/settings_page/BUILD.gn120
-rw-r--r--chromium/chrome/browser/resources/settings/settings_resources.grd1102
-rw-r--r--chromium/chrome/browser/resources/settings/settings_resources_v3.grdp815
-rw-r--r--chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd100
-rw-r--r--chromium/chrome/browser/resources/settings/settings_ui/BUILD.gn60
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings/BUILD.gn664
-rw-r--r--chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn139
-rw-r--r--chromium/chrome/browser/resources/settings/system_page/BUILD.gn54
-rw-r--r--chromium/chrome/browser/resources/signin/BUILD.gn13
-rw-r--r--chromium/chrome/browser/resources/signin/signin_email_confirmation/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html6
-rw-r--r--chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.html5
-rw-r--r--chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.js9
-rw-r--r--chromium/chrome/browser/resources/signin/signin_error/BUILD.gn23
-rw-r--r--chromium/chrome/browser/resources/signin/signin_error/signin_error.html113
-rw-r--r--chromium/chrome/browser/resources/signin/signin_error/signin_error.js76
-rw-r--r--chromium/chrome/browser/resources/signin/signin_error/signin_error_app.html98
-rw-r--r--chromium/chrome/browser/resources/signin/signin_error/signin_error_app.js100
-rw-r--r--chromium/chrome/browser/resources/signin/signin_shared_css.html5
-rw-r--r--chromium/chrome/browser/resources/signin/sync_confirmation/BUILD.gn37
-rw-r--r--chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js20
-rw-r--r--chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.html62
-rw-r--r--chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.js74
-rw-r--r--chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.html45
-rw-r--r--chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.js90
-rw-r--r--chromium/chrome/browser/resources/snippets_internals/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/ssl/ssl_error_assistant/BUILD.gn44
-rw-r--r--chromium/chrome/browser/resources/ssl/ssl_error_assistant/PRESUBMIT.py41
-rwxr-xr-xchromium/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py71
-rwxr-xr-xchromium/chrome/browser/resources/ssl/ssl_error_assistant/push_proto.py89
-rw-r--r--chromium/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.asciipb356
-rw-r--r--chromium/chrome/browser/resources/tab_strip/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/tab_strip/BUILD.gn68
-rw-r--r--chromium/chrome/browser/resources/tab_strip/alert_indicator.html10
-rw-r--r--chromium/chrome/browser/resources/tab_strip/alert_indicator.js2
-rw-r--r--chromium/chrome/browser/resources/tab_strip/alert_indicators.js4
-rw-r--r--chromium/chrome/browser/resources/tab_strip/alert_indicators/tab_hid_connected.svg1
-rw-r--r--chromium/chrome/browser/resources/tab_strip/custom_element.js16
-rw-r--r--chromium/chrome/browser/resources/tab_strip/drag_manager.js519
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab.html68
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab.js73
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab_group.html181
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab_group.js101
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab_list.html108
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab_list.js465
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab_strip.html38
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js13
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab_strip_resources.grd23
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tab_swiper.js14
-rw-r--r--chromium/chrome/browser/resources/tab_strip/tabs_api_proxy.js83
-rw-r--r--chromium/chrome/browser/resources/tools/rollup_plugin.js2
-rw-r--r--chromium/chrome/browser/resources/usb_internals/BUILD.gn5
-rw-r--r--chromium/chrome/browser/resources/user_manager/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/user_manager/control_bar.js8
-rw-r--r--chromium/chrome/browser/resources/user_manager/create_profile.js34
-rw-r--r--chromium/chrome/browser/resources/user_manager/error_dialog.js2
-rw-r--r--chromium/chrome/browser/resources/user_manager/user_manager.html2
-rw-r--r--chromium/chrome/browser/resources/user_manager/user_manager_pages.js10
-rw-r--r--chromium/chrome/browser/resources/user_manager/user_manager_tutorial.html2
-rw-r--r--chromium/chrome/browser/resources/user_manager/user_manager_tutorial.js10
-rw-r--r--chromium/chrome/browser/resources/vr/OWNERS1
-rw-r--r--chromium/chrome/browser/resources/webapks/BUILD.gn4
-rw-r--r--chromium/chrome/browser/resources/welcome/.eslintrc.js11
-rw-r--r--chromium/chrome/browser/resources/welcome/BUILD.gn14
-rw-r--r--chromium/chrome/browser/resources/welcome/OWNERS2
-rw-r--r--chromium/chrome/browser/resources/welcome/google_apps/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/welcome/google_apps/nux_google_apps.js36
-rw-r--r--chromium/chrome/browser/resources/welcome/landing_view.js8
-rw-r--r--chromium/chrome/browser/resources/welcome/navigation_behavior.js18
-rw-r--r--chromium/chrome/browser/resources/welcome/ntp_background/nux_ntp_background.js32
-rw-r--r--chromium/chrome/browser/resources/welcome/set_as_default/BUILD.gn8
-rw-r--r--chromium/chrome/browser/resources/welcome/set_as_default/nux_set_as_default.js16
-rw-r--r--chromium/chrome/browser/resources/welcome/shared/BUILD.gn6
-rw-r--r--chromium/chrome/browser/resources/welcome/shared/module_metrics_proxy.js4
-rw-r--r--chromium/chrome/browser/resources/welcome/shared/step_indicator.js6
-rw-r--r--chromium/chrome/browser/resources/welcome/signin_view.js12
-rw-r--r--chromium/chrome/browser/resources/welcome/welcome_app.js12
-rw-r--r--chromium/chrome/browser/safe_browsing/BUILD.gn111
-rw-r--r--chromium/chrome/browser/safe_browsing/chrome_cleaner/BUILD.gn2
-rw-r--r--chromium/chrome/browser/safe_browsing/incident_reporting/BUILD.gn4
-rw-r--r--chromium/chrome/browser/safe_browsing/incident_reporting/verifier_test/BUILD.gn7
-rw-r--r--chromium/chrome/browser/search/BUILD.gn8
-rw-r--r--chromium/chrome/browser/settings/BUILD.gn38
-rw-r--r--chromium/chrome/browser/share/BUILD.gn4
-rw-r--r--chromium/chrome/browser/share/android/BUILD.gn20
-rw-r--r--chromium/chrome/browser/share/android/java_sources.gni22
-rw-r--r--chromium/chrome/browser/share/android/test_java_sources.gni6
-rw-r--r--chromium/chrome/browser/sharing/BUILD.gn11
-rw-r--r--chromium/chrome/browser/sharing/buildflags.gni7
-rw-r--r--chromium/chrome/browser/sharing/proto/BUILD.gn20
-rw-r--r--chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc62
-rw-r--r--chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.h9
-rw-r--r--chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc74
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc7
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.h2
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc371
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc26
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h2
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc8
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_mac_view_interactive_uitest.mm (renamed from chromium/chrome/browser/spellchecker/spellcheck_mac_view_browsertest.mm)8
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_service.cc61
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_service.h38
-rw-r--r--chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc24
-rw-r--r--chromium/chrome/browser/spellchecker/spelling_request.cc61
-rw-r--r--chromium/chrome/browser/spellchecker/spelling_request.h39
-rw-r--r--chromium/chrome/browser/storage_access_api/BUILD.gn21
-rw-r--r--chromium/chrome/browser/subresource_filter/BUILD.gn12
-rw-r--r--chromium/chrome/browser/supervised_user/BUILD.gn19
-rw-r--r--chromium/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn8
-rw-r--r--chromium/chrome/browser/supervised_user/supervised_user_unscaled_resources.grd14
-rw-r--r--chromium/chrome/browser/sync_file_system/drive_backend/BUILD.gn4
-rw-r--r--chromium/chrome/browser/tab_contents/OWNERS2
-rw-r--r--chromium/chrome/browser/tab_contents/form_interaction_tab_helper.cc116
-rw-r--r--chromium/chrome/browser/tab_contents/form_interaction_tab_helper.h47
-rw-r--r--chromium/chrome/browser/tab_contents/form_interaction_tab_helper_unittest.cc161
-rw-r--r--chromium/chrome/browser/tab_contents/navigation_metrics_recorder.cc87
-rw-r--r--chromium/chrome/browser/tab_contents/navigation_metrics_recorder.h38
-rw-r--r--chromium/chrome/browser/tab_contents/navigation_metrics_recorder_browsertest.cc38
-rw-r--r--chromium/chrome/browser/tab_contents/tab_util.cc79
-rw-r--r--chromium/chrome/browser/tab_contents/tab_util.h34
-rw-r--r--chromium/chrome/browser/tab_contents/view_source_browsertest.cc685
-rw-r--r--chromium/chrome/browser/thumbnail/BUILD.gn48
-rw-r--r--chromium/chrome/browser/thumbnail/cc/BUILD.gn46
-rw-r--r--chromium/chrome/browser/thumbnail/generator/BUILD.gn163
-rw-r--r--chromium/chrome/browser/touch_to_fill/BUILD.gn12
-rw-r--r--chromium/chrome/browser/touch_to_fill/android/BUILD.gn11
-rw-r--r--chromium/chrome/browser/touch_to_fill/android/internal/BUILD.gn21
-rw-r--r--chromium/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd28
-rw-r--r--chromium/chrome/browser/ui/BUILD.gn627
-rw-r--r--chromium/chrome/browser/ui/android/appmenu/BUILD.gn22
-rw-r--r--chromium/chrome/browser/ui/android/appmenu/internal/BUILD.gn43
-rw-r--r--chromium/chrome/browser/ui/android/favicon/BUILD.gn70
-rw-r--r--chromium/chrome/browser/ui/android/native_page/BUILD.gn19
-rw-r--r--chromium/chrome/browser/ui/android/strings/android_chrome_strings.grd572
-rw-r--r--chromium/chrome/browser/ui/android/strings/xr_consent_ui_strings_java.grdp13
-rw-r--r--chromium/chrome/browser/ui/android/styles/BUILD.gn33
-rw-r--r--chromium/chrome/browser/ui/android/widget/BUILD.gn147
-rw-r--r--chromium/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn4
-rw-r--r--chromium/chrome/browser/ui/app_list/search/search_result_ranker/BUILD.gn16
-rw-r--r--chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn8
-rw-r--r--chromium/chrome/browser/ui/color/BUILD.gn21
-rw-r--r--chromium/chrome/browser/ui/libgtkui/BUILD.gn110
-rw-r--r--chromium/chrome/browser/ui/messages/android/BUILD.gn96
-rw-r--r--chromium/chrome/browser/ui/views/BUILD.gn8
-rw-r--r--chromium/chrome/browser/ui/webui/about_ui.cc126
-rw-r--r--chromium/chrome/browser/ui/webui/app_management/BUILD.gn8
-rw-r--r--chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.h2
-rw-r--r--chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/autofill_internals_ui.h5
-rw-r--r--chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui.h5
-rw-r--r--chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui_browsertest.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn13
-rw-r--r--chromium/chrome/browser/ui/webui/bluetooth_internals/OWNERS2
-rw-r--r--chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.cc7
-rw-r--r--chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.h10
-rw-r--r--chromium/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/browser_switch/browser_switch_ui.cc31
-rw-r--r--chromium/chrome/browser/ui/webui/certificate_manager_localized_strings_provider.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/certificate_viewer_ui.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/certificate_viewer_webui.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/certificates_handler.cc15
-rw-r--r--chromium/chrome/browser/ui/webui/chrome_url_disabled_ui.cc34
-rw-r--r--chromium/chrome/browser/ui/webui/chrome_url_disabled_ui.h22
-rw-r--r--chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc86
-rw-r--r--chromium/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc111
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/OWNERS3
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.cc17
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.h3
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc5
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_test.js2
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/add_supervision/BUILD.gn4
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom3
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc12
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h7
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc33
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h21
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.cc9
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.h1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc16
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc5
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/cellular_setup/OWNERS1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h9
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.cc15
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_installer/BUILD.gn9
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_installer/OWNERS4
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom13
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc40
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.h13
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.cc54
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h6
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc52
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h16
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/BUILD.gn4
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/OWNERS4
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom37
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc68
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h19
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc104
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h31
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc37
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h21
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc30
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.cc346
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.h149
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_unittest.cc363
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/image_source.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.h9
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.h8
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc74
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h16
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.cc120
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.h85
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.cc125
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc29
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/base_screen_handler.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc52
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h4
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.cc22
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h11
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app_test.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc24
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc80
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h11
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc7
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h2
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h2
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc9
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc89
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h14
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.cc83
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h64
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc46
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h21
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.cc71
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h29
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/l10n_util.cc36
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc101
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h31
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc12
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.h1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc83
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.h36
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc23
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h20
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc28
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h24
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/signin_userlist_unittest.cc24
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc35
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.cc34
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h19
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.cc30
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h11
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/machine_learning/BUILD.gn8
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.cc7
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.h11
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc13
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h10
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h6
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/network_ui.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/network_ui.h8
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/power_ui.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/set_time_ui.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.cc67
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h32
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog_browsertest.cc104
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.cc17
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h9
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.cc23
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.cc88
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.h16
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler_unittest.cc271
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc15
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc21
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/terminal/OWNERS4
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_source.cc89
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_source.h39
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_ui.cc16
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_ui.h19
-rw-r--r--chromium/chrome/browser/ui/webui/chromeos/video_source.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/components/components_handler.cc166
-rw-r--r--chromium/chrome/browser/ui/webui/components/components_handler.h61
-rw-r--r--chromium/chrome/browser/ui/webui/components/components_handler_unittest.cc34
-rw-r--r--chromium/chrome/browser/ui/webui/components/components_ui.cc96
-rw-r--r--chromium/chrome/browser/ui/webui/components/components_ui.h30
-rw-r--r--chromium/chrome/browser/ui/webui/components_ui.cc282
-rw-r--r--chromium/chrome/browser/ui/webui/components_ui.h45
-rw-r--r--chromium/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/cookies_tree_model_util.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/crashes_ui.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/device_log_ui.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/devtools_ui_data_source.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/discards/BUILD.gn1
-rw-r--r--chromium/chrome/browser/ui/webui/discards/discards.mojom92
-rw-r--r--chromium/chrome/browser/ui/webui/discards/discards_ui.cc220
-rw-r--r--chromium/chrome/browser/ui/webui/discards/discards_ui.h22
-rw-r--r--chromium/chrome/browser/ui/webui/discards/graph_dump_impl.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/discards/graph_dump_impl.h9
-rw-r--r--chromium/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/discards/site_data.mojom90
-rw-r--r--chromium/chrome/browser/ui/webui/discards/site_data_provider_impl.cc147
-rw-r--r--chromium/chrome/browser/ui/webui/discards/site_data_provider_impl.h58
-rw-r--r--chromium/chrome/browser/ui/webui/domain_reliability_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/download_internals/download_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/downloads/BUILD.gn4
-rw-r--r--chromium/chrome/browser/ui/webui/downloads/OWNERS2
-rw-r--r--chromium/chrome/browser/ui/webui/downloads/downloads.mojom5
-rw-r--r--chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc37
-rw-r--r--chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.h3
-rw-r--r--chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler_unittest.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/downloads/downloads_ui.cc16
-rw-r--r--chromium/chrome/browser/ui/webui/downloads/downloads_ui.h8
-rw-r--r--chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.h10
-rw-r--r--chromium/chrome/browser/ui/webui/explore_sites_internals/BUILD.gn4
-rw-r--r--chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_page_handler.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.cc12
-rw-r--r--chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.h10
-rw-r--r--chromium/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.cc18
-rw-r--r--chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.h5
-rw-r--r--chromium/chrome/browser/ui/webui/extensions/extensions_ui.cc54
-rw-r--r--chromium/chrome/browser/ui/webui/extensions/extensions_ui.h11
-rw-r--r--chromium/chrome/browser/ui/webui/favicon_source.cc21
-rw-r--r--chromium/chrome/browser/ui/webui/favicon_source_unittest.cc53
-rw-r--r--chromium/chrome/browser/ui/webui/feed_internals/BUILD.gn8
-rw-r--r--chromium/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc13
-rw-r--r--chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.h10
-rw-r--r--chromium/chrome/browser/ui/webui/flags_ui.cc17
-rw-r--r--chromium/chrome/browser/ui/webui/flags_ui_handler.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/gcm_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/help/version_updater_chromeos.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/help/version_updater_mac.mm11
-rw-r--r--chromium/chrome/browser/ui/webui/help/version_updater_win.cc13
-rw-r--r--chromium/chrome/browser/ui/webui/history/browsing_history_handler.cc171
-rw-r--r--chromium/chrome/browser/ui/webui/history/browsing_history_handler.h10
-rw-r--r--chromium/chrome/browser/ui/webui/history/browsing_history_handler_unittest.cc99
-rw-r--r--chromium/chrome/browser/ui/webui/history/foreign_session_handler.cc65
-rw-r--r--chromium/chrome/browser/ui/webui/history/foreign_session_handler.h13
-rw-r--r--chromium/chrome/browser/ui/webui/history/history_ui.cc46
-rw-r--r--chromium/chrome/browser/ui/webui/history/navigation_handler.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/identity_internals_ui.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.js31
-rw-r--r--chromium/chrome/browser/ui/webui/inspect_ui_browsertest.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/interstitials/interstitial_ui.cc175
-rw-r--r--chromium/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc5
-rw-r--r--chromium/chrome/browser/ui/webui/interventions_internals/BUILD.gn8
-rw-r--r--chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc9
-rw-r--r--chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.h10
-rw-r--r--chromium/chrome/browser/ui/webui/invalidations_message_handler.cc26
-rw-r--r--chromium/chrome/browser/ui/webui/invalidations_message_handler.h6
-rw-r--r--chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc34
-rw-r--r--chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h2
-rw-r--r--chromium/chrome/browser/ui/webui/local_state/local_state_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/log_web_ui_url.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/management_ui.cc9
-rw-r--r--chromium/chrome/browser/ui/webui/management_ui_handler.cc115
-rw-r--r--chromium/chrome/browser/ui/webui/management_ui_handler.h7
-rw-r--r--chromium/chrome/browser/ui/webui/management_ui_handler_unittest.cc527
-rw-r--r--chromium/chrome/browser/ui/webui/media/media_engagement_ui.cc9
-rw-r--r--chromium/chrome/browser/ui/webui/media/media_engagement_ui.h10
-rw-r--r--chromium/chrome/browser/ui/webui/media/media_feeds_ui.cc70
-rw-r--r--chromium/chrome/browser/ui/webui/media/media_feeds_ui.h44
-rw-r--r--chromium/chrome/browser/ui/webui/media/media_history_ui.cc82
-rw-r--r--chromium/chrome/browser/ui/webui/media/media_history_ui.h48
-rw-r--r--chromium/chrome/browser/ui/webui/media/webrtc_logs_ui.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.cc62
-rw-r--r--chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.h14
-rw-r--r--chromium/chrome/browser/ui/webui/memory_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/nacl_ui.cc14
-rw-r--r--chromium/chrome/browser/ui/webui/net_export_ui.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc15
-rw-r--r--chromium/chrome/browser/ui/webui/new_tab_page/BUILD.gn8
-rw-r--r--chromium/chrome/browser/ui/webui/new_tab_page/OWNERS1
-rw-r--r--chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom164
-rw-r--r--chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc405
-rw-r--r--chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h97
-rw-r--r--chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc168
-rw-r--r--chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h28
-rw-r--r--chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc198
-rw-r--r--chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.h69
-rw-r--r--chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.cc5
-rw-r--r--chromium/chrome/browser/ui/webui/ntp/OWNERS1
-rw-r--r--chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.cc38
-rw-r--r--chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.h9
-rw-r--r--chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc130
-rw-r--r--chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.h39
-rw-r--r--chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler_unittest.cc51
-rw-r--r--chromium/chrome/browser/ui/webui/ntp/core_app_launcher_handler.h1
-rw-r--r--chromium/chrome/browser/ui/webui/ntp/new_tab_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc44
-rw-r--r--chromium/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/omnibox/BUILD.gn4
-rw-r--r--chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc123
-rw-r--r--chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.h27
-rw-r--r--chromium/chrome/browser/ui/webui/omnibox/omnibox_popup_handler.cc7
-rw-r--r--chromium/chrome/browser/ui/webui/omnibox/omnibox_popup_handler.h26
-rw-r--r--chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.cc21
-rw-r--r--chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.h25
-rw-r--r--chromium/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/policy_ui.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/policy_ui_browsertest.cc30
-rw-r--r--chromium/chrome/browser/ui/webui/policy_ui_handler.cc154
-rw-r--r--chromium/chrome/browser/ui/webui/policy_ui_handler.h18
-rw-r--r--chromium/chrome/browser/ui/webui/predictors/predictors_handler.cc3
-rw-r--r--chromium/chrome/browser/ui/webui/predictors/predictors_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc50
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h46
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc32
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc11
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc54
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc22
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc76
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h5
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc76
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc30
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h11
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_browsertest.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/print_preview/print_preview_utils.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/profile_helper.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/profile_helper_browsertest.cc16
-rw-r--r--chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc19
-rw-r--r--chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h1
-rw-r--r--chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc24
-rw-r--r--chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h5
-rw-r--r--chromium/chrome/browser/ui/webui/recent_site_settings_helper.cc249
-rw-r--r--chromium/chrome/browser/ui/webui/recent_site_settings_helper.h65
-rw-r--r--chromium/chrome/browser/ui/webui/recent_site_settings_helper_unittest.cc349
-rw-r--r--chromium/chrome/browser/ui/webui/reset_password/BUILD.gn4
-rw-r--r--chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.cc15
-rw-r--r--chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.h8
-rw-r--r--chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc53
-rw-r--r--chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/settings/OWNERS5
-rw-r--r--chromium/chrome/browser/ui/webui/settings/about_handler.cc105
-rw-r--r--chromium/chrome/browser/ui/webui/settings/about_handler.h13
-rw-r--r--chromium/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc9
-rw-r--r--chromium/chrome/browser/ui/webui/settings/change_password_handler.cc81
-rw-r--r--chromium/chrome/browser/ui/webui/settings/change_password_handler.h51
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/DEPS4
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/OWNERS4
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc85
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h28
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_unittest.cc103
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc29
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h3
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc32
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h39
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc393
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h296
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h156
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc5
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h2
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc335
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h42
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc120
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h24
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc46
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc68
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc312
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h57
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc322
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc520
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h169
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc516
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.cc252
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.h59
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h2
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc2136
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h91
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.cc66
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.h47
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_unittest.cc104
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.cc32
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.h73
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc350
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h47
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc33
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h4
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/pref_names.cc20
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/pref_names.h18
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc38
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h42
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/BUILD.gn17
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/OWNERS7
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/search.mojom33
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/search_concept.h62
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc107
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.h77
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.cc61
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.h45
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_unittest.cc78
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom14
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.cc131
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.h74
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker_unittest.cc176
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom28
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.cc73
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.h30
-rw-r--r--chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util_unittest.cc89
-rw-r--r--chromium/chrome/browser/ui/webui/settings/font_handler.cc77
-rw-r--r--chromium/chrome/browser/ui/webui/settings/font_handler.h31
-rw-r--r--chromium/chrome/browser/ui/webui/settings/hats_handler.cc37
-rw-r--r--chromium/chrome/browser/ui/webui/settings/hats_handler.h39
-rw-r--r--chromium/chrome/browser/ui/webui/settings/hats_handler_unittest.cc65
-rw-r--r--chromium/chrome/browser/ui/webui/settings/import_data_handler.cc (renamed from chromium/chrome/browser/ui/webui/settings/settings_import_data_handler.cc)103
-rw-r--r--chromium/chrome/browser/ui/webui/settings/import_data_handler.h (renamed from chromium/chrome/browser/ui/webui/settings/settings_import_data_handler.h)22
-rw-r--r--chromium/chrome/browser/ui/webui/settings/people_handler.cc137
-rw-r--r--chromium/chrome/browser/ui/webui/settings/people_handler.h29
-rw-r--r--chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc266
-rw-r--r--chromium/chrome/browser/ui/webui/settings/profile_info_handler.cc5
-rw-r--r--chromium/chrome/browser/ui/webui/settings/safe_browsing_handler.cc130
-rw-r--r--chromium/chrome/browser/ui/webui/settings/safe_browsing_handler.h62
-rw-r--r--chromium/chrome/browser/ui/webui/settings/safe_browsing_handler_unittest.cc248
-rw-r--r--chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc600
-rw-r--r--chromium/chrome/browser/ui/webui/settings/safety_check_handler.h179
-rw-r--r--chromium/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc1055
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc121
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h21
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc110
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc2470
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h14
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc314
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h89
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc609
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_security_key_handler.cc7
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_ui.cc378
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_ui.h33
-rw-r--r--chromium/chrome/browser/ui/webui/settings/settings_ui_browsertest.cc14
-rw-r--r--chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc243
-rw-r--r--chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h36
-rw-r--r--chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc396
-rw-r--r--chromium/chrome/browser/ui/webui/settings/site_settings_handler.h38
-rw-r--r--chromium/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc388
-rw-r--r--chromium/chrome/browser/ui/webui/settings_utils_linux.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/settings_utils_win.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.cc13
-rw-r--r--chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc5
-rw-r--r--chromium/chrome/browser/ui/webui/signin/inline_login_handler.cc44
-rw-r--r--chromium/chrome/browser/ui/webui/signin/inline_login_handler.h4
-rw-r--r--chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc161
-rw-r--r--chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h3
-rw-r--r--chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc108
-rw-r--r--chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h9
-rw-r--r--chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc13
-rw-r--r--chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.h5
-rw-r--r--chromium/chrome/browser/ui/webui/signin/inline_login_ui.cc123
-rw-r--r--chromium/chrome/browser/ui/webui/signin/login_ui_service.cc7
-rw-r--r--chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.cc129
-rw-r--r--chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.h9
-rw-r--r--chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc46
-rw-r--r--chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h31
-rw-r--r--chromium/chrome/browser/ui/webui/signin/signin_error_handler.cc7
-rw-r--r--chromium/chrome/browser/ui/webui/signin/signin_error_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc23
-rw-r--r--chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.h3
-rw-r--r--chromium/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc18
-rw-r--r--chromium/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc14
-rw-r--r--chromium/chrome/browser/ui/webui/signin_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/site_settings_helper.cc362
-rw-r--r--chromium/chrome/browser/ui/webui/site_settings_helper.h90
-rw-r--r--chromium/chrome/browser/ui/webui/site_settings_helper_unittest.cc376
-rw-r--r--chromium/chrome/browser/ui/webui/snippets_internals/BUILD.gn4
-rw-r--r--chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc11
-rw-r--r--chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.h8
-rw-r--r--chromium/chrome/browser/ui/webui/supervised_user_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/sync_internals_browsertest.js225
-rw-r--r--chromium/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part.cc39
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part.h27
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part_browsertest.cc73
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.cc48
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.h38
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc624
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.h32
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc70
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h38
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc883
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.h99
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc568
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.cc8
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h1
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h4
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc68
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.h32
-rw-r--r--chromium/chrome/browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/test_data_source.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/theme_source.cc7
-rw-r--r--chromium/chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/usb_internals/BUILD.gn4
-rw-r--r--chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc10
-rw-r--r--chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.h2
-rw-r--r--chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.h10
-rw-r--r--chromium/chrome/browser/ui/webui/user_actions/user_actions_ui.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.cc4
-rw-r--r--chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.h6
-rw-r--r--chromium/chrome/browser/ui/webui/version_handler.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/version_handler_chromeos.cc36
-rw-r--r--chromium/chrome/browser/ui/webui/version_handler_win.cc6
-rw-r--r--chromium/chrome/browser/ui/webui/version_ui.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/web_ui_test_handler.h3
-rw-r--r--chromium/chrome/browser/ui/webui/webui_util.cc1
-rw-r--r--chromium/chrome/browser/ui/webui/webui_util.h6
-rw-r--r--chromium/chrome/browser/ui/webui/webui_webview_browsertest.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/welcome/OWNERS2
-rw-r--r--chromium/chrome/browser/ui/webui/welcome/welcome_handler.cc2
-rw-r--r--chromium/chrome/browser/ui/webui/welcome/welcome_ui.cc1
-rw-r--r--chromium/chrome/browser/upboarding/BUILD.gn23
-rw-r--r--chromium/chrome/browser/upboarding/query_tiles/BUILD.gn129
-rw-r--r--chromium/chrome/browser/upboarding/query_tiles/internal/BUILD.gn78
-rw-r--r--chromium/chrome/browser/upboarding/query_tiles/proto/BUILD.gn (renamed from chromium/chrome/browser/ssl/BUILD.gn)6
-rw-r--r--chromium/chrome/browser/upboarding/query_tiles/test/BUILD.gn24
-rw-r--r--chromium/chrome/browser/updates/BUILD.gn49
-rw-r--r--chromium/chrome/browser/updates/announcement_notification/BUILD.gn6
-rw-r--r--chromium/chrome/browser/updates/internal/BUILD.gn18
-rw-r--r--chromium/chrome/browser/util/BUILD.gn26
-rw-r--r--chromium/chrome/browser/vr/BUILD.gn81
-rw-r--r--chromium/chrome/browser/vr/testapp/BUILD.gn6
-rw-r--r--chromium/chrome/browser/web_applications/BUILD.gn95
-rw-r--r--chromium/chrome/browser/web_applications/chrome_pwa_launcher/BUILD.gn81
-rw-r--r--chromium/chrome/browser/web_applications/components/BUILD.gn63
-rw-r--r--chromium/chrome/browser/web_applications/extensions/BUILD.gn34
-rw-r--r--chromium/chrome/browser/web_applications/proto/BUILD.gn6
-rw-r--r--chromium/chrome/browser/win/conflicts/BUILD.gn9
-rw-r--r--chromium/chrome/browser/xsurface/BUILD.gn18
1842 files changed, 77675 insertions, 42076 deletions
diff --git a/chromium/chrome/browser/BUILD.gn b/chromium/chrome/browser/BUILD.gn
index aefba4a5a3c..b3f8ac15272 100644
--- a/chromium/chrome/browser/BUILD.gn
+++ b/chromium/chrome/browser/BUILD.gn
@@ -4,6 +4,7 @@
import("//base/allocator/allocator.gni")
import("//build/buildflag_header.gni")
+import("//build/config/buildflags_paint_preview.gni")
import("//build/config/chrome_build.gni")
import("//build/config/crypto.gni")
import("//build/config/features.gni")
@@ -11,7 +12,9 @@ import("//build/config/jumbo.gni")
import("//build/config/linux/gtk/gtk.gni")
import("//build/config/ui.gni")
import("//chrome/browser/buildflags.gni")
+import("//chrome/browser/downgrade/buildflags.gni")
import("//chrome/common/features.gni")
+import("//components/captive_portal/core/features.gni")
import("//components/feature_engagement/features.gni")
import("//components/feed/features.gni")
import("//components/nacl/features.gni")
@@ -53,9 +56,9 @@ if (is_win) {
"cryptui.lib",
"dwmapi.lib",
"netapi32.lib",
- "ndfapi.lib", # Used by browser/net/net_error_diagnostics_dialog_win.h
- "pdh.lib", # Used by browser/private_working_set_snapshot.h
- "wbemuuid.lib", # Used by browser/metrics/antivirus_metrics_provider_win.cc
+ "ndfapi.lib", # For browser/net/net_error_diagnostics_dialog_win.h
+ "pdh.lib", # For browser/private_working_set_snapshot.h
+ "wbemuuid.lib", # For browser/metrics/antivirus_metrics_provider_win.cc
]
ldflags = [
"/DELAYLOAD:ndfapi.dll",
@@ -71,9 +74,7 @@ buildflag_header("buildflags") {
# This proto library is used for non-android NTPs below.
proto_library("ntp_background_proto") {
- sources = [
- "search/background/ntp_background.proto",
- ]
+ sources = [ "search/background/ntp_background.proto" ]
generate_python = false
}
@@ -170,6 +171,12 @@ jumbo_static_library("browser") {
"bitmap_fetcher/bitmap_fetcher_service.h",
"bitmap_fetcher/bitmap_fetcher_service_factory.cc",
"bitmap_fetcher/bitmap_fetcher_service_factory.h",
+ "bluetooth/bluetooth_chooser_context.cc",
+ "bluetooth/bluetooth_chooser_context.h",
+ "bluetooth/bluetooth_chooser_context_factory.cc",
+ "bluetooth/bluetooth_chooser_context_factory.h",
+ "bluetooth/chrome_bluetooth_delegate.cc",
+ "bluetooth/chrome_bluetooth_delegate.h",
"bookmarks/bookmark_model_factory.cc",
"bookmarks/bookmark_model_factory.h",
"bookmarks/chrome_bookmark_client.cc",
@@ -215,8 +222,6 @@ jumbo_static_library("browser") {
"browsing_data/browsing_data_important_sites_util.h",
"browsing_data/browsing_data_indexed_db_helper.cc",
"browsing_data/browsing_data_indexed_db_helper.h",
- "browsing_data/browsing_data_local_storage_helper.cc",
- "browsing_data/browsing_data_local_storage_helper.h",
"browsing_data/browsing_data_media_license_helper.cc",
"browsing_data/browsing_data_media_license_helper.h",
"browsing_data/browsing_data_quota_helper.cc",
@@ -283,18 +288,16 @@ jumbo_static_library("browser") {
"chrome_content_browser_client_parts.h",
"chrome_content_browser_client_receiver_bindings.cc",
"chrome_notification_types.h",
- "chrome_quota_permission_context.cc",
- "chrome_quota_permission_context.h",
"chrome_resource_bundle_helper.cc",
"chrome_resource_bundle_helper.h",
"client_hints/client_hints.cc",
"client_hints/client_hints.h",
"client_hints/client_hints_factory.cc",
"client_hints/client_hints_factory.h",
- "clipboard/clipboard_read_permission_context.cc",
- "clipboard/clipboard_read_permission_context.h",
- "clipboard/clipboard_write_permission_context.cc",
- "clipboard/clipboard_write_permission_context.h",
+ "clipboard/clipboard_read_write_permission_context.cc",
+ "clipboard/clipboard_read_write_permission_context.h",
+ "clipboard/clipboard_sanitized_write_permission_context.cc",
+ "clipboard/clipboard_sanitized_write_permission_context.h",
"command_observer.h",
"command_updater.h",
"command_updater_delegate.h",
@@ -330,9 +333,12 @@ jumbo_static_library("browser") {
"component_updater/recovery_component_installer.h",
"component_updater/recovery_improved_component_installer.cc",
"component_updater/recovery_improved_component_installer.h",
- "component_updater/recovery_improved_component_installer_win.cc",
+ "component_updater/registration.cc",
+ "component_updater/registration.h",
"component_updater/safety_tips_component_installer.cc",
"component_updater/safety_tips_component_installer.h",
+ "component_updater/soda_component_installer.cc",
+ "component_updater/soda_component_installer.h",
"component_updater/ssl_error_assistant_component_installer.cc",
"component_updater/ssl_error_assistant_component_installer.h",
"component_updater/sth_set_component_remover.cc",
@@ -341,6 +347,8 @@ jumbo_static_library("browser") {
"component_updater/subresource_filter_component_installer.h",
"component_updater/sw_reporter_installer_win.cc",
"component_updater/sw_reporter_installer_win.h",
+ "component_updater/tls_deprecation_config_component_installer.cc",
+ "component_updater/tls_deprecation_config_component_installer.h",
"consent_auditor/consent_auditor_factory.cc",
"consent_auditor/consent_auditor_factory.h",
"content_index/content_index_metrics.cc",
@@ -365,8 +373,6 @@ jumbo_static_library("browser") {
"content_settings/sound_content_setting_observer.h",
"content_settings/tab_specific_content_settings.cc",
"content_settings/tab_specific_content_settings.h",
- "content_settings/web_site_settings_uma_util.cc",
- "content_settings/web_site_settings_uma_util.h",
"crash_upload_list/crash_upload_list.cc",
"crash_upload_list/crash_upload_list.h",
"crash_upload_list/crash_upload_list_android.cc",
@@ -385,6 +391,7 @@ jumbo_static_library("browser") {
"data_use_measurement/chrome_data_use_measurement.h",
"defaults.cc",
"defaults.h",
+ "device_oauth2_token_store.h",
"dom_distiller/dom_distiller_service_factory.cc",
"dom_distiller/dom_distiller_service_factory.h",
"dom_distiller/lazy_dom_distiller_service.cc",
@@ -452,8 +459,6 @@ jumbo_static_library("browser") {
"download/download_ui_model.cc",
"download/download_ui_model.h",
"download/drag_download_item.h",
- "download/image_thumbnail_request.cc",
- "download/image_thumbnail_request.h",
"download/mixed_content_download_blocking.cc",
"download/mixed_content_download_blocking.h",
"download/offline_item_model.cc",
@@ -469,8 +474,6 @@ jumbo_static_library("browser") {
"download/save_package_file_picker.h",
"download/simple_download_manager_coordinator_factory.cc",
"download/simple_download_manager_coordinator_factory.h",
- "download/thumbnail_util.cc",
- "download/thumbnail_util.h",
"download/trusted_sources_manager.cc",
"download/trusted_sources_manager.h",
"download/trusted_sources_manager_win.cc",
@@ -532,10 +535,10 @@ jumbo_static_library("browser") {
"gcm/instance_id/instance_id_profile_service_factory.h",
"generic_sensor/sensor_permission_context.cc",
"generic_sensor/sensor_permission_context.h",
- "geolocation/geolocation_permission_context.cc",
- "geolocation/geolocation_permission_context.h",
- "geolocation/geolocation_permission_context_android.cc",
- "geolocation/geolocation_permission_context_android.h",
+ "geolocation/geolocation_permission_context_delegate.cc",
+ "geolocation/geolocation_permission_context_delegate.h",
+ "geolocation/geolocation_permission_context_delegate_android.cc",
+ "geolocation/geolocation_permission_context_delegate_android.h",
"geolocation/geolocation_permission_context_extensions.cc",
"geolocation/geolocation_permission_context_extensions.h",
"global_keyboard_shortcuts_mac.h",
@@ -569,6 +572,10 @@ jumbo_static_library("browser") {
"history/chrome_history_backend_client.h",
"history/chrome_history_client.cc",
"history/chrome_history_client.h",
+ "history/domain_diversity_reporter.cc",
+ "history/domain_diversity_reporter.h",
+ "history/domain_diversity_reporter_factory.cc",
+ "history/domain_diversity_reporter_factory.h",
"history/history_service_factory.cc",
"history/history_service_factory.h",
"history/history_tab_helper.cc",
@@ -591,8 +598,6 @@ jumbo_static_library("browser") {
"icon_manager.h",
"idle/idle_detection_permission_context.cc",
"idle/idle_detection_permission_context.h",
- "image_decoder.cc",
- "image_decoder.h",
"image_fetcher/image_decoder_impl.cc",
"image_fetcher/image_decoder_impl.h",
"image_fetcher/image_fetcher_service_factory.cc",
@@ -620,14 +625,10 @@ jumbo_static_library("browser") {
"installable/installable_task_queue.h",
"internal_auth.cc",
"internal_auth.h",
- "interstitials/chrome_metrics_helper.cc",
- "interstitials/chrome_metrics_helper.h",
"interstitials/enterprise_util.cc",
"interstitials/enterprise_util.h",
"intranet_redirect_detector.cc",
"intranet_redirect_detector.h",
- "invalidation/deprecated_profile_invalidation_provider_factory.cc",
- "invalidation/deprecated_profile_invalidation_provider_factory.h",
"invalidation/profile_invalidation_provider_factory.cc",
"invalidation/profile_invalidation_provider_factory.h",
"language/language_model_manager_factory.cc",
@@ -641,10 +642,14 @@ jumbo_static_library("browser") {
"lifetime/application_lifetime_mac.mm",
"lifetime/browser_shutdown.cc",
"lifetime/browser_shutdown.h",
+ "local_search_service/local_search_service_proxy.cc",
+ "local_search_service/local_search_service_proxy.h",
+ "local_search_service/local_search_service_proxy_factory.cc",
+ "local_search_service/local_search_service_proxy_factory.h",
+ "lookalikes/lookalike_url_blocking_page.cc",
+ "lookalikes/lookalike_url_blocking_page.h",
"lookalikes/lookalike_url_controller_client.cc",
"lookalikes/lookalike_url_controller_client.h",
- "lookalikes/lookalike_url_interstitial_page.cc",
- "lookalikes/lookalike_url_interstitial_page.h",
"lookalikes/lookalike_url_navigation_throttle.cc",
"lookalikes/lookalike_url_navigation_throttle.h",
"lookalikes/lookalike_url_service.cc",
@@ -675,10 +680,24 @@ jumbo_static_library("browser") {
"media/cast_mirroring_service_host.h",
"media/cast_remoting_connector.cc",
"media/cast_remoting_connector.h",
+ "media/feeds/media_feeds_contents_observer.cc",
+ "media/feeds/media_feeds_contents_observer.h",
+ "media/feeds/media_feeds_fetcher.cc",
+ "media/feeds/media_feeds_fetcher.h",
+ "media/feeds/media_feeds_service.cc",
+ "media/feeds/media_feeds_service.h",
+ "media/feeds/media_feeds_service_factory.cc",
+ "media/feeds/media_feeds_service_factory.h",
+ "media/feeds/media_feeds_utils.cc",
+ "media/feeds/media_feeds_utils.h",
"media/history/media_history_contents_observer.cc",
"media/history/media_history_contents_observer.h",
- "media/history/media_history_engagement_table.cc",
- "media/history/media_history_engagement_table.h",
+ "media/history/media_history_feed_items_table.cc",
+ "media/history/media_history_feed_items_table.h",
+ "media/history/media_history_feeds_table.cc",
+ "media/history/media_history_feeds_table.h",
+ "media/history/media_history_images_table.cc",
+ "media/history/media_history_images_table.h",
"media/history/media_history_keyed_service.cc",
"media/history/media_history_keyed_service.h",
"media/history/media_history_keyed_service_factory.cc",
@@ -687,6 +706,10 @@ jumbo_static_library("browser") {
"media/history/media_history_origin_table.h",
"media/history/media_history_playback_table.cc",
"media/history/media_history_playback_table.h",
+ "media/history/media_history_session_images_table.cc",
+ "media/history/media_history_session_images_table.h",
+ "media/history/media_history_session_table.cc",
+ "media/history/media_history_session_table.h",
"media/history/media_history_store.cc",
"media/history/media_history_store.h",
"media/history/media_history_table_base.cc",
@@ -809,8 +832,6 @@ jumbo_static_library("browser") {
"metrics/chrome_metrics_services_manager_client.h",
"metrics/chrome_stability_metrics_provider.cc",
"metrics/chrome_stability_metrics_provider.h",
- "metrics/field_trial_synchronizer.cc",
- "metrics/field_trial_synchronizer.h",
"metrics/google_update_metrics_provider_win.cc",
"metrics/google_update_metrics_provider_win.h",
"metrics/https_engagement_metrics_provider.cc",
@@ -861,6 +882,12 @@ jumbo_static_library("browser") {
"native_file_system/native_file_system_permission_context_factory.h",
"native_file_system/native_file_system_permission_request_manager.cc",
"native_file_system/native_file_system_permission_request_manager.h",
+ "native_file_system/native_file_system_tab_helper.cc",
+ "native_file_system/native_file_system_tab_helper.h",
+ "native_file_system/origin_scoped_native_file_system_permission_context.cc",
+ "native_file_system/origin_scoped_native_file_system_permission_context.h",
+ "native_file_system/tab_scoped_native_file_system_permission_context.cc",
+ "native_file_system/tab_scoped_native_file_system_permission_context.h",
"native_window_notification_source.h",
"navigation_predictor/navigation_predictor.cc",
"navigation_predictor/navigation_predictor.h",
@@ -870,6 +897,8 @@ jumbo_static_library("browser") {
"navigation_predictor/navigation_predictor_keyed_service_factory.h",
"navigation_predictor/navigation_predictor_preconnect_client.cc",
"navigation_predictor/navigation_predictor_preconnect_client.h",
+ "navigation_predictor/search_engine_preconnector.cc",
+ "navigation_predictor/search_engine_preconnector.h",
"net/chrome_cookie_notification_details.h",
"net/chrome_mojo_proxy_resolver_factory.cc",
"net/chrome_mojo_proxy_resolver_factory.h",
@@ -912,12 +941,16 @@ jumbo_static_library("browser") {
"net/secure_dns_policy_handler.h",
"net/service_providers_win.cc",
"net/service_providers_win.h",
+ "net/stub_resolver_config_reader.cc",
+ "net/stub_resolver_config_reader.h",
"net/system_network_context_manager.cc",
"net/system_network_context_manager.h",
"net_benchmarking.cc",
"net_benchmarking.h",
"nfc/nfc_permission_context.cc",
"nfc/nfc_permission_context.h",
+ "nfc/nfc_permission_context_android.cc",
+ "nfc/nfc_permission_context_android.h",
"notifications/alert_dispatcher_mac.h",
"notifications/metrics/notification_metrics_logger.cc",
"notifications/metrics/notification_metrics_logger.h",
@@ -1031,6 +1064,8 @@ jumbo_static_library("browser") {
"page_load_metrics/observers/https_engagement_metrics/https_engagement_service.h",
"page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.cc",
"page_load_metrics/observers/https_engagement_metrics/https_engagement_service_factory.h",
+ "page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.cc",
+ "page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.h",
"page_load_metrics/observers/live_tab_count_page_load_metrics_observer.cc",
"page_load_metrics/observers/live_tab_count_page_load_metrics_observer.h",
"page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc",
@@ -1067,8 +1102,6 @@ jumbo_static_library("browser") {
"page_load_metrics/observers/service_worker_page_load_metrics_observer.h",
"page_load_metrics/observers/signed_exchange_page_load_metrics_observer.cc",
"page_load_metrics/observers/signed_exchange_page_load_metrics_observer.h",
- "page_load_metrics/observers/subresource_loading_page_load_metrics_observer.cc",
- "page_load_metrics/observers/subresource_loading_page_load_metrics_observer.h",
"page_load_metrics/observers/tab_restore_page_load_metrics_observer.cc",
"page_load_metrics/observers/tab_restore_page_load_metrics_observer.h",
"page_load_metrics/observers/third_party_metrics_observer.cc",
@@ -1077,8 +1110,21 @@ jumbo_static_library("browser") {
"page_load_metrics/observers/ukm_page_load_metrics_observer.h",
"page_load_metrics/page_load_metrics_initialize.cc",
"page_load_metrics/page_load_metrics_initialize.h",
+ "paint_preview/services/paint_preview_demo_service.cc",
+ "paint_preview/services/paint_preview_demo_service.h",
+ "paint_preview/services/paint_preview_demo_service_factory.cc",
+ "paint_preview/services/paint_preview_demo_service_factory.h",
+ "paint_preview/services/paint_preview_tab_service.cc",
+ "paint_preview/services/paint_preview_tab_service.h",
+ "paint_preview/services/paint_preview_tab_service_factory.cc",
+ "paint_preview/services/paint_preview_tab_service_factory.h",
"password_manager/account_storage/account_password_store_factory.cc",
"password_manager/account_storage/account_password_store_factory.h",
+ "password_manager/biometric_authenticator_android.cc",
+ "password_manager/biometric_authenticator_android.h",
+ "password_manager/bulk_leak_check_service_factory.cc",
+ "password_manager/bulk_leak_check_service_factory.h",
+ "password_manager/chrome_biometric_authenticator.h",
"password_manager/chrome_password_manager_client.cc",
"password_manager/chrome_password_manager_client.h",
"password_manager/field_info_manager_factory.cc",
@@ -1091,10 +1137,11 @@ jumbo_static_library("browser") {
"password_manager/password_store_factory.h",
"password_manager/password_store_utils.cc",
"password_manager/password_store_utils.h",
- "password_manager/reauth_purpose.h",
"payments/payment_handler_permission_context.cc",
"payments/payment_handler_permission_context.h",
"payments/ssl_validity_checker.cc",
+ "performance_hints/performance_hints_observer.cc",
+ "performance_hints/performance_hints_observer.h",
"performance_manager/browser_child_process_watcher.cc",
"performance_manager/browser_child_process_watcher.h",
"performance_manager/chrome_browser_main_extra_parts_performance_manager.cc",
@@ -1105,14 +1152,16 @@ jumbo_static_library("browser") {
"performance_manager/decorators/frame_priority_decorator.h",
"performance_manager/decorators/frozen_frame_aggregator.cc",
"performance_manager/decorators/frozen_frame_aggregator.h",
+ "performance_manager/decorators/helpers/page_live_state_decorator_helper.cc",
+ "performance_manager/decorators/helpers/page_live_state_decorator_helper.h",
"performance_manager/decorators/page_aggregator.cc",
"performance_manager/decorators/page_aggregator.h",
- "performance_manager/decorators/page_almost_idle_decorator.cc",
- "performance_manager/decorators/page_almost_idle_decorator.h",
"performance_manager/decorators/process_metrics_decorator.cc",
"performance_manager/decorators/process_metrics_decorator.h",
"performance_manager/decorators/process_priority_aggregator.cc",
"performance_manager/decorators/process_priority_aggregator.h",
+ "performance_manager/graph/policies/high_pmf_memory_pressure_policy.cc",
+ "performance_manager/graph/policies/high_pmf_memory_pressure_policy.h",
"performance_manager/graph/policies/policy_features.cc",
"performance_manager/graph/policies/policy_features.h",
"performance_manager/graph/policies/working_set_trimmer_policy.cc",
@@ -1121,46 +1170,21 @@ jumbo_static_library("browser") {
"performance_manager/graph/policies/working_set_trimmer_policy_chromeos.h",
"performance_manager/graph/policies/working_set_trimmer_policy_win.cc",
"performance_manager/graph/policies/working_set_trimmer_policy_win.h",
+ "performance_manager/mechanisms/high_pmf_memory_pressure_signals.cc",
+ "performance_manager/mechanisms/high_pmf_memory_pressure_signals.h",
"performance_manager/mechanisms/working_set_trimmer.cc",
"performance_manager/mechanisms/working_set_trimmer.h",
"performance_manager/mechanisms/working_set_trimmer_chromeos.cc",
"performance_manager/mechanisms/working_set_trimmer_chromeos.h",
"performance_manager/mechanisms/working_set_trimmer_win.cc",
"performance_manager/mechanisms/working_set_trimmer_win.h",
+ "performance_manager/metrics/memory_pressure_metrics.cc",
+ "performance_manager/metrics/memory_pressure_metrics.h",
"performance_manager/observers/background_metrics_reporter.h",
"performance_manager/observers/isolation_context_metrics.cc",
"performance_manager/observers/isolation_context_metrics.h",
"performance_manager/observers/metrics_collector.cc",
"performance_manager/observers/metrics_collector.h",
- "performance_manager/performance_manager_features.cc",
- "performance_manager/performance_manager_features.h",
- "performance_manager/persistence/site_data/exponential_moving_average.cc",
- "performance_manager/persistence/site_data/exponential_moving_average.h",
- "performance_manager/persistence/site_data/feature_usage.h",
- "performance_manager/persistence/site_data/leveldb_site_data_store.cc",
- "performance_manager/persistence/site_data/leveldb_site_data_store.h",
- "performance_manager/persistence/site_data/non_recording_site_data_cache.cc",
- "performance_manager/persistence/site_data/non_recording_site_data_cache.h",
- "performance_manager/persistence/site_data/noop_site_data_writer.cc",
- "performance_manager/persistence/site_data/noop_site_data_writer.h",
- "performance_manager/persistence/site_data/site_data_cache.h",
- "performance_manager/persistence/site_data/site_data_cache_facade.cc",
- "performance_manager/persistence/site_data/site_data_cache_facade.h",
- "performance_manager/persistence/site_data/site_data_cache_facade_factory.cc",
- "performance_manager/persistence/site_data/site_data_cache_facade_factory.h",
- "performance_manager/persistence/site_data/site_data_cache_factory.cc",
- "performance_manager/persistence/site_data/site_data_cache_factory.h",
- "performance_manager/persistence/site_data/site_data_cache_impl.cc",
- "performance_manager/persistence/site_data/site_data_cache_impl.h",
- "performance_manager/persistence/site_data/site_data_cache_inspector.h",
- "performance_manager/persistence/site_data/site_data_impl.cc",
- "performance_manager/persistence/site_data/site_data_impl.h",
- "performance_manager/persistence/site_data/site_data_reader.cc",
- "performance_manager/persistence/site_data/site_data_reader.h",
- "performance_manager/persistence/site_data/site_data_store.h",
- "performance_manager/persistence/site_data/site_data_writer.cc",
- "performance_manager/persistence/site_data/site_data_writer.h",
- "performance_manager/persistence/site_data/tab_visibility.h",
"performance_monitor/metric_evaluator_helper_win.cc",
"performance_monitor/metric_evaluator_helper_win.h",
"performance_monitor/process_metrics_history.cc",
@@ -1169,41 +1193,20 @@ jumbo_static_library("browser") {
"performance_monitor/process_monitor.h",
"performance_monitor/system_monitor.cc",
"performance_monitor/system_monitor.h",
- "performance_monitor/system_monitor_metrics_logger.cc",
- "performance_monitor/system_monitor_metrics_logger.h",
"permissions/adaptive_quiet_notification_permission_ui_enabler.cc",
"permissions/adaptive_quiet_notification_permission_ui_enabler.h",
- "permissions/chooser_context_base.cc",
- "permissions/chooser_context_base.h",
+ "permissions/chrome_permissions_client.cc",
+ "permissions/chrome_permissions_client.h",
"permissions/contextual_notification_permission_ui_selector.cc",
"permissions/contextual_notification_permission_ui_selector.h",
"permissions/crowd_deny_preload_data.cc",
"permissions/crowd_deny_preload_data.h",
"permissions/crowd_deny_safe_browsing_request.cc",
"permissions/crowd_deny_safe_browsing_request.h",
- "permissions/notification_permission_ui_selector.h",
- "permissions/permission_context_base.cc",
- "permissions/permission_context_base.h",
- "permissions/permission_decision_auto_blocker.cc",
- "permissions/permission_decision_auto_blocker.h",
- "permissions/permission_manager.cc",
- "permissions/permission_manager.h",
+ "permissions/permission_decision_auto_blocker_factory.cc",
+ "permissions/permission_decision_auto_blocker_factory.h",
"permissions/permission_manager_factory.cc",
"permissions/permission_manager_factory.h",
- "permissions/permission_request.cc",
- "permissions/permission_request.h",
- "permissions/permission_request_id.cc",
- "permissions/permission_request_id.h",
- "permissions/permission_request_impl.cc",
- "permissions/permission_request_impl.h",
- "permissions/permission_request_manager.cc",
- "permissions/permission_request_manager.h",
- "permissions/permission_result.cc",
- "permissions/permission_result.h",
- "permissions/permission_uma_util.cc",
- "permissions/permission_uma_util.h",
- "permissions/permission_util.cc",
- "permissions/permission_util.h",
"permissions/quiet_notification_permission_ui_config.cc",
"permissions/quiet_notification_permission_ui_config.h",
"permissions/quiet_notification_permission_ui_state.cc",
@@ -1231,6 +1234,8 @@ jumbo_static_library("browser") {
"policy/browsing_history_policy_handler.h",
"policy/chrome_browser_policy_connector.cc",
"policy/chrome_browser_policy_connector.h",
+ "policy/chrome_policy_conversions_client.cc",
+ "policy/chrome_policy_conversions_client.h",
"policy/cloud/cloud_policy_invalidator.cc",
"policy/cloud/cloud_policy_invalidator.h",
"policy/cloud/policy_invalidation_util.cc",
@@ -1249,18 +1254,16 @@ jumbo_static_library("browser") {
"policy/developer_tools_policy_handler.h",
"policy/device_management_service_configuration.cc",
"policy/device_management_service_configuration.h",
+ "policy/enrollment_status.cc",
+ "policy/enrollment_status.h",
"policy/file_selection_dialogs_policy_handler.cc",
"policy/file_selection_dialogs_policy_handler.h",
"policy/homepage_location_policy_handler.cc",
"policy/homepage_location_policy_handler.h",
"policy/javascript_policy_handler.cc",
"policy/javascript_policy_handler.h",
- "policy/managed_bookmarks_policy_handler.cc",
- "policy/managed_bookmarks_policy_handler.h",
"policy/network_prediction_policy_handler.cc",
"policy/network_prediction_policy_handler.h",
- "policy/policy_conversions.cc",
- "policy/policy_conversions.h",
"policy/profile_policy_connector.cc",
"policy/profile_policy_connector.h",
"policy/profile_policy_connector_builder.cc",
@@ -1285,9 +1288,6 @@ jumbo_static_library("browser") {
"predictors/loading_predictor_config.h",
"predictors/loading_predictor_factory.cc",
"predictors/loading_predictor_factory.h",
- "predictors/loading_predictor_key_value_data.h",
- "predictors/loading_predictor_key_value_table.cc",
- "predictors/loading_predictor_key_value_table.h",
"predictors/loading_predictor_tab_helper.cc",
"predictors/loading_predictor_tab_helper.h",
"predictors/loading_stats_collector.cc",
@@ -1302,8 +1302,7 @@ jumbo_static_library("browser") {
"predictors/predictor_database.h",
"predictors/predictor_database_factory.cc",
"predictors/predictor_database_factory.h",
- "predictors/predictor_table_base.cc",
- "predictors/predictor_table_base.h",
+ "predictors/predictors_enums.h",
"predictors/predictors_features.cc",
"predictors/predictors_features.h",
"predictors/proxy_lookup_client_impl.cc",
@@ -1336,6 +1335,28 @@ jumbo_static_library("browser") {
"prefs/profile_pref_store_manager.h",
"prefs/session_startup_pref.cc",
"prefs/session_startup_pref.h",
+ "prerender/isolated/isolated_prerender_features.cc",
+ "prerender/isolated/isolated_prerender_features.h",
+ "prerender/isolated/isolated_prerender_from_string_url_loader.cc",
+ "prerender/isolated/isolated_prerender_from_string_url_loader.h",
+ "prerender/isolated/isolated_prerender_params.cc",
+ "prerender/isolated/isolated_prerender_params.h",
+ "prerender/isolated/isolated_prerender_proxy_configurator.cc",
+ "prerender/isolated/isolated_prerender_proxy_configurator.h",
+ "prerender/isolated/isolated_prerender_service.cc",
+ "prerender/isolated/isolated_prerender_service.h",
+ "prerender/isolated/isolated_prerender_service_factory.cc",
+ "prerender/isolated/isolated_prerender_service_factory.h",
+ "prerender/isolated/isolated_prerender_service_workers_observer.cc",
+ "prerender/isolated/isolated_prerender_service_workers_observer.h",
+ "prerender/isolated/isolated_prerender_tab_helper.cc",
+ "prerender/isolated/isolated_prerender_tab_helper.h",
+ "prerender/isolated/isolated_prerender_url_loader.cc",
+ "prerender/isolated/isolated_prerender_url_loader.h",
+ "prerender/isolated/isolated_prerender_url_loader_interceptor.cc",
+ "prerender/isolated/isolated_prerender_url_loader_interceptor.h",
+ "prerender/isolated/prefetched_mainframe_response_container.cc",
+ "prerender/isolated/prefetched_mainframe_response_container.h",
"prerender/prerender_config.cc",
"prerender/prerender_config.h",
"prerender/prerender_contents.cc",
@@ -1362,6 +1383,8 @@ jumbo_static_library("browser") {
"prerender/prerender_message_filter.h",
"prerender/prerender_origin.cc",
"prerender/prerender_origin.h",
+ "prerender/prerender_processor_impl.cc",
+ "prerender/prerender_processor_impl.h",
"prerender/prerender_tab_helper.cc",
"prerender/prerender_tab_helper.h",
"prerender/prerender_util.cc",
@@ -1419,8 +1442,6 @@ jumbo_static_library("browser") {
"profiles/incognito_mode_policy_handler.h",
"profiles/off_the_record_profile_impl.cc",
"profiles/off_the_record_profile_impl.h",
- "profiles/off_the_record_profile_io_data.cc",
- "profiles/off_the_record_profile_io_data.h",
"profiles/pref_service_builder_utils.cc",
"profiles/pref_service_builder_utils.h",
"profiles/profile.cc",
@@ -1440,14 +1461,14 @@ jumbo_static_library("browser") {
"profiles/profile_downloader_delegate.h",
"profiles/profile_impl.cc",
"profiles/profile_impl.h",
- "profiles/profile_impl_io_data.cc",
- "profiles/profile_impl_io_data.h",
"profiles/profile_info_cache.cc",
"profiles/profile_info_cache.h",
"profiles/profile_info_cache_observer.h",
"profiles/profile_info_interface.h",
"profiles/profile_io_data.cc",
"profiles/profile_io_data.h",
+ "profiles/profile_io_data_handle.cc",
+ "profiles/profile_io_data_handle.h",
"profiles/profile_key.cc",
"profiles/profile_key.h",
"profiles/profile_manager.cc",
@@ -1475,6 +1496,8 @@ jumbo_static_library("browser") {
"push_messaging/push_messaging_app_identifier.h",
"push_messaging/push_messaging_constants.cc",
"push_messaging/push_messaging_constants.h",
+ "push_messaging/push_messaging_features.cc",
+ "push_messaging/push_messaging_features.h",
"push_messaging/push_messaging_notification_manager.cc",
"push_messaging/push_messaging_notification_manager.h",
"push_messaging/push_messaging_service_factory.cc",
@@ -1520,8 +1543,6 @@ jumbo_static_library("browser") {
"resources_util.h",
"search/instant_io_context.cc",
"search/instant_io_context.h",
- "search/ntp_icon_source.cc",
- "search/ntp_icon_source.h",
"search/search.cc",
"search/search.h",
"search/suggestions/suggestions_service_factory.cc",
@@ -1568,8 +1589,8 @@ jumbo_static_library("browser") {
"sessions/session_data_deleter.cc",
"sessions/session_data_deleter.h",
"sessions/session_restore_android.cc",
- "sessions/session_tab_helper.cc",
- "sessions/session_tab_helper.h",
+ "sessions/session_tab_helper_factory.cc",
+ "sessions/session_tab_helper_factory.h",
"sessions/tab_restore_service_factory.cc",
"sessions/tab_restore_service_factory.h",
"sharing/ack_message_handler.cc",
@@ -1578,8 +1599,6 @@ jumbo_static_library("browser") {
"sharing/click_to_call/click_to_call_message_handler_android.h",
"sharing/click_to_call/feature.cc",
"sharing/click_to_call/feature.h",
- "sharing/fake_device_info.cc",
- "sharing/fake_device_info.h",
"sharing/features.cc",
"sharing/features.h",
"sharing/ping_message_handler.cc",
@@ -1605,7 +1624,14 @@ jumbo_static_library("browser") {
"sharing/sharing_handler_registry.h",
"sharing/sharing_handler_registry_impl.cc",
"sharing/sharing_handler_registry_impl.h",
+ "sharing/sharing_message_bridge.h",
+ "sharing/sharing_message_bridge_factory.cc",
+ "sharing/sharing_message_bridge_factory.h",
+ "sharing/sharing_message_bridge_impl.cc",
+ "sharing/sharing_message_bridge_impl.h",
"sharing/sharing_message_handler.h",
+ "sharing/sharing_message_model_type_controller.cc",
+ "sharing/sharing_message_model_type_controller.h",
"sharing/sharing_message_sender.cc",
"sharing/sharing_message_sender.h",
"sharing/sharing_metrics.cc",
@@ -1629,6 +1655,12 @@ jumbo_static_library("browser") {
"sharing/sms/sms_remote_fetcher.h",
"sharing/vapid_key_manager.cc",
"sharing/vapid_key_manager.h",
+ "sharing/web_push/json_web_token_util.cc",
+ "sharing/web_push/json_web_token_util.h",
+ "sharing/web_push/web_push_common.cc",
+ "sharing/web_push/web_push_common.h",
+ "sharing/web_push/web_push_sender.cc",
+ "sharing/web_push/web_push_sender.h",
"sharing/webrtc/webrtc_flags.cc",
"sharing/webrtc/webrtc_flags.h",
"shell_integration.cc",
@@ -1673,6 +1705,9 @@ jumbo_static_library("browser") {
"signin/investigator_dependency_provider.h",
"signin/local_auth.cc",
"signin/local_auth.h",
+ "signin/reauth_result.h",
+ "signin/reauth_tab_helper.cc",
+ "signin/reauth_tab_helper.h",
"signin/signin_error_controller_factory.cc",
"signin/signin_error_controller_factory.h",
"signin/signin_profile_attributes_updater.cc",
@@ -1691,6 +1726,10 @@ jumbo_static_library("browser") {
"site_isolation/site_details.h",
"site_isolation/site_isolation_policy.cc",
"site_isolation/site_isolation_policy.h",
+ "soda/soda_service.cc",
+ "soda/soda_service.h",
+ "soda/soda_service_factory.cc",
+ "soda/soda_service_factory.h",
"speech/chrome_speech_recognition_manager_delegate.cc",
"speech/chrome_speech_recognition_manager_delegate.h",
"speech/speech_recognizer.cc",
@@ -1698,26 +1737,10 @@ jumbo_static_library("browser") {
"speech/speech_recognizer_delegate.h",
"speech/tts_controller_delegate_impl.cc",
"speech/tts_controller_delegate_impl.h",
- "ssl/bad_clock_blocking_page.cc",
- "ssl/bad_clock_blocking_page.h",
- "ssl/blocked_interception_blocking_page.cc",
- "ssl/blocked_interception_blocking_page.h",
- "ssl/captive_portal_blocking_page.cc",
- "ssl/captive_portal_blocking_page.h",
- "ssl/captive_portal_helper.h",
- "ssl/captive_portal_helper_android.cc",
- "ssl/captive_portal_helper_android.h",
- "ssl/captive_portal_helper_win.cc",
"ssl/certificate_error_reporter.cc",
"ssl/certificate_error_reporter.h",
"ssl/chrome_security_blocking_page_factory.cc",
"ssl/chrome_security_blocking_page_factory.h",
- "ssl/chrome_ssl_host_state_delegate.cc",
- "ssl/chrome_ssl_host_state_delegate.h",
- "ssl/chrome_ssl_host_state_delegate_factory.cc",
- "ssl/chrome_ssl_host_state_delegate_factory.h",
- "ssl/common_name_mismatch_handler.cc",
- "ssl/common_name_mismatch_handler.h",
"ssl/connection_help_tab_helper.cc",
"ssl/connection_help_tab_helper.h",
"ssl/insecure_sensitive_input_driver.cc",
@@ -1726,8 +1749,6 @@ jumbo_static_library("browser") {
"ssl/insecure_sensitive_input_driver_factory.h",
"ssl/known_interception_disclosure_infobar_delegate.cc",
"ssl/known_interception_disclosure_infobar_delegate.h",
- "ssl/mitm_software_blocking_page.cc",
- "ssl/mitm_software_blocking_page.h",
"ssl/secure_origin_policy_handler.cc",
"ssl/secure_origin_policy_handler.h",
"ssl/secure_origin_prefs_observer.cc",
@@ -1739,12 +1760,10 @@ jumbo_static_library("browser") {
"ssl/ssl_client_certificate_selector.h",
"ssl/ssl_config_service_manager.h",
"ssl/ssl_config_service_manager_pref.cc",
- "ssl/ssl_error_assistant.cc",
- "ssl/ssl_error_assistant.h",
"ssl/ssl_error_controller_client.cc",
"ssl/ssl_error_controller_client.h",
- "ssl/ssl_error_handler.cc",
- "ssl/ssl_error_handler.h",
+ "ssl/stateful_ssl_host_state_delegate_factory.cc",
+ "ssl/stateful_ssl_host_state_delegate_factory.h",
"ssl/tls_deprecation_config.cc",
"ssl/tls_deprecation_config.h",
"ssl/typed_navigation_timing_throttle.cc",
@@ -1760,12 +1779,6 @@ jumbo_static_library("browser") {
"status_icons/status_tray.h",
"storage/durable_storage_permission_context.cc",
"storage/durable_storage_permission_context.h",
- "storage/storage_info_fetcher.cc",
- "storage/storage_info_fetcher.h",
- "storage/storage_notification_service_factory.cc",
- "storage/storage_notification_service_factory.h",
- "storage/storage_notification_service_impl.cc",
- "storage/storage_notification_service_impl.h",
"subresource_filter/chrome_subresource_filter_client.cc",
"subresource_filter/chrome_subresource_filter_client.h",
"subresource_filter/subresource_filter_content_settings_manager.cc",
@@ -1774,6 +1787,8 @@ jumbo_static_library("browser") {
"subresource_filter/subresource_filter_profile_context.h",
"subresource_filter/subresource_filter_profile_context_factory.cc",
"subresource_filter/subresource_filter_profile_context_factory.h",
+ "subresource_redirect/subresource_redirect_observer.cc",
+ "subresource_redirect/subresource_redirect_observer.h",
"sync/bookmark_sync_service_factory.cc",
"sync/bookmark_sync_service_factory.h",
"sync/chrome_sync_client.cc",
@@ -1800,18 +1815,24 @@ jumbo_static_library("browser") {
"sync/sessions/sync_sessions_web_contents_router_factory.h",
"sync/sync_encryption_keys_tab_helper.cc",
"sync/sync_encryption_keys_tab_helper.h",
+ "sync/sync_error_infobar_delegate_android.cc",
+ "sync/sync_error_infobar_delegate_android.h",
"sync/sync_startup_tracker.cc",
"sync/sync_startup_tracker.h",
+ "sync/trusted_vault_client_android.cc",
+ "sync/trusted_vault_client_android.h",
"sync/user_event_service_factory.cc",
"sync/user_event_service_factory.h",
+ "tab/state/tab_state_db.cc",
+ "tab/state/tab_state_db.h",
"tab_contents/navigation_metrics_recorder.cc",
"tab_contents/navigation_metrics_recorder.h",
"tab_contents/tab_util.cc",
"tab_contents/tab_util.h",
"task_manager/web_contents_tags.cc",
"task_manager/web_contents_tags.h",
- "themes/theme_service_win.cc",
- "themes/theme_service_win.h",
+ "themes/theme_helper_win.cc",
+ "themes/theme_helper_win.h",
"tracing/background_tracing_field_trial.cc",
"tracing/background_tracing_field_trial.h",
"tracing/background_tracing_metrics_provider.cc",
@@ -1844,6 +1865,8 @@ jumbo_static_library("browser") {
"unexpire_flags.h",
"unified_consent/unified_consent_service_factory.cc",
"unified_consent/unified_consent_service_factory.h",
+ "upboarding/query_tiles/tile_service_factory.cc",
+ "upboarding/query_tiles/tile_service_factory.h",
"update_client/chrome_update_query_params_delegate.cc",
"update_client/chrome_update_query_params_delegate.h",
"usb/usb_blocklist.cc",
@@ -1867,6 +1890,8 @@ jumbo_static_library("browser") {
"vr/ui_suppressed_element.h",
"vr/vr_tab_helper.cc",
"vr/vr_tab_helper.h",
+ "vr/webxr_permission_context.cc",
+ "vr/webxr_permission_context.h",
"wake_lock/wake_lock_permission_context.cc",
"wake_lock/wake_lock_permission_context.h",
"web_data_service_factory.cc",
@@ -1939,6 +1964,7 @@ jumbo_static_library("browser") {
"//components/nacl/common:buildflags",
"//components/payments/core",
"//components/safe_browsing:buildflags",
+ "//components/services/storage/public/mojom",
"//components/sync",
"//components/sync_device_info",
"//content/public/browser",
@@ -1955,6 +1981,7 @@ jumbo_static_library("browser") {
":ntp_background_proto",
":permissions_proto",
":resource_prefetch_predictor_proto",
+ ":tab_state_db_content_proto",
"//base:i18n",
"//base/allocator:buildflags",
"//base/util/memory_pressure:memory_pressure",
@@ -1968,8 +1995,11 @@ jumbo_static_library("browser") {
"//chrome/app/resources:platform_locale_settings",
"//chrome/app/theme:theme_resources",
"//chrome/browser/devtools",
+ "//chrome/browser/image_decoder",
"//chrome/browser/media:media_engagement_preload_proto",
"//chrome/browser/media:mojo_bindings",
+ "//chrome/browser/media/feeds:mojo_bindings",
+ "//chrome/browser/media/feeds:proto",
"//chrome/browser/media/router",
"//chrome/browser/metrics:expired_histograms_array",
"//chrome/browser/metrics/variations:chrome_ui_string_overrider_factory",
@@ -1982,18 +2012,23 @@ jumbo_static_library("browser") {
"//chrome/browser/resource_coordinator:mojo_bindings",
"//chrome/browser/resource_coordinator:tab_manager_features",
"//chrome/browser/safe_browsing",
- "//chrome/browser/ssl:proto",
+ "//chrome/browser/sharing:buildflags",
+ "//chrome/browser/sharing/proto",
+ "//chrome/browser/storage_access_api:permissions",
+ "//chrome/browser/thumbnail",
"//chrome/browser/touch_to_fill",
"//chrome/browser/ui",
"//chrome/browser/ui/webui/bluetooth_internals",
+ "//chrome/browser/upboarding",
"//chrome/browser/updates/announcement_notification",
"//chrome/common:channel_info",
"//chrome/common/net",
"//chrome/installer/util:with_no_strings",
- "//components/app_modal",
+ "//chrome/services/local_search_service:local_search_service",
"//components/assist_ranker",
"//components/autofill/content/browser",
"//components/autofill/core/browser",
+ "//components/background_task_scheduler",
"//components/blacklist/opt_out_blacklist:opt_out_blacklist",
"//components/blacklist/opt_out_blacklist/sql:opt_out_blacklist_sql",
"//components/bookmarks/browser",
@@ -2001,7 +2036,9 @@ jumbo_static_library("browser") {
"//components/browser_sync",
"//components/browsing_data/content",
"//components/browsing_data/core",
- "//components/captive_portal",
+ "//components/captive_portal/content",
+ "//components/captive_portal/core",
+ "//components/captive_portal/core:buildflags",
"//components/certificate_matching",
"//components/certificate_transparency",
"//components/cloud_devices/common",
@@ -2026,6 +2063,7 @@ jumbo_static_library("browser") {
"//components/download/content/factory",
"//components/download/database",
"//components/download/public/background_service:public",
+ "//components/embedder_support",
"//components/encrypted_messages",
"//components/error_page/common",
"//components/favicon/content",
@@ -2033,6 +2071,7 @@ jumbo_static_library("browser") {
"//components/favicon_base",
"//components/feature_engagement",
"//components/filename_generation",
+ "//components/find_in_page",
"//components/flags_ui",
"//components/games/core",
"//components/gcm_driver",
@@ -2042,11 +2081,13 @@ jumbo_static_library("browser") {
"//components/history/core/common",
"//components/infobars/core",
"//components/invalidation/impl",
+ "//components/javascript_dialogs",
"//components/keyed_service/content",
"//components/language/content/browser",
"//components/language/core/browser",
"//components/language/core/common",
"//components/leveldb_proto",
+ "//components/lookalikes",
"//components/metrics:call_stack_profile_collector",
"//components/metrics:component_metrics",
"//components/metrics:demographic_metrics_provider",
@@ -2070,11 +2111,14 @@ jumbo_static_library("browser") {
"//components/omnibox/browser",
"//components/optimization_guide",
"//components/os_crypt",
+ "//components/paint_preview/buildflags",
+ "//components/paint_preview/features",
"//components/password_manager/content/browser",
"//components/password_manager/core/browser",
"//components/password_manager/core/common",
"//components/payments/core",
"//components/performance_manager",
+ "//components/permissions",
"//components/policy:generated",
"//components/policy/content/",
"//components/policy/core/browser",
@@ -2086,12 +2130,14 @@ jumbo_static_library("browser") {
"//components/proxy_config",
"//components/query_parser",
"//components/rappor",
- "//components/rappor:rappor_recorder",
"//components/renderer_context_menu",
"//components/resources",
- "//components/safe_browsing:public",
+ "//components/safe_browsing/core:public",
+ "//components/safe_browsing/core/common:safe_browsing_policy_handler",
"//components/safe_search_api",
"//components/safe_search_api:safe_search_client",
+ "//components/schema_org:extractor",
+ "//components/schema_org/common:improved_mojom",
"//components/search",
"//components/search_engines",
"//components/search_provider_logos",
@@ -2112,10 +2158,11 @@ jumbo_static_library("browser") {
"//components/signin/public/base:signin_buildflags",
"//components/signin/public/identity_manager",
"//components/signin/public/webdata",
+ "//components/soda:constants",
"//components/spellcheck:buildflags",
+ "//components/sqlite_proto",
"//components/ssl_errors",
- "//components/startup_metric_utils/browser:host",
- "//components/startup_metric_utils/browser:lib",
+ "//components/startup_metric_utils/browser",
"//components/storage_monitor",
"//components/strings",
"//components/subresource_filter/content/browser",
@@ -2192,13 +2239,13 @@ jumbo_static_library("browser") {
"//services/device/public/cpp/usb",
"//services/device/public/mojom",
"//services/device/public/mojom:usb",
- "//services/identity:lib",
- "//services/identity/public/cpp:cpp_types",
"//services/image_annotation:service",
+ "//services/media_session/public/mojom",
"//services/metrics/public/cpp:ukm_builders",
"//services/network:network_service",
"//services/network/public/cpp",
"//services/network/public/mojom",
+ "//services/network/public/proto",
"//services/preferences/public/cpp",
"//services/preferences/public/cpp/tracked",
"//services/preferences/public/mojom",
@@ -2225,7 +2272,6 @@ jumbo_static_library("browser") {
"//third_party/libyuv",
"//third_party/metrics_proto",
"//third_party/re2",
- "//third_party/smhasher:cityhash",
"//third_party/webrtc_overrides:webrtc_component",
"//third_party/widevine/cdm:buildflags",
"//third_party/zlib",
@@ -2237,7 +2283,6 @@ jumbo_static_library("browser") {
"//ui/base:ui_data_pack",
"//ui/base/idle",
"//ui/base/ime",
- "//ui/color:color_buildflags",
"//ui/events:events_base",
"//ui/gfx",
"//ui/gfx/geometry",
@@ -2254,6 +2299,9 @@ jumbo_static_library("browser") {
if (is_win) {
libs += [ "secur32.lib" ]
+ sources +=
+ [ "component_updater/recovery_improved_component_installer_win.cc" ]
+ deps += [ "//chrome/elevation_service:elevation_service_idl" ]
}
if (is_posix || is_fuchsia) {
@@ -2278,20 +2326,34 @@ jumbo_static_library("browser") {
"android/autofill_assistant/assistant_collect_user_data_delegate.h",
"android/autofill_assistant/assistant_form_delegate.cc",
"android/autofill_assistant/assistant_form_delegate.h",
+ "android/autofill_assistant/assistant_generic_ui_delegate.cc",
+ "android/autofill_assistant/assistant_generic_ui_delegate.h",
"android/autofill_assistant/assistant_header_delegate.cc",
"android/autofill_assistant/assistant_header_delegate.h",
"android/autofill_assistant/assistant_overlay_delegate.cc",
"android/autofill_assistant/assistant_overlay_delegate.h",
"android/autofill_assistant/client_android.cc",
"android/autofill_assistant/client_android.h",
+ "android/autofill_assistant/generic_ui_controller_android.cc",
+ "android/autofill_assistant/generic_ui_controller_android.h",
+ "android/autofill_assistant/generic_ui_events_android.cc",
+ "android/autofill_assistant/generic_ui_events_android.h",
+ "android/autofill_assistant/generic_ui_interactions_android.cc",
+ "android/autofill_assistant/generic_ui_interactions_android.h",
+ "android/autofill_assistant/interaction_handler_android.cc",
+ "android/autofill_assistant/interaction_handler_android.h",
"android/autofill_assistant/ui_controller_android.cc",
"android/autofill_assistant/ui_controller_android.h",
+ "android/autofill_assistant/ui_controller_android_utils.cc",
+ "android/autofill_assistant/ui_controller_android_utils.h",
"android/background_sync_launcher_android.cc",
"android/background_sync_launcher_android.h",
"android/background_tab_manager.cc",
"android/background_tab_manager.h",
"android/background_task_scheduler/chrome_background_task_factory.cc",
"android/background_task_scheduler/chrome_background_task_factory.h",
+ "android/background_task_scheduler/proxy_native_task.cc",
+ "android/background_task_scheduler/proxy_native_task.h",
"android/bookmarks/bookmark_bridge.cc",
"android/bookmarks/bookmark_bridge.h",
"android/bookmarks/partner_bookmarks_reader.cc",
@@ -2311,8 +2373,8 @@ jumbo_static_library("browser") {
"android/chrome_backup_watcher.h",
"android/chrome_context_util.cc",
"android/chrome_context_util.h",
- "android/chrome_feature_list.cc",
- "android/chrome_feature_list.h",
+ "android/chrome_session_state.cc",
+ "android/chrome_session_state.h",
"android/chrome_startup_flags.cc",
"android/chrome_startup_flags.h",
"android/color_helpers.cc",
@@ -2327,8 +2389,6 @@ jumbo_static_library("browser") {
"android/compositor/layer/content_layer.h",
"android/compositor/layer/contextual_search_layer.cc",
"android/compositor/layer/contextual_search_layer.h",
- "android/compositor/layer/ephemeral_tab_layer.cc",
- "android/compositor/layer/ephemeral_tab_layer.h",
"android/compositor/layer/layer.h",
"android/compositor/layer/overlay_panel_layer.cc",
"android/compositor/layer/overlay_panel_layer.h",
@@ -2353,8 +2413,6 @@ jumbo_static_library("browser") {
"android/compositor/resources/toolbar_resource.h",
"android/compositor/scene_layer/contextual_search_scene_layer.cc",
"android/compositor/scene_layer/contextual_search_scene_layer.h",
- "android/compositor/scene_layer/ephemeral_tab_scene_layer.cc",
- "android/compositor/scene_layer/ephemeral_tab_scene_layer.h",
"android/compositor/scene_layer/scene_layer.cc",
"android/compositor/scene_layer/scene_layer.h",
"android/compositor/scene_layer/scrolling_bottom_view_scene_layer.cc",
@@ -2400,9 +2458,11 @@ jumbo_static_library("browser") {
"android/cookies/cookies_fetcher_util.cc",
"android/crash/pure_java_exception_handler.cc",
"android/crash/pure_java_exception_handler.h",
+ "android/customtabs/client_data_header_web_contents_observer.cc",
+ "android/customtabs/client_data_header_web_contents_observer.h",
+ "android/customtabs/custom_tabs_connection.cc",
"android/customtabs/detached_resource_request.cc",
"android/customtabs/detached_resource_request.h",
- "android/customtabs/detached_resource_request_android.cc",
"android/customtabs/origin_verifier.cc",
"android/customtabs/origin_verifier.h",
"android/devtools_manager_delegate_android.cc",
@@ -2468,14 +2528,10 @@ jumbo_static_library("browser") {
"android/favicon_helper.cc",
"android/favicon_helper.h",
"android/feature_engagement/tracker_factory_android.cc",
- "android/feature_utilities.cc",
- "android/feature_utilities.h",
"android/feedback/connectivity_checker.cc",
"android/feedback/process_id_feedback_source.cc",
"android/feedback/screenshot_task.cc",
"android/feedback/system_info_feedback_source.cc",
- "android/find_in_page/find_in_page_bridge.cc",
- "android/find_in_page/find_in_page_bridge.h",
"android/foreign_session_helper.cc",
"android/foreign_session_helper.h",
"android/headers_classifier.cc",
@@ -2511,6 +2567,7 @@ jumbo_static_library("browser") {
"android/hung_renderer_infobar_delegate.h",
"android/image_fetcher/image_fetcher_bridge.cc",
"android/image_fetcher/image_fetcher_bridge.h",
+ "android/installedapp/installed_app_verifier.cc",
"android/instantapps/instant_apps_infobar_delegate.cc",
"android/instantapps/instant_apps_infobar_delegate.h",
"android/instantapps/instant_apps_settings.cc",
@@ -2524,9 +2581,6 @@ jumbo_static_library("browser") {
"android/locale/locale_manager.h",
"android/locale/locale_template_url_loader.cc",
"android/locale/locale_template_url_loader.h",
- "android/location_settings.h",
- "android/location_settings_impl.cc",
- "android/location_settings_impl.h",
"android/logo_bridge.cc",
"android/logo_bridge.h",
"android/media/media_capture_devices_dispatcher_android.cc",
@@ -2545,6 +2599,7 @@ jumbo_static_library("browser") {
"android/metrics/variations_session.cc",
"android/mojo/chrome_interface_registrar_android.cc",
"android/mojo/chrome_interface_registrar_android.h",
+ "android/navigation_predictor/navigation_predictor_bridge.cc",
"android/net/nqe/network_quality_provider.cc",
"android/net/nqe/network_quality_provider.h",
"android/ntp/get_remote_suggestions_scheduler.cc",
@@ -2581,7 +2636,6 @@ jumbo_static_library("browser") {
"android/password_editing_bridge.h",
"android/password_ui_view_android.cc",
"android/password_ui_view_android.h",
- "android/payments/service_worker_payment_app_bridge.cc",
"android/permissions/permission_settings_bridge.cc",
"android/photo_picker_sandbox_bridge.cc",
"android/policy/policy_auditor.cc",
@@ -2592,6 +2646,10 @@ jumbo_static_library("browser") {
"android/preferences/browser_prefs_android.h",
"android/preferences/clipboard_android.cc",
"android/preferences/clipboard_android.h",
+ "android/preferences/cookie_controls_bridge.cc",
+ "android/preferences/cookie_controls_bridge.h",
+ "android/preferences/cookie_controls_service_bridge.cc",
+ "android/preferences/cookie_controls_service_bridge.h",
"android/preferences/pref_change_registrar_android.cc",
"android/preferences/pref_change_registrar_android.h",
"android/preferences/pref_service_bridge.cc",
@@ -2599,13 +2657,10 @@ jumbo_static_library("browser") {
"android/preferences/prefs.h",
"android/preferences/privacy_preferences_manager.cc",
"android/preferences/website_preference_bridge.cc",
- "android/preferences/website_preference_bridge.h",
"android/profile_key_startup_accessor.cc",
"android/profile_key_startup_accessor.h",
"android/profile_key_util.cc",
"android/profile_key_util.h",
- "android/profiles/profile_downloader_android.cc",
- "android/profiles/profile_manager_utils.cc",
"android/provider/blocking_ui_thread_async_request.cc",
"android/provider/blocking_ui_thread_async_request.h",
"android/provider/bookmark_model_task.cc",
@@ -2623,6 +2678,7 @@ jumbo_static_library("browser") {
"android/rlz/revenue_stats.cc",
"android/rlz/rlz_ping_handler.cc",
"android/rlz/rlz_ping_handler.h",
+ "android/screenshot/editor_screenshot_task.cc",
"android/search_permissions/search_geolocation_disclosure_infobar_delegate.cc",
"android/search_permissions/search_geolocation_disclosure_infobar_delegate.h",
"android/search_permissions/search_geolocation_disclosure_tab_helper.cc",
@@ -2642,7 +2698,6 @@ jumbo_static_library("browser") {
"android/send_tab_to_self/send_tab_to_self_model_observer_bridge.h",
"android/service_tab_launcher.cc",
"android/service_tab_launcher.h",
- "android/sessions/session_tab_helper_android.cc",
"android/shortcut_helper.cc",
"android/shortcut_helper.h",
"android/shortcut_info.cc",
@@ -2670,11 +2725,6 @@ jumbo_static_library("browser") {
"android/tab_state.h",
"android/tab_web_contents_delegate_android.cc",
"android/tab_web_contents_delegate_android.h",
- "android/thumbnail/scoped_ptr_expiring_cache.h",
- "android/thumbnail/thumbnail.cc",
- "android/thumbnail/thumbnail.h",
- "android/thumbnail/thumbnail_cache.cc",
- "android/thumbnail/thumbnail_cache.h",
"android/trusted_cdn.cc",
"android/trusted_cdn.h",
"android/usage_stats/notification_suspender.cc",
@@ -2684,7 +2734,6 @@ jumbo_static_library("browser") {
"android/usage_stats/usage_stats_database.h",
"android/usb/web_usb_chooser_android.cc",
"android/usb/web_usb_chooser_android.h",
- "android/util/url_utilities.cc",
"android/warmup_manager.cc",
"android/web_contents_factory.cc",
"android/webapk/webapk_handler_delegate.cc",
@@ -2723,8 +2772,6 @@ jumbo_static_library("browser") {
"android/webapps/add_to_homescreen_params.h",
"android/webapps/webapp_registry.cc",
"android/webapps/webapp_registry.h",
- "android/widget/thumbnail_generator.cc",
- "android/widget/thumbnail_generator.h",
"autofill/accessory_controller.h",
"autofill/address_accessory_controller.h",
"autofill/address_accessory_controller_impl.cc",
@@ -2771,10 +2818,6 @@ jumbo_static_library("browser") {
"download/android/download_manager_bridge.h",
"download/android/download_manager_service.cc",
"download/android/download_manager_service.h",
- "download/android/download_media_parser.cc",
- "download/android/download_media_parser.h",
- "download/android/download_media_parser_bridge.cc",
- "download/android/download_media_parser_bridge.h",
"download/android/download_open_source.h",
"download/android/download_startup_utils.cc",
"download/android/download_startup_utils.h",
@@ -2785,8 +2828,6 @@ jumbo_static_library("browser") {
"download/android/intercept_oma_download_navigation_throttle.cc",
"download/android/intercept_oma_download_navigation_throttle.h",
"download/android/items/offline_content_aggregator_factory_android.cc",
- "download/android/local_media_data_source_factory.cc",
- "download/android/local_media_data_source_factory.h",
"download/android/rename_utils.cc",
"download/android/service/download_background_task.cc",
"download/android/service/download_task_scheduler.cc",
@@ -2794,6 +2835,8 @@ jumbo_static_library("browser") {
"engagement/site_engagement_service_android.cc",
"engagement/site_engagement_service_android.h",
"first_run/android/first_run_utils.cc",
+ "flags/android/chrome_feature_list.cc",
+ "flags/android/chrome_feature_list.h",
"history/android/android_history_provider_service.cc",
"history/android/android_history_provider_service.h",
"history/android/android_provider_backend.cc",
@@ -2809,8 +2852,6 @@ jumbo_static_library("browser") {
"installable/installed_webapp_provider.h",
"lifetime/application_lifetime_android.cc",
"lifetime/application_lifetime_android.h",
- "media/android/cdm/media_drm_license_manager.cc",
- "media/android/cdm/media_drm_license_manager.h",
"media/android/cdm/media_drm_origin_id_manager.cc",
"media/android/cdm/media_drm_origin_id_manager.h",
"media/android/cdm/media_drm_origin_id_manager_factory.cc",
@@ -2843,12 +2884,20 @@ jumbo_static_library("browser") {
"notifications/scheduler/display_agent_android.h",
"notifications/scheduler/notification_background_task_scheduler_android.cc",
"notifications/scheduler/notification_background_task_scheduler_android.h",
+ "offline_pages/prefetch/notifications/prefetch_notification_service_bridge_android.cc",
+ "offline_pages/prefetch/notifications/prefetch_notification_service_bridge_android.h",
+ "offline_pages/prefetch/notifications/prefetch_notification_service_factory.cc",
+ "offline_pages/prefetch/notifications/prefetch_notification_service_factory.h",
+ "optimization_guide/android/optimization_guide_bridge.cc",
+ "optimization_guide/android/optimization_guide_bridge.h",
"page_load_metrics/observers/android_page_load_metrics_observer.cc",
"page_load_metrics/observers/android_page_load_metrics_observer.h",
"password_manager/account_chooser_dialog_android.cc",
"password_manager/account_chooser_dialog_android.h",
"password_manager/auto_signin_first_run_dialog_android.cc",
"password_manager/auto_signin_first_run_dialog_android.h",
+ "password_manager/auto_signin_prompt_controller.cc",
+ "password_manager/auto_signin_prompt_controller.h",
"password_manager/credential_android.cc",
"password_manager/credential_android.h",
"password_manager/credential_leak_controller_android.cc",
@@ -2869,8 +2918,6 @@ jumbo_static_library("browser") {
"password_manager/password_manager_launcher_android.h",
"password_manager/save_password_infobar_delegate_android.cc",
"password_manager/save_password_infobar_delegate_android.h",
- "password_manager/touch_to_fill_controller.cc",
- "password_manager/touch_to_fill_controller.h",
"password_manager/touch_to_fill_view.h",
"password_manager/update_password_infobar_delegate_android.cc",
"password_manager/update_password_infobar_delegate_android.h",
@@ -2879,17 +2926,10 @@ jumbo_static_library("browser") {
"payments/android/journey_logger_android.h",
"payments/android/payment_manifest_web_data_service_android.cc",
"payments/android/payment_manifest_web_data_service_android.h",
+ "payments/android/service_worker_payment_app_bridge.cc",
"payments/android/ssl_validity_checker_android.cc",
"permissions/grouped_permission_infobar_delegate_android.cc",
"permissions/grouped_permission_infobar_delegate_android.h",
- "permissions/permission_dialog_delegate.cc",
- "permissions/permission_dialog_delegate.h",
- "permissions/permission_prompt_android.cc",
- "permissions/permission_prompt_android.h",
- "permissions/permission_request_notification_android.cc",
- "permissions/permission_request_notification_android.h",
- "permissions/permission_request_notification_handler.cc",
- "permissions/permission_request_notification_handler.h",
"permissions/permission_update_infobar_delegate_android.cc",
"permissions/permission_update_infobar_delegate_android.h",
"platform_util_android.cc",
@@ -2899,6 +2939,8 @@ jumbo_static_library("browser") {
"prerender/external_prerender_handler_android.h",
"previews/android/previews_android_bridge.cc",
"previews/android/previews_android_bridge.h",
+ "profiles/android/profile_downloader_android.cc",
+ "profiles/android/profile_manager_utils.cc",
"profiles/incognito_utils_android.cc",
"profiles/profile_android.cc",
"profiles/profile_android.h",
@@ -2910,6 +2952,8 @@ jumbo_static_library("browser") {
"reputation/safety_tip_infobar.h",
"reputation/safety_tip_infobar_delegate.cc",
"reputation/safety_tip_infobar_delegate.h",
+ "safe_browsing/android/password_reuse_controller_android.cc",
+ "safe_browsing/android/password_reuse_controller_android.h",
"search/contextual_search_policy_handler_android.cc",
"search/contextual_search_policy_handler_android.h",
"search_engines/template_url_service_factory_android.cc",
@@ -2919,9 +2963,10 @@ jumbo_static_library("browser") {
"signin/identity_services_provider_android.cc",
"signin/signin_manager_android_factory.cc",
"signin/signin_manager_android_factory.h",
+ "ssl/chrome_security_state_model_delegate.cc",
+ "ssl/chrome_security_state_model_delegate.h",
"ssl/known_interception_disclosure_infobar.cc",
"ssl/known_interception_disclosure_infobar.h",
- "ssl/security_state_model_android.cc",
"sync/glue/synced_tab_delegate_android.cc",
"sync/glue/synced_tab_delegate_android.h",
"sync/glue/synced_window_delegate_android.cc",
@@ -2930,17 +2975,15 @@ jumbo_static_library("browser") {
"sync/glue/synced_window_delegates_getter_android.h",
"sync/profile_sync_service_android.cc",
"sync/profile_sync_service_android.h",
+ "touch_to_fill/touch_to_fill_controller.cc",
+ "touch_to_fill/touch_to_fill_controller.h",
"translate/android/translate_bridge.cc",
"translate/android/translate_bridge.h",
+ "upboarding/query_tiles/android/tile_provider_factory.cc",
"updates/update_notification_client.cc",
"updates/update_notification_client.h",
- "updates/update_notification_config.cc",
- "updates/update_notification_config.h",
- "updates/update_notification_service.h",
- "updates/update_notification_service_factory.cc",
- "updates/update_notification_service_factory.h",
- "updates/update_notification_service_impl.cc",
- "updates/update_notification_service_impl.h",
+ "updates/update_notification_service_bridge_android.cc",
+ "updates/update_notification_service_bridge_android.h",
]
public_deps += [
"//chrome/android/features/dev_ui:buildflags",
@@ -2953,34 +2996,57 @@ jumbo_static_library("browser") {
":explore_sites_proto",
":usage_stats_proto",
"//chrome/android:jni_headers",
+ "//chrome/android/features/cablev2_authenticator/internal:native",
"//chrome/android/modules/extra_icu/provider:native",
"//chrome/browser/android/thin_webview/internal",
"//chrome/browser/android/webapk:proto",
+ "//chrome/browser/flags:flags_android",
"//chrome/browser/notifications/chime/android",
"//chrome/browser/notifications/scheduler/public",
+ "//chrome/browser/offline_pages/prefetch/notifications",
+ "//chrome/browser/optimization_guide/android:jni_headers",
+ "//chrome/browser/payments/android:jni_headers",
"//chrome/browser/share",
+ "//chrome/browser/upboarding",
+ "//chrome/browser/updates",
+ "//chrome/common:non_code_constants",
"//chrome/services/media_gallery_util/public/cpp",
"//components/autofill_assistant/browser",
+ "//components/browser_ui/site_settings/android",
+ "//components/browser_ui/util/android",
+ "//components/cbor",
"//components/cdm/browser",
"//components/content_capture/android",
+ "//components/content_settings/android",
"//components/crash/android:crash_android",
+ "//components/embedder_support/android:util",
"//components/embedder_support/android:web_contents_delegate",
+ "//components/external_intents/android",
"//components/feed:buildflags",
"//components/feed:feature_list",
"//components/invalidation/impl:feature_list",
+ "//components/javascript_dialogs/android:jni_headers",
"//components/language/android:language_bridge",
+ "//components/location/android:settings",
"//components/module_installer/android:native",
"//components/omnibox/browser",
"//components/page_load_metrics/browser",
+ "//components/paint_preview/browser/android",
+ "//components/paint_preview/player/android",
+ "//components/password_manager/content/browser",
"//components/payments/content/android",
+ "//components/permissions/android:native",
"//components/resources:components_resources",
+ "//components/security_state/content/android",
"//components/send_tab_to_self",
- "//components/signin/internal/identity_manager", # see android/signin/DEPS
+ "//components/signin/internal/identity_manager", # cf android/signin/DEPS
+ "//components/subresource_filter/android",
+ "//components/viz/common",
"//media/mojo/clients",
- "//media/mojo/mojom:constants",
"//rlz:rlz_utils",
"//sandbox",
"//sandbox:sandbox_buildflags",
+ "//services/device/public/cpp:device_feature_list",
"//services/proxy_resolver:lib",
"//third_party/android_ndk:cpu_features",
"//third_party/android_opengl/etc1",
@@ -2988,6 +3054,7 @@ jumbo_static_library("browser") {
"//third_party/libaddressinput:util",
"//third_party/libphonenumber",
"//third_party/smhasher:murmurhash2",
+ "//url:origin_android",
]
deps -= [ "//components/storage_monitor" ]
@@ -3012,6 +3079,15 @@ jumbo_static_library("browser") {
]
deps += [ "//chrome/android/modules/dev_ui/provider:native" ]
}
+
+ if (enable_password_change_in_leaked_dialog) {
+ sources += [
+ "password_manager/credential_leak_password_change_controller_android.cc",
+ "password_manager/credential_leak_password_change_controller_android.h",
+ ]
+
+ defines += [ "ENABLE_PASSWORD_CHANGE" ]
+ }
} else { # !is_android
sources += [
"accessibility/invert_bubble_prefs.cc",
@@ -3028,8 +3104,12 @@ jumbo_static_library("browser") {
"apps/app_service/app_service_proxy.h",
"apps/app_service/app_service_proxy_factory.cc",
"apps/app_service/app_service_proxy_factory.h",
+ "apps/app_service/browser_app_launcher.cc",
+ "apps/app_service/browser_app_launcher.h",
"apps/app_service/dip_px_util.cc",
"apps/app_service/dip_px_util.h",
+ "apps/app_service/launch_utils.cc",
+ "apps/app_service/launch_utils.h",
"apps/app_service/uninstall_dialog.cc",
"apps/app_service/uninstall_dialog.h",
"apps/intent_helper/apps_navigation_throttle.cc",
@@ -3062,10 +3142,6 @@ jumbo_static_library("browser") {
"badging/badge_manager_factory.h",
"banners/app_banner_manager_desktop.cc",
"banners/app_banner_manager_desktop.h",
- "bluetooth/bluetooth_chooser_context.cc",
- "bluetooth/bluetooth_chooser_context.h",
- "bluetooth/bluetooth_chooser_context_factory.cc",
- "bluetooth/bluetooth_chooser_context_factory.h",
"bookmarks/bookmark_html_writer.cc",
"bookmarks/bookmark_html_writer.h",
"certificate_viewer.h",
@@ -3073,10 +3149,17 @@ jumbo_static_library("browser") {
"chrome_browser_field_trials_desktop.h",
"chrome_process_singleton.cc",
"chrome_process_singleton.h",
- "component_updater/tls_deprecation_config_component_installer.cc",
- "component_updater/tls_deprecation_config_component_installer.h",
+ "component_updater/intervention_policy_database_component_installer.cc",
+ "component_updater/intervention_policy_database_component_installer.h",
"custom_handlers/register_protocol_handler_permission_request.cc",
"custom_handlers/register_protocol_handler_permission_request.h",
+ "device_identity/device_identity_provider.cc",
+ "device_identity/device_identity_provider.h",
+ "device_identity/device_oauth2_token_service.cc",
+ "device_identity/device_oauth2_token_service.h",
+ "device_identity/device_oauth2_token_service_factory.cc",
+ "device_identity/device_oauth2_token_service_factory.h",
+ "device_identity/device_oauth2_token_store.h",
"diagnostics/diagnostics_controller.cc",
"diagnostics/diagnostics_controller.h",
"diagnostics/diagnostics_metrics.cc",
@@ -3111,27 +3194,37 @@ jumbo_static_library("browser") {
"download/download_shelf_context_menu.h",
"download/download_shelf_controller.cc",
"download/download_shelf_controller.h",
- "enterprise_reporting/browser_report_generator.cc",
- "enterprise_reporting/browser_report_generator.h",
- "enterprise_reporting/extension_info.cc",
- "enterprise_reporting/extension_info.h",
- "enterprise_reporting/policy_info.cc",
- "enterprise_reporting/policy_info.h",
- "enterprise_reporting/prefs.cc",
- "enterprise_reporting/prefs.h",
- "enterprise_reporting/profile_report_generator.cc",
- "enterprise_reporting/profile_report_generator.h",
- "enterprise_reporting/report_generator.cc",
- "enterprise_reporting/report_generator.h",
- "enterprise_reporting/report_request_definition.h",
- "enterprise_reporting/report_request_queue_generator.cc",
- "enterprise_reporting/report_request_queue_generator.h",
- "enterprise_reporting/report_scheduler.cc",
- "enterprise_reporting/report_scheduler.h",
- "enterprise_reporting/report_uploader.cc",
- "enterprise_reporting/report_uploader.h",
- "enterprise_reporting/request_timer.cc",
- "enterprise_reporting/request_timer.h",
+ "enterprise/connectors/connectors_manager.cc",
+ "enterprise/connectors/connectors_manager.h",
+ "enterprise/connectors/enterprise_connectors_policy_handler.cc",
+ "enterprise/connectors/enterprise_connectors_policy_handler.h",
+ "enterprise/reporting/browser_report_generator.cc",
+ "enterprise/reporting/browser_report_generator.h",
+ "enterprise/reporting/extension_info.cc",
+ "enterprise/reporting/extension_info.h",
+ "enterprise/reporting/extension_request_policy_handler.cc",
+ "enterprise/reporting/extension_request_policy_handler.h",
+ "enterprise/reporting/notification/extension_request_notification.cc",
+ "enterprise/reporting/notification/extension_request_notification.h",
+ "enterprise/reporting/notification/extension_request_observer.cc",
+ "enterprise/reporting/notification/extension_request_observer.h",
+ "enterprise/reporting/notification/extension_request_observer_factory.cc",
+ "enterprise/reporting/notification/extension_request_observer_factory.h",
+ "enterprise/reporting/policy_info.cc",
+ "enterprise/reporting/policy_info.h",
+ "enterprise/reporting/prefs.cc",
+ "enterprise/reporting/prefs.h",
+ "enterprise/reporting/profile_report_generator.cc",
+ "enterprise/reporting/profile_report_generator.h",
+ "enterprise/reporting/report_generator.cc",
+ "enterprise/reporting/report_generator.h",
+ "enterprise/reporting/report_request_definition.h",
+ "enterprise/reporting/report_request_queue_generator.cc",
+ "enterprise/reporting/report_request_queue_generator.h",
+ "enterprise/reporting/report_scheduler.cc",
+ "enterprise/reporting/report_scheduler.h",
+ "enterprise/reporting/report_uploader.cc",
+ "enterprise/reporting/report_uploader.h",
"feedback/feedback_dialog_utils.cc",
"feedback/feedback_dialog_utils.h",
"feedback/feedback_uploader_chrome.cc",
@@ -3204,18 +3297,6 @@ jumbo_static_library("browser") {
"media/webrtc/system_media_capture_permissions_stats_mac.mm",
"media/webrtc/tab_desktop_media_list.cc",
"media/webrtc/tab_desktop_media_list.h",
- "media_galleries/chromeos/mtp_device_delegate_impl_chromeos.cc",
- "media_galleries/chromeos/mtp_device_delegate_impl_chromeos.h",
- "media_galleries/chromeos/mtp_device_object_enumerator.cc",
- "media_galleries/chromeos/mtp_device_object_enumerator.h",
- "media_galleries/chromeos/mtp_device_task_helper.cc",
- "media_galleries/chromeos/mtp_device_task_helper.h",
- "media_galleries/chromeos/mtp_device_task_helper_map_service.cc",
- "media_galleries/chromeos/mtp_device_task_helper_map_service.h",
- "media_galleries/chromeos/mtp_read_file_worker.cc",
- "media_galleries/chromeos/mtp_read_file_worker.h",
- "media_galleries/chromeos/snapshot_file_details.cc",
- "media_galleries/chromeos/snapshot_file_details.h",
"media_galleries/fileapi/av_scanning_file_validator.cc",
"media_galleries/fileapi/av_scanning_file_validator.h",
"media_galleries/fileapi/media_file_system_backend.cc",
@@ -3235,8 +3316,6 @@ jumbo_static_library("browser") {
"media_galleries/gallery_watch_manager.cc",
"media_galleries/gallery_watch_manager.h",
"media_galleries/gallery_watch_manager_observer.h",
- "media_galleries/mac/mtp_device_delegate_impl_mac.h",
- "media_galleries/mac/mtp_device_delegate_impl_mac.mm",
"media_galleries/media_file_system_registry.cc",
"media_galleries/media_file_system_registry.h",
"media_galleries/media_galleries_dialog_controller.cc",
@@ -3251,25 +3330,6 @@ jumbo_static_library("browser") {
"media_galleries/media_galleries_preferences_factory.h",
"media_galleries/media_gallery_context_menu.cc",
"media_galleries/media_gallery_context_menu.h",
- "media_galleries/win/mtp_device_delegate_impl_win.cc",
- "media_galleries/win/mtp_device_delegate_impl_win.h",
- "media_galleries/win/mtp_device_object_entry.cc",
- "media_galleries/win/mtp_device_object_entry.h",
- "media_galleries/win/mtp_device_object_enumerator.cc",
- "media_galleries/win/mtp_device_object_enumerator.h",
- "media_galleries/win/mtp_device_operations_util.cc",
- "media_galleries/win/mtp_device_operations_util.h",
- "media_galleries/win/portable_device_map_service.cc",
- "media_galleries/win/portable_device_map_service.h",
- "media_galleries/win/snapshot_file_details.cc",
- "media_galleries/win/snapshot_file_details.h",
- "memory/memory_pressure_monitor.cc",
- "memory/memory_pressure_monitor.h",
- "memory/memory_pressure_monitor_utils.cc",
- "memory/memory_pressure_monitor_utils.h",
- "memory/memory_pressure_monitor_utils_impl.h",
- "memory/memory_pressure_monitor_win.cc",
- "memory/memory_pressure_monitor_win.h",
"memory/oom_memory_details.cc",
"memory/oom_memory_details.h",
"memory/swap_thrashing_monitor.cc",
@@ -3314,8 +3374,47 @@ jumbo_static_library("browser") {
"obsolete_system/obsolete_system_win.cc",
"page_load_metrics/observers/session_restore_page_load_metrics_observer.cc",
"page_load_metrics/observers/session_restore_page_load_metrics_observer.h",
+ "performance_manager/graph/policies/background_tab_loading_policy.cc",
+ "performance_manager/graph/policies/background_tab_loading_policy.h",
+ "performance_manager/graph/policies/background_tab_loading_policy_helpers.cc",
+ "performance_manager/graph/policies/background_tab_loading_policy_helpers.h",
+ "performance_manager/graph/policies/urgent_page_discarding_policy.cc",
+ "performance_manager/graph/policies/urgent_page_discarding_policy.h",
+ "performance_manager/mechanisms/page_discarder.cc",
+ "performance_manager/mechanisms/page_discarder.h",
+ "performance_manager/mechanisms/page_loader.cc",
+ "performance_manager/mechanisms/page_loader.h",
+ "performance_manager/persistence/site_data/exponential_moving_average.cc",
+ "performance_manager/persistence/site_data/exponential_moving_average.h",
+ "performance_manager/persistence/site_data/feature_usage.h",
+ "performance_manager/persistence/site_data/leveldb_site_data_store.cc",
+ "performance_manager/persistence/site_data/leveldb_site_data_store.h",
+ "performance_manager/persistence/site_data/non_recording_site_data_cache.cc",
+ "performance_manager/persistence/site_data/non_recording_site_data_cache.h",
+ "performance_manager/persistence/site_data/noop_site_data_writer.cc",
+ "performance_manager/persistence/site_data/noop_site_data_writer.h",
+ "performance_manager/persistence/site_data/site_data_cache.h",
+ "performance_manager/persistence/site_data/site_data_cache_facade.cc",
+ "performance_manager/persistence/site_data/site_data_cache_facade.h",
+ "performance_manager/persistence/site_data/site_data_cache_facade_factory.cc",
+ "performance_manager/persistence/site_data/site_data_cache_facade_factory.h",
+ "performance_manager/persistence/site_data/site_data_cache_factory.cc",
+ "performance_manager/persistence/site_data/site_data_cache_factory.h",
+ "performance_manager/persistence/site_data/site_data_cache_impl.cc",
+ "performance_manager/persistence/site_data/site_data_cache_impl.h",
+ "performance_manager/persistence/site_data/site_data_cache_inspector.h",
+ "performance_manager/persistence/site_data/site_data_impl.cc",
+ "performance_manager/persistence/site_data/site_data_impl.h",
+ "performance_manager/persistence/site_data/site_data_reader.cc",
+ "performance_manager/persistence/site_data/site_data_reader.h",
+ "performance_manager/persistence/site_data/site_data_store.h",
+ "performance_manager/persistence/site_data/site_data_writer.cc",
+ "performance_manager/persistence/site_data/site_data_writer.h",
+ "performance_manager/persistence/site_data/tab_visibility.h",
"permissions/attestation_permission_request.cc",
"permissions/attestation_permission_request.h",
+ "policy/device_account_initializer.cc",
+ "policy/device_account_initializer.h",
"policy/local_sync_policy_handler.cc",
"policy/local_sync_policy_handler.h",
"process_singleton_modal_dialog_lock.cc",
@@ -3339,6 +3438,8 @@ jumbo_static_library("browser") {
"profile_resetter/triggered_profile_resetter_factory.cc",
"profile_resetter/triggered_profile_resetter_factory.h",
"profile_resetter/triggered_profile_resetter_win.cc",
+ "profiles/independent_otr_profile_manager.cc",
+ "profiles/independent_otr_profile_manager.h",
"profiles/profile_shortcut_manager.cc",
"profiles/profile_shortcut_manager.h",
"profiles/profile_window.cc",
@@ -3361,6 +3462,8 @@ jumbo_static_library("browser") {
"resource_coordinator/decision_details.h",
"resource_coordinator/discard_metrics_lifecycle_unit_observer.cc",
"resource_coordinator/discard_metrics_lifecycle_unit_observer.h",
+ "resource_coordinator/intervention_policy_database.cc",
+ "resource_coordinator/intervention_policy_database.h",
"resource_coordinator/leveldb_site_characteristics_database.cc",
"resource_coordinator/leveldb_site_characteristics_database.h",
"resource_coordinator/lifecycle_unit.cc",
@@ -3447,6 +3550,8 @@ jumbo_static_library("browser") {
"search/ntp_custom_background_enabled_policy_handler.h",
"search/ntp_features.cc",
"search/ntp_features.h",
+ "search/ntp_icon_source.cc",
+ "search/ntp_icon_source.h",
"search/one_google_bar/one_google_bar_data.cc",
"search/one_google_bar/one_google_bar_data.h",
"search/one_google_bar/one_google_bar_loader.h",
@@ -3517,16 +3622,34 @@ jumbo_static_library("browser") {
"sharing/sharing_notification_handler.h",
"sharing/sharing_ui_controller.cc",
"sharing/sharing_ui_controller.h",
+ "sharing/webrtc/ice_config_fetcher.cc",
+ "sharing/webrtc/ice_config_fetcher.h",
+ "sharing/webrtc/sharing_mojo_service.cc",
+ "sharing/webrtc/sharing_mojo_service.h",
+ "sharing/webrtc/sharing_service_host.cc",
+ "sharing/webrtc/sharing_service_host.h",
+ "sharing/webrtc/sharing_webrtc_connection_host.cc",
+ "sharing/webrtc/sharing_webrtc_connection_host.h",
+ "sharing/webrtc/webrtc_message_handler.cc",
+ "sharing/webrtc/webrtc_message_handler.h",
+ "sharing/webrtc/webrtc_signalling_host_fcm.cc",
+ "sharing/webrtc/webrtc_signalling_host_fcm.h",
"signin/signin_promo.cc",
"signin/signin_promo.h",
"signin/signin_ui_util.cc",
"signin/signin_ui_util.h",
- "speech/extension_api/tts_extension_api_constants.cc", # Should be moved to extensions section?
+ "speech/extension_api/tts_extension_api_constants.cc", # Should be moved
+ # to extensions
+ # section?
"speech/extension_api/tts_extension_api_constants.h",
"ssl/ssl_client_auth_observer.cc",
"ssl/ssl_client_auth_observer.h",
"status_icons/desktop_notification_balloon.cc",
"status_icons/desktop_notification_balloon.h",
+ "storage/storage_notification_service_factory.cc",
+ "storage/storage_notification_service_factory.h",
+ "storage/storage_notification_service_impl.cc",
+ "storage/storage_notification_service_impl.h",
"sync/glue/extension_model_type_controller.cc",
"sync/glue/extension_model_type_controller.h",
"sync/glue/extension_setting_model_type_controller.cc",
@@ -3535,6 +3658,8 @@ jumbo_static_library("browser") {
"sync/sessions/browser_list_router_helper.h",
"sync/sync_ui_util.cc",
"sync/sync_ui_util.h",
+ "tab_contents/form_interaction_tab_helper.cc",
+ "tab_contents/form_interaction_tab_helper.h",
"task_manager/providers/browser_process_task.cc",
"task_manager/providers/browser_process_task.h",
"task_manager/providers/browser_process_task_provider.cc",
@@ -3545,12 +3670,10 @@ jumbo_static_library("browser") {
"task_manager/providers/child_process_task_provider.h",
"task_manager/providers/fallback_task_provider.cc",
"task_manager/providers/fallback_task_provider.h",
+ "task_manager/providers/per_profile_worker_task_tracker.cc",
+ "task_manager/providers/per_profile_worker_task_tracker.h",
"task_manager/providers/render_process_host_task_provider.cc",
"task_manager/providers/render_process_host_task_provider.h",
- "task_manager/providers/service_worker_task.cc",
- "task_manager/providers/service_worker_task.h",
- "task_manager/providers/service_worker_task_provider.cc",
- "task_manager/providers/service_worker_task_provider.h",
"task_manager/providers/task.cc",
"task_manager/providers/task.h",
"task_manager/providers/task_provider.cc",
@@ -3572,6 +3695,10 @@ jumbo_static_library("browser") {
"task_manager/providers/web_contents/guest_tag.h",
"task_manager/providers/web_contents/guest_task.cc",
"task_manager/providers/web_contents/guest_task.h",
+ "task_manager/providers/web_contents/portal_tag.cc",
+ "task_manager/providers/web_contents/portal_tag.h",
+ "task_manager/providers/web_contents/portal_task.cc",
+ "task_manager/providers/web_contents/portal_task.h",
"task_manager/providers/web_contents/prerender_tag.cc",
"task_manager/providers/web_contents/prerender_tag.h",
"task_manager/providers/web_contents/prerender_task.cc",
@@ -3594,6 +3721,10 @@ jumbo_static_library("browser") {
"task_manager/providers/web_contents/web_contents_tags_manager.h",
"task_manager/providers/web_contents/web_contents_task_provider.cc",
"task_manager/providers/web_contents/web_contents_task_provider.h",
+ "task_manager/providers/worker_task.cc",
+ "task_manager/providers/worker_task.h",
+ "task_manager/providers/worker_task_provider.cc",
+ "task_manager/providers/worker_task_provider.h",
"task_manager/sampling/shared_sampler.h",
"task_manager/sampling/shared_sampler_win.cc",
"task_manager/sampling/shared_sampler_win_defines.h",
@@ -3613,6 +3744,8 @@ jumbo_static_library("browser") {
"themes/custom_theme_supplier.h",
"themes/increased_contrast_theme_supplier.cc",
"themes/increased_contrast_theme_supplier.h",
+ "themes/theme_helper.cc",
+ "themes/theme_helper.h",
"themes/theme_properties.cc",
"themes/theme_service.cc",
"themes/theme_service.h",
@@ -3620,6 +3753,9 @@ jumbo_static_library("browser") {
"themes/theme_service_factory.h",
"themes/theme_syncable_service.cc",
"themes/theme_syncable_service.h",
+ "upgrade_detector/build_state.cc",
+ "upgrade_detector/build_state.h",
+ "upgrade_detector/build_state_observer.h",
"upgrade_detector/upgrade_detector.cc",
"upgrade_detector/upgrade_detector.h",
"upgrade_detector/upgrade_observer.h",
@@ -3648,6 +3784,7 @@ jumbo_static_library("browser") {
"//chrome/app/vector_icons",
"//chrome/browser/policy:path_parser",
"//chrome/browser/profile_resetter:profile_reset_report_proto",
+ "//chrome/browser/resource_coordinator:intervention_policy_database_proto",
"//chrome/browser/resource_coordinator:tab_metrics_event_proto",
"//chrome/browser/resource_coordinator/tab_ranker",
"//chrome/browser/resources:component_extension_resources",
@@ -3660,6 +3797,8 @@ jumbo_static_library("browser") {
"//chrome/services/app_service/public/cpp:icon_loader",
"//chrome/services/app_service/public/cpp:intents",
"//chrome/services/app_service/public/cpp:preferred_apps",
+ "//chrome/services/sharing/public/cpp",
+ "//chrome/services/sharing/public/mojom",
"//components/feedback",
"//components/image_fetcher/core",
"//components/keep_alive_registry",
@@ -3699,19 +3838,27 @@ jumbo_static_library("browser") {
"apps/app_service/extension_apps.h",
"apps/app_service/icon_key_util.cc",
"apps/app_service/icon_key_util.h",
+ "apps/app_service/menu_util.cc",
+ "apps/app_service/menu_util.h",
+ "apps/app_service/paused_apps.cc",
+ "apps/app_service/paused_apps.h",
"apps/app_service/web_apps.cc",
"apps/app_service/web_apps.h",
- "ash_service_registry.cc",
- "ash_service_registry.h",
"component_updater/cros_component_installer_chromeos.cc",
"component_updater/cros_component_installer_chromeos.h",
"component_updater/cros_component_manager.h",
"component_updater/metadata_table_chromeos.cc",
"component_updater/metadata_table_chromeos.h",
+ "component_updater/smart_dim_component_installer.cc",
+ "component_updater/smart_dim_component_installer.h",
+ "device_identity/chromeos/device_oauth2_token_store_chromeos.cc",
+ "device_identity/chromeos/device_oauth2_token_store_chromeos.h",
"download/notification/download_item_notification.cc",
"download/notification/download_item_notification.h",
"download/notification/download_notification_manager.cc",
"download/notification/download_notification_manager.h",
+ "enterprise/reporting/android_app_info_generator.cc",
+ "enterprise/reporting/android_app_info_generator.h",
"feedback/feedback_util_chromeos.cc",
"feedback/feedback_util_chromeos.h",
"google/google_brand_chromeos.cc",
@@ -3726,6 +3873,18 @@ jumbo_static_library("browser") {
"media/public_session_tab_capture_access_handler.h",
"media/webrtc/desktop_media_list_ash.cc",
"media/webrtc/desktop_media_list_ash.h",
+ "media_galleries/chromeos/mtp_device_delegate_impl_chromeos.cc",
+ "media_galleries/chromeos/mtp_device_delegate_impl_chromeos.h",
+ "media_galleries/chromeos/mtp_device_object_enumerator.cc",
+ "media_galleries/chromeos/mtp_device_object_enumerator.h",
+ "media_galleries/chromeos/mtp_device_task_helper.cc",
+ "media_galleries/chromeos/mtp_device_task_helper.h",
+ "media_galleries/chromeos/mtp_device_task_helper_map_service.cc",
+ "media_galleries/chromeos/mtp_device_task_helper_map_service.h",
+ "media_galleries/chromeos/mtp_read_file_worker.cc",
+ "media_galleries/chromeos/mtp_read_file_worker.h",
+ "media_galleries/chromeos/snapshot_file_details.cc",
+ "media_galleries/chromeos/snapshot_file_details.h",
"memory/memory_kills_histogram.h",
"memory/memory_kills_monitor.cc",
"memory/memory_kills_monitor.h",
@@ -3737,8 +3896,6 @@ jumbo_static_library("browser") {
"metrics/perf/collection_params.h",
"metrics/perf/cpu_identity.cc",
"metrics/perf/cpu_identity.h",
- "metrics/perf/heap_collector.cc",
- "metrics/perf/heap_collector.h",
"metrics/perf/metric_collector.cc",
"metrics/perf/metric_collector.h",
"metrics/perf/metric_provider.cc",
@@ -3766,6 +3923,8 @@ jumbo_static_library("browser") {
"notifications/web_page_notifier_controller.h",
"policy/default_geolocation_policy_handler.cc",
"policy/default_geolocation_policy_handler.h",
+ "renderer_context_menu/quick_answers_menu_observer.cc",
+ "renderer_context_menu/quick_answers_menu_observer.h",
"signin/signin_error_notifier_ash.cc",
"signin/signin_error_notifier_ash.h",
"signin/signin_error_notifier_factory_ash.cc",
@@ -3792,6 +3951,8 @@ jumbo_static_library("browser") {
"task_manager/providers/vm/vm_process_task_provider.h",
"task_manager/sampling/arc_shared_sampler.cc",
"task_manager/sampling/arc_shared_sampler.h",
+ "upgrade_detector/installed_version_updater_chromeos.cc",
+ "upgrade_detector/installed_version_updater_chromeos.h",
"upgrade_detector/upgrade_detector_chromeos.cc",
"upgrade_detector/upgrade_detector_chromeos.h",
]
@@ -3800,6 +3961,7 @@ jumbo_static_library("browser") {
"//chrome/browser/chromeos",
"//chrome/services/app_service/public/cpp:instance_update",
"//chromeos/components/account_manager",
+ "//chromeos/components/quick_answers",
"//chromeos/components/sync_wifi",
"//chromeos/services/assistant/public:feature_flags",
"//chromeos/services/assistant/public/cpp:prefs",
@@ -3812,6 +3974,7 @@ jumbo_static_library("browser") {
"//chromeos/services/network_config/public/mojom",
"//chromeos/services/secure_channel/public/mojom",
"//chromeos/strings",
+ "//components/metrics/structured",
"//components/services/font:lib",
"//components/services/font/public/mojom",
"//ui/events/ozone",
@@ -3856,20 +4019,28 @@ jumbo_static_library("browser") {
"browser_switcher/browser_switcher_policy_migrator.h",
"browser_switcher/browser_switcher_service_win.cc",
"browser_switcher/browser_switcher_service_win.h",
- "downgrade/downgrade_manager.cc",
- "downgrade/downgrade_manager.h",
- "downgrade/user_data_downgrade.cc",
- "downgrade/user_data_downgrade.h",
+ "media_galleries/win/mtp_device_delegate_impl_win.cc",
+ "media_galleries/win/mtp_device_delegate_impl_win.h",
+ "media_galleries/win/mtp_device_object_entry.cc",
+ "media_galleries/win/mtp_device_object_entry.h",
+ "media_galleries/win/mtp_device_object_enumerator.cc",
+ "media_galleries/win/mtp_device_object_enumerator.h",
+ "media_galleries/win/mtp_device_operations_util.cc",
+ "media_galleries/win/mtp_device_operations_util.h",
+ "media_galleries/win/portable_device_map_service.cc",
+ "media_galleries/win/portable_device_map_service.h",
+ "media_galleries/win/snapshot_file_details.cc",
+ "media_galleries/win/snapshot_file_details.h",
"notifications/win/notification_image_retainer.cc",
"notifications/win/notification_image_retainer.h",
"notifications/win/notification_template_builder.cc",
"notifications/win/notification_template_builder.h",
- "performance_monitor/wmi_refresher.cc",
- "performance_monitor/wmi_refresher.h",
"sync/roaming_profile_directory_deleter_win.cc",
"sync/roaming_profile_directory_deleter_win.h",
"taskbar/taskbar_decorator_win.cc",
"taskbar/taskbar_decorator_win.h",
+ "win/parental_controls.cc",
+ "win/parental_controls.h",
"win/util_win_service.cc",
"win/util_win_service.h",
]
@@ -3885,14 +4056,11 @@ jumbo_static_library("browser") {
"//chrome/browser/win/conflicts:module_info",
"//chrome/chrome_elf:constants",
"//chrome/chrome_elf:dll_hash",
- "//chrome/chrome_watcher:client",
- "//chrome/common:metrics_constants_util_win",
"//chrome/common:version_header",
"//chrome/credential_provider/common:common_constants",
"//chrome/install_static:install_static_util",
"//chrome/notification_helper:constants",
"//chrome/services/util_win/public/mojom",
- "//components/browser_watcher",
"//components/browser_watcher:browser_watcher_client",
"//components/browser_watcher:stability_client",
"//components/chrome_cleaner/public/constants",
@@ -3937,6 +4105,8 @@ jumbo_static_library("browser") {
sources += [
"component_updater/third_party_module_list_component_installer_win.cc",
"component_updater/third_party_module_list_component_installer_win.h",
+ "google/google_update_policy_fetcher_win.cc",
+ "google/google_update_policy_fetcher_win.h",
"google/google_update_win.cc",
"google/google_update_win.h",
"win/conflicts/incompatible_applications_updater.cc",
@@ -3987,6 +4157,8 @@ jumbo_static_library("browser") {
"badging/badge_manager_delegate_mac.cc",
"badging/badge_manager_delegate_mac.h",
"download/drag_download_item_mac.mm",
+ "media_galleries/mac/mtp_device_delegate_impl_mac.h",
+ "media_galleries/mac/mtp_device_delegate_impl_mac.mm",
]
deps += [
"//chrome/app_shim",
@@ -4007,6 +4179,7 @@ jumbo_static_library("browser") {
"ImageCaptureCore.framework",
"OpenGL.framework",
"QuartzCore.framework",
+ "SafariServices.framework",
"SecurityInterface.framework",
]
}
@@ -4046,6 +4219,7 @@ jumbo_static_library("browser") {
"shell_integration_linux.h",
"themes/theme_service_aura_linux.cc",
"themes/theme_service_aura_linux.h",
+ "upgrade_detector/get_installed_version_linux.cc",
]
if (use_dbus) {
@@ -4143,12 +4317,30 @@ jumbo_static_library("browser") {
defines += [ "USE_CRAS" ]
}
+ if (enable_downgrade_processing) {
+ sources += [
+ "downgrade/downgrade_manager.cc",
+ "downgrade/downgrade_manager.h",
+ "downgrade/downgrade_prefs.cc",
+ "downgrade/downgrade_prefs.h",
+ "downgrade/downgrade_utils.cc",
+ "downgrade/downgrade_utils.h",
+ "downgrade/snapshot_file_collector.cc",
+ "downgrade/snapshot_file_collector.h",
+ "downgrade/snapshot_manager.cc",
+ "downgrade/snapshot_manager.h",
+ "downgrade/user_data_downgrade.cc",
+ "downgrade/user_data_downgrade.h",
+ ]
+ }
+
if (!is_android && !is_chromeos) {
sources += [
+ "device_identity/device_oauth2_token_store_desktop.cc",
+ "device_identity/device_oauth2_token_store_desktop.h",
"first_run/upgrade_util.cc",
"first_run/upgrade_util.h",
- "first_run/upgrade_util_mac.h",
- "first_run/upgrade_util_mac.mm",
+ "first_run/upgrade_util_mac.cc",
"first_run/upgrade_util_win.cc",
"first_run/upgrade_util_win.h",
"lifetime/switch_utils.cc",
@@ -4200,6 +4392,12 @@ jumbo_static_library("browser") {
"signin/signin_global_error.h",
"signin/signin_global_error_factory.cc",
"signin/signin_global_error_factory.h",
+ "upgrade_detector/get_installed_version.cc",
+ "upgrade_detector/get_installed_version.h",
+ "upgrade_detector/get_installed_version_mac.mm",
+ "upgrade_detector/get_installed_version_win.cc",
+ "upgrade_detector/installed_version_poller.cc",
+ "upgrade_detector/installed_version_poller.h",
"upgrade_detector/upgrade_detector_impl.cc",
"upgrade_detector/upgrade_detector_impl.h",
]
@@ -4217,8 +4415,8 @@ jumbo_static_library("browser") {
"//chrome/app/chrome_crash_reporter_client.h",
]
deps += [
- "//components/crash/content/app",
"//components/crash/content/browser",
+ "//components/crash/core/app",
"//components/version_info:generate_version_info",
]
}
@@ -4279,7 +4477,7 @@ jumbo_static_library("browser") {
"//ui/snapshot",
]
if (use_gtk) {
- deps += [ "//chrome/browser/ui/libgtkui" ]
+ deps += [ "//ui/gtk" ]
}
}
@@ -4346,8 +4544,8 @@ jumbo_static_library("browser") {
]
deps += [
"//components/printing/browser",
- "//components/services/pdf_compositor/public/cpp",
- "//components/services/pdf_compositor/public/mojom",
+ "//components/services/print_compositor/public/cpp",
+ "//components/services/print_compositor/public/mojom",
"//printing",
]
@@ -4417,25 +4615,25 @@ jumbo_static_library("browser") {
}
}
+ if (enable_paint_preview) {
+ deps += [
+ "//components/paint_preview/browser",
+ "//components/paint_preview/common",
+ ]
+ }
+
if (enable_captive_portal_detection) {
sources += [
- "captive_portal/captive_portal_login_detector.cc",
- "captive_portal/captive_portal_login_detector.h",
- "captive_portal/captive_portal_service.cc",
- "captive_portal/captive_portal_service.h",
"captive_portal/captive_portal_service_factory.cc",
"captive_portal/captive_portal_service_factory.h",
- "captive_portal/captive_portal_tab_helper.cc",
- "captive_portal/captive_portal_tab_helper.h",
- "captive_portal/captive_portal_tab_reloader.cc",
- "captive_portal/captive_portal_tab_reloader.h",
- "ssl/captive_portal_metrics_recorder.cc",
- "ssl/captive_portal_metrics_recorder.h",
]
}
if (enable_kaleidoscope) {
- deps += [ "//chrome/browser/media/kaleidoscope/internal" ]
+ deps += [
+ "//chrome/browser/media/kaleidoscope/internal",
+ "//chrome/browser/media/kaleidoscope/internal/mojom",
+ ]
}
if (enable_legacy_desktop_in_product_help) {
@@ -4663,6 +4861,7 @@ jumbo_static_library("browser") {
"//chrome/browser/web_applications",
# TODO(loyso): Erase these. crbug.com/877898.
+ "//chrome/browser/web_applications:common",
"//chrome/browser/web_applications:web_applications_on_extensions",
"//chrome/browser/web_applications/components",
"//chrome/browser/web_applications/extensions",
@@ -4671,6 +4870,7 @@ jumbo_static_library("browser") {
"//apps",
"//chrome/browser/sync_file_system/drive_backend:sync_file_system_drive_proto",
"//chrome/browser/web_applications",
+ "//chrome/browser/web_applications:common",
"//chrome/browser/web_applications:web_applications_on_extensions",
"//chrome/browser/web_applications/components",
"//chrome/browser/web_applications/extensions",
@@ -4707,8 +4907,17 @@ jumbo_static_library("browser") {
"android/feed/feed_scheduler_bridge.h",
"android/feed/history/feed_history_helper.cc",
"android/feed/history/feed_history_helper.h",
+ "android/feed/v2/feed_service_bridge.cc",
+ "android/feed/v2/feed_service_bridge.h",
+ "android/feed/v2/feed_service_factory.cc",
+ "android/feed/v2/feed_service_factory.h",
+ "android/feed/v2/feed_stream_surface.cc",
+ "android/feed/v2/feed_stream_surface.h",
+ ]
+ deps += [
+ "//components/feed/content:feed_content",
+ "//components/feed/core/v2:feed_core_v2",
]
- deps += [ "//components/feed/content:feed_content" ]
}
if (enable_library_cdms) {
@@ -4748,10 +4957,7 @@ jumbo_static_library("browser") {
}
if (mojo_media_host == "browser") {
- deps += [
- "//media/mojo/mojom:constants",
- "//media/mojo/services",
- ]
+ deps += [ "//media/mojo/services" ]
}
}
@@ -5148,10 +5354,6 @@ jumbo_static_library("browser") {
"supervised_user/child_accounts/kids_management_api.h",
"supervised_user/child_accounts/permission_request_creator_apiary.cc",
"supervised_user/child_accounts/permission_request_creator_apiary.h",
- "supervised_user/experimental/supervised_user_blacklist.cc",
- "supervised_user/experimental/supervised_user_blacklist.h",
- "supervised_user/experimental/supervised_user_filtering_switches.cc",
- "supervised_user/experimental/supervised_user_filtering_switches.h",
"supervised_user/kids_chrome_management/kids_chrome_management_client.cc",
"supervised_user/kids_chrome_management/kids_chrome_management_client.h",
"supervised_user/kids_chrome_management/kids_chrome_management_client_factory.cc",
@@ -5159,10 +5361,14 @@ jumbo_static_library("browser") {
"supervised_user/kids_management_url_checker_client.cc",
"supervised_user/kids_management_url_checker_client.h",
"supervised_user/permission_request_creator.h",
+ "supervised_user/supervised_user_blacklist.cc",
+ "supervised_user/supervised_user_blacklist.h",
"supervised_user/supervised_user_constants.cc",
"supervised_user/supervised_user_constants.h",
"supervised_user/supervised_user_features.cc",
"supervised_user/supervised_user_features.h",
+ "supervised_user/supervised_user_filtering_switches.cc",
+ "supervised_user/supervised_user_filtering_switches.h",
"supervised_user/supervised_user_google_auth_navigation_throttle.cc",
"supervised_user/supervised_user_google_auth_navigation_throttle.h",
"supervised_user/supervised_user_interstitial.cc",
@@ -5207,6 +5413,20 @@ jumbo_static_library("browser") {
"supervised_user/legacy/custodian_profile_downloader_service_factory.h",
]
}
+ if (enable_supervised_users && enable_extensions) {
+ sources += [
+ "supervised_user/supervised_user_extensions_metrics_recorder.cc",
+ "supervised_user/supervised_user_extensions_metrics_recorder.h",
+ "supervised_user/supervised_user_service_management_api_delegate.cc",
+ "supervised_user/supervised_user_service_management_api_delegate.h",
+ ]
+ }
+ if (is_chromeos) {
+ sources += [
+ "supervised_user/child_accounts/secondary_account_consent_logger.cc",
+ "supervised_user/child_accounts/secondary_account_consent_logger.h",
+ ]
+ }
if (enable_vr) {
if (enable_gvr_services) {
@@ -5217,8 +5437,10 @@ jumbo_static_library("browser") {
if (is_win) {
sources += [
- "vr/service/xr_session_request_consent_manager_impl.cc",
- "vr/service/xr_session_request_consent_manager_impl.h",
+ "vr/consent/win_xr_consent_helper.cc",
+ "vr/consent/win_xr_consent_helper.h",
+ "vr/consent/xr_session_request_consent_manager_impl.cc",
+ "vr/consent/xr_session_request_consent_manager_impl.h",
"vr/ui_host/vr_ui_host_impl.cc",
"vr/ui_host/vr_ui_host_impl.h",
]
@@ -5226,12 +5448,31 @@ jumbo_static_library("browser") {
deps += [ "//device/vr/public/mojom" ]
}
+ if (!is_android) {
+ sources += [
+ "vr/service/isolated_device_provider.cc",
+ "vr/service/isolated_device_provider.h",
+ ]
+ }
+
sources += [
"component_updater/vr_assets_component_installer.cc",
"component_updater/vr_assets_component_installer.h",
+ "vr/chrome_xr_integration_client.cc",
+ "vr/chrome_xr_integration_client.h",
+ "vr/service/browser_xr_runtime_impl.cc",
+ "vr/service/browser_xr_runtime_impl.h",
+ "vr/service/vr_service_impl.cc",
+ "vr/service/vr_service_impl.h",
+ "vr/service/xr_runtime_manager_impl.cc",
+ "vr/service/xr_runtime_manager_impl.h",
+ "vr/xr_runtime_manager_statics.h",
]
- deps += [ "//chrome/browser/vr:vr_common" ]
+ deps += [
+ "//chrome/browser/vr:vr_common",
+ "//device/vr",
+ ]
}
if (enable_wayland_server) {
@@ -5284,6 +5525,10 @@ jumbo_static_library("browser") {
if (is_android && notouch_build) {
configs += [ ":notouch_config" ]
}
+
+ if (tpm_fallback) {
+ defines += [ "TPM_FALLBACK" ]
+ }
}
config("notouch_config") {
@@ -5292,27 +5537,19 @@ config("notouch_config") {
if (is_android) {
proto_library("client_discourse_context_proto") {
- sources = [
- "android/proto/client_discourse_context.proto",
- ]
+ sources = [ "android/proto/client_discourse_context.proto" ]
}
proto_library("delta_file_proto") {
- sources = [
- "android/proto/delta_file.proto",
- ]
+ sources = [ "android/proto/delta_file.proto" ]
}
proto_library("explore_sites_proto") {
- sources = [
- "android/explore_sites/catalog.proto",
- ]
+ sources = [ "android/explore_sites/catalog.proto" ]
}
proto_library("usage_stats_proto") {
- sources = [
- "android/usage_stats/website_event.proto",
- ]
+ sources = [ "android/usage_stats/website_event.proto" ]
}
}
@@ -5341,41 +5578,35 @@ source_set("active_use_util") {
deps = [
"//base",
"//chrome/common:constants",
+ "//chrome/install_static:buildflags",
]
- if (is_win) {
- deps += [ "//chrome/install_static:install_static_util" ]
- }
}
source_set("theme_properties") {
- sources = [
- "themes/theme_properties.h",
- ]
+ sources = [ "themes/theme_properties.h" ]
}
proto_library("availability_protos") {
- sources = [
- "availability/proto/availability_prober_cache_entry.proto",
- ]
+ sources = [ "availability/proto/availability_prober_cache_entry.proto" ]
+}
+
+proto_library("tab_state_db_content_proto") {
+ sources = [ "tab/state/tab_state_db_content.proto" ]
}
proto_library("resource_prefetch_predictor_proto") {
- sources = [
- "predictors/resource_prefetch_predictor.proto",
- ]
+ sources = [ "predictors/resource_prefetch_predictor.proto" ]
}
proto_library("permissions_proto") {
- sources = [
- "permissions/crowd_deny.proto",
- ]
+ sources = [ "permissions/crowd_deny.proto" ]
}
grit("resources") {
source = "browser_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
+ # Required due to flattenhtml="true" on a generated file.
+ enable_input_discovery_for_gn_analyze = false
use_brotli = true
@@ -5400,13 +5631,7 @@ grit("resources") {
deps = [
":chrome_internal_resources_gen",
- "//chrome/browser/engagement:mojo_bindings_js",
- "//chrome/browser/media:mojo_bindings_js",
"//chrome/browser/resources/browser_switch:app_module",
- "//chrome/browser/resources/ssl/ssl_error_assistant:make_ssl_error_assistant_protobuf",
- "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings_js",
- "//chrome/browser/ui/webui/interventions_internals:mojo_bindings_js",
- "//chrome/browser/ui/webui/omnibox:mojo_bindings_js",
"//chrome/browser/ui/webui/usb_internals:mojo_bindings_js",
"//device/bluetooth/public/mojom:deprecated_experimental_interfaces_js",
"//device/bluetooth/public/mojom:mojom_js",
@@ -5418,30 +5643,23 @@ grit("resources") {
if (enable_plugins) {
# .json is not in the default sources_assignment_filter.
if (is_chromeos) {
- inputs = [
- "resources/plugin_metadata/plugins_chromeos.json",
- ]
+ inputs = [ "resources/plugin_metadata/plugins_chromeos.json" ]
}
if (is_linux && !is_chromeos) {
- inputs = [
- "resources/plugin_metadata/plugins_linux.json",
- ]
+ inputs = [ "resources/plugin_metadata/plugins_linux.json" ]
}
if (is_mac) {
- inputs = [
- "resources/plugin_metadata/plugins_mac.json",
- ]
+ inputs = [ "resources/plugin_metadata/plugins_mac.json" ]
}
if (is_win) {
- inputs = [
- "resources/plugin_metadata/plugins_win.json",
- ]
+ inputs = [ "resources/plugin_metadata/plugins_win.json" ]
}
}
if (is_win || is_mac || is_desktop_linux || is_chromeos) {
deps += [
"//chrome/browser/resources/discards:discards_resources_gen",
+ "//chrome/browser/resources/gaia_auth_host:modulize",
"//chrome/browser/resources/management:polymer3_elements",
"//chrome/browser/resources/signin:polymer3_elements",
"//chrome/browser/ui/webui/discards:mojo_bindings_js",
@@ -5450,25 +5668,24 @@ grit("resources") {
}
if (is_android) {
- deps += [
- "//chrome/browser/ui/webui/explore_sites_internals:mojo_bindings_js",
- "//chrome/browser/ui/webui/feed_internals:mojo_bindings_js",
- "//chrome/browser/ui/webui/snippets_internals:mojo_bindings_js",
- ]
- } else {
- deps += [ "//chrome/browser/ui/webui/app_management:mojo_bindings_js" ]
+ deps +=
+ [ "//chrome/browser/ui/webui/explore_sites_internals:mojo_bindings_js" ]
}
-
if (is_chromeos) {
deps += [
"//chrome/browser/resources/chromeos/crostini_installer:polymer3_elements",
"//chrome/browser/resources/chromeos/crostini_upgrader:polymer3_elements",
+ "//chrome/browser/resources/chromeos/edu_login:polymer3_elements",
"//chrome/browser/resources/chromeos/emulator:polymer3_elements",
"//chrome/browser/resources/chromeos/set_time_dialog:polymer3_elements",
+ "//chrome/browser/resources/chromeos/smb_shares:polymer3_elements",
+ "//chrome/browser/supervised_user:supervised_user_unscaled_resources",
+ "//chrome/browser/ui/webui/app_management:mojo_bindings_js",
"//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings_js",
"//chrome/browser/ui/webui/chromeos/crostini_installer:mojo_bindings_js",
"//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings_js",
"//chrome/browser/ui/webui/chromeos/machine_learning:mojo_bindings_js",
+ "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings_js",
]
}
@@ -5480,11 +5697,6 @@ grit("resources") {
]
}
- if (safe_browsing_mode > 0) {
- deps +=
- [ "//chrome/browser/resources/safe_browsing:make_file_types_protobuf" ]
- }
-
if (safe_browsing_mode == 1) {
deps += [ "//chrome/browser/ui/webui/reset_password:mojo_bindings_js" ]
}
@@ -5493,12 +5705,8 @@ grit("resources") {
if (is_chrome_branded) {
action("chrome_internal_resources_gen") {
script = "internal/transform_additional_modules_list.py"
- sources = [
- "internal/resources/additional_modules_list.input",
- ]
- outputs = [
- additional_modules_list_file,
- ]
+ sources = [ "internal/resources/additional_modules_list.input" ]
+ outputs = [ additional_modules_list_file ]
args = rebase_path(sources, root_build_dir) +
rebase_path(outputs, root_build_dir)
}
@@ -5508,28 +5716,48 @@ if (is_chrome_branded) {
}
}
-action("expired_flags_list_gen") {
- script = "//tools/flags/generate_expired_list.py"
- sources = [
- "flag-metadata.json",
+grit("dev_ui_browser_resources") {
+ source = "dev_ui_browser_resources.grd"
+
+ defines = chrome_grit_defines
+
+ output_dir = "$root_gen_dir/chrome"
+ outputs = [
+ "grit/dev_ui_browser_resources.h",
+ "dev_ui_browser_resources.pak",
]
- inputs = [
- "//chrome/VERSION",
+
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
- outputs = [
- "$root_gen_dir/chrome/browser/expired_flags_list.cc",
+
+ deps = [
+ "//chrome/browser/engagement:mojo_bindings_js",
+ "//chrome/browser/media:mojo_bindings_js",
+ "//chrome/browser/media/feeds:mojo_bindings_js",
+ "//chrome/browser/ui/webui/interventions_internals:mojo_bindings_js",
]
+ if (is_android) {
+ deps += [
+ "//chrome/browser/ui/webui/feed_internals:mojo_bindings_js",
+ "//chrome/browser/ui/webui/snippets_internals:mojo_bindings_js",
+ ]
+ }
+}
+
+action("expired_flags_list_gen") {
+ script = "//tools/flags/generate_expired_list.py"
+ sources = [ "flag-metadata.json" ]
+ inputs = [ "//chrome/VERSION" ]
+ outputs = [ "$root_gen_dir/chrome/browser/expired_flags_list.cc" ]
args = rebase_path(sources, root_build_dir) +
rebase_path(outputs, root_build_dir)
}
source_set("expired_flags_list") {
- deps = [
- ":expired_flags_list_gen",
- ]
- sources = [
- "$root_gen_dir/chrome/browser/expired_flags_list.cc",
- ]
+ deps = [ ":expired_flags_list_gen" ]
+ sources = [ "$root_gen_dir/chrome/browser/expired_flags_list.cc" ]
}
# Use a static library here because many test binaries depend on this but don't
@@ -5593,8 +5821,6 @@ static_library("test_support") {
"notifications/notification_test_util.h",
"notifications/stub_notification_display_service.cc",
"notifications/stub_notification_display_service.h",
- "permissions/mock_permission_request.cc",
- "permissions/mock_permission_request.h",
"plugins/plugin_test_utils.cc",
"plugins/plugin_test_utils.h",
"policy/fake_browser_dm_token_storage.cc",
@@ -5644,7 +5870,7 @@ static_library("test_support") {
"//components/password_manager/core/browser:test_support",
"//components/policy/core/browser:test_support",
"//components/prefs:test_support",
- "//components/safe_browsing:csd_proto",
+ "//components/safe_browsing/core:csd_proto",
"//components/search_engines:test_support",
"//components/services/unzip/content",
"//components/sessions:test_support",
@@ -5700,6 +5926,8 @@ static_library("test_support") {
"sessions/session_service_test_helper.h",
"sessions/tab_loader_tester.cc",
"sessions/tab_loader_tester.h",
+ "sessions/tab_restore_service_load_waiter.cc",
+ "sessions/tab_restore_service_load_waiter.h",
"ui/tabs/tab_activity_simulator.cc",
"ui/tabs/tab_activity_simulator.h",
]
@@ -5719,6 +5947,8 @@ static_library("test_support") {
"chromeos/input_method/mock_input_method_engine.h",
"chromeos/input_method/mock_input_method_manager_impl.cc",
"chromeos/input_method/mock_input_method_manager_impl.h",
+ "chromeos/input_method/mock_suggestion_window_controller.cc",
+ "chromeos/input_method/mock_suggestion_window_controller.h",
"chromeos/login/screens/mock_device_disabled_screen_view.cc",
"chromeos/login/screens/mock_device_disabled_screen_view.h",
"chromeos/login/session/user_session_manager_test_api.cc",
@@ -5892,21 +6122,15 @@ if (!is_android) {
"//components/translate/content/common",
]
- public_deps = [
- "//net:test_support",
- ]
+ public_deps = [ "//net:test_support" ]
}
}
if (is_android) {
java_cpp_enum("sharing_send_message_result_generated_enum") {
- sources = [
- "sharing/sharing_send_message_result.h",
- ]
+ sources = [ "sharing/sharing_send_message_result.h" ]
}
java_cpp_enum("sharing_dialog_type_generated_enum") {
- sources = [
- "sharing/sharing_metrics.h",
- ]
+ sources = [ "sharing/sharing_metrics.h" ]
}
}
diff --git a/chromium/chrome/browser/accessibility/accessibility_extension_api_browsertest.cc b/chromium/chrome/browser/accessibility/accessibility_extension_api_browsertest.cc
index 74a925eddd5..f198952673a 100644
--- a/chromium/chrome/browser/accessibility/accessibility_extension_api_browsertest.cc
+++ b/chromium/chrome/browser/accessibility/accessibility_extension_api_browsertest.cc
@@ -23,9 +23,10 @@ IN_PROC_BROWSER_TEST_F(AccessibilityPrivateApiTest, SendSyntheticKeyEvent) {
<< message_;
}
-IN_PROC_BROWSER_TEST_F(AccessibilityPrivateApiTest, GetDisplayLanguageTest) {
+IN_PROC_BROWSER_TEST_F(AccessibilityPrivateApiTest,
+ GetDisplayNameForLocaleTest) {
ASSERT_TRUE(
- RunExtensionSubtest("accessibility_private/", "display_language.html"))
+ RunExtensionSubtest("accessibility_private/", "display_locale.html"))
<< message_;
}
diff --git a/chromium/chrome/browser/accessibility/accessibility_permission_context.cc b/chromium/chrome/browser/accessibility/accessibility_permission_context.cc
index b1c0c4f8c98..6c3a12172a3 100644
--- a/chromium/chrome/browser/accessibility/accessibility_permission_context.cc
+++ b/chromium/chrome/browser/accessibility/accessibility_permission_context.cc
@@ -4,9 +4,10 @@
#include "chrome/browser/accessibility/accessibility_permission_context.h"
-AccessibilityPermissionContext::AccessibilityPermissionContext(Profile* profile)
+AccessibilityPermissionContext::AccessibilityPermissionContext(
+ content::BrowserContext* browser_context)
: PermissionContextBase(
- profile,
+ browser_context,
ContentSettingsType::ACCESSIBILITY_EVENTS,
blink::mojom::FeaturePolicyFeature::kAccessibilityEvents) {}
diff --git a/chromium/chrome/browser/accessibility/accessibility_permission_context.h b/chromium/chrome/browser/accessibility/accessibility_permission_context.h
index c22e5bd6a57..35ff1332540 100644
--- a/chromium/chrome/browser/accessibility/accessibility_permission_context.h
+++ b/chromium/chrome/browser/accessibility/accessibility_permission_context.h
@@ -6,11 +6,13 @@
#define CHROME_BROWSER_ACCESSIBILITY_ACCESSIBILITY_PERMISSION_CONTEXT_H_
#include "base/macros.h"
-#include "chrome/browser/permissions/permission_context_base.h"
+#include "components/permissions/permission_context_base.h"
-class AccessibilityPermissionContext : public PermissionContextBase {
+class AccessibilityPermissionContext
+ : public permissions::PermissionContextBase {
public:
- explicit AccessibilityPermissionContext(Profile* profile);
+ explicit AccessibilityPermissionContext(
+ content::BrowserContext* browser_context);
~AccessibilityPermissionContext() override;
private:
diff --git a/chromium/chrome/browser/accessibility/accessibility_ui.cc b/chromium/chrome/browser/accessibility/accessibility_ui.cc
index 57d14748140..c77a24e895d 100644
--- a/chromium/chrome/browser/accessibility/accessibility_ui.cc
+++ b/chromium/chrome/browser/accessibility/accessibility_ui.cc
@@ -22,7 +22,7 @@
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/webui_url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/accessibility_tree_formatter.h"
@@ -222,8 +222,8 @@ void HandleAccessibilityRequestCallback(
content::WebContentsDelegate* delegate = web_contents->GetDelegate();
if (!delegate)
continue;
- // Ignore views that are never visible, like background pages.
- if (delegate->IsNeverVisible(web_contents))
+ // Ignore views that are never user-visible, like background pages.
+ if (delegate->IsNeverComposited(web_contents))
continue;
content::BrowserContext* context = rvh->GetProcess()->GetBrowserContext();
if (context != current_context)
@@ -360,7 +360,7 @@ AccessibilityUIObserver::~AccessibilityUIObserver() = default;
void AccessibilityUIObserver::AccessibilityEventReceived(
const content::AXEventNotificationDetails& details) {
- for (const ui::AXEvent event : details.events) {
+ for (const ui::AXEvent& event : details.events) {
event_logs_->push_back(event.ToString());
}
}
@@ -555,6 +555,8 @@ void AccessibilityUIMessageHandler::RequestWebContentsTree(
// because we are about to show the accessibility tree
web_contents->SetAccessibilityMode(
ui::AXMode(ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents));
+ // Enable AXMode to access to AX objects.
+ ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
std::vector<content::AccessibilityTreeFormatter::PropertyFilter>
property_filters;
diff --git a/chromium/chrome/browser/accessibility/caption_settings_dialog_win.cc b/chromium/chrome/browser/accessibility/caption_settings_dialog_win.cc
index acbbe5111fc..a1893fba4e8 100644
--- a/chromium/chrome/browser/accessibility/caption_settings_dialog_win.cc
+++ b/chromium/chrome/browser/accessibility/caption_settings_dialog_win.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/win/windows_version.h"
namespace {
@@ -26,9 +27,8 @@ void CaptionSettingsDialogCallback() {
namespace captions {
void CaptionSettingsDialog::ShowCaptionSettingsDialog() {
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(CaptionSettingsDialogCallback));
}
diff --git a/chromium/chrome/browser/accessibility/image_annotation_browsertest.cc b/chromium/chrome/browser/accessibility/image_annotation_browsertest.cc
index fc03b62b96d..b4dd6e1dcca 100644
--- a/chromium/chrome/browser/accessibility/image_annotation_browsertest.cc
+++ b/chromium/chrome/browser/accessibility/image_annotation_browsertest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind_helpers.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
diff --git a/chromium/chrome/browser/android/crypto/BUILD.gn b/chromium/chrome/browser/android/crypto/BUILD.gn
new file mode 100644
index 00000000000..1eeabe44342
--- /dev/null
+++ b/chromium/chrome/browser/android/crypto/BUILD.gn
@@ -0,0 +1,16 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+ deps = [
+ "//base:base_java",
+ "//content/public/android:content_java",
+ ]
+ sources = [
+ "java/src/org/chromium/chrome/browser/crypto/ByteArrayGenerator.java",
+ "java/src/org/chromium/chrome/browser/crypto/CipherFactory.java",
+ ]
+}
diff --git a/chromium/chrome/browser/android/lifecycle/BUILD.gn b/chromium/chrome/browser/android/lifecycle/BUILD.gn
new file mode 100644
index 00000000000..77d91994cbd
--- /dev/null
+++ b/chromium/chrome/browser/android/lifecycle/BUILD.gn
@@ -0,0 +1,22 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+ deps = [ "//third_party/android_deps:androidx_annotation_annotation_java" ]
+ sources = [
+ "java/src/org/chromium/chrome/browser/lifecycle/ActivityLifecycleDispatcher.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/ActivityResultWithNativeObserver.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/ConfigurationChangedObserver.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/Destroyable.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/InflationObserver.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/LifecycleObserver.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/NativeInitObserver.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/PauseResumeWithNativeObserver.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/StartStopWithNativeObserver.java",
+ "java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java",
+ ]
+}
diff --git a/chromium/chrome/browser/android/metrics/BUILD.gn b/chromium/chrome/browser/android/metrics/BUILD.gn
index f4698a607e8..d79c9ffb7ea 100644
--- a/chromium/chrome/browser/android/metrics/BUILD.gn
+++ b/chromium/chrome/browser/android/metrics/BUILD.gn
@@ -5,13 +5,11 @@
if (is_android) {
import("//build/config/android/rules.gni")
- _jni_java_files = [ "javatests/src/org/chromium/chrome/browser/metrics/util/UkmUtilsForTest.java" ]
+ _jni_sources = [ "javatests/src/org/chromium/chrome/browser/metrics/util/UkmUtilsForTest.java" ]
static_library("ukm_utils_for_test") {
testonly = true
- sources = [
- "ukm_utils_for_test.cc",
- ]
+ sources = [ "ukm_utils_for_test.cc" ]
deps = [
"//chrome/browser",
"//chrome/browser/android/metrics:jni_headers",
@@ -22,20 +20,18 @@ if (is_android) {
generate_jni("jni_headers") {
testonly = true
- sources = _jni_java_files
+ sources = _jni_sources
}
android_library("ukm_java_test_support") {
testonly = true
- java_files = _jni_java_files
- deps = [
- "//base:base_java",
- ]
+ sources = _jni_sources
+ deps = [ "//base:base_java" ]
}
android_library("ukm_javatests") {
testonly = true
- java_files =
+ sources =
[ "javatests/src/org/chromium/chrome/browser/metrics/UkmTest.java" ]
deps = [
diff --git a/chromium/chrome/browser/android/thin_webview/BUILD.gn b/chromium/chrome/browser/android/thin_webview/BUILD.gn
index b01c57b3e9c..e29fbc5ff1b 100644
--- a/chromium/chrome/browser/android/thin_webview/BUILD.gn
+++ b/chromium/chrome/browser/android/thin_webview/BUILD.gn
@@ -6,16 +6,12 @@ import("//build/config/android/config.gni")
import("//build/config/android/rules.gni")
source_set("thin_webview") {
- sources = [
- "compositor_view.h",
- ]
- public_deps = [
- "//base",
- ]
+ sources = [ "compositor_view.h" ]
+ public_deps = [ "//base" ]
}
android_library("java") {
- java_files = [
+ sources = [
"java/src/org/chromium/chrome/browser/thinwebview/CompositorView.java",
"java/src/org/chromium/chrome/browser/thinwebview/ThinWebView.java",
"java/src/org/chromium/chrome/browser/thinwebview/ThinWebViewConstraints.java",
@@ -23,13 +19,14 @@ android_library("java") {
deps = [
"//base:base_java",
+ "//components/embedder_support/android:web_contents_delegate_java",
"//content/public/android:content_java",
"//ui/android:ui_java",
]
}
android_library("factory_java") {
- java_files = [
+ sources = [
"java/src/org/chromium/chrome/browser/thinwebview/CompositorViewFactory.java",
"java/src/org/chromium/chrome/browser/thinwebview/ThinWebViewFactory.java",
]
diff --git a/chromium/chrome/browser/android/thin_webview/internal/BUILD.gn b/chromium/chrome/browser/android/thin_webview/internal/BUILD.gn
index 220ecc9d9f5..8ec4528a11e 100644
--- a/chromium/chrome/browser/android/thin_webview/internal/BUILD.gn
+++ b/chromium/chrome/browser/android/thin_webview/internal/BUILD.gn
@@ -16,19 +16,22 @@ static_library("internal") {
deps = [
":jni_headers",
"//cc",
+ "//chrome/browser/ui",
+ "//components/permissions",
"//skia",
]
public_deps = [
"//base",
"//chrome/browser/android/thin_webview",
+ "//components/embedder_support/android:web_contents_delegate",
"//content/public/browser",
"//ui/android",
]
}
android_library("internal_java") {
- java_files = [
+ sources = [
"java/src/org/chromium/chrome/browser/thinwebview/internal/CompositorViewImpl.java",
"java/src/org/chromium/chrome/browser/thinwebview/internal/ThinWebViewImpl.java",
]
@@ -37,6 +40,7 @@ android_library("internal_java") {
"//base:base_java",
"//base:jni_java",
"//chrome/browser/android/thin_webview:java",
+ "//components/embedder_support/android:web_contents_delegate_java",
"//content/public/android:content_java",
"//ui/android:ui_java",
]
diff --git a/chromium/chrome/browser/android/vr/BUILD.gn b/chromium/chrome/browser/android/vr/BUILD.gn
index 33261084f0a..34d55fd50dc 100644
--- a/chromium/chrome/browser/android/vr/BUILD.gn
+++ b/chromium/chrome/browser/android/vr/BUILD.gn
@@ -16,6 +16,8 @@ static_library("vr_android") {
sources = [
"android_ui_gesture_target.cc",
"android_ui_gesture_target.h",
+ "android_vr_utils.cc",
+ "android_vr_utils.h",
"android_vsync_helper.cc",
"android_vsync_helper.h",
"autocomplete_controller.cc",
@@ -25,12 +27,14 @@ static_library("vr_android") {
"cardboard_input_delegate.cc",
"cardboard_input_delegate.h",
"gl_browser_interface.h",
- "gvr_consent_helper_impl.cc",
- "gvr_consent_helper_impl.h",
+ "gvr_consent_helper.cc",
+ "gvr_consent_helper.h",
"gvr_graphics_delegate.cc",
"gvr_graphics_delegate.h",
"gvr_input_delegate.cc",
"gvr_input_delegate.h",
+ "gvr_install_helper.cc",
+ "gvr_install_helper.h",
"gvr_keyboard_delegate.cc",
"gvr_keyboard_delegate.h",
"gvr_keyboard_shim.cc",
@@ -72,6 +76,8 @@ static_library("vr_android") {
"arcore_device/ar_renderer.cc",
"arcore_device/ar_renderer.h",
"arcore_device/arcore.h",
+ "arcore_device/arcore_anchor_manager.cc",
+ "arcore_device/arcore_anchor_manager.h",
"arcore_device/arcore_consent_prompt.cc",
"arcore_device/arcore_consent_prompt.h",
"arcore_device/arcore_device.cc",
@@ -84,12 +90,17 @@ static_library("vr_android") {
"arcore_device/arcore_gl_thread.h",
"arcore_device/arcore_impl.cc",
"arcore_device/arcore_impl.h",
+ "arcore_device/arcore_install_helper.cc",
+ "arcore_device/arcore_install_helper.h",
"arcore_device/arcore_java_utils.cc",
"arcore_device/arcore_java_utils.h",
+ "arcore_device/arcore_plane_manager.cc",
+ "arcore_device/arcore_plane_manager.h",
"arcore_device/arcore_sdk.h",
"arcore_device/arcore_session_utils.h",
"arcore_device/arcore_shim.cc",
"arcore_device/arcore_shim.h",
+ "arcore_device/scoped_arcore_objects.h",
"arcore_device/type_converters.cc",
"arcore_device/type_converters.h",
]
@@ -104,8 +115,12 @@ static_library("vr_android") {
"//chrome/browser/vr:vr_common",
"//chrome/common",
"//chrome/common:constants",
+ "//components/browser_ui/util/android",
+ "//components/content_settings/core/browser",
"//components/language/core/browser",
"//components/omnibox/browser",
+ "//components/page_info",
+ "//components/permissions",
"//components/rappor",
"//components/search_engines:search_engines",
"//content/public/browser",
@@ -127,9 +142,7 @@ static_library("vr_android") {
deps += [ ":ar_jni_headers" ]
}
- public_deps = [
- "//device/vr/public/mojom",
- ]
+ public_deps = [ "//device/vr/public/mojom" ]
libs = [ "android" ]
@@ -145,12 +158,8 @@ static_library("vr_android") {
# The VR UI module factory interface.
source_set("ui_factory") {
- sources = [
- "ui_factory.h",
- ]
- deps = [
- "//chrome/browser/vr:vr_base",
- ]
+ sources = [ "ui_factory.h" ]
+ deps = [ "//chrome/browser/vr:vr_base" ]
}
# The default UI factory implementation, which simply instantiates an object.
@@ -188,13 +197,9 @@ source_set("ui_module_factory") {
# vr_android_with_factory).
group("module_factory") {
if (use_native_partitions) {
- deps = [
- ":ui_module_factory",
- ]
+ deps = [ ":ui_module_factory" ]
} else {
- deps = [
- ":ui_default_factory",
- ]
+ deps = [ ":ui_default_factory" ]
}
}
@@ -205,7 +210,7 @@ android_library("ar_java") {
"//third_party/arcore-android-sdk-client:com_google_ar_core_java",
]
- java_files = [ "//chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShimImpl.java" ]
+ sources = [ "//chrome/android/java/src/org/chromium/chrome/browser/vr/ArCoreShimImpl.java" ]
}
if (enable_arcore) {
@@ -219,16 +224,15 @@ if (enable_arcore) {
if (current_toolchain == default_toolchain) {
generate_jni_registration("jni_registration") {
- target = "//chrome/android:chrome_modern_public_bundle__vr_bundle_module"
+ targets =
+ [ "//chrome/android:chrome_modern_public_bundle__vr_bundle_module" ]
header_output = "$target_gen_dir/${target_name}.h"
namespace = "vr"
}
}
group("test_support") {
- public_deps = [
- ":ui_default_factory",
- ]
+ public_deps = [ ":ui_default_factory" ]
}
test("vr_android_unittests") {
@@ -251,7 +255,7 @@ test("vr_android_unittests") {
"//base/test:test_support",
"//chrome/browser",
"//components/translate/core/language_detection:language_detection",
- "//device/vr:fakes",
+ "//device/vr:vr_fakes",
"//device/vr/public/mojom",
"//mojo/core/embedder",
"//mojo/public/cpp/bindings",
@@ -259,6 +263,7 @@ test("vr_android_unittests") {
"//testing/android/native_test:native_test_native_code",
"//testing/gmock",
"//testing/gtest",
- "//ui/android:ui_java", # TODO: Remove once http://crbug.com/951419 is fixed!
+ "//ui/android:ui_java", # TODO: Remove once http://crbug.com/951419 is
+ # fixed!
]
}
diff --git a/chromium/chrome/browser/android/webapk/BUILD.gn b/chromium/chrome/browser/android/webapk/BUILD.gn
index 6bcd0ac4dc4..70409625e27 100644
--- a/chromium/chrome/browser/android/webapk/BUILD.gn
+++ b/chromium/chrome/browser/android/webapk/BUILD.gn
@@ -5,7 +5,5 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
- sources = [
- "webapk.proto",
- ]
+ sources = [ "webapk.proto" ]
}
diff --git a/chromium/chrome/browser/apps/BUILD.gn b/chromium/chrome/browser/apps/BUILD.gn
deleted file mode 100644
index 52efd75a06e..00000000000
--- a/chromium/chrome/browser/apps/BUILD.gn
+++ /dev/null
@@ -1,21 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//extensions/buildflags/buildflags.gni")
-
-# TODO(loyso): Remove this assertion. apps/ will be based off-extensions.
-assert(enable_extensions)
-
-source_set("apps") {
- sources = [
- "apps_launch.cc",
- "apps_launch.h",
- ]
-
- deps = [
- "//chrome/browser/apps/platform_apps",
- ]
-
- configs += [ "//build/config/compiler:wexit_time_destructors" ]
-}
diff --git a/chromium/chrome/browser/apps/app_shim/BUILD.gn b/chromium/chrome/browser/apps/app_shim/BUILD.gn
index ee6922e2f67..1a6daa7e73d 100644
--- a/chromium/chrome/browser/apps/app_shim/BUILD.gn
+++ b/chromium/chrome/browser/apps/app_shim/BUILD.gn
@@ -12,20 +12,20 @@ source_set("app_shim") {
"app_shim_host_mac.h",
"app_shim_listener.h",
"app_shim_listener.mm",
+ "app_shim_manager_mac.cc",
+ "app_shim_manager_mac.h",
"app_shim_termination_manager.cc",
"app_shim_termination_manager.h",
- "extension_app_shim_handler_mac.cc",
- "extension_app_shim_handler_mac.h",
"mach_bootstrap_acceptor.cc",
"mach_bootstrap_acceptor.h",
+ "web_app_shim_manager_delegate_mac.cc",
+ "web_app_shim_manager_delegate_mac.h",
]
deps = [
"//apps",
- "//chrome/browser/apps/platform_apps",
- "//chrome/browser/extensions",
+ "//chrome/browser/web_applications:web_applications_on_extensions",
"//chrome/browser/web_applications/components",
- "//chrome/browser/web_applications/extensions",
"//chrome/common",
"//chrome/common:app_mode_app_support",
"//chrome/common:constants",
@@ -36,8 +36,7 @@ source_set("app_shim") {
"//components/version_info",
"//content/public/browser",
"//content/public/common",
- "//extensions/browser",
- "//extensions/common",
+ "//services/preferences/public/cpp:cpp",
"//ui/views:views",
]
}
diff --git a/chromium/chrome/browser/apps/platform_apps/BUILD.gn b/chromium/chrome/browser/apps/platform_apps/BUILD.gn
index 37975f0e9c3..1ec39f4efe9 100644
--- a/chromium/chrome/browser/apps/platform_apps/BUILD.gn
+++ b/chromium/chrome/browser/apps/platform_apps/BUILD.gn
@@ -12,8 +12,6 @@ source_set("platform_apps") {
"app_load_service.h",
"app_load_service_factory.cc",
"app_load_service_factory.h",
- "app_shim_registry_mac.cc",
- "app_shim_registry_mac.h",
"app_termination_observer.cc",
"app_termination_observer.h",
"app_window_registry_util.cc",
@@ -24,6 +22,8 @@ source_set("platform_apps") {
"browser_context_keyed_service_factories.h",
"chrome_apps_browser_api_provider.cc",
"chrome_apps_browser_api_provider.h",
+ "extension_app_shim_manager_delegate_mac.cc",
+ "extension_app_shim_manager_delegate_mac.h",
"install_chrome_app.cc",
"install_chrome_app.h",
"platform_app_launch.cc",
@@ -48,6 +48,7 @@ source_set("platform_apps") {
"//chrome/app:command_ids",
"//chrome/browser/extensions",
"//chrome/browser/media/router/discovery",
+ "//chrome/browser/web_applications/components:components",
"//chrome/browser/web_applications/extensions",
"//chrome/common",
"//components/crx_file",
@@ -64,5 +65,9 @@ source_set("platform_apps") {
"//ui/gfx",
]
+ if (is_mac) {
+ deps += [ "//chrome/browser/apps/app_shim" ]
+ }
+
allow_circular_includes_from = [ "//chrome/browser/extensions" ]
}
diff --git a/chromium/chrome/browser/apps/platform_apps/api/BUILD.gn b/chromium/chrome/browser/apps/platform_apps/api/BUILD.gn
index de346538910..2e47c268cfe 100644
--- a/chromium/chrome/browser/apps/platform_apps/api/BUILD.gn
+++ b/chromium/chrome/browser/apps/platform_apps/api/BUILD.gn
@@ -59,9 +59,8 @@ source_set("api") {
"//extensions/browser",
]
- public_deps = [
- "//chrome/browser/apps/platform_apps/api/music_manager_private",
- ]
+ public_deps =
+ [ "//chrome/browser/apps/platform_apps/api/music_manager_private" ]
if (is_chromeos) {
sources += [
diff --git a/chromium/chrome/browser/browser_resources.grd b/chromium/chrome/browser/browser_resources.grd
index 1deaa699ca4..5544091d5eb 100644
--- a/chromium/chrome/browser/browser_resources.grd
+++ b/chromium/chrome/browser/browser_resources.grd
@@ -15,8 +15,8 @@
<if expr="not is_android">
<!-- New Tab Page WebUI. -->
<structure name="IDR_INCOGNITO_TAB_HTML" file="resources\ntp4\incognito_tab.html" compress="gzip" flattenhtml="true" type="chrome_html" />
+ <structure name="IDR_INCOGNITO_TAB_THEME_CSS" file="resources\ntp4\incognito_tab_theme.css" compress="gzip" flattenhtml="true" type="chrome_html" />
<structure name="IDR_GUEST_TAB_HTML" file="resources\ntp4\guest_tab.html" compress="gzip" flattenhtml="true" type="chrome_html" />
- <structure name="IDR_NEW_INCOGNITO_TAB_THEME_CSS" file="resources\ntp4\new_incognito_tab_theme.css" compress="gzip" flattenhtml="true" type="chrome_html" />
<structure name="IDR_NEW_TAB_4_HTML" file="resources\ntp4\new_tab.html" compress="gzip" flattenhtml="true" type="chrome_html" />
<structure name="IDR_NEW_TAB_4_THEME_CSS" file="resources\ntp4\new_tab_theme.css" compress="gzip" flattenhtml="true" type="chrome_html" />
@@ -38,6 +38,14 @@
<structure name="IDR_CUSTOM_ELEMENTS_LOGIN_JS" file="resources\chromeos\login\custom_elements_login.js" compress="gzip" flattenhtml="true" type="chrome_html" />
<structure name="IDR_ASSISTANT_OPTIN_HTML" file="resources\chromeos\assistant_optin\assistant_optin.html" compress="gzip" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
<structure name="IDR_ASSISTANT_OPTIN_JS" file="resources\chromeos\assistant_optin\assistant_optin.js" compress="gzip" flattenhtml="true" allowexternalscript="true" type="chrome_html" />
+
+ <!-- Gesture Navigation animations. -->
+ <structure type="chrome_html" name="IDR_GESTURE_NAVIGATION_GO_HOME_ANIMATION" file="resources\chromeos\login\images\gesture_go_home.json" compress="gzip" />
+ <structure type="chrome_html" name="IDR_GESTURE_NAVIGATION_GO_BACK_ANIMATION" file="resources\chromeos\login\images\gesture_go_back.json" compress="gzip" />
+ <structure type="chrome_html" name="IDR_GESTURE_NAVIGATION_HOTSEAT_OVERVIEW_ANIMATION" file="resources\chromeos\login\images\gesture_hotseat_overview.json" compress="gzip" />
+
+ <!-- Marketing Opt In animation. -->
+ <structure name="IDR_MARKETING_OPT_IN_ALL_SET_ANIMATION" file="resources\chromeos\login\images\all_set.json" compress="gzip" type="chrome_html" />
</if>
</structures>
<includes>
@@ -52,9 +60,10 @@
<include name="IDR_DISCARDS_LIFECYCLE_UNIT_STATE_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\resource_coordinator\lifecycle_unit_state.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
<include name="IDR_DISCARDS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\discards\discards.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
<include name="IDR_DISCARDS_MOJO_PUBLIC_BASE_PROCESS_ID_MOJOM_LITE_JS" file="${root_gen_dir}\mojo\public\mojom\base\process_id.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
+ <include name="IDR_DISCARDS_SITE_DATA_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\discards\site_data.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
<include name="IDR_DISCARDS_SORTED_TABLE_BEHAVIOR_JS" file="resources\discards\sorted_table_behavior.js" compress="gzip" type="BINDATA" />
</if>
- <if expr="is_win or is_macosx or (is_linux and not is_chromeos)">
+ <if expr="is_win or is_macosx or (is_linux and not chromeos)">
<include name="IDR_BROWSER_SWITCH_APP_JS" file="${root_gen_dir}\chrome\browser\resources\browser_switch\app.js" compress="gzip" use_base_dir="false" type="BINDATA" />
<include name="IDR_BROWSER_SWITCH_PROXY_JS" file="resources\browser_switch\browser_switch_proxy.js" compress="gzip" type="BINDATA" />
<include name="IDR_BROWSER_SWITCH_HTML" file="resources\browser_switch\browser_switch.html" compress="gzip" allowexternalscript="true" type="BINDATA" />
@@ -75,9 +84,6 @@
<include name="IDR_ABOUT_SYS_CSS" file="resources\about_sys\about_sys.css" compress="gzip" flattenhtml="true" type="BINDATA" />
<include name="IDR_ABOUT_SYS_JS" file="resources\about_sys\about_sys.js" compress="gzip" type="BINDATA" />
</if>
- <include name="IDR_ACCESSIBILITY_HTML" file="resources\accessibility\accessibility.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
- <include name="IDR_ACCESSIBILITY_CSS" file="resources\accessibility\accessibility.css" compress="gzip" type="BINDATA" />
- <include name="IDR_ACCESSIBILITY_JS" file="resources\accessibility\accessibility.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_AD_NETWORK_HASHES" file="resources\ad_networks.dat" type="BINDATA" />
<if expr="is_posix and not is_macosx">
<include name="IDR_CERTIFICATE_VIEWER_HTML" file="resources\certificate_viewer.html" compress="gzip" type="BINDATA" />
@@ -91,26 +97,6 @@
<include name="IDR_CLOUDPRINT_MANIFEST" file="resources\cloud_print_app\manifest.json" type="BINDATA" />
</if>
<include name="IDR_DEVTOOLS_DISCOVERY_PAGE_HTML" file="devtools\frontend\devtools_discovery_page.html" type="BINDATA" compress="gzip"/>
- <include name="IDR_DOMAIN_RELIABILITY_INTERNALS_HTML" file="resources\domain_reliability_internals\domain_reliability_internals.html" compress="gzip" type="BINDATA" />
- <include name="IDR_DOMAIN_RELIABILITY_INTERNALS_CSS" file="resources\domain_reliability_internals\domain_reliability_internals.css" compress="gzip" type="BINDATA" />
- <include name="IDR_DOMAIN_RELIABILITY_INTERNALS_JS" file="resources\domain_reliability_internals\domain_reliability_internals.js" compress="gzip" type="BINDATA" />
- <if expr="safe_browsing_mode != 0">
- <include name="IDR_DOWNLOAD_FILE_TYPES_PB" file="${root_gen_dir}\chrome\browser\resources\safe_browsing\download_file_types.pb" use_base_dir="false" type="BINDATA" />
- </if>
- <include name="IDR_DOWNLOAD_INTERNALS_HTML" file="resources\download_internals\download_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_DOWNLOAD_INTERNALS_CSS" file="resources\download_internals\download_internals.css" type="BINDATA" compress="gzip" />
- <include name="IDR_DOWNLOAD_INTERNALS_JS" file="resources\download_internals\download_internals.js" type="BINDATA" compress="gzip" />
- <include name="IDR_DOWNLOAD_INTERNALS_BROWSER_PROXY_JS" file="resources\download_internals\download_internals_browser_proxy.js" type="BINDATA" compress="gzip" />
- <include name="IDR_DOWNLOAD_INTERNALS_VISUALS_JS" file="resources\download_internals\download_internals_visuals.js" type="BINDATA" compress="gzip" />
- <include name="IDR_NOTIFICATIONS_INTERNALS_HTML" file="resources\notifications_internals\notifications_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_NOTIFICATIONS_INTERNALS_CSS" file="resources\notifications_internals\notifications_internals.css" type="BINDATA" compress="gzip" />
- <include name="IDR_NOTIFICATIONS_INTERNALS_JS" file="resources\notifications_internals\notifications_internals.js" type="BINDATA" compress="gzip" />
- <include name="IDR_NOTIFICATIONS_INTERNALS_BROWSER_PROXY_JS" file="resources\notifications_internals\notifications_internals_browser_proxy.js" type="BINDATA" compress="gzip" />
- <include name="IDR_UKM_INTERNALS_HTML" file="../../components/ukm/debug/ukm_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
- <include name="IDR_UKM_INTERNALS_JS" file="../../components/ukm/debug/ukm_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
- <include name="IDR_UKM_INTERNALS_CSS" file="../../components/ukm/debug/ukm_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
- <include name="IDR_TRANSLATE_INTERNALS_HTML" file="../../components/translate/translate_internals/translate_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
- <include name="IDR_TRANSLATE_INTERNALS_JS" file="../../components/translate/translate_internals/translate_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
<include name="IDR_FEEDBACK_MANIFEST" file="resources\feedback\manifest.json" type="BINDATA" />
<if expr="is_android">
<include name="IDR_DEV_UI_LOADER_ERROR_HTML" file="resources/dev_ui/dev_ui_loader_error.html" compress="gzip" type="BINDATA" />
@@ -118,24 +104,18 @@
<include name="IDR_EXPLORE_SITES_INTERNALS_CSS" file="resources\explore_sites_internals\explore_sites_internals.css" compress="gzip" type="BINDATA" />
<include name="IDR_EXPLORE_SITES_INTERNALS_JS" file="resources\explore_sites_internals\explore_sites_internals.js" compress="gzip" type="BINDATA" />
<include name="IDR_EXPLORE_SITES_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\explore_sites_internals\explore_sites_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
- <include name="IDR_FEED_INTERNALS_HTML" file="resources\feed_internals\feed_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
- <include name="IDR_FEED_INTERNALS_CSS" file="resources\feed_internals\feed_internals.css" allowexternalscript="true" compress="gzip" type="BINDATA" />
- <include name="IDR_FEED_INTERNALS_JS" file="resources\feed_internals\feed_internals.js" compress="gzip" type="BINDATA" />
- <include name="IDR_FEED_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\feed_internals\feed_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_OFFLINE_INTERNALS_HTML" file="resources\offline_pages\offline_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
<include name="IDR_OFFLINE_INTERNALS_CSS" file="resources\offline_pages\offline_internals.css" type="BINDATA" compress="gzip" />
<include name="IDR_OFFLINE_INTERNALS_JS" file="resources\offline_pages\offline_internals.js" type="BINDATA" compress="gzip" />
<include name="IDR_OFFLINE_INTERNALS_BROWSER_PROXY_JS" file="resources\offline_pages\offline_internals_browser_proxy.js" type="BINDATA" compress="gzip" />
- <include name="IDR_SNIPPETS_INTERNALS_HTML" file="resources\snippets_internals\snippets_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
- <include name="IDR_SNIPPETS_INTERNALS_CSS" file="resources\snippets_internals\snippets_internals.css" compress="gzip" type="BINDATA" />
- <include name="IDR_SNIPPETS_INTERNALS_JS" file="resources\snippets_internals\snippets_internals.js" compress="gzip" type="BINDATA" />
- <include name="IDR_SNIPPETS_INTERNALS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\snippets_internals\snippets_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ </if>
+
+ <if expr="not is_android">
+ <!-- New Tab Page -->
+ <part file="resources/local_ntp/icons.grdp" />
</if>
<if expr="enable_supervised_users">
- <include name="IDR_SUPERVISED_USER_INTERNALS_HTML" file="resources\supervised_user_internals\supervised_user_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
- <include name="IDR_SUPERVISED_USER_INTERNALS_CSS" file="resources\supervised_user_internals\supervised_user_internals.css" compress="gzip" type="BINDATA" />
- <include name="IDR_SUPERVISED_USER_INTERNALS_JS" file="resources\supervised_user_internals\supervised_user_internals.js" compress="gzip" type="BINDATA" />
<part file="resources/supervised_user_error_page_resources.grdp" />
</if>
@@ -148,26 +128,13 @@
<include name="IDR_HANGOUT_SERVICES_MANIFEST" file="resources\hangout_services\manifest.json" type="BINDATA" />
</if>
- <!-- App Management. -->
- <if expr="chromeos">
- <include name="IDR_APP_MANAGEMENT_BITMAP_MOJO_LITE_JS" file="${root_gen_dir}\skia\public\mojom\bitmap.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
- <include name="IDR_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS" file="${root_gen_dir}\skia\public\mojom\image_info.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
- <include name="IDR_APP_MANAGEMENT_IMAGE_MOJO_LITE_JS" file="${root_gen_dir}\ui\gfx\image\mojom\image.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
- <include name="IDR_APP_MANAGEMENT_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\app_management\app_management.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
- <include name="IDR_APP_MANAGEMENT_TYPES_MOJO_LITE_JS" file="${root_gen_dir}\chrome\services\app_service\public\mojom\types.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
-
- <include name="IDR_APP_MANAGEMENT_APP_HTML" file="resources\app_management\app.html" compress="gzip" type="BINDATA" />
- <include name="IDR_APP_MANAGEMENT_APP_JS" file="resources\app_management\app.js" compress="gzip" type="BINDATA" />
- <include name="IDR_APP_MANAGEMENT_EXPANDABLE_APP_LIST_HTML" file="resources\app_management\expandable_app_list.html" compress="gzip" type="BINDATA" />
- <include name="IDR_APP_MANAGEMENT_EXPANDABLE_APP_LIST_JS" file="resources\app_management\expandable_app_list.js" compress="gzip" type="BINDATA" />
- <include name="IDR_APP_MANAGEMENT_INDEX_HTML" file="resources\app_management\index.html" compress="gzip" type="BINDATA" />
- </if>
-
<if expr="not is_android">
<!-- Page not available for guest. -->
<include name="IDR_PAGE_NOT_AVAILABLE_FOR_GUEST_APP_HTML" file="resources\page_not_available_for_guest\app.html" type="BINDATA" />
</if>
+ <include name="IDR_CHROME_URLS_DISABLED_PAGE_HTML" file="resources\chrome_urls_disabled_page\app.html" type="BINDATA" />
+
<include name="IDR_IDENTITY_API_SCOPE_APPROVAL_MANIFEST" file="resources\identity_scope_approval_dialog\manifest.json" type="BINDATA" />
<include name="IDR_INLINE_LOGIN_HTML" file="resources\inline_login\inline_login.html" compress="gzip" flattenhtml="true" allowexternalscript="true" type="BINDATA" preprocess="true" />
@@ -179,13 +146,7 @@
<include name="IDR_INSPECT_HTML" file="resources\inspect\inspect.html" compress="gzip" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_INSPECT_JS" file="resources\inspect\inspect.js" compress="gzip" flattenhtml="true" type="BINDATA" />
- <include name="IDR_INTERVENTIONS_INTERNALS_INDEX_HTML" file="resources\interventions_internals\index.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
- <include name="IDR_INTERVENTIONS_INTERNALS_INDEX_JS" file="resources\interventions_internals\index.js" type="BINDATA" compress="gzip" />
- <include name="IDR_INTERVENTIONS_INTERNALS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\interventions_internals\interventions_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
- <include name="IDR_INTERVENTIONS_INTERNALS_UNSUPPORTED_PAGE_HTML" file="resources\interventions_internals\unsupported_page.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
<include name="IDR_NETWORK_SPEECH_SYNTHESIS_MANIFEST" file="resources\network_speech_synthesis\manifest.json" type="BINDATA" />
- <include name="IDR_PREDICTORS_HTML" file="resources\predictors\predictors.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_PREDICTORS_JS" file="resources\predictors\predictors.js" flattenhtml="true" type="BINDATA" compress="gzip" />
<if expr="enable_service_discovery">
<include name="IDR_LOCAL_DISCOVERY_HTML" file="resources\local_discovery\local_discovery.html" compress="gzip" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
@@ -193,14 +154,8 @@
<include name="IDR_LOCAL_DISCOVERY_JS" file="resources\local_discovery\local_discovery.js" compress="gzip" flattenhtml="true" type="BINDATA" />
</if>
- <include name="IDR_LOCAL_STATE_HTML" file="resources\local_state\local_state.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_LOCAL_STATE_JS" file="resources\local_state\local_state.js" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
<include name="IDR_DESKTOP_HATS_HTML" file="resources\hats\hats.html" type="BINDATA" />
<include name="IDR_ORIGIN_MOJO_JS" file="${root_gen_dir}\url\mojom\origin.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip"/>
- <include name="IDR_COMPONENTS_COMPONENTS_HTML" file="resources\components\components.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_COMPONENTS_COMPONENTS_JS" file="resources\components\components.js" type="BINDATA" compress="gzip" />
- <include name="IDR_MEMORY_INTERNALS_HTML" file="resources\memory_internals\memory_internals.html" flattenhtml="true" type="BINDATA" compress="gzip" />
- <include name="IDR_MEMORY_INTERNALS_JS" file="resources\memory_internals\memory_internals.js" type="BINDATA" compress="gzip" />
<if expr="enable_plugins">
<include name="IDR_PDF_MANIFEST" file="resources\pdf\manifest.json" type="BINDATA" />
</if>
@@ -222,13 +177,10 @@
<include name="IDR_MANAGEMENT_BROWSER_PROXY_JS" file="resources\management\management_browser_proxy.js" type="BINDATA" compress="gzip" preprocess="true" />
<include name="IDR_MANAGEMENT_ICONS_JS" file="${root_gen_dir}/chrome/browser/resources/management/icons.js" use_base_dir="false" type="BINDATA" compress="gzip" preprocess="true" />
</if>
- <include name="IDR_SITE_ENGAGEMENT_HTML" file="resources\engagement\site_engagement.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_SITE_ENGAGEMENT_JS" file="resources\engagement\site_engagement.js" flattenhtml="true" type="BINDATA" compress="gzip" />
- <include name="IDR_SITE_ENGAGEMENT_DETAILS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\engagement\site_engagement_details.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_URL_MOJOM_LITE_JS" file="${root_gen_dir}\url\mojom\url.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
<if expr="is_win or is_macosx or desktop_linux or chromeos">
- <include name="IDR_SYNC_DISABLED_CONFIRMATION_HTML" file="resources\signin\sync_confirmation\sync_disabled_confirmation.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
- <include name="IDR_SYNC_DISABLED_CONFIRMATION_JS" file="resources\signin\sync_confirmation\sync_disabled_confirmation.js" type="BINDATA" />
+ <include name="IDR_SYNC_DISABLED_CONFIRMATION_HTML" file="resources\signin\sync_confirmation\sync_disabled_confirmation.html" type="BINDATA" />
+ <include name="IDR_SYNC_DISABLED_CONFIRMATION_APP_JS" file="${root_gen_dir}\chrome\browser\resources\signin\sync_confirmation\sync_disabled_confirmation_app.js" use_base_dir="false" preprocess="true" type="BINDATA" />
<include name="IDR_SYNC_CONFIRMATION_HTML" file="resources\signin\sync_confirmation\sync_confirmation.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_SYNC_CONFIRMATION_JS" file="resources\signin\sync_confirmation\sync_confirmation.js" type="BINDATA" />
<include name="IDR_SYNC_CONFIRMATION_BROWSER_PROXY_JS" file="resources\signin\sync_confirmation\sync_confirmation_browser_proxy.js" type="BINDATA" />
@@ -239,8 +191,10 @@
<if expr="is_win or is_macosx or desktop_linux">
<include name="IDR_SIGNIN_EMAIL_CONFIRMATION_HTML" file="resources\signin\signin_email_confirmation\signin_email_confirmation.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_SIGNIN_EMAIL_CONFIRMATION_APP_JS" file="${root_gen_dir}\chrome\browser\resources\signin\signin_email_confirmation\signin_email_confirmation_app.js" use_base_dir="false" preprocess="true" type="BINDATA" />
- <include name="IDR_SIGNIN_ERROR_HTML" file="resources\signin\signin_error\signin_error.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
+ <include name="IDR_SIGNIN_ERROR_HTML" file="resources\signin\signin_error\signin_error.html" type="BINDATA" />
<include name="IDR_SIGNIN_ERROR_JS" file="resources\signin\signin_error\signin_error.js" type="BINDATA" />
+ <include name="IDR_SIGNIN_ERROR_APP_HTML" file="resources\signin\signin_error\signin_error_app.html" preprocess="true" type="BINDATA" />
+ <include name="IDR_SIGNIN_ERROR_APP_JS" file="resources\signin\signin_error\signin_error_app.js" type="BINDATA" />
</if>
<include name="IDR_USB_ENUMERATION_OPTIONS_MOJOM_LITE_JS" file="${root_gen_dir}\services\device\public\mojom\usb_enumeration_options.mojom-lite.js" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
<include name="IDR_USB_DEVICE_MANAGER_CLIENT_MOJOM_LITE_JS" file="${root_gen_dir}\services\device\public\mojom\usb_manager_client.mojom-lite.js" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
@@ -261,6 +215,22 @@
<include name="IDR_BLUETOOTH_PAIRING_DIALOG_JS" file="resources\chromeos\bluetooth_pairing_dialog\bluetooth_pairing_dialog.js" type="chrome_html" />
</else>
</if>
+ <!-- Edu account login resources -->
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_HTML" file="resources\chromeos\edu_login\edu_login.html" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\app.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_UTIL_JS" file="resources\chromeos\edu_login\edu_login_util.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_EDU_LOGIN_BROWSER_PROXY_JS" file="resources\chromeos\edu_login\browser_proxy.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_EDU_LOGIN_ICONS_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\icons.js" use_base_dir="false" type ="BINDATA" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_BUTTON_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\edu_login_button.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_TEMPLATE_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\edu_login_template.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_CSS_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\edu_login_css.js" use_base_dir="false" type ="BINDATA" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_WELCOME_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\edu_login_welcome.js" use_base_dir="false" type ="BINDATA" compress="gzip" preprocess="true" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_PARENTS_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\edu_login_parents.js" use_base_dir="false" type ="BINDATA" compress="gzip" preprocess="true" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_PARENT_SIGNIN_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\edu_login_parent_signin.js" use_base_dir="false" type ="BINDATA" compress="gzip" preprocess="true" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_PARENT_INFO_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\edu_login_parent_info.js" use_base_dir="false" type ="BINDATA" compress="gzip" preprocess="true" />
+ <include name="IDR_EDU_LOGIN_EDU_LOGIN_SIGNIN_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\edu_login\edu_login_signin.js" use_base_dir="false" type ="BINDATA" compress="gzip" />
+ <include name="IDR_FAMILY_LINK_LOGO_SVG" file="resources\chromeos\family_link_logo.svg" type="BINDATA" compress="gzip" />
+
<!-- Chrome OS Account Manager welcome screen resources -->
<include name="IDR_ACCOUNT_MANAGER_SHARED_CSS" file="resources\chromeos\account_manager_shared.css" type="BINDATA" compress="gzip" />
<include name="IDR_ACCOUNT_MANAGER_WELCOME_HTML" file="resources\chromeos\account_manager_welcome.html" allowexternalscript="true" type="BINDATA" compress="gzip" preprocess="true"/>
@@ -290,7 +260,7 @@
<include name="IDR_CROSTINI_INSTALLER_APP_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\crostini_installer\app.js" compress="gzip" type="BINDATA" use_base_dir="false" />
<include name="IDR_CROSTINI_INSTALLER_BROWSER_PROXY_JS" file="resources\chromeos\crostini_installer\browser_proxy.js" compress="gzip" type="BINDATA" />
<include name="IDR_CROSTINI_INSTALLER_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\chromeos\crostini_installer\crostini_installer.mojom-lite.js" use_base_dir="false" compress="gzip" type="BINDATA" />
- <include name="IDR_CROSTINI_INSTALLER_TYPES_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\chromeos\crostini\crostini_installer_types.mojom-lite.js" use_base_dir="false" compress="gzip" type="BINDATA" />
+ <include name="IDR_CROSTINI_INSTALLER_TYPES_MOJO_LITE_JS" file="${root_gen_dir}\chrome\browser\chromeos\crostini\crostini_types.mojom-lite.js" use_base_dir="false" compress="gzip" type="BINDATA" />
<include name="IDR_CROSTINI_UPGRADER_INDEX_HTML" file="resources\chromeos\crostini_upgrader\index.html" compress="gzip" type="BINDATA" />
<include name="IDR_CROSTINI_UPGRADER_APP_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\crostini_upgrader\app.js" compress="gzip" type="BINDATA" use_base_dir="false" />
<include name="IDR_CROSTINI_UPGRADER_BROWSER_PROXY_JS" file="resources\chromeos\crostini_upgrader\browser_proxy.js" compress="gzip" type="BINDATA" />
@@ -328,7 +298,7 @@
<include name="IDR_INTERNET_DETAIL_DIALOG_JS" file="resources\chromeos\internet_detail_dialog\internet_detail_dialog.js" type="chrome_html" />
</else>
</if>
- <include name="IDR_CERT_MANAGER_DIALOG_HTML" file="resources\chromeos\certificate_manager_dialog.html" flattenhtml="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_CERT_MANAGER_DIALOG_HTML" file="resources\chromeos\certificate_manager_dialog.html" type="BINDATA" compress="gzip" />
<include name="IDR_SLOW_CSS" file="resources\chromeos\slow.css" type="BINDATA" compress="gzip" />
<include name="IDR_SLOW_HTML" file="resources\chromeos\slow.html" type="BINDATA" compress="gzip" />
<include name="IDR_SLOW_JS" file="resources\chromeos\slow.js" type="BINDATA" compress="gzip" />
@@ -367,9 +337,6 @@
<include name="IDR_IDENTITY_INTERNALS_CSS" file="resources\identity_internals\identity_internals.css" compress="gzip" type="BINDATA" />
<include name="IDR_IDENTITY_INTERNALS_JS" file="resources\identity_internals\identity_internals.js" compress="gzip" type="BINDATA" />
</if>
- <include name="IDR_DEVICE_LOG_UI_HTML" file="resources\device_log_ui\device_log_ui.html" type="BINDATA" compress="gzip" />
- <include name="IDR_DEVICE_LOG_UI_JS" file="resources\device_log_ui\device_log_ui.js" type="BINDATA" compress="gzip" />
- <include name="IDR_DEVICE_LOG_UI_CSS" file="resources\device_log_ui\device_log_ui.css" type="BINDATA" compress="gzip" />
<if expr="chromeos">
<include name="IDR_NETWORK_UI_HTML" file="resources\chromeos\network_ui\network_ui.html" compress="gzip" type="BINDATA" />
<include name="IDR_NETWORK_UI_JS" file="resources\chromeos\network_ui\network_ui.js" compress="gzip" type="BINDATA" />
@@ -456,26 +423,12 @@
<include name="IDR_IME_WINDOW_CLOSE_C" file="resources\input_ime\ime_window_close_click.png" type="BINDATA" />
<include name="IDR_IME_WINDOW_CLOSE_H" file="resources\input_ime\ime_window_close_hover.png" type="BINDATA" />
</if>
- <include name="IDR_SSL_ERROR_ASSISTANT_PB" file="${root_gen_dir}/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.pb" use_base_dir="false" type="BINDATA" compress="gzip" />
- <if expr="is_android or is_linux">
- <include name="IDR_SANDBOX_INTERNALS_HTML" file="resources\sandbox_internals\sandbox_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_SANDBOX_INTERNALS_JS" file="resources\sandbox_internals\sandbox_internals.js" type="BINDATA" compress="gzip" />
- </if>
- <if expr="is_win">
- <include name="IDR_SANDBOX_INTERNALS_HTML" file="resources\sandbox_internals\sandbox_internals.html" preprocess="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_SANDBOX_INTERNALS_JS" file="resources\sandbox_internals\sandbox_internals_win.js" type="BINDATA" compress="gzip" />
- </if>
- <include name="IDR_MEDIA_ENGAGEMENT_HTML" file="resources\media\media_engagement.html" flattenhtml="true" type="BINDATA" compress="gzip" allowexternalscript="true" />
- <include name="IDR_MEDIA_ENGAGEMENT_JS" file="resources\media\media_engagement.js" flattenhtml="true" type="BINDATA" compress="gzip" />
- <include name="IDR_MEDIA_ENGAGEMENT_SCORE_DETAILS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\media\media_engagement_score_details.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_PWA_HTML" file="resources\pwa.html" type="BINDATA" />
<if expr="chromeos">
<include name="IDR_SMB_SHARES_DIALOG_CONTAINER_HTML" file="resources\chromeos\smb_shares\smb_share_dialog_container.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="chrome_html" />
- <include name="IDR_SMB_SHARES_DIALOG_HTML" file="resources\chromeos\smb_shares\smb_share_dialog.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="chrome_html" />
- <include name="IDR_SMB_SHARES_DIALOG_JS" file="resources\chromeos\smb_shares\smb_share_dialog.js" compress="gzip" type="chrome_html" />
+ <include name="IDR_SMB_SHARES_DIALOG_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\smb_shares\smb_share_dialog.js" use_base_dir="false" compress="gzip" type="chrome_html" />
<include name="IDR_SMB_CREDENTIALS_DIALOG_CONTAINER_HTML" file="resources\chromeos\smb_shares\smb_credentials_dialog_container.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="chrome_html" />
- <include name="IDR_SMB_CREDENTIALS_DIALOG_HTML" file="resources\chromeos\smb_shares\smb_credentials_dialog.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="chrome_html" />
- <include name="IDR_SMB_CREDENTIALS_DIALOG_JS" file="resources\chromeos\smb_shares\smb_credentials_dialog.js" compress="gzip" type="chrome_html" />
+ <include name="IDR_SMB_CREDENTIALS_DIALOG_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\smb_shares\smb_credentials_dialog.js" use_base_dir="false" compress="gzip" type="BINDATA" />
<include name="IDR_SYS_INTERNALS_HTML" file="resources\chromeos\sys_internals\index.html" compress="gzip" type="BINDATA" />
<include name="IDR_SYS_INTERNALS_CSS" file="resources\chromeos\sys_internals\index.css" compress="gzip" type="BINDATA" />
<include name="IDR_SYS_INTERNALS_JS" file="resources\chromeos\sys_internals\index.js" compress="gzip" type="BINDATA" />
@@ -495,8 +448,14 @@
<include name="IDR_ADD_SUPERVISION_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\chromeos\add_supervision\add_supervision.mojom-lite.js" compress="gzip" use_base_dir="false" type="BINDATA" />
</if>
<if expr="chromeos">
+ <!-- OOBE / Login resources -->
<include name="IDR_ASSISTANT_LOGO_PNG" file="resources\chromeos\assistant_optin\assistant_logo.png" type="BINDATA" />
<include name="IDR_SUPERVISION_ICON_PNG" file="resources\chromeos\supervision\supervision_icon.png" type="BINDATA" />
+
+ <if expr="_google_chrome">
+ <!-- ARC Apps dowloading animation. -->
+ <include name="IDR_OOBE_ARC_APPS_DOWNLOADING_VIDEO" file="internal\resources\arc_support\videos\app_downloading.mp4" type="BINDATA" />
+ </if>
</if>
<if expr="safe_browsing_mode == 1">
<include name="IDR_RESET_PASSWORD_HTML" file="resources\reset_password\reset_password.html" type="BINDATA" compress="gzip" />
diff --git a/chromium/chrome/browser/browser_switcher/bho/BUILD.gn b/chromium/chrome/browser/browser_switcher/bho/BUILD.gn
index 66a05b4e65c..56203fe8755 100644
--- a/chromium/chrome/browser/browser_switcher/bho/BUILD.gn
+++ b/chromium/chrome/browser/browser_switcher/bho/BUILD.gn
@@ -70,9 +70,7 @@ shared_library("browser_switcher_bho") {
"resource.h",
]
}
- deps = [
- ":ie_bho_idl",
- ]
+ deps = [ ":ie_bho_idl" ]
}
test("browser_switcher_bho_unittests") {
@@ -88,60 +86,53 @@ test("browser_switcher_bho_unittests") {
]
}
-if (is_clang) {
- browser_switcher_x64_toolchain = "//build/toolchain/win:win_clang_x64"
- browser_switcher_x86_toolchain = "//build/toolchain/win:win_clang_x86"
-} else {
- browser_switcher_x64_toolchain = "//build/toolchain/win:x64"
- browser_switcher_x86_toolchain = "//build/toolchain/win:x86"
-}
-
+assert(is_clang)
browser_switcher_x64_label =
- ":browser_switcher_bho($browser_switcher_x64_toolchain)"
-browser_switcher_x86_label =
- ":browser_switcher_bho($browser_switcher_x86_toolchain)"
-
-copy("copy_browser_switcher_binaries") {
- # Make sure we have both bitnesses in the root out directory.
- if (target_cpu == "x86") {
- cross_build_label = browser_switcher_x64_label
- cross_build_dll = "browser_switcher_bho_64.dll"
- } else if (target_cpu == "x64") {
- cross_build_label = browser_switcher_x86_label
- cross_build_dll = "browser_switcher_bho.dll"
- }
-
- cross_build_out_dir = get_label_info(cross_build_label, "root_out_dir")
-
- sources = [
- "$cross_build_out_dir/$cross_build_dll",
- ]
- if (symbol_level > 0) {
- sources += [ "$cross_build_out_dir/$cross_build_dll.pdb" ]
+ ":browser_switcher_bho(//build/toolchain/win:win_clang_x64)"
+
+if (!is_asan) {
+ browser_switcher_x86_label =
+ ":browser_switcher_bho(//build/toolchain/win:win_clang_x86)"
+
+ copy("copy_browser_switcher_binaries") {
+ # Make sure we have both bitnesses in the root out directory.
+ if (target_cpu == "x86") {
+ cross_build_label = browser_switcher_x64_label
+ cross_build_dll = "browser_switcher_bho_64.dll"
+ } else if (target_cpu == "x64") {
+ cross_build_label = browser_switcher_x86_label
+ cross_build_dll = "browser_switcher_bho.dll"
+ }
+
+ cross_build_out_dir = get_label_info(cross_build_label, "root_out_dir")
+
+ sources = [ "$cross_build_out_dir/$cross_build_dll" ]
+ if (symbol_level > 0) {
+ sources += [ "$cross_build_out_dir/$cross_build_dll.pdb" ]
+ }
+
+ outputs = [ "$root_out_dir/{{source_file_part}}" ]
+ deps = [
+ browser_switcher_x64_label,
+ browser_switcher_x86_label,
+ ]
}
-
- outputs = [
- "$root_out_dir/{{source_file_part}}",
- ]
- deps = [
- browser_switcher_x64_label,
- browser_switcher_x86_label,
- ]
}
group("browser_switcher_dlls") {
# Build a DLL for each bitness, and put them in the root out dir.
- deps = [
- ":copy_browser_switcher_binaries",
- browser_switcher_x64_label,
- browser_switcher_x86_label,
- ]
+ # Asan builds only support 64-bit builds, so don't do this there.
+ deps = [ browser_switcher_x64_label ]
+ if (!is_asan) {
+ deps += [
+ ":copy_browser_switcher_binaries",
+ browser_switcher_x86_label,
+ ]
+ }
}
midl("ie_bho_idl") {
- sources = [
- "ie_bho_idl.idl",
- ]
+ sources = [ "ie_bho_idl.idl" ]
# We have a custom output directory (that excludes the toolchain details).
generated_dir =
diff --git a/chromium/chrome/browser/buildflags.gni b/chromium/chrome/browser/buildflags.gni
index db389b34b7c..16404b08165 100644
--- a/chromium/chrome/browser/buildflags.gni
+++ b/chromium/chrome/browser/buildflags.gni
@@ -4,4 +4,5 @@
declare_args() {
enable_kaleidoscope = false
+ tpm_fallback = false
}
diff --git a/chromium/chrome/browser/chrome_notification_types.h b/chromium/chrome/browser/chrome_notification_types.h
index 5acdb9e037a..6518315e146 100644
--- a/chromium/chrome/browser/chrome_notification_types.h
+++ b/chromium/chrome/browser/chrome_notification_types.h
@@ -197,11 +197,6 @@ enum NotificationType {
NOTIFICATION_TAB_DRAG_LOOP_DONE,
#endif
- // Sent when the CaptivePortalService checks if we're behind a captive portal.
- // The Source is the Profile the CaptivePortalService belongs to, and the
- // Details are a Details<CaptivePortalService::CheckResults>.
- NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
-
// Sent when the applications in the NTP app launcher have been reordered.
// The details, if not NoDetails, is the std::string ID of the extension that
// was moved.
diff --git a/chromium/chrome/browser/chromeos/BUILD.gn b/chromium/chrome/browser/chromeos/BUILD.gn
index 7e17fab96c1..94294ae0a10 100644
--- a/chromium/chrome/browser/chromeos/BUILD.gn
+++ b/chromium/chrome/browser/chromeos/BUILD.gn
@@ -29,6 +29,7 @@ source_set("chromeos") {
"//chrome/app/theme:chrome_unscaled_resources",
"//chrome/app/theme:theme_resources",
"//chrome/browser/chromeos/power/ml:user_activity_ukm_logger_helpers",
+ "//chromeos/components/security_token_pin",
"//chromeos/dbus:anomaly_detector_proto",
"//chromeos/dbus:cicerone_proto",
"//chromeos/dbus:concierge_proto",
@@ -62,6 +63,7 @@ source_set("chromeos") {
"//apps",
"//ash",
"//ash/public/cpp",
+ "//ash/public/mojom",
"//ash/system/message_center/arc",
"//build:branding_buildflags",
"//chrome/app:command_ids",
@@ -73,10 +75,12 @@ source_set("chromeos") {
"//chrome/browser/chromeos/power/ml/smart_dim",
"//chrome/browser/devtools",
"//chrome/browser/extensions",
+ "//chrome/browser/image_decoder",
"//chrome/browser/resource_coordinator:tab_metrics_event_proto",
- "//chrome/browser/ssl:proto",
"//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings",
+ "//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings",
"//chrome/browser/web_applications",
+ "//chrome/browser/web_applications:common",
"//chrome/browser/web_applications:web_applications_on_extensions",
"//chrome/browser/web_applications/components",
"//chrome/browser/web_applications/extensions:extensions",
@@ -85,7 +89,9 @@ source_set("chromeos") {
"//chrome/common/string_matching",
"//chrome/services/app_service:lib",
"//chrome/services/app_service/public/cpp:app_update",
+ "//chrome/services/app_service/public/cpp:instance_update",
"//chrome/services/file_util/public/cpp",
+ "//chrome/services/keymaster/public/mojom",
"//chrome/services/printing/public/mojom",
"//chrome/services/wilco_dtc_supportd/public/mojom",
"//chromeos",
@@ -95,12 +101,20 @@ source_set("chromeos") {
"//chromeos/components/account_manager",
"//chromeos/components/drivefs",
"//chromeos/components/drivefs/mojom",
+ "//chromeos/components/help_app_ui",
+ "//chromeos/components/media_app_ui",
"//chromeos/components/mojo_bootstrap",
"//chromeos/components/multidevice",
"//chromeos/components/multidevice/logging",
"//chromeos/components/power",
+ "//chromeos/components/print_management/mojom",
"//chromeos/components/proximity_auth",
+ "//chromeos/components/quick_answers/public/cpp:prefs",
+ "//chromeos/components/smbfs",
+ "//chromeos/components/smbfs/mojom",
+ "//chromeos/components/sync_wifi",
"//chromeos/components/tether",
+ "//chromeos/constants",
"//chromeos/cryptohome",
"//chromeos/dbus",
"//chromeos/dbus:metrics_event_proto",
@@ -132,6 +146,8 @@ source_set("chromeos") {
"//chromeos/dbus/session_manager",
"//chromeos/dbus/session_manager:login_manager_proto",
"//chromeos/dbus/system_clock",
+ "//chromeos/dbus/system_proxy",
+ "//chromeos/dbus/system_proxy:system_proxy_proto",
"//chromeos/dbus/upstart",
"//chromeos/disks",
"//chromeos/geolocation",
@@ -156,6 +172,7 @@ source_set("chromeos") {
"//chromeos/services/multidevice_setup/public/cpp:auth_token_validator",
"//chromeos/services/multidevice_setup/public/cpp:oobe_completion_tracker",
"//chromeos/services/multidevice_setup/public/cpp:prefs",
+ "//chromeos/services/network_config:in_process_instance",
"//chromeos/services/secure_channel",
"//chromeos/services/secure_channel/public/cpp/client",
"//chromeos/settings",
@@ -165,13 +182,14 @@ source_set("chromeos") {
"//components/arc",
"//components/arc/media_session",
"//components/arc/mojom:mojom_traits",
+ "//components/autofill/core/browser",
"//components/browser_sync",
- "//components/captive_portal",
+ "//components/captive_portal/core",
"//components/component_updater:crl_set_remover",
"//components/consent_auditor:consent_auditor",
"//components/constrained_window",
"//components/content_settings/core/browser",
- "//components/crash/content/app",
+ "//components/crash/core/app",
"//components/crx_file",
"//components/device_event_log",
"//components/download/content/public",
@@ -199,19 +217,22 @@ source_set("chromeos") {
"//components/ownership",
"//components/password_manager/core/browser",
"//components/password_manager/core/browser:hash_password_manager",
+ "//components/performance_manager",
+ "//components/permissions",
"//components/policy:generated",
"//components/policy/core/browser",
"//components/policy/core/common",
"//components/policy/core/common:common_constants",
"//components/pref_registry",
+ "//components/prefs",
"//components/printing/common:mojo_interfaces",
"//components/proxy_config",
"//components/quirks",
"//components/rappor",
"//components/renderer_context_menu",
"//components/rlz",
- "//components/safe_browsing:csd_proto",
- "//components/safe_browsing/db:metadata_proto",
+ "//components/safe_browsing/core:csd_proto",
+ "//components/safe_browsing/core/db:metadata_proto",
"//components/session_manager/core",
"//components/signin/public/identity_manager",
"//components/signin/public/webdata",
@@ -223,6 +244,7 @@ source_set("chromeos") {
"//components/tracing:startup_tracing",
"//components/translate/core/browser",
"//components/ukm/content",
+ "//components/unified_consent",
"//components/user_manager",
"//components/vector_icons",
@@ -248,6 +270,7 @@ source_set("chromeos") {
"//gpu/ipc/host",
"//gpu/ipc/service",
"//media",
+ "//media/capture:capture_switches",
"//media/mojo/mojom",
"//mojo/public/cpp/platform",
"//mojo/public/cpp/system",
@@ -262,8 +285,6 @@ source_set("chromeos") {
"//services/device/public/cpp/usb",
"//services/device/public/mojom",
"//services/device/public/mojom:usb",
- "//services/identity/public/cpp:cpp_types",
- "//services/identity/public/mojom",
"//services/metrics/public/cpp:ukm_builders",
"//services/preferences/public/mojom",
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
@@ -274,6 +295,7 @@ source_set("chromeos") {
"//third_party/blink/public/common",
"//third_party/cacheinvalidation",
"//third_party/icu",
+ "//third_party/libaddressinput",
"//third_party/libipp",
"//third_party/metrics_proto",
"//third_party/protobuf:protobuf_lite",
@@ -311,14 +333,13 @@ source_set("chromeos") {
"//ui/wm/public",
"//url",
]
- data_deps = [
- ":dbus_service_files",
- ]
+ data_deps = [ ":dbus_service_files" ]
allow_circular_includes_from = [
"//chrome/browser/extensions",
"//chrome/browser/apps/platform_apps/api",
"//chrome/browser/web_applications",
+ "//chrome/browser/web_applications:common",
"//chrome/browser/web_applications/components",
]
@@ -358,6 +379,8 @@ source_set("chromeos") {
"account_manager/account_manager_util.h",
"account_manager/account_migration_runner.cc",
"account_manager/account_migration_runner.h",
+ "account_manager/child_account_type_changed_user_data.cc",
+ "account_manager/child_account_type_changed_user_data.h",
"android_sms/android_sms_app_manager.cc",
"android_sms/android_sms_app_manager.h",
"android_sms/android_sms_app_manager_impl.cc",
@@ -455,6 +478,8 @@ source_set("chromeos") {
"apps/intent_helper/chromeos_apps_navigation_throttle.h",
"apps/intent_helper/common_apps_navigation_throttle.cc",
"apps/intent_helper/common_apps_navigation_throttle.h",
+ "apps/metrics/intent_handling_metrics.cc",
+ "apps/metrics/intent_handling_metrics.h",
"arc/accessibility/accessibility_info_data_wrapper.cc",
"arc/accessibility/accessibility_info_data_wrapper.h",
"arc/accessibility/accessibility_node_info_data_wrapper.cc",
@@ -467,6 +492,8 @@ source_set("chromeos") {
"arc/accessibility/arc_accessibility_util.h",
"arc/accessibility/ax_tree_source_arc.cc",
"arc/accessibility/ax_tree_source_arc.h",
+ "arc/accessibility/geometry_util.cc",
+ "arc/accessibility/geometry_util.h",
"arc/app_shortcuts/arc_app_shortcut_item.cc",
"arc/app_shortcuts/arc_app_shortcut_item.h",
"arc/app_shortcuts/arc_app_shortcuts_menu_builder.cc",
@@ -519,10 +546,16 @@ source_set("chromeos") {
"arc/enterprise/cert_store/arc_cert_store_bridge.h",
"arc/enterprise/cert_store/arc_smart_card_manager_bridge.cc",
"arc/enterprise/cert_store/arc_smart_card_manager_bridge.h",
+ "arc/enterprise/cert_store/security_token_operation_bridge.cc",
+ "arc/enterprise/cert_store/security_token_operation_bridge.h",
"arc/extensions/arc_support_message_host.cc",
"arc/extensions/arc_support_message_host.h",
"arc/file_system_watcher/arc_file_system_watcher_service.cc",
"arc/file_system_watcher/arc_file_system_watcher_service.h",
+ "arc/file_system_watcher/arc_file_system_watcher_util.cc",
+ "arc/file_system_watcher/arc_file_system_watcher_util.h",
+ "arc/file_system_watcher/file_system_scanner.cc",
+ "arc/file_system_watcher/file_system_scanner.h",
"arc/fileapi/arc_content_file_system_async_file_util.cc",
"arc/fileapi/arc_content_file_system_async_file_util.h",
"arc/fileapi/arc_content_file_system_backend_delegate.cc",
@@ -600,6 +633,10 @@ source_set("chromeos") {
"arc/intent_helper/open_with_menu.h",
"arc/intent_helper/start_smart_selection_action_menu.cc",
"arc/intent_helper/start_smart_selection_action_menu.h",
+ "arc/keymaster/arc_keymaster_bridge.cc",
+ "arc/keymaster/arc_keymaster_bridge.h",
+ "arc/keymaster/cert_store_bridge.cc",
+ "arc/keymaster/cert_store_bridge.h",
"arc/kiosk/arc_kiosk_bridge.cc",
"arc/kiosk/arc_kiosk_bridge.h",
"arc/metrics/arc_metrics_service_proxy.cc",
@@ -715,6 +752,8 @@ source_set("chromeos") {
"attestation/tpm_challenge_key.h",
"attestation/tpm_challenge_key_result.cc",
"attestation/tpm_challenge_key_result.h",
+ "attestation/tpm_challenge_key_subtle.cc",
+ "attestation/tpm_challenge_key_subtle.h",
"attestation/tpm_challenge_key_with_timeout.cc",
"attestation/tpm_challenge_key_with_timeout.h",
"authpolicy/authpolicy_credentials_manager.cc",
@@ -743,6 +782,10 @@ source_set("chromeos") {
"camera_detector.h",
"camera_presence_notifier.cc",
"camera_presence_notifier.h",
+ "cert_provisioning/cert_provisioning_common.cc",
+ "cert_provisioning/cert_provisioning_common.h",
+ "cert_provisioning/cert_provisioning_worker.cc",
+ "cert_provisioning/cert_provisioning_worker.h",
"certificate_provider/certificate_info.cc",
"certificate_provider/certificate_info.h",
"certificate_provider/certificate_provider.h",
@@ -789,18 +832,35 @@ source_set("chromeos") {
"child_accounts/time_limit_notifier.h",
"child_accounts/time_limit_override.cc",
"child_accounts/time_limit_override.h",
+ "child_accounts/time_limits/app_activity_registry.cc",
+ "child_accounts/time_limits/app_activity_registry.h",
+ "child_accounts/time_limits/app_activity_report_interface.cc",
+ "child_accounts/time_limits/app_activity_report_interface.h",
"child_accounts/time_limits/app_service_wrapper.cc",
"child_accounts/time_limits/app_service_wrapper.h",
"child_accounts/time_limits/app_time_controller.cc",
"child_accounts/time_limits/app_time_controller.h",
+ "child_accounts/time_limits/app_time_limit_interface.cc",
+ "child_accounts/time_limits/app_time_limit_interface.h",
+ "child_accounts/time_limits/app_time_limit_utils.cc",
+ "child_accounts/time_limits/app_time_limit_utils.h",
+ "child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.cc",
+ "child_accounts/time_limits/app_time_limits_whitelist_policy_wrapper.h",
+ "child_accounts/time_limits/app_time_notification_delegate.h",
+ "child_accounts/time_limits/app_time_policy_helpers.cc",
+ "child_accounts/time_limits/app_time_policy_helpers.h",
"child_accounts/time_limits/app_types.cc",
"child_accounts/time_limits/app_types.h",
+ "child_accounts/time_limits/persisted_app_info.cc",
+ "child_accounts/time_limits/persisted_app_info.h",
+ "child_accounts/time_limits/web_time_activity_provider.cc",
+ "child_accounts/time_limits/web_time_activity_provider.h",
"child_accounts/time_limits/web_time_limit_enforcer.cc",
"child_accounts/time_limits/web_time_limit_enforcer.h",
- "child_accounts/time_limits/web_time_limit_interface.cc",
- "child_accounts/time_limits/web_time_limit_interface.h",
"child_accounts/time_limits/web_time_limit_navigation_throttle.cc",
"child_accounts/time_limits/web_time_limit_navigation_throttle.h",
+ "child_accounts/time_limits/web_time_navigation_observer.cc",
+ "child_accounts/time_limits/web_time_navigation_observer.h",
"child_accounts/usage_time_limit_processor.cc",
"child_accounts/usage_time_limit_processor.h",
"child_accounts/usage_time_state_notifier.cc",
@@ -815,16 +875,12 @@ source_set("chromeos") {
"crostini/ansible/ansible_management_service.h",
"crostini/ansible/ansible_management_service_factory.cc",
"crostini/ansible/ansible_management_service_factory.h",
- "crostini/ansible/ansible_management_util.cc",
- "crostini/ansible/ansible_management_util.h",
- "crostini/ansible/pending_software_changes.cc",
- "crostini/ansible/pending_software_changes.h",
- "crostini/ansible/software_config.cc",
- "crostini/ansible/software_config.h",
+ "crostini/crostini_disk.cc",
+ "crostini/crostini_disk.h",
"crostini/crostini_export_import.cc",
"crostini/crostini_export_import.h",
- "crostini/crostini_export_import_notification.cc",
- "crostini/crostini_export_import_notification.h",
+ "crostini/crostini_export_import_notification_controller.cc",
+ "crostini/crostini_export_import_notification_controller.h",
"crostini/crostini_export_import_status_tracker.cc",
"crostini/crostini_export_import_status_tracker.h",
"crostini/crostini_features.cc",
@@ -847,16 +903,16 @@ source_set("chromeos") {
"crostini/crostini_package_operation_status.h",
"crostini/crostini_package_service.cc",
"crostini/crostini_package_service.h",
+ "crostini/crostini_port_forwarder.cc",
+ "crostini/crostini_port_forwarder.h",
"crostini/crostini_pref_names.cc",
"crostini/crostini_pref_names.h",
- "crostini/crostini_registry_service.cc",
- "crostini/crostini_registry_service.h",
- "crostini/crostini_registry_service_factory.cc",
- "crostini/crostini_registry_service_factory.h",
"crostini/crostini_remover.cc",
"crostini/crostini_remover.h",
"crostini/crostini_reporting_util.cc",
"crostini/crostini_reporting_util.h",
+ "crostini/crostini_shelf_utils.cc",
+ "crostini/crostini_shelf_utils.h",
"crostini/crostini_simple_types.h",
"crostini/crostini_terminal.cc",
"crostini/crostini_terminal.h",
@@ -913,6 +969,8 @@ source_set("chromeos") {
"dbus/metrics_event_service_provider.h",
"dbus/plugin_vm_service_provider.cc",
"dbus/plugin_vm_service_provider.h",
+ "dbus/printers_service_provider.cc",
+ "dbus/printers_service_provider.h",
"dbus/proxy_resolution_service_provider.cc",
"dbus/proxy_resolution_service_provider.h",
"dbus/screen_lock_service_provider.cc",
@@ -954,6 +1012,8 @@ source_set("chromeos") {
"extensions/dictionary_event_router.h",
"extensions/extension_tab_util_delegate_chromeos.cc",
"extensions/extension_tab_util_delegate_chromeos.h",
+ "extensions/extensions_permissions_tracker.cc",
+ "extensions/extensions_permissions_tracker.h",
"extensions/external_cache.cc",
"extensions/external_cache.h",
"extensions/external_cache_delegate.h",
@@ -979,6 +1039,8 @@ source_set("chromeos") {
"extensions/permissions_updater_delegate_chromeos.h",
"extensions/public_session_permission_helper.cc",
"extensions/public_session_permission_helper.h",
+ "extensions/signin_screen_extensions_external_loader.cc",
+ "extensions/signin_screen_extensions_external_loader.h",
"extensions/signin_screen_policy_provider.cc",
"extensions/signin_screen_policy_provider.h",
"external_metrics.cc",
@@ -1171,6 +1233,10 @@ source_set("chromeos") {
"first_run/steps/tray_step.h",
"guest_os/guest_os_pref_names.cc",
"guest_os/guest_os_pref_names.h",
+ "guest_os/guest_os_registry_service.cc",
+ "guest_os/guest_os_registry_service.h",
+ "guest_os/guest_os_registry_service_factory.cc",
+ "guest_os/guest_os_registry_service_factory.h",
"guest_os/guest_os_share_path.cc",
"guest_os/guest_os_share_path.h",
"guest_os/guest_os_share_path_factory.cc",
@@ -1185,6 +1251,8 @@ source_set("chromeos") {
"idle_detector.h",
"input_method/accessibility.cc",
"input_method/accessibility.h",
+ "input_method/assistive_suggester.cc",
+ "input_method/assistive_suggester.h",
"input_method/browser_state_monitor.cc",
"input_method/browser_state_monitor.h",
"input_method/candidate_window_controller.cc",
@@ -1193,6 +1261,8 @@ source_set("chromeos") {
"input_method/candidate_window_controller_impl.h",
"input_method/component_extension_ime_manager_impl.cc",
"input_method/component_extension_ime_manager_impl.h",
+ "input_method/emoji_suggester.cc",
+ "input_method/emoji_suggester.h",
"input_method/ime_service_connector.cc",
"input_method/ime_service_connector.h",
"input_method/input_method_configuration.cc",
@@ -1209,6 +1279,14 @@ source_set("chromeos") {
"input_method/input_method_syncer.h",
"input_method/native_input_method_engine.cc",
"input_method/native_input_method_engine.h",
+ "input_method/personal_info_suggester.cc",
+ "input_method/personal_info_suggester.h",
+ "input_method/suggester.h",
+ "input_method/suggestion_enums.h",
+ "input_method/suggestion_window_controller.cc",
+ "input_method/suggestion_window_controller.h",
+ "input_method/suggestion_window_controller_impl.cc",
+ "input_method/suggestion_window_controller_impl.h",
"kerberos/kerberos_credentials_manager.cc",
"kerberos/kerberos_credentials_manager.h",
"kerberos/kerberos_credentials_manager_factory.cc",
@@ -1357,6 +1435,8 @@ source_set("chromeos") {
"login/login_screen_extensions_storage_cleaner.cc",
"login/login_screen_extensions_storage_cleaner.h",
"login/login_wizard.h",
+ "login/marketing_backend_connector.cc",
+ "login/marketing_backend_connector.h",
"login/mojo_system_info_dispatcher.cc",
"login/mojo_system_info_dispatcher.h",
"login/oobe_configuration.cc",
@@ -1429,6 +1509,8 @@ source_set("chromeos") {
"login/screens/fingerprint_setup_screen.h",
"login/screens/gaia_screen.cc",
"login/screens/gaia_screen.h",
+ "login/screens/gesture_navigation_screen.cc",
+ "login/screens/gesture_navigation_screen.h",
"login/screens/hid_detection_screen.cc",
"login/screens/hid_detection_screen.h",
"login/screens/kiosk_autolaunch_screen.cc",
@@ -1474,12 +1556,14 @@ source_set("chromeos") {
"login/security_token_pin_dialog_host_ash_impl.h",
"login/session/chrome_session_manager.cc",
"login/session/chrome_session_manager.h",
+ "login/session/user_session_initializer.cc",
+ "login/session/user_session_initializer.h",
"login/session/user_session_manager.cc",
"login/session/user_session_manager.h",
- "login/signin/auth_sync_observer.cc",
- "login/signin/auth_sync_observer.h",
- "login/signin/auth_sync_observer_factory.cc",
- "login/signin/auth_sync_observer_factory.h",
+ "login/signin/auth_error_observer.cc",
+ "login/signin/auth_error_observer.h",
+ "login/signin/auth_error_observer_factory.cc",
+ "login/signin/auth_error_observer_factory.h",
"login/signin/merge_session_navigation_throttle.cc",
"login/signin/merge_session_navigation_throttle.h",
"login/signin/merge_session_throttling_utils.cc",
@@ -1590,6 +1674,8 @@ source_set("chromeos") {
"login/users/supervised_user_manager.h",
"login/users/supervised_user_manager_impl.cc",
"login/users/supervised_user_manager_impl.h",
+ "login/users/test_users.cc",
+ "login/users/test_users.h",
"login/users/user_manager_interface.h",
"login/version_info_updater.cc",
"login/version_info_updater.h",
@@ -1619,6 +1705,8 @@ source_set("chromeos") {
"net/delay_network_call.h",
"net/dhcp_wpad_url_client.cc",
"net/dhcp_wpad_url_client.h",
+ "net/network_health.cc",
+ "net/network_health.h",
"net/network_portal_detector_impl.cc",
"net/network_portal_detector_impl.h",
"net/network_portal_detector_test_impl.cc",
@@ -1649,33 +1737,39 @@ source_set("chromeos") {
"ownership/owner_settings_service_chromeos.h",
"ownership/owner_settings_service_chromeos_factory.cc",
"ownership/owner_settings_service_chromeos_factory.h",
+ "platform_keys/extension_platform_keys_service.cc",
+ "platform_keys/extension_platform_keys_service.h",
+ "platform_keys/extension_platform_keys_service_factory.cc",
+ "platform_keys/extension_platform_keys_service_factory.h",
"platform_keys/key_permissions.cc",
"platform_keys/key_permissions.h",
"platform_keys/key_permissions_policy_handler.cc",
"platform_keys/key_permissions_policy_handler.h",
- "platform_keys/platform_keys.cc",
- "platform_keys/platform_keys.h",
- "platform_keys/platform_keys_nss.cc",
"platform_keys/platform_keys_service.cc",
"platform_keys/platform_keys_service.h",
"platform_keys/platform_keys_service_factory.cc",
"platform_keys/platform_keys_service_factory.h",
+ "platform_keys/platform_keys_service_nss.cc",
+ "plugin_vm/plugin_vm_drive_image_download_service.cc",
+ "plugin_vm/plugin_vm_drive_image_download_service.h",
"plugin_vm/plugin_vm_engagement_metrics_service.cc",
"plugin_vm/plugin_vm_engagement_metrics_service.h",
"plugin_vm/plugin_vm_files.cc",
"plugin_vm/plugin_vm_files.h",
"plugin_vm/plugin_vm_image_download_client.cc",
"plugin_vm/plugin_vm_image_download_client.h",
- "plugin_vm/plugin_vm_image_manager.cc",
- "plugin_vm/plugin_vm_image_manager.h",
- "plugin_vm/plugin_vm_image_manager_factory.cc",
- "plugin_vm/plugin_vm_image_manager_factory.h",
+ "plugin_vm/plugin_vm_installer.cc",
+ "plugin_vm/plugin_vm_installer.h",
+ "plugin_vm/plugin_vm_installer_factory.cc",
+ "plugin_vm/plugin_vm_installer_factory.h",
"plugin_vm/plugin_vm_manager.cc",
"plugin_vm/plugin_vm_manager.h",
"plugin_vm/plugin_vm_metrics_util.cc",
"plugin_vm/plugin_vm_metrics_util.h",
"plugin_vm/plugin_vm_pref_names.cc",
"plugin_vm/plugin_vm_pref_names.h",
+ "plugin_vm/plugin_vm_uninstaller_notification.cc",
+ "plugin_vm/plugin_vm_uninstaller_notification.h",
"plugin_vm/plugin_vm_util.cc",
"plugin_vm/plugin_vm_util.h",
"policy/active_directory_join_delegate.h",
@@ -1724,8 +1818,6 @@ source_set("chromeos") {
"policy/component_active_directory_policy_service.h",
"policy/configuration_policy_handler_chromeos.cc",
"policy/configuration_policy_handler_chromeos.h",
- "policy/device_account_initializer.cc",
- "policy/device_account_initializer.h",
"policy/device_auto_update_time_restrictions_decoder.cc",
"policy/device_auto_update_time_restrictions_decoder.h",
"policy/device_auto_update_time_restrictions_utils.cc",
@@ -1777,8 +1869,6 @@ source_set("chromeos") {
"policy/enrollment_config.h",
"policy/enrollment_handler_chromeos.cc",
"policy/enrollment_handler_chromeos.h",
- "policy/enrollment_status_chromeos.cc",
- "policy/enrollment_status_chromeos.h",
"policy/external_data_handlers/cloud_external_data_policy_handler.cc",
"policy/external_data_handlers/cloud_external_data_policy_handler.h",
"policy/external_data_handlers/crostini_ansible_playbook_external_data_handler.cc",
@@ -1811,6 +1901,8 @@ source_set("chromeos") {
"policy/login_profile_policy_provider.h",
"policy/minimum_version_policy_handler.cc",
"policy/minimum_version_policy_handler.h",
+ "policy/minimum_version_policy_handler_delegate_impl.cc",
+ "policy/minimum_version_policy_handler_delegate_impl.h",
"policy/network_configuration_updater.cc",
"policy/network_configuration_updater.h",
"policy/off_hours/device_off_hours_controller.cc",
@@ -1827,6 +1919,8 @@ source_set("chromeos") {
"policy/policy_oauth2_token_fetcher.h",
"policy/policy_pref_names.cc",
"policy/policy_pref_names.h",
+ "policy/powerwash_requirements_checker.cc",
+ "policy/powerwash_requirements_checker.h",
"policy/pre_signin_policy_fetcher.cc",
"policy/pre_signin_policy_fetcher.h",
"policy/remote_commands/affiliated_remote_commands_invalidator.cc",
@@ -1835,12 +1929,18 @@ source_set("chromeos") {
"policy/remote_commands/crd_host_delegate.h",
"policy/remote_commands/device_command_fetch_status_job.cc",
"policy/remote_commands/device_command_fetch_status_job.h",
+ "policy/remote_commands/device_command_get_available_routines_job.cc",
+ "policy/remote_commands/device_command_get_available_routines_job.h",
+ "policy/remote_commands/device_command_get_routine_update_job.cc",
+ "policy/remote_commands/device_command_get_routine_update_job.h",
"policy/remote_commands/device_command_reboot_job.cc",
"policy/remote_commands/device_command_reboot_job.h",
"policy/remote_commands/device_command_refresh_machine_certificate_job.cc",
"policy/remote_commands/device_command_refresh_machine_certificate_job.h",
"policy/remote_commands/device_command_remote_powerwash_job.cc",
"policy/remote_commands/device_command_remote_powerwash_job.h",
+ "policy/remote_commands/device_command_run_routine_job.cc",
+ "policy/remote_commands/device_command_run_routine_job.h",
"policy/remote_commands/device_command_screenshot_job.cc",
"policy/remote_commands/device_command_screenshot_job.h",
"policy/remote_commands/device_command_set_volume_job.cc",
@@ -1877,6 +1977,8 @@ source_set("chromeos") {
"policy/single_app_install_event_log.h",
"policy/status_collector/activity_storage.cc",
"policy/status_collector/activity_storage.h",
+ "policy/status_collector/app_info_generator.cc",
+ "policy/status_collector/app_info_generator.h",
"policy/status_collector/child_activity_storage.cc",
"policy/status_collector/child_activity_storage.h",
"policy/status_collector/child_status_collector.cc",
@@ -1885,14 +1987,19 @@ source_set("chromeos") {
"policy/status_collector/device_status_collector.h",
"policy/status_collector/enterprise_activity_storage.cc",
"policy/status_collector/enterprise_activity_storage.h",
+ "policy/status_collector/interval_map.h",
"policy/status_collector/status_collector.cc",
"policy/status_collector/status_collector.h",
"policy/status_collector/status_collector_state.cc",
"policy/status_collector/status_collector_state.h",
"policy/status_uploader.cc",
"policy/status_uploader.h",
+ "policy/system_features_disable_list_policy_handler.cc",
+ "policy/system_features_disable_list_policy_handler.h",
"policy/system_log_uploader.cc",
"policy/system_log_uploader.h",
+ "policy/system_proxy_settings_policy_handler.cc",
+ "policy/system_proxy_settings_policy_handler.h",
"policy/tpm_auto_update_mode_policy_handler.cc",
"policy/tpm_auto_update_mode_policy_handler.h",
"policy/upload_job.h",
@@ -1994,6 +2101,8 @@ source_set("chromeos") {
"power/renderer_freezer.h",
"power/smart_charging/smart_charging_manager.cc",
"power/smart_charging/smart_charging_manager.h",
+ "power/smart_charging/smart_charging_ukm_logger.cc",
+ "power/smart_charging/smart_charging_ukm_logger.h",
"preferences.cc",
"preferences.h",
"printing/automatic_usb_printer_configurer.cc",
@@ -2018,6 +2127,8 @@ source_set("chromeos") {
"printing/cups_printers_manager.h",
"printing/cups_printers_manager_factory.cc",
"printing/cups_printers_manager_factory.h",
+ "printing/cups_printers_manager_proxy.cc",
+ "printing/cups_printers_manager_proxy.h",
"printing/enterprise_printers_provider.cc",
"printing/enterprise_printers_provider.h",
"printing/history/print_job_database.h",
@@ -2039,6 +2150,10 @@ source_set("chromeos") {
"printing/ppd_resolution_state.h",
"printing/ppd_resolution_tracker.cc",
"printing/ppd_resolution_tracker.h",
+ "printing/print_management/print_job_info_mojom_conversions.cc",
+ "printing/print_management/print_job_info_mojom_conversions.h",
+ "printing/print_management/printing_manager.cc",
+ "printing/print_management/printing_manager.h",
"printing/print_server.cc",
"printing/print_server.h",
"printing/print_servers_provider.cc",
@@ -2099,12 +2214,6 @@ source_set("chromeos") {
"set_time_dialog.h",
"settings/cros_settings.cc",
"settings/cros_settings.h",
- "settings/device_identity_provider.cc",
- "settings/device_identity_provider.h",
- "settings/device_oauth2_token_service.cc",
- "settings/device_oauth2_token_service.h",
- "settings/device_oauth2_token_service_factory.cc",
- "settings/device_oauth2_token_service_factory.h",
"settings/device_settings_cache.cc",
"settings/device_settings_cache.h",
"settings/device_settings_provider.cc",
@@ -2139,6 +2248,10 @@ source_set("chromeos") {
"smb_client/discovery/netbios_host_locator.h",
"smb_client/discovery/network_scanner.cc",
"smb_client/discovery/network_scanner.h",
+ "smb_client/fileapi/smbfs_async_file_util.cc",
+ "smb_client/fileapi/smbfs_async_file_util.h",
+ "smb_client/fileapi/smbfs_file_system_backend_delegate.cc",
+ "smb_client/fileapi/smbfs_file_system_backend_delegate.h",
"smb_client/smb_constants.cc",
"smb_client/smb_constants.h",
"smb_client/smb_errors.cc",
@@ -2147,6 +2260,10 @@ source_set("chromeos") {
"smb_client/smb_file_system.h",
"smb_client/smb_file_system_id.cc",
"smb_client/smb_file_system_id.h",
+ "smb_client/smb_kerberos_credentials_updater.cc",
+ "smb_client/smb_kerberos_credentials_updater.h",
+ "smb_client/smb_persisted_share_registry.cc",
+ "smb_client/smb_persisted_share_registry.h",
"smb_client/smb_provider.cc",
"smb_client/smb_provider.h",
"smb_client/smb_service.cc",
@@ -2157,18 +2274,30 @@ source_set("chromeos") {
"smb_client/smb_service_helper.h",
"smb_client/smb_share_finder.cc",
"smb_client/smb_share_finder.h",
+ "smb_client/smb_share_info.cc",
+ "smb_client/smb_share_info.h",
"smb_client/smb_task_queue.cc",
"smb_client/smb_task_queue.h",
"smb_client/smb_url.cc",
"smb_client/smb_url.h",
+ "smb_client/smbfs_share.cc",
+ "smb_client/smbfs_share.h",
"smb_client/temp_file_manager.cc",
"smb_client/temp_file_manager.h",
"startup_settings_cache.cc",
"startup_settings_cache.h",
- "sync/os_preferences_model_type_controller.cc",
- "sync/os_preferences_model_type_controller.h",
+ "sync/app_settings_model_type_controller.cc",
+ "sync/app_settings_model_type_controller.h",
+ "sync/apps_model_type_controller.cc",
+ "sync/apps_model_type_controller.h",
"sync/os_sync_model_type_controller.cc",
"sync/os_sync_model_type_controller.h",
+ "sync/os_sync_util.cc",
+ "sync/os_sync_util.h",
+ "sync/os_syncable_service_model_type_controller.cc",
+ "sync/os_syncable_service_model_type_controller.h",
+ "sync/turn_sync_on_helper.cc",
+ "sync/turn_sync_on_helper.h",
"system/automatic_reboot_manager.cc",
"system/automatic_reboot_manager.h",
"system/automatic_reboot_manager_observer.h",
@@ -2254,6 +2383,12 @@ source_set("chromeos") {
"usb/cros_usb_detector.h",
"virtual_machines/virtual_machines_util.cc",
"virtual_machines/virtual_machines_util.h",
+ "web_applications/chrome_help_app_ui_delegate.cc",
+ "web_applications/chrome_help_app_ui_delegate.h",
+ "web_applications/chrome_media_app_ui_delegate.cc",
+ "web_applications/chrome_media_app_ui_delegate.h",
+ "web_applications/terminal_source.cc",
+ "web_applications/terminal_source.h",
"wilco_dtc_supportd/fake_wilco_dtc_supportd_client.cc",
"wilco_dtc_supportd/fake_wilco_dtc_supportd_client.h",
"wilco_dtc_supportd/mojo_utils.cc",
@@ -2266,6 +2401,7 @@ source_set("chromeos") {
"wilco_dtc_supportd/wilco_dtc_supportd_manager.h",
"wilco_dtc_supportd/wilco_dtc_supportd_messaging.cc",
"wilco_dtc_supportd/wilco_dtc_supportd_messaging.h",
+ "wilco_dtc_supportd/wilco_dtc_supportd_network_context.cc",
"wilco_dtc_supportd/wilco_dtc_supportd_notification_controller.cc",
"wilco_dtc_supportd/wilco_dtc_supportd_notification_controller.h",
"wilco_dtc_supportd/wilco_dtc_supportd_web_request_service.cc",
@@ -2319,6 +2455,8 @@ source_set("chromeos") {
"extensions/input_method_api.h",
"extensions/login_screen/login/login_api.cc",
"extensions/login_screen/login/login_api.h",
+ "extensions/login_screen/login/login_api_lock_handler.cc",
+ "extensions/login_screen/login/login_api_lock_handler.h",
"extensions/login_screen/login_screen_storage/login_screen_storage_api.cc",
"extensions/login_screen/login_screen_storage/login_screen_storage_api.h",
"extensions/login_screen/login_screen_ui/login_screen_ui_api.cc",
@@ -2331,6 +2469,10 @@ source_set("chromeos") {
"extensions/login_screen/login_state/session_state_changed_event_dispatcher.h",
"extensions/media_player_api.cc",
"extensions/media_player_api.h",
+ "extensions/printing/print_job_controller.cc",
+ "extensions/printing/print_job_controller.h",
+ "extensions/printing/printer_capabilities_provider.cc",
+ "extensions/printing/printer_capabilities_provider.h",
"extensions/printing_metrics/print_job_finished_event_dispatcher.cc",
"extensions/printing_metrics/print_job_finished_event_dispatcher.h",
"extensions/printing_metrics/print_job_info_idl_conversions.cc",
@@ -2354,11 +2496,14 @@ source_set("chromeos") {
]
if (use_cups) {
+ configs += [ "//printing:cups" ]
deps += [
"//chrome/services/cups_proxy",
"//chrome/services/cups_proxy/public/mojom",
]
sources += [
+ "extensions/printing/print_job_submitter.cc",
+ "extensions/printing/print_job_submitter.h",
"extensions/printing/printing_api.cc",
"extensions/printing/printing_api.h",
"extensions/printing/printing_api_handler.cc",
@@ -2374,6 +2519,7 @@ source_set("chromeos") {
"printing/cups_proxy_service_manager_factory.h",
"printing/cups_wrapper.cc",
"printing/cups_wrapper.h",
+ "printing/cups_wrapper_impl.cc",
"printing/printer_error_codes.cc",
"printing/printer_error_codes.h",
"printing/printer_info_cups.cc",
@@ -2405,15 +2551,14 @@ action("dbus_service_files") {
"dbus/org.chromium.MetricsEventService.conf",
"dbus/org.chromium.NetworkProxyService.conf",
"dbus/org.chromium.PluginVmService.conf",
+ "dbus/org.chromium.PrintersService.conf",
"dbus/org.chromium.ScreenLockService.conf",
"dbus/org.chromium.SmbFsService.conf",
"dbus/org.chromium.VirtualFileRequestService.conf",
"dbus/org.chromium.VmApplicationsService.conf",
]
output_conf_file = "$root_out_dir/dbus/chrome_dbus_services.conf"
- outputs = [
- output_conf_file,
- ]
+ outputs = [ output_conf_file ]
script = "//chromeos/tools/concat_dbus_conf_files.py"
args = [ rebase_path(output_conf_file, root_build_dir) ]
@@ -2426,6 +2571,8 @@ static_library("arc_test_support") {
sources = [
"arc/test/arc_data_removed_waiter.cc",
"arc/test/arc_data_removed_waiter.h",
+ "arc/test/test_arc_session_manager.cc",
+ "arc/test/test_arc_session_manager.h",
]
deps = [
@@ -2497,6 +2644,8 @@ static_library("test_support") {
"login/test/test_predicate_waiter.h",
"login/version_updater/mock_version_updater_delegate.cc",
"login/version_updater/mock_version_updater_delegate.h",
+ "platform_keys/mock_platform_keys_service.cc",
+ "platform_keys/mock_platform_keys_service.h",
"printing/printing_stubs.cc",
"printing/printing_stubs.h",
"scoped_set_running_on_chromeos_for_testing.cc",
@@ -2507,6 +2656,7 @@ static_library("test_support") {
deps = [
":chromeos",
+ "//chrome/browser/web_applications/components",
"//chrome/test:test_support",
"//chromeos",
"//chromeos/components/drivefs",
@@ -2551,9 +2701,12 @@ source_set("unit_tests") {
"android_sms/connection_manager_unittest.cc",
"android_sms/fcm_connection_establisher_unittest.cc",
"android_sms/pairing_lost_notifier_unittest.cc",
+ "app_mode/app_session_unittest.cc",
"app_mode/startup_app_launcher_unittest.cc",
+ "app_mode/web_app/web_kiosk_app_launcher_unittest.cc",
"apps/apk_web_app_installer_unittest.cc",
"apps/intent_helper/chromeos_apps_navigation_throttle_unittest.cc",
+ "apps/metrics/intent_handling_metrics_unittest.cc",
"arc/accessibility/arc_accessibility_helper_bridge_unittest.cc",
"arc/accessibility/ax_tree_source_arc_unittest.cc",
"arc/app_shortcuts/arc_app_shortcuts_menu_builder_unittest.cc",
@@ -2566,10 +2719,12 @@ source_set("unit_tests") {
"arc/bluetooth/arc_bluetooth_task_queue_unittest.cc",
"arc/boot_phase_monitor/arc_boot_phase_monitor_bridge_unittest.cc",
"arc/enterprise/cert_store/arc_cert_installer_unittest.cc",
- "arc/enterprise/cert_store/arc_cert_installer_utils_unittest.cc",
"arc/enterprise/cert_store/arc_smart_card_manager_bridge_unittest.cc",
+ "arc/enterprise/cert_store/security_token_operation_bridge_unittest.cc",
"arc/extensions/arc_support_message_host_unittest.cc",
"arc/file_system_watcher/arc_file_system_watcher_service_unittest.cc",
+ "arc/file_system_watcher/arc_file_system_watcher_util_unittest.cc",
+ "arc/file_system_watcher/file_system_scanner_unittest.cc",
"arc/fileapi/arc_content_file_system_async_file_util_unittest.cc",
"arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc",
"arc/fileapi/arc_content_file_system_file_stream_writer_unittest.cc",
@@ -2624,12 +2779,15 @@ source_set("unit_tests") {
"attestation/machine_certificate_uploader_impl_unittest.cc",
"attestation/mock_tpm_challenge_key.cc",
"attestation/mock_tpm_challenge_key.h",
+ "attestation/mock_tpm_challenge_key_subtle.cc",
+ "attestation/mock_tpm_challenge_key_subtle.h",
"attestation/platform_verification_flow_unittest.cc",
"attestation/tpm_challenge_key_unittest.cc",
"authpolicy/authpolicy_credentials_manager_unittest.cc",
"authpolicy/authpolicy_helper.unittest.cc",
"base/file_flusher_unittest.cc",
"bluetooth/debug_logs_manager_unittest.cc",
+ "cert_provisioning/cert_provisioning_worker_unittest.cc",
"certificate_provider/certificate_provider_service_unittest.cc",
"child_accounts/child_user_service_unittest.cc",
"child_accounts/event_based_status_reporting_service_unittest.cc",
@@ -2638,15 +2796,23 @@ source_set("unit_tests") {
"child_accounts/parent_access_code/parent_access_test_utils.h",
"child_accounts/time_limit_notifier_unittest.cc",
"child_accounts/time_limit_test_utils.cc",
+ "child_accounts/time_limits/app_activity_registry_unittest.cc",
"child_accounts/time_limits/app_service_wrapper_unittest.cc",
"child_accounts/time_limits/app_time_controller_unittest.cc",
+ "child_accounts/time_limits/app_time_limits_policy_builder.cc",
+ "child_accounts/time_limits/app_time_limits_policy_builder.h",
+ "child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.cc",
+ "child_accounts/time_limits/app_time_limits_whitelist_policy_test_utils.h",
+ "child_accounts/time_limits/app_time_test_utils.cc",
+ "child_accounts/time_limits/app_time_test_utils.h",
+ "child_accounts/time_limits/app_types_unittest.cc",
+ "child_accounts/time_limits/persisted_app_info_unittest.cc",
"child_accounts/usage_time_limit_processor_unittest.cc",
"child_accounts/usage_time_state_notifier_unittest.cc",
"chrome_content_browser_client_chromeos_part_unittest.cc",
"concierge_helper_service_unittest.cc",
"crostini/ansible/ansible_management_service_unittest.cc",
- "crostini/ansible/pending_software_changes_unittest.cc",
- "crostini/ansible/software_config_unittest.cc",
+ "crostini/crostini_disk_unittest.cc",
"crostini/crostini_export_import_unittest.cc",
"crostini/crostini_features_unittest.cc",
"crostini/crostini_force_close_watcher_unittest.cc",
@@ -2655,9 +2821,11 @@ source_set("unit_tests") {
"crostini/crostini_mime_types_service_unittest.cc",
"crostini/crostini_package_notification_unittest.cc",
"crostini/crostini_package_service_unittest.cc",
- "crostini/crostini_registry_service_unittest.cc",
+ "crostini/crostini_port_forwarder_unittest.cc",
"crostini/crostini_reporting_util_unittest.cc",
+ "crostini/crostini_shelf_utils_unittest.cc",
"crostini/crostini_unsupported_action_notifier_unittest.cc",
+ "crostini/crostini_util_unittest.cc",
"crostini/crosvm_metrics_unittest.cc",
"crostini/crosvm_process_list_unittest.cc",
"crostini/throttle/crostini_active_window_throttle_observer_unittest.cc",
@@ -2685,6 +2853,9 @@ source_set("unit_tests") {
"extensions/login_screen/login_state/login_state_api_unittest.cc",
"extensions/login_screen/login_state/session_state_changed_event_dispatcher_unittest.cc",
"extensions/permissions_updater_delegate_chromeos_unittest.cc",
+ "extensions/printing/fake_print_job_controller.cc",
+ "extensions/printing/fake_print_job_controller.h",
+ "extensions/printing/printer_capabilities_provider_unittest.cc",
"extensions/printing_metrics/print_job_finished_event_dispatcher_unittest.cc",
"extensions/printing_metrics/print_job_info_idl_conversions_unittest.cc",
"extensions/printing_metrics/printing_metrics_api_unittest.cc",
@@ -2693,6 +2864,7 @@ source_set("unit_tests") {
"extensions/signin_screen_policy_provider_unittest.cc",
"extensions/wallpaper_private_api_unittest.cc",
"external_metrics_unittest.cc",
+ "file_manager/crostini_file_tasks_unittest.cc",
"file_manager/documents_provider_root_manager_unittest.cc",
"file_manager/file_tasks_notifier_unittest.cc",
"file_manager/file_tasks_unittest.cc",
@@ -2752,6 +2924,7 @@ source_set("unit_tests") {
"fileapi/recent_disk_source_unittest.cc",
"fileapi/recent_model_unittest.cc",
"fileapi/test/fake_recent_source.cc",
+ "guest_os/guest_os_registry_service_unittest.cc",
"guest_os/guest_os_share_path_unittest.cc",
"hats/hats_finch_helper_unittest.cc",
"hats/hats_notification_controller_unittest.cc",
@@ -2780,6 +2953,7 @@ source_set("unit_tests") {
"login/enterprise_user_session_metrics_unittest.cc",
"login/error_screens_histogram_helper_unittest.cc",
"login/existing_user_controller_auto_login_unittest.cc",
+ "login/existing_user_controller_forced_online_auth_unittest.cc",
"login/hwid_checker_unittest.cc",
"login/lock/screen_locker_unittest.cc",
"login/profile_auth_data_unittest.cc",
@@ -2806,6 +2980,7 @@ source_set("unit_tests") {
"login/version_updater/version_updater_unittest.cc",
"mobile/mobile_activator_unittest.cc",
"net/client_cert_store_chromeos_unittest.cc",
+ "net/network_health_unittest.cc",
"net/network_portal_detector_impl_unittest.cc",
"net/network_pref_state_observer_unittest.cc",
"net/network_throttling_observer_unittest.cc",
@@ -2815,7 +2990,7 @@ source_set("unit_tests") {
"note_taking_helper_unittest.cc",
"ownership/owner_settings_service_chromeos_unittest.cc",
"plugin_vm/plugin_vm_files_unittest.cc",
- "plugin_vm/plugin_vm_image_manager_unittest.cc",
+ "plugin_vm/plugin_vm_installer_unittest.cc",
"plugin_vm/plugin_vm_manager_unittest.cc",
"plugin_vm/plugin_vm_test_helper.cc",
"plugin_vm/plugin_vm_test_helper.h",
@@ -2855,12 +3030,17 @@ source_set("unit_tests") {
"policy/heartbeat_scheduler_unittest.cc",
"policy/hostname_handler_unittest.cc",
"policy/lock_to_single_user_manager_unittest.cc",
+ "policy/minimum_version_policy_handler_unittest.cc",
"policy/network_configuration_updater_unittest.cc",
"policy/off_hours/device_off_hours_controller_unittest.cc",
"policy/off_hours/off_hours_policy_applier_unittest.cc",
"policy/off_hours/off_hours_proto_parser_unittest.cc",
+ "policy/powerwash_requirements_checker_unittest.cc",
"policy/pre_signin_policy_fetcher_unittest.cc",
+ "policy/remote_commands/device_command_get_available_routines_job_unittest.cc",
+ "policy/remote_commands/device_command_get_routine_update_job_unittest.cc",
"policy/remote_commands/device_command_remote_powerwash_job_unittest.cc",
+ "policy/remote_commands/device_command_run_routine_job_unittest.cc",
"policy/remote_commands/device_command_screenshot_job_unittest.cc",
"policy/remote_commands/device_command_set_volume_job_unittest.cc",
"policy/remote_commands/device_command_start_crd_session_unittest.cc",
@@ -2871,8 +3051,11 @@ source_set("unit_tests") {
"policy/secondary_google_account_signin_policy_handler_unittest.cc",
"policy/server_backed_state_keys_broker_unittest.cc",
"policy/single_app_install_event_log_unittest.cc",
+ "policy/status_collector/app_info_generator_unittest.cc",
+ "policy/status_collector/interval_map_unittest.cc",
"policy/status_uploader_unittest.cc",
"policy/system_log_uploader_unittest.cc",
+ "policy/system_proxy_settings_policy_handler_unittest.cc",
"policy/tpm_auto_update_mode_policy_handler_unittest.cc",
"policy/upload_job_unittest.cc",
"policy/user_cloud_policy_manager_chromeos_unittest.cc",
@@ -2894,6 +3077,8 @@ source_set("unit_tests") {
"power/ml/boot_clock_unittest.cc",
"power/ml/idle_event_notifier_unittest.cc",
"power/ml/recent_events_counter_unittest.cc",
+ "power/ml/smart_dim/ml_agent_unittest.cc",
+ "power/ml/smart_dim/ml_agent_util_unittest.cc",
"power/ml/smart_dim/model_unittest.cc",
"power/ml/user_activity_manager_unittest.cc",
"power/ml/user_activity_ukm_logger_helpers_unittest.cc",
@@ -2903,11 +3088,13 @@ source_set("unit_tests") {
"power/process_data_collector_unittest.cc",
"power/renderer_freezer_unittest.cc",
"power/smart_charging/smart_charging_manager_unittest.cc",
+ "power/smart_charging/smart_charging_ukm_logger_unittest.cc",
"preferences_unittest.cc",
"printing/automatic_usb_printer_configurer_unittest.cc",
"printing/bulk_printers_calculator_unittest.cc",
"printing/calculators_policies_binder_unittest.cc",
"printing/cups_printers_manager_unittest.cc",
+ "printing/enterprise_printers_provider_unittest.cc",
"printing/history/mock_print_job_history_service.cc",
"printing/history/mock_print_job_history_service.h",
"printing/history/print_job_database_impl_unittest.cc",
@@ -2920,6 +3107,7 @@ source_set("unit_tests") {
"printing/history/test_print_job_history_service_observer.h",
"printing/ppd_resolution_state_unittest.cc",
"printing/ppd_resolution_tracker_unittest.cc",
+ "printing/print_management/print_job_info_mojom_conversions_unittest.cc",
"printing/print_servers_provider_unittest.cc",
"printing/printer_detector_test_util.h",
"printing/printer_event_tracker_unittest.cc",
@@ -2942,7 +3130,6 @@ source_set("unit_tests") {
"scheduler_configuration_manager_unittest.cc",
"session_length_limiter_unittest.cc",
"settings/cros_settings_unittest.cc",
- "settings/device_oauth2_token_service_unittest.cc",
"settings/device_settings_cache_unittest.cc",
"settings/device_settings_provider_unittest.cc",
"settings/device_settings_service_unittest.cc",
@@ -2959,13 +3146,18 @@ source_set("unit_tests") {
"smb_client/smb_errors_unittest.cc",
"smb_client/smb_file_system_id_test.cc",
"smb_client/smb_file_system_unittest.cc",
+ "smb_client/smb_kerberos_credentials_updater_unittest.cc",
+ "smb_client/smb_persisted_share_registry_unittest.cc",
"smb_client/smb_service_helper_unittest.cc",
"smb_client/smb_service_unittest.cc",
"smb_client/smb_share_finder_unittest.cc",
"smb_client/smb_task_queue_unittest.cc",
"smb_client/smb_url_unittest.cc",
+ "smb_client/smbfs_share_unittest.cc",
"smb_client/temp_file_manager_unittest.cc",
"startup_settings_cache_unittest.cc",
+ "sync/os_sync_util_unittest.cc",
+ "sync/turn_sync_on_helper_unittest.cc",
"system/automatic_reboot_manager_unittest.cc",
"system/device_disabling_manager_unittest.cc",
"system/procfs_util_unittest.cc",
@@ -2983,6 +3175,8 @@ source_set("unit_tests") {
"usb/cros_usb_detector_unittest.cc",
"wilco_dtc_supportd/testing_wilco_dtc_supportd_bridge_wrapper.cc",
"wilco_dtc_supportd/testing_wilco_dtc_supportd_bridge_wrapper.h",
+ "wilco_dtc_supportd/testing_wilco_dtc_supportd_network_context.cc",
+ "wilco_dtc_supportd/testing_wilco_dtc_supportd_network_context.h",
"wilco_dtc_supportd/wilco_dtc_supportd_bridge_unittest.cc",
"wilco_dtc_supportd/wilco_dtc_supportd_manager_unittest.cc",
"wilco_dtc_supportd/wilco_dtc_supportd_messaging_unittest.cc",
@@ -3002,20 +3196,26 @@ source_set("unit_tests") {
"../ui/webui/chromeos/login/l10n_util_unittest.cc",
"../ui/webui/chromeos/login/oobe_display_chooser_unittest.cc",
"../ui/webui/chromeos/login/signin_userlist_unittest.cc",
+ "../ui/webui/settings/chromeos/accessibility_handler_unittest.cc",
+ "../ui/webui/settings/chromeos/calculator/size_calculator_test_api.h",
"../ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc",
+ "../ui/webui/settings/chromeos/device_storage_handler_unittest.cc",
"../ui/webui/settings/chromeos/internet_handler_unittest.cc",
"../ui/webui/settings/chromeos/multidevice_handler_unittest.cc",
+ "../ui/webui/settings/chromeos/os_settings_localized_strings_provider_unittest.cc",
+ "../ui/webui/settings/chromeos/search/search_handler_unittest.cc",
+ "../ui/webui/settings/chromeos/search/settings_user_action_tracker_unittest.cc",
]
if (use_cups) {
sources += [
"extensions/printing/printing_api_handler_unittest.cc",
"extensions/printing/printing_api_utils_unittest.cc",
+ "printing/test_cups_wrapper.cc",
+ "printing/test_cups_wrapper.h",
]
}
- public_deps = [
- ":chromeos",
- ]
+ public_deps = [ ":chromeos" ]
deps = [
":arc_test_support",
":attestation_proto",
@@ -3032,6 +3232,9 @@ source_set("unit_tests") {
"//chrome/browser/ui:ash_test_support",
"//chrome/browser/web_applications/components",
"//chrome/common",
+ "//chrome/services/keymaster/public/mojom",
+ "//chrome/services/local_search_service",
+ "//chrome/services/local_search_service:test_utils",
"//chrome/services/wilco_dtc_supportd/public/mojom",
"//chrome/test:test_support",
"//chrome/test:test_support_ui",
@@ -3127,53 +3330,40 @@ source_set("unit_tests") {
"//ui/events/devices:test_support",
"//ui/shell_dialogs",
]
- data = [
- "//chromeos/test/data/",
- ]
+ if (use_udev) {
+ deps += [ "//device/udev_linux:test_support" ]
+ }
+ data = [ "//chromeos/test/data/" ]
}
proto_library("attestation_proto") {
- sources = [
- "attestation/attestation_key_payload.proto",
- ]
+ sources = [ "attestation/attestation_key_payload.proto" ]
}
proto_library("screen_brightness_event_proto") {
- sources = [
- "power/ml/screen_brightness_event.proto",
- ]
+ sources = [ "power/ml/screen_brightness_event.proto" ]
}
proto_library("user_charging_event_proto") {
- sources = [
- "power/smart_charging/user_charging_event.proto",
- ]
+ sources = [ "power/smart_charging/user_charging_event.proto" ]
}
proto_library("user_activity_event_proto") {
- sources = [
- "power/ml/user_activity_event.proto",
- ]
+ sources = [ "power/ml/user_activity_event.proto" ]
}
proto_library("backdrop_wallpaper_proto") {
- sources = [
- "backdrop_wallpaper_handlers/backdrop_wallpaper.proto",
- ]
+ sources = [ "backdrop_wallpaper_handlers/backdrop_wallpaper.proto" ]
generate_python = false
}
proto_library("device_configuration_proto") {
- sources = [
- "login/screens/recommend_apps/device_configuration.proto",
- ]
+ sources = [ "login/screens/recommend_apps/device_configuration.proto" ]
generate_python = false
}
proto_library("print_job_info_proto") {
- sources = [
- "printing/history/print_job_info.proto",
- ]
+ sources = [ "printing/history/print_job_info.proto" ]
}
device_policy_remover_path = "$target_gen_dir/device_policy_remover.cc"
@@ -3199,9 +3389,7 @@ action("device_policy_remover_generate") {
chrome_device_policy_pb2_path,
]
- outputs = [
- device_policy_remover_path,
- ]
+ outputs = [ device_policy_remover_path ]
args = [
# generated file name
@@ -3220,13 +3408,9 @@ action("device_policy_remover_generate") {
}
static_library("device_policy_remover_generated") {
- sources = [
- device_policy_remover_path,
- ]
+ sources = [ device_policy_remover_path ]
- public_deps = [
- ":device_policy_remover_generate",
- ]
+ public_deps = [ ":device_policy_remover_generate" ]
}
fuzzer_test("smb_url_fuzzer") {
@@ -3250,9 +3434,7 @@ fuzzer_test("smb_url_fuzzer") {
}
fuzzer_test("zeroconf_printer_detector_fuzzer") {
- sources = [
- "printing/zeroconf_printer_detector_fuzzer.cc",
- ]
+ sources = [ "printing/zeroconf_printer_detector_fuzzer.cc" ]
deps = [
"//base/test:test_support",
"//chrome/browser",
@@ -3262,9 +3444,7 @@ fuzzer_test("zeroconf_printer_detector_fuzzer") {
if (use_libfuzzer) {
fuzzer_test("policy_fuzzer") {
- sources = [
- "policy/fuzzer/policy_fuzzer.cc",
- ]
+ sources = [ "policy/fuzzer/policy_fuzzer.cc" ]
deps = [
":policy_fuzzer_proto",
@@ -3276,13 +3456,16 @@ if (use_libfuzzer) {
}
fuzzable_proto_library("policy_fuzzer_proto") {
- sources = [
- "policy/fuzzer/policy_fuzzer.proto",
- ]
+ sources = [ "policy/fuzzer/policy_fuzzer.proto" ]
- import_dirs = [ "//components/policy/proto" ]
+ import_dirs = [
+ "//components/policy/proto",
+ "$root_gen_dir/components/policy/proto",
+ ]
- link_deps =
- [ "//components/policy/proto:chrome_device_policy_full_runtime_proto" ]
+ link_deps = [
+ "//components/policy:cloud_policy_full_runtime_proto",
+ "//components/policy/proto:chrome_device_policy_full_runtime_proto",
+ ]
}
}
diff --git a/chromium/chrome/browser/chromeos/crostini/BUILD.gn b/chromium/chrome/browser/chromeos/crostini/BUILD.gn
index b83dad29d49..b1e0da7eaa3 100644
--- a/chromium/chrome/browser/chromeos/crostini/BUILD.gn
+++ b/chromium/chrome/browser/chromeos/crostini/BUILD.gn
@@ -5,7 +5,5 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("crostini_installer_types_mojom") {
- sources = [
- "crostini_installer_types.mojom",
- ]
+ sources = [ "crostini_types.mojom" ]
}
diff --git a/chromium/chrome/browser/chromeos/crostini/crostini_installer_types.mojom b/chromium/chrome/browser/chromeos/crostini/crostini_types.mojom
index 401b081ee85..65efb5c212b 100644
--- a/chromium/chrome/browser/chromeos/crostini/crostini_installer_types.mojom
+++ b/chromium/chrome/browser/chromeos/crostini/crostini_types.mojom
@@ -31,4 +31,12 @@ enum InstallerError {
kErrorSettingUpContainer,
kErrorInsufficientDiskSpace,
kErrorConfiguringContainer,
+ kErrorCreateContainer,
+ kErrorUnknown,
+};
+
+struct DiskSliderTick {
+ int64 value; // Size in bytes.
+ string label; // Localised human-readable value e.g. 4.6GB.
+ string aria_value; // Value for e.g. screen readers.
};
diff --git a/chromium/chrome/browser/chromeos/power/ml/BUILD.gn b/chromium/chrome/browser/chromeos/power/ml/BUILD.gn
index 0bcddd465a9..a4f29c799d0 100644
--- a/chromium/chrome/browser/chromeos/power/ml/BUILD.gn
+++ b/chromium/chrome/browser/chromeos/power/ml/BUILD.gn
@@ -3,13 +3,9 @@
# found in the LICENSE file.
source_set("user_activity_ukm_logger_helpers") {
- public = [
- "user_activity_ukm_logger_helpers.h",
- ]
+ public = [ "user_activity_ukm_logger_helpers.h" ]
- sources = [
- "user_activity_ukm_logger_helpers.cc",
- ]
+ sources = [ "user_activity_ukm_logger_helpers.cc" ]
deps = [
"//base",
diff --git a/chromium/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn b/chromium/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn
index 567781435cb..702899d9cbb 100644
--- a/chromium/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn
+++ b/chromium/chrome/browser/chromeos/power/ml/smart_dim/BUILD.gn
@@ -4,16 +4,29 @@
source_set("smart_dim") {
public = [
+ "ml_agent.h",
"model.h",
"model_impl.h",
]
sources = [
+ "builtin_worker.cc",
+ "builtin_worker.h",
+ "download_worker.cc",
+ "download_worker.h",
+ "metrics.cc",
+ "metrics.h",
+ "ml_agent.cc",
+ "ml_agent.h",
+ "ml_agent_util.cc",
+ "ml_agent_util.h",
"ml_service_client.cc",
"ml_service_client.h",
"model.h",
"model_impl.cc",
"model_impl.h",
+ "smart_dim_worker.cc",
+ "smart_dim_worker.h",
]
deps = [
@@ -28,6 +41,7 @@ source_set("smart_dim") {
"//components/assist_ranker",
"//components/assist_ranker/proto",
"//components/sessions",
+ "//services/data_decoder/public/cpp",
"//ui/base",
]
}
diff --git a/chromium/chrome/browser/chromeos/secure_channel/BUILD.gn b/chromium/chrome/browser/chromeos/secure_channel/BUILD.gn
index 8c12f1a99fc..c5edacdcc4a 100644
--- a/chromium/chrome/browser/chromeos/secure_channel/BUILD.gn
+++ b/chromium/chrome/browser/chromeos/secure_channel/BUILD.gn
@@ -8,7 +8,5 @@ static_library("secure_channel") {
"secure_channel_client_factory.h",
]
- deps = [
- "//chromeos/services/secure_channel/public/cpp/client",
- ]
+ deps = [ "//chromeos/services/secure_channel/public/cpp/client" ]
}
diff --git a/chromium/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc b/chromium/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc
index 9790e7494e9..27bd712bbc5 100644
--- a/chromium/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc
+++ b/chromium/chrome/browser/custom_handlers/protocol_handler_registry_browsertest.cc
@@ -11,13 +11,13 @@
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "chrome/browser/extensions/extension_browsertest.h"
-#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "components/permissions/permission_request_manager.h"
+#include "components/permissions/test/mock_permission_prompt_factory.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
@@ -25,12 +25,22 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/blink/public/common/context_menu_data/media_type.h"
+#if defined(OS_MACOSX)
+#include "chrome/test/base/launchservices_utils_mac.h"
+#endif
+
using content::WebContents;
class RegisterProtocolHandlerBrowserTest : public InProcessBrowserTest {
public:
RegisterProtocolHandlerBrowserTest() { }
+ void SetUpOnMainThread() override {
+#if defined(OS_MACOSX)
+ ASSERT_TRUE(test::RegisterAppWithLaunchServices());
+#endif
+ }
+
TestRenderViewContextMenu* CreateContextMenu(GURL url) {
content::ContextMenuParams params;
params.media_type = blink::ContextMenuDataMediaType::kNone;
@@ -140,10 +150,13 @@ using RegisterProtocolHandlerExtensionBrowserTest =
extensions::ExtensionBrowserTest;
IN_PROC_BROWSER_TEST_F(RegisterProtocolHandlerExtensionBrowserTest, Basic) {
- PermissionRequestManager* manager = PermissionRequestManager::FromWebContents(
- browser()->tab_strip_model()->GetActiveWebContents());
- auto prompt_factory = std::make_unique<MockPermissionPromptFactory>(manager);
- prompt_factory->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestManager* manager =
+ permissions::PermissionRequestManager::FromWebContents(
+ browser()->tab_strip_model()->GetActiveWebContents());
+ auto prompt_factory =
+ std::make_unique<permissions::MockPermissionPromptFactory>(manager);
+ prompt_factory->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
const extensions::Extension* extension =
LoadExtension(test_data_dir_.AppendASCII("protocol_handler"));
diff --git a/chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc b/chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc
index b79eb6c2b0d..9641c4d199d 100644
--- a/chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc
+++ b/chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.cc
@@ -12,21 +12,23 @@
#include "components/vector_icons/vector_icons.h"
#include "ui/base/l10n/l10n_util.h"
-RegisterProtocolHandlerPermissionRequest
-::RegisterProtocolHandlerPermissionRequest(
- ProtocolHandlerRegistry* registry,
- const ProtocolHandler& handler,
- GURL url,
- bool user_gesture)
+RegisterProtocolHandlerPermissionRequest::
+ RegisterProtocolHandlerPermissionRequest(
+ ProtocolHandlerRegistry* registry,
+ const ProtocolHandler& handler,
+ GURL url,
+ bool user_gesture,
+ base::ScopedClosureRunner fullscreen_block)
: registry_(registry),
handler_(handler),
- origin_(url.GetOrigin()) {}
+ origin_(url.GetOrigin()),
+ fullscreen_block_(std::move(fullscreen_block)) {}
RegisterProtocolHandlerPermissionRequest::
-~RegisterProtocolHandlerPermissionRequest() {}
+ ~RegisterProtocolHandlerPermissionRequest() = default;
-PermissionRequest::IconId RegisterProtocolHandlerPermissionRequest::GetIconId()
- const {
+permissions::PermissionRequest::IconId
+RegisterProtocolHandlerPermissionRequest::GetIconId() const {
return vector_icons::kProtocolHandlerIcon;
}
@@ -69,7 +71,7 @@ void RegisterProtocolHandlerPermissionRequest::RequestFinished() {
delete this;
}
-PermissionRequestType
+permissions::PermissionRequestType
RegisterProtocolHandlerPermissionRequest::GetPermissionRequestType() const {
- return PermissionRequestType::REGISTER_PROTOCOL_HANDLER;
+ return permissions::PermissionRequestType::REGISTER_PROTOCOL_HANDLER;
}
diff --git a/chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h b/chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h
index 2cb9d62d8cd..cd41fdc6fba 100644
--- a/chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h
+++ b/chromium/chrome/browser/custom_handlers/register_protocol_handler_permission_request.h
@@ -5,25 +5,28 @@
#ifndef CHROME_BROWSER_CUSTOM_HANDLERS_REGISTER_PROTOCOL_HANDLER_PERMISSION_REQUEST_H_
#define CHROME_BROWSER_CUSTOM_HANDLERS_REGISTER_PROTOCOL_HANDLER_PERMISSION_REQUEST_H_
+#include "base/callback_helpers.h"
#include "base/macros.h"
-#include "chrome/browser/permissions/permission_request.h"
#include "chrome/common/custom_handlers/protocol_handler.h"
+#include "components/permissions/permission_request.h"
class ProtocolHandlerRegistry;
// This class provides display data for a permission request, shown when a page
// wants to register a protocol handler and was triggered by a user action.
-class RegisterProtocolHandlerPermissionRequest : public PermissionRequest {
+class RegisterProtocolHandlerPermissionRequest
+ : public permissions::PermissionRequest {
public:
RegisterProtocolHandlerPermissionRequest(
ProtocolHandlerRegistry* registry,
const ProtocolHandler& handler,
GURL url,
- bool user_gesture);
+ bool user_gesture,
+ base::ScopedClosureRunner fullscreen_block);
~RegisterProtocolHandlerPermissionRequest() override;
private:
- // PermissionRequest:
+ // permissions::PermissionRequest:
IconId GetIconId() const override;
base::string16 GetMessageTextFragment() const override;
GURL GetOrigin() const override;
@@ -31,11 +34,15 @@ class RegisterProtocolHandlerPermissionRequest : public PermissionRequest {
void PermissionDenied() override;
void Cancelled() override;
void RequestFinished() override;
- PermissionRequestType GetPermissionRequestType() const override;
+ permissions::PermissionRequestType GetPermissionRequestType() const override;
ProtocolHandlerRegistry* registry_;
ProtocolHandler handler_;
GURL origin_;
+ // Fullscreen will be blocked for the duration of the lifetime of this block.
+ // TODO(avi): Move to either permissions::PermissionRequest or the
+ // PermissionRequestManager?
+ base::ScopedClosureRunner fullscreen_block_;
DISALLOW_COPY_AND_ASSIGN(RegisterProtocolHandlerPermissionRequest);
};
diff --git a/chromium/chrome/browser/dev_ui_browser_resources.grd b/chromium/chrome/browser/dev_ui_browser_resources.grd
new file mode 100644
index 00000000000..1ea72168d2e
--- /dev/null
+++ b/chromium/chrome/browser/dev_ui_browser_resources.grd
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+This file specifies browser resources for developer-facing chrome:// pages
+(DevUI pages). This is needed by the Developer WebUI Dynamic Feature Module
+(DevUI DFM) for Android Chrome. Details:
+* User-facing resources should reside in browser_resources.grd.
+* DevUI page resources that are *not* for Android Chrome can reside in
+ browser_resources.grd
+* This file is the "miscellaneous" bin among DevUI pages; individual DevUI pages
+ (e.g., chrome://bluetooth-internals) can have their own GRD files.
+-->
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
+ <outputs>
+ <output filename="grit/dev_ui_browser_resources.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="dev_ui_browser_resources.pak" type="data_package" />
+ </outputs>
+ <release seq="1">
+ <includes>
+ <include name="IDR_ACCESSIBILITY_HTML" file="resources\accessibility\accessibility.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_ACCESSIBILITY_CSS" file="resources\accessibility\accessibility.css" compress="gzip" type="BINDATA" />
+ <include name="IDR_ACCESSIBILITY_JS" file="resources\accessibility\accessibility.js" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_COMPONENTS_COMPONENTS_HTML" file="resources\components\components.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_COMPONENTS_COMPONENTS_JS" file="resources\components\components.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_DEVICE_LOG_UI_HTML" file="resources\device_log_ui\device_log_ui.html" type="BINDATA" compress="gzip" />
+ <include name="IDR_DEVICE_LOG_UI_JS" file="resources\device_log_ui\device_log_ui.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_DEVICE_LOG_UI_CSS" file="resources\device_log_ui\device_log_ui.css" type="BINDATA" compress="gzip" />
+ <include name="IDR_DOMAIN_RELIABILITY_INTERNALS_HTML" file="resources\domain_reliability_internals\domain_reliability_internals.html" compress="gzip" type="BINDATA" />
+ <include name="IDR_DOMAIN_RELIABILITY_INTERNALS_CSS" file="resources\domain_reliability_internals\domain_reliability_internals.css" compress="gzip" type="BINDATA" />
+ <include name="IDR_DOMAIN_RELIABILITY_INTERNALS_JS" file="resources\domain_reliability_internals\domain_reliability_internals.js" compress="gzip" type="BINDATA" />
+ <include name="IDR_DOWNLOAD_INTERNALS_HTML" file="resources\download_internals\download_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_DOWNLOAD_INTERNALS_CSS" file="resources\download_internals\download_internals.css" type="BINDATA" compress="gzip" />
+ <include name="IDR_DOWNLOAD_INTERNALS_JS" file="resources\download_internals\download_internals.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_DOWNLOAD_INTERNALS_BROWSER_PROXY_JS" file="resources\download_internals\download_internals_browser_proxy.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_DOWNLOAD_INTERNALS_VISUALS_JS" file="resources\download_internals\download_internals_visuals.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_INTERVENTIONS_INTERNALS_INDEX_HTML" file="resources\interventions_internals\index.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_INTERVENTIONS_INTERNALS_INDEX_JS" file="resources\interventions_internals\index.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_INTERVENTIONS_INTERNALS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\interventions_internals\interventions_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_INTERVENTIONS_INTERNALS_UNSUPPORTED_PAGE_HTML" file="resources\interventions_internals\unsupported_page.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_LOCAL_STATE_HTML" file="resources\local_state\local_state.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_STATE_JS" file="resources\local_state\local_state.js" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEDIA_DATA_TABLE_JS" file="resources\media\media_data_table.js" flattenhtml="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEDIA_ENGAGEMENT_HTML" file="resources\media\media_engagement.html" flattenhtml="true" type="BINDATA" compress="gzip" allowexternalscript="true" />
+ <include name="IDR_MEDIA_ENGAGEMENT_JS" file="resources\media\media_engagement.js" flattenhtml="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEDIA_ENGAGEMENT_SCORE_DETAILS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\media\media_engagement_score_details.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEDIA_FEEDS_HTML" file="resources\media\media_feeds.html" flattenhtml="true" type="BINDATA" compress="gzip" allowexternalscript="true" />
+ <include name="IDR_MEDIA_FEEDS_JS" file="resources\media\media_feeds.js" flattenhtml="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEDIA_FEEDS_STORE_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\media\feeds\media_feeds_store.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEDIA_HISTORY_HTML" file="resources\media\media_history.html" flattenhtml="true" type="BINDATA" compress="gzip" allowexternalscript="true" />
+ <include name="IDR_MEDIA_HISTORY_JS" file="resources\media\media_history.js" flattenhtml="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEDIA_HISTORY_STORE_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\media\history\media_history_store.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEMORY_INTERNALS_HTML" file="resources\memory_internals\memory_internals.html" flattenhtml="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEMORY_INTERNALS_JS" file="resources\memory_internals\memory_internals.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_NOTIFICATIONS_INTERNALS_HTML" file="resources\notifications_internals\notifications_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_NOTIFICATIONS_INTERNALS_CSS" file="resources\notifications_internals\notifications_internals.css" type="BINDATA" compress="gzip" />
+ <include name="IDR_NOTIFICATIONS_INTERNALS_JS" file="resources\notifications_internals\notifications_internals.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_NOTIFICATIONS_INTERNALS_BROWSER_PROXY_JS" file="resources\notifications_internals\notifications_internals_browser_proxy.js" type="BINDATA" compress="gzip" />
+ <include name="IDR_PREDICTORS_HTML" file="resources\predictors\predictors.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_PREDICTORS_JS" file="resources\predictors\predictors.js" flattenhtml="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_MEDIA_SESSION_MOJOM_LITE_JS" file="${root_gen_dir}\services\media_session\public\mojom\media_session.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_UI_GEOMETRY_MOJOM_LITE_JS" file="${root_gen_dir}\ui\gfx\geometry\mojom\geometry.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+
+ <if expr="is_android or is_linux">
+ <include name="IDR_SANDBOX_INTERNALS_HTML" file="resources\sandbox_internals\sandbox_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_SANDBOX_INTERNALS_JS" file="resources\sandbox_internals\sandbox_internals.js" type="BINDATA" compress="gzip" />
+ </if>
+ <if expr="is_win">
+ <include name="IDR_SANDBOX_INTERNALS_HTML" file="resources\sandbox_internals\sandbox_internals.html" preprocess="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_SANDBOX_INTERNALS_JS" file="resources\sandbox_internals\sandbox_internals_win.js" type="BINDATA" compress="gzip" />
+ </if>
+
+ <include name="IDR_SITE_ENGAGEMENT_HTML" file="resources\engagement\site_engagement.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_SITE_ENGAGEMENT_JS" file="resources\engagement\site_engagement.js" flattenhtml="true" type="BINDATA" compress="gzip" />
+ <include name="IDR_SITE_ENGAGEMENT_DETAILS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\engagement\site_engagement_details.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+
+ <if expr="is_android">
+ <include name="IDR_FEED_INTERNALS_HTML" file="resources\feed_internals\feed_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_FEED_INTERNALS_CSS" file="resources\feed_internals\feed_internals.css" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_FEED_INTERNALS_JS" file="resources\feed_internals\feed_internals.js" compress="gzip" type="BINDATA" />
+ <include name="IDR_FEED_INTERNALS_MOJO_JS" file="${root_gen_dir}\chrome\browser\ui\webui\feed_internals\feed_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_SNIPPETS_INTERNALS_HTML" file="resources\snippets_internals\snippets_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_SNIPPETS_INTERNALS_CSS" file="resources\snippets_internals\snippets_internals.css" compress="gzip" type="BINDATA" />
+ <include name="IDR_SNIPPETS_INTERNALS_JS" file="resources\snippets_internals\snippets_internals.js" compress="gzip" type="BINDATA" />
+ <include name="IDR_SNIPPETS_INTERNALS_MOJOM_LITE_JS" file="${root_gen_dir}\chrome\browser\ui\webui\snippets_internals\snippets_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+ </if>
+
+ <if expr="enable_supervised_users">
+ <include name="IDR_SUPERVISED_USER_INTERNALS_HTML" file="resources\supervised_user_internals\supervised_user_internals.html" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_SUPERVISED_USER_INTERNALS_CSS" file="resources\supervised_user_internals\supervised_user_internals.css" compress="gzip" type="BINDATA" />
+ <include name="IDR_SUPERVISED_USER_INTERNALS_JS" file="resources\supervised_user_internals\supervised_user_internals.js" compress="gzip" type="BINDATA" />
+ </if>
+
+ <include name="IDR_TRANSLATE_INTERNALS_HTML" file="../../components/translate/translate_internals/translate_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_TRANSLATE_INTERNALS_JS" file="../../components/translate/translate_internals/translate_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_UKM_INTERNALS_HTML" file="../../components/ukm/debug/ukm_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_UKM_INTERNALS_JS" file="../../components/ukm/debug/ukm_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
+ <include name="IDR_UKM_INTERNALS_CSS" file="../../components/ukm/debug/ukm_internals.css" flattenhtml="true" compress="gzip" type="BINDATA" />
+ </includes>
+ </release>
+</grit>
diff --git a/chromium/chrome/browser/devtools/BUILD.gn b/chromium/chrome/browser/devtools/BUILD.gn
index fbdc1752d9f..26ff8701508 100644
--- a/chromium/chrome/browser/devtools/BUILD.gn
+++ b/chromium/chrome/browser/devtools/BUILD.gn
@@ -44,19 +44,13 @@ if (!is_android) {
action("concatenate_protocols") {
script = _inspector_protocol + "/concatenate_protocols.py"
- deps = [
- "//third_party/blink/public/devtools_protocol:protocol_version",
- ]
+ deps = [ "//third_party/blink/public/devtools_protocol:protocol_version" ]
_blink_protocol_path =
"$root_gen_dir/third_party/blink/public/devtools_protocol/protocol.json"
- inputs = [
- _blink_protocol_path,
- ]
+ inputs = [ _blink_protocol_path ]
output_file = _concatenated_protocol_path
- outputs = [
- output_file,
- ]
+ outputs = [ output_file ]
args = [ rebase_path(_blink_protocol_path, root_build_dir) ]
if (is_chromeos) {
@@ -70,9 +64,7 @@ if (!is_android) {
inspector_protocol_generate("protocol_generated_sources") {
inspector_protocol_dir = _inspector_protocol
visibility = [ ":*" ] # Only targets in this file can depend on this.
- deps = [
- ":concatenate_protocols",
- ]
+ deps = [ ":concatenate_protocols" ]
out_dir = target_gen_dir
config_file = "inspector_protocol_config.json"
@@ -119,6 +111,7 @@ static_library("devtools") {
"//skia",
"//third_party/icu",
"//third_party/leveldatabase",
+ "//ui/base/mojom:cursor_type",
]
sources += [
"chrome_devtools_manager_delegate.cc",
@@ -202,6 +195,7 @@ static_library("devtools") {
if (!is_android) {
deps += [
":protocol_generated_sources",
+ "//components/subresource_filter/content/browser:browser",
"//third_party/inspector_protocol:crdtp",
]
sources += [
diff --git a/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
index 34d0e9675b4..f7844f6f885 100644
--- a/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
+++ b/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -23,12 +23,17 @@
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/grit/browser_resources.h"
#include "components/guest_view/browser/guest_view_base.h"
+#include "components/keep_alive_registry/keep_alive_types.h"
+#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "content/public/browser/devtools_agent_host.h"
+#include "content/public/browser/devtools_agent_host_client_channel.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/process_manager.h"
@@ -87,6 +92,18 @@ ChromeDevToolsManagerDelegate* ChromeDevToolsManagerDelegate::GetInstance() {
ChromeDevToolsManagerDelegate::ChromeDevToolsManagerDelegate() {
DCHECK(!g_instance);
g_instance = this;
+
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kNoStartupWindow) &&
+ (command_line->HasSwitch(switches::kRemoteDebuggingPipe) ||
+ command_line->HasSwitch(switches::kRemoteDebuggingPort))) {
+ // If running without a startup window with remote debugging,
+ // we are controlled entirely by the automation process.
+ // Keep the application running until explicit close through DevTools
+ // protocol.
+ keep_alive_.reset(new ScopedKeepAlive(KeepAliveOrigin::REMOTE_DEBUGGING,
+ KeepAliveRestartOption::DISABLED));
+ }
}
ChromeDevToolsManagerDelegate::~ChromeDevToolsManagerDelegate() {
@@ -100,19 +117,18 @@ void ChromeDevToolsManagerDelegate::Inspect(
}
void ChromeDevToolsManagerDelegate::HandleCommand(
- DevToolsAgentHost* agent_host,
- content::DevToolsAgentHostClient* client,
- const std::string& method,
- const std::string& message,
+ content::DevToolsAgentHostClientChannel* channel,
+ base::span<const uint8_t> message,
NotHandledCallback callback) {
- if (sessions_.find(client) == sessions_.end()) {
+ auto it = sessions_.find(channel);
+ if (it == sessions_.end()) {
std::move(callback).Run(message);
// This should not happen, but happens. NOTREACHED tries to get
// a repro in some test.
NOTREACHED();
return;
}
- sessions_[client]->HandleCommand(method, message, std::move(callback));
+ it->second->HandleCommand(message, std::move(callback));
}
std::string ChromeDevToolsManagerDelegate::GetTargetType(
@@ -201,17 +217,14 @@ bool ChromeDevToolsManagerDelegate::AllowInspection(
}
void ChromeDevToolsManagerDelegate::ClientAttached(
- content::DevToolsAgentHost* agent_host,
- content::DevToolsAgentHostClient* client) {
- DCHECK(sessions_.find(client) == sessions_.end());
- sessions_[client] =
- std::make_unique<ChromeDevToolsSession>(agent_host, client);
+ content::DevToolsAgentHostClientChannel* channel) {
+ DCHECK(sessions_.find(channel) == sessions_.end());
+ sessions_.emplace(channel, std::make_unique<ChromeDevToolsSession>(channel));
}
void ChromeDevToolsManagerDelegate::ClientDetached(
- content::DevToolsAgentHost* agent_host,
- content::DevToolsAgentHostClient* client) {
- sessions_.erase(client);
+ content::DevToolsAgentHostClientChannel* channel) {
+ sessions_.erase(channel);
}
scoped_refptr<DevToolsAgentHost>
@@ -321,3 +334,9 @@ void ChromeDevToolsManagerDelegate::ResetAndroidDeviceManagerForTesting() {
// task using a raw pointer to the DeviceManager we just deleted.
device_discovery_.reset();
}
+
+void ChromeDevToolsManagerDelegate::BrowserCloseRequested() {
+ // Do not keep the application running anymore, we got an explicit request
+ // to close.
+ keep_alive_.reset();
+}
diff --git a/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h b/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h
index 0e7bdc0eb74..d552030f68c 100644
--- a/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h
+++ b/chromium/chrome/browser/devtools/chrome_devtools_manager_delegate.h
@@ -20,6 +20,7 @@
#include "net/base/host_port_pair.h"
class ChromeDevToolsSession;
+class ScopedKeepAlive;
using RemoteLocations = std::set<net::HostPortPair>;
namespace extensions {
@@ -53,15 +54,15 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
std::vector<content::BrowserContext*> GetBrowserContexts() override;
content::BrowserContext* GetDefaultBrowserContext() override;
+ void BrowserCloseRequested();
+
private:
friend class DevToolsManagerDelegateTest;
// content::DevToolsManagerDelegate implementation.
void Inspect(content::DevToolsAgentHost* agent_host) override;
- void HandleCommand(content::DevToolsAgentHost* agent_host,
- content::DevToolsAgentHostClient* client,
- const std::string& method,
- const std::string& message,
+ void HandleCommand(content::DevToolsAgentHostClientChannel* channel,
+ base::span<const uint8_t> message,
NotHandledCallback callback) override;
std::string GetTargetType(content::WebContents* web_contents) override;
std::string GetTargetTitle(content::WebContents* web_contents) override;
@@ -71,10 +72,10 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
DisposeCallback callback) override;
bool AllowInspectingRenderFrameHost(content::RenderFrameHost* rfh) override;
- void ClientAttached(content::DevToolsAgentHost* agent_host,
- content::DevToolsAgentHostClient* client) override;
- void ClientDetached(content::DevToolsAgentHost* agent_host,
- content::DevToolsAgentHostClient* client) override;
+ void ClientAttached(
+ content::DevToolsAgentHostClientChannel* channel) override;
+ void ClientDetached(
+ content::DevToolsAgentHostClientChannel* channel) override;
scoped_refptr<content::DevToolsAgentHost> CreateNewTarget(
const GURL& url) override;
std::string GetDiscoveryPageHTML() override;
@@ -83,7 +84,7 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
void DevicesAvailable(
const DevToolsDeviceDiscovery::CompleteDevices& devices);
- std::map<content::DevToolsAgentHostClient*,
+ std::map<content::DevToolsAgentHostClientChannel*,
std::unique_ptr<ChromeDevToolsSession>>
sessions_;
@@ -91,6 +92,7 @@ class ChromeDevToolsManagerDelegate : public content::DevToolsManagerDelegate {
std::unique_ptr<DevToolsDeviceDiscovery> device_discovery_;
content::DevToolsAgentHost::List remote_agent_hosts_;
RemoteLocations remote_locations_;
+ std::unique_ptr<ScopedKeepAlive> keep_alive_;
DISALLOW_COPY_AND_ASSIGN(ChromeDevToolsManagerDelegate);
};
diff --git a/chromium/chrome/browser/devtools/chrome_devtools_session.cc b/chromium/chrome/browser/devtools/chrome_devtools_session.cc
index 66328d8eaff..018463fda2a 100644
--- a/chromium/chrome/browser/devtools/chrome_devtools_session.cc
+++ b/chromium/chrome/browser/devtools/chrome_devtools_session.cc
@@ -13,30 +13,31 @@
#include "chrome/browser/devtools/protocol/target_handler.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_agent_host_client.h"
+#include "content/public/browser/devtools_agent_host_client_channel.h"
#include "content/public/browser/devtools_manager_delegate.h"
-#include "third_party/inspector_protocol/crdtp/json.h"
+#include "third_party/inspector_protocol/crdtp/dispatch.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/devtools/protocol/window_manager_handler.h"
#endif
ChromeDevToolsSession::ChromeDevToolsSession(
- content::DevToolsAgentHost* agent_host,
- content::DevToolsAgentHostClient* client)
- : agent_host_(agent_host), client_(client), dispatcher_(this) {
+ content::DevToolsAgentHostClientChannel* channel)
+ : dispatcher_(this), client_channel_(channel) {
+ content::DevToolsAgentHost* agent_host = channel->GetAgentHost();
if (agent_host->GetWebContents() &&
agent_host->GetType() == content::DevToolsAgentHost::kTypePage) {
page_handler_ = std::make_unique<PageHandler>(agent_host->GetWebContents(),
&dispatcher_);
security_handler_ = std::make_unique<SecurityHandler>(
agent_host->GetWebContents(), &dispatcher_);
- if (client->MayAttachToBrowser()) {
+ if (channel->GetClient()->MayAttachToBrowser()) {
cast_handler_ = std::make_unique<CastHandler>(
agent_host->GetWebContents(), &dispatcher_);
}
}
target_handler_ = std::make_unique<TargetHandler>(&dispatcher_);
- if (client->MayAttachToBrowser()) {
+ if (channel->GetClient()->MayAttachToBrowser()) {
browser_handler_ =
std::make_unique<BrowserHandler>(&dispatcher_, agent_host->GetId());
}
@@ -49,61 +50,39 @@ ChromeDevToolsSession::ChromeDevToolsSession(
ChromeDevToolsSession::~ChromeDevToolsSession() = default;
void ChromeDevToolsSession::HandleCommand(
- const std::string& method,
- const std::string& message,
+ base::span<const uint8_t> message,
content::DevToolsManagerDelegate::NotHandledCallback callback) {
- if (!dispatcher_.canDispatch(method)) {
+ crdtp::Dispatchable dispatchable(crdtp::SpanFrom(message));
+ DCHECK(dispatchable.ok()); // Checked by content::DevToolsSession.
+ crdtp::UberDispatcher::DispatchResult dispatched =
+ dispatcher_.Dispatch(dispatchable);
+ if (!dispatched.MethodFound()) {
std::move(callback).Run(message);
return;
}
-
- int call_id;
- std::string unused;
- std::unique_ptr<protocol::DictionaryValue> value =
- protocol::DictionaryValue::cast(
- protocol::StringUtil::parseMessage(message, /*binary=*/true));
- if (!dispatcher_.parseCommand(value.get(), &call_id, &unused))
- return;
- pending_commands_[call_id] = std::move(callback);
- dispatcher_.dispatch(call_id, method, std::move(value), message);
+ pending_commands_[dispatchable.CallId()] = std::move(callback);
+ dispatched.Run();
}
// The following methods handle responses or notifications coming from
// the browser to the client.
-static void SendProtocolResponseOrNotification(
- content::DevToolsAgentHostClient* client,
- content::DevToolsAgentHost* agent_host,
- std::unique_ptr<protocol::Serializable> message) {
- std::vector<uint8_t> cbor = std::move(*message).TakeSerialized();
- if (client->UsesBinaryProtocol()) {
- client->DispatchProtocolMessage(agent_host,
- std::string(cbor.begin(), cbor.end()));
- return;
- }
- std::string json;
- crdtp::Status status =
- crdtp::json::ConvertCBORToJSON(crdtp::SpanFrom(cbor), &json);
- LOG_IF(ERROR, !status.ok()) << status.ToASCIIString();
- client->DispatchProtocolMessage(agent_host, json);
-}
-
-void ChromeDevToolsSession::sendProtocolResponse(
+void ChromeDevToolsSession::SendProtocolResponse(
int call_id,
std::unique_ptr<protocol::Serializable> message) {
pending_commands_.erase(call_id);
- SendProtocolResponseOrNotification(client_, agent_host_, std::move(message));
+ client_channel_->DispatchProtocolMessageToClient(message->Serialize());
}
-void ChromeDevToolsSession::sendProtocolNotification(
+void ChromeDevToolsSession::SendProtocolNotification(
std::unique_ptr<protocol::Serializable> message) {
- SendProtocolResponseOrNotification(client_, agent_host_, std::move(message));
+ client_channel_->DispatchProtocolMessageToClient(message->Serialize());
}
-void ChromeDevToolsSession::flushProtocolNotifications() {}
+void ChromeDevToolsSession::FlushProtocolNotifications() {}
-void ChromeDevToolsSession::fallThrough(int call_id,
- const std::string& method,
- const std::string& message) {
+void ChromeDevToolsSession::FallThrough(int call_id,
+ crdtp::span<uint8_t> method,
+ crdtp::span<uint8_t> message) {
auto callback = std::move(pending_commands_[call_id]);
pending_commands_.erase(call_id);
std::move(callback).Run(message);
diff --git a/chromium/chrome/browser/devtools/chrome_devtools_session.h b/chromium/chrome/browser/devtools/chrome_devtools_session.h
index 56394c83a1d..1e67e00453e 100644
--- a/chromium/chrome/browser/devtools/chrome_devtools_session.h
+++ b/chromium/chrome/browser/devtools/chrome_devtools_session.h
@@ -15,9 +15,8 @@
#include "content/public/browser/devtools_manager_delegate.h"
namespace content {
-class DevToolsAgentHost;
-class DevToolsAgentHostClient;
-}
+class DevToolsAgentHostClientChannel;
+} // namespace content
class BrowserHandler;
class CastHandler;
@@ -28,31 +27,28 @@ class WindowManagerHandler;
class ChromeDevToolsSession : public protocol::FrontendChannel {
public:
- ChromeDevToolsSession(content::DevToolsAgentHost* agent_host,
- content::DevToolsAgentHostClient* client);
+ explicit ChromeDevToolsSession(
+ content::DevToolsAgentHostClientChannel* channel);
~ChromeDevToolsSession() override;
void HandleCommand(
- const std::string& method,
- const std::string& message,
+ base::span<const uint8_t> message,
content::DevToolsManagerDelegate::NotHandledCallback callback);
TargetHandler* target_handler() { return target_handler_.get(); }
private:
// protocol::FrontendChannel:
- void sendProtocolResponse(
+ void SendProtocolResponse(
int call_id,
std::unique_ptr<protocol::Serializable> message) override;
- void sendProtocolNotification(
+ void SendProtocolNotification(
std::unique_ptr<protocol::Serializable> message) override;
- void flushProtocolNotifications() override;
- void fallThrough(int call_id,
- const std::string& method,
- const std::string& message) override;
+ void FlushProtocolNotifications() override;
+ void FallThrough(int call_id,
+ crdtp::span<uint8_t> method,
+ crdtp::span<uint8_t> message) override;
- content::DevToolsAgentHost* const agent_host_;
- content::DevToolsAgentHostClient* const client_;
base::flat_map<int, content::DevToolsManagerDelegate::NotHandledCallback>
pending_commands_;
@@ -65,6 +61,7 @@ class ChromeDevToolsSession : public protocol::FrontendChannel {
#if defined(OS_CHROMEOS)
std::unique_ptr<WindowManagerHandler> window_manager_handler_;
#endif
+ content::DevToolsAgentHostClientChannel* client_channel_;
DISALLOW_COPY_AND_ASSIGN(ChromeDevToolsSession);
};
diff --git a/chromium/chrome/browser/devtools/device/android_device_manager.cc b/chromium/chrome/browser/devtools/device/android_device_manager.cc
index 4c4cf0b8584..bbf6bc5750e 100644
--- a/chromium/chrome/browser/devtools/device/android_device_manager.cc
+++ b/chromium/chrome/browser/devtools/device/android_device_manager.cc
@@ -18,6 +18,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/devtools/device/usb/usb_device_manager_helper.h"
@@ -541,10 +542,10 @@ AndroidDeviceManager::HandlerThread::~HandlerThread() {
if (!thread_)
return;
// Shut down thread on a thread other than UI so it can join a thread.
- base::PostTask(FROM_HERE,
- {base::ThreadPool(), base::WithBaseSyncPrimitives(),
- base::TaskPriority::BEST_EFFORT},
- base::BindOnce(&HandlerThread::StopThread, thread_));
+ base::ThreadPool::PostTask(
+ FROM_HERE,
+ {base::WithBaseSyncPrimitives(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&HandlerThread::StopThread, thread_));
}
// static
diff --git a/chromium/chrome/browser/devtools/device/devtools_device_discovery.cc b/chromium/chrome/browser/devtools/device/devtools_device_discovery.cc
index b623a1475a4..42cedd7c4a6 100644
--- a/chromium/chrome/browser/devtools/device/devtools_device_discovery.cc
+++ b/chromium/chrome/browser/devtools/device/devtools_device_discovery.cc
@@ -121,14 +121,15 @@ class WebSocketProxy : public AndroidDeviceManager::AndroidWebSocket::Delegate {
}
void OnFrameRead(const std::string& message) override {
- proxy_->DispatchOnClientHost(message);
+ proxy_->DispatchOnClientHost(base::as_bytes(base::make_span(message)));
}
void OnSocketClosed() override {
- std::string message =
- "{ \"method\": \"Inspector.detached\", "
- "\"params\": { \"reason\": \"Connection lost.\"} }";
- proxy_->DispatchOnClientHost(message);
+ constexpr char kMsg[] =
+ "{\"method\":\"Inspector.detached\",\"params\":"
+ "{\"reason\":\"Connection lost.\"}}";
+ proxy_->DispatchOnClientHost(
+ base::as_bytes(base::make_span(kMsg, strlen(kMsg))));
web_socket_.reset();
socket_opened_ = false;
proxy_->ConnectionClosed(); // Deletes |this|.
@@ -176,7 +177,7 @@ class AgentHostDelegate : public content::DevToolsExternalAgentProxyDelegate {
bool Close() override;
base::TimeTicks GetLastActivityTime() override;
void SendMessageToBackend(content::DevToolsExternalAgentProxy* proxy,
- const std::string& message) override;
+ base::span<const uint8_t> message) override;
scoped_refptr<AndroidDeviceManager::Device> device_;
std::string browser_id_;
@@ -354,12 +355,12 @@ base::TimeTicks AgentHostDelegate::GetLastActivityTime() {
void AgentHostDelegate::SendMessageToBackend(
content::DevToolsExternalAgentProxy* proxy,
- const std::string& message) {
+ base::span<const uint8_t> message) {
auto it = proxies_.find(proxy);
// We could have detached due to physical connection being closed.
if (it == proxies_.end())
return;
- it->second->SendMessageToBackend(message);
+ it->second->SendMessageToBackend(std::string(message.begin(), message.end()));
}
} // namespace
diff --git a/chromium/chrome/browser/devtools/device/tcp_device_provider.cc b/chromium/chrome/browser/devtools/device/tcp_device_provider.cc
index 9c6878f2966..52c3216c503 100644
--- a/chromium/chrome/browser/devtools/device/tcp_device_provider.cc
+++ b/chromium/chrome/browser/devtools/device/tcp_device_provider.cc
@@ -43,17 +43,25 @@ static void RunSocketCallback(
class ResolveHostAndOpenSocket final : public network::ResolveHostClientBase {
public:
- ResolveHostAndOpenSocket(
- const net::HostPortPair& address,
- const AdbClientSocket::SocketCallback& callback,
- mojo::Remote<network::mojom::HostResolver>* host_resolver)
+ ResolveHostAndOpenSocket(const net::HostPortPair& address,
+ const AdbClientSocket::SocketCallback& callback)
: callback_(callback) {
+ mojo::Remote<network::mojom::HostResolver> resolver;
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(
+ [](mojo::PendingReceiver<network::mojom::HostResolver>
+ pending_receiver) {
+ g_browser_process->system_network_context_manager()
+ ->GetContext()
+ ->CreateHostResolver(base::nullopt,
+ std::move(pending_receiver));
+ },
+ resolver.BindNewPipeAndPassReceiver()));
// Fine to use a transient NetworkIsolationKey here - this is for debugging,
// so performance doesn't matter, and it doesn't need to share a DNS cache
// with anything else.
- (*host_resolver)
- ->ResolveHost(address, net::NetworkIsolationKey::CreateTransient(),
- nullptr, receiver_.BindNewPipeAndPassRemote());
+ resolver->ResolveHost(address, net::NetworkIsolationKey::CreateTransient(),
+ nullptr, receiver_.BindNewPipeAndPassRemote());
receiver_.set_disconnect_handler(
base::BindOnce(&ResolveHostAndOpenSocket::OnComplete,
base::Unretained(this), net::ERR_NAME_NOT_RESOLVED,
@@ -139,15 +147,7 @@ void TCPDeviceProvider::OpenSocket(const std::string& serial,
// (debugging purposes).
int port;
base::StringToInt(socket_name, &port);
- net::HostPortPair host_port(serial, port);
-
- // OpenSocket() is run on the devtools ADB thread, while TCPDeviceProvider is
- // created on the UI thread, so do any initialization of |host_resolver_|
- // here.
- if (!host_resolver_) {
- InitializeHostResolver();
- }
- new ResolveHostAndOpenSocket(host_port, callback, &host_resolver_);
+ new ResolveHostAndOpenSocket(net::HostPortPair(serial, port), callback);
}
void TCPDeviceProvider::ReleaseDevice(const std::string& serial) {
@@ -162,20 +162,3 @@ void TCPDeviceProvider::set_release_callback_for_test(
TCPDeviceProvider::~TCPDeviceProvider() {
}
-
-void TCPDeviceProvider::InitializeHostResolver() {
- host_resolver_.reset();
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&TCPDeviceProvider::InitializeHostResolverOnUI, this,
- host_resolver_.BindNewPipeAndPassReceiver()));
- host_resolver_.set_disconnect_handler(base::BindOnce(
- &TCPDeviceProvider::InitializeHostResolver, base::Unretained(this)));
-}
-
-void TCPDeviceProvider::InitializeHostResolverOnUI(
- mojo::PendingReceiver<network::mojom::HostResolver> receiver) {
- g_browser_process->system_network_context_manager()
- ->GetContext()
- ->CreateHostResolver(base::nullopt, std::move(receiver));
-}
diff --git a/chromium/chrome/browser/devtools/device/tcp_device_provider.h b/chromium/chrome/browser/devtools/device/tcp_device_provider.h
index 17dea4f6d02..a15bca62748 100644
--- a/chromium/chrome/browser/devtools/device/tcp_device_provider.h
+++ b/chromium/chrome/browser/devtools/device/tcp_device_provider.h
@@ -13,10 +13,8 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/host_port_pair.h"
-#include "services/network/public/mojom/host_resolver.mojom.h"
+#include "services/network/public/mojom/host_resolver.mojom-forward.h"
-// Instantiate this class only in a test and/or when the DEBUG_DEVTOOLS
-// BUILDFLAG is set.
class TCPDeviceProvider : public AndroidDeviceManager::DeviceProvider {
public:
static scoped_refptr<TCPDeviceProvider> CreateForLocalhost(uint16_t port);
@@ -42,13 +40,8 @@ class TCPDeviceProvider : public AndroidDeviceManager::DeviceProvider {
private:
~TCPDeviceProvider() override;
- void InitializeHostResolver();
- void InitializeHostResolverOnUI(
- mojo::PendingReceiver<network::mojom::HostResolver> receiver);
-
HostPortSet targets_;
base::Closure release_callback_;
- mojo::Remote<network::mojom::HostResolver> host_resolver_;
};
#endif // CHROME_BROWSER_DEVTOOLS_DEVICE_TCP_DEVICE_PROVIDER_H_
diff --git a/chromium/chrome/browser/devtools/device/usb/android_usb_browsertest.cc b/chromium/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
index aecce8b5966..e61c5eb8b6a 100644
--- a/chromium/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
+++ b/chromium/chrome/browser/devtools/device/usb/android_usb_browsertest.cc
@@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/containers/queue.h"
#include "base/location.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
diff --git a/chromium/chrome/browser/devtools/device/usb/android_usb_device.h b/chromium/chrome/browser/devtools/device/usb/android_usb_device.h
index 3a66cdba358..195aa9bb7d0 100644
--- a/chromium/chrome/browser/devtools/device/usb/android_usb_device.h
+++ b/chromium/chrome/browser/devtools/device/usb/android_usb_device.h
@@ -19,7 +19,7 @@
#include "base/memory/weak_ptr.h"
#include "chrome/browser/devtools/device/usb/usb_device_manager_helper.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/device/public/mojom/usb_device.mojom.h"
+#include "services/device/public/mojom/usb_device.mojom-forward.h"
namespace base {
class RefCountedBytes;
diff --git a/chromium/chrome/browser/devtools/device/usb/usb_device_manager_helper.cc b/chromium/chrome/browser/devtools/device/usb/usb_device_manager_helper.cc
index b45c11ae051..fcc10845fc9 100644
--- a/chromium/chrome/browser/devtools/device/usb/usb_device_manager_helper.cc
+++ b/chromium/chrome/browser/devtools/device/usb/usb_device_manager_helper.cc
@@ -13,13 +13,11 @@
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/system_connector.h"
+#include "content/public/browser/device_service.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/usb_enumeration_options.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
using device::mojom::UsbTransferDirection;
using device::mojom::UsbTransferType;
@@ -109,8 +107,7 @@ void BindDeviceServiceOnUIThread(
mojo::PendingReceiver<device::mojom::UsbDeviceManager> receiver) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// Bind to the DeviceService for USB device manager.
- content::GetSystemConnector()->Connect(device::mojom::kServiceName,
- std::move(receiver));
+ content::GetDeviceService().BindUsbDeviceManager(std::move(receiver));
}
} // namespace
diff --git a/chromium/chrome/browser/devtools/devtools_auto_opener.cc b/chromium/chrome/browser/devtools/devtools_auto_opener.cc
index f08d593bfd7..f4aa8a7041a 100644
--- a/chromium/chrome/browser/devtools/devtools_auto_opener.cc
+++ b/chromium/chrome/browser/devtools/devtools_auto_opener.cc
@@ -8,7 +8,7 @@
#include "chrome/browser/devtools/devtools_window.h"
DevToolsAutoOpener::DevToolsAutoOpener()
- : browser_tab_strip_tracker_(this, nullptr, nullptr) {
+ : browser_tab_strip_tracker_(this, nullptr) {
browser_tab_strip_tracker_.Init();
}
diff --git a/chromium/chrome/browser/devtools/devtools_browser_context_manager.cc b/chromium/chrome/browser/devtools/devtools_browser_context_manager.cc
index fddd8e01c52..acccd7533a6 100644
--- a/chromium/chrome/browser/devtools/devtools_browser_context_manager.cc
+++ b/chromium/chrome/browser/devtools/devtools_browser_context_manager.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window.h"
DevToolsBrowserContextManager::DevToolsBrowserContextManager() {}
@@ -101,9 +102,17 @@ void DevToolsBrowserContextManager::DisposeBrowserContext(
void DevToolsBrowserContextManager::OnOriginalProfileDestroyed(
Profile* profile) {
- base::EraseIf(registrations_, [&profile](const auto& it) {
- return it.second->profile()->GetOriginalProfile() == profile;
- });
+ // This is likely happening during shutdown. We'll immediately
+ // close all browser windows for our profile without unload handling.
+ BrowserList::BrowserVector browsers_to_close;
+ for (auto* browser : *BrowserList::GetInstance()) {
+ if (browser->profile() == profile)
+ browsers_to_close.push_back(browser);
+ }
+ for (auto* browser : browsers_to_close)
+ browser->window()->Close();
+ std::string context_id = profile->UniqueId();
+ registrations_.erase(context_id);
}
void DevToolsBrowserContextManager::OnBrowserRemoved(Browser* browser) {
diff --git a/chromium/chrome/browser/devtools/devtools_browser_context_manager.h b/chromium/chrome/browser/devtools/devtools_browser_context_manager.h
index cf1b24df30a..5f413aa5091 100644
--- a/chromium/chrome/browser/devtools/devtools_browser_context_manager.h
+++ b/chromium/chrome/browser/devtools/devtools_browser_context_manager.h
@@ -7,7 +7,7 @@
#include "base/memory/weak_ptr.h"
#include "base/no_destructor.h"
-#include "chrome/browser/media/router/presentation/independent_otr_profile_manager.h"
+#include "chrome/browser/profiles/independent_otr_profile_manager.h"
#include "content/public/browser/devtools_manager_delegate.h"
class DevToolsBrowserContextManager : public BrowserListObserver {
diff --git a/chromium/chrome/browser/devtools/devtools_eye_dropper.cc b/chromium/chrome/browser/devtools/devtools_eye_dropper.cc
index 9c37d658ddc..a3b4d68b1b2 100644
--- a/chromium/chrome/browser/devtools/devtools_eye_dropper.cc
+++ b/chromium/chrome/browser/devtools/devtools_eye_dropper.cc
@@ -16,18 +16,19 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
-#include "content/public/common/cursor_info.h"
#include "content/public/common/screen_info.h"
#include "media/base/limits.h"
#include "media/base/video_frame.h"
#include "media/capture/mojom/video_capture_types.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "third_party/blink/public/platform/web_input_event.h"
-#include "third_party/blink/public/platform/web_mouse_event.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
+#include "third_party/blink/public/common/input/web_mouse_event.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPixmap.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/mojom/cursor_type.mojom-shared.h"
#include "ui/gfx/geometry/size_conversions.h"
DevToolsEyeDropper::DevToolsEyeDropper(content::WebContents* web_contents,
@@ -80,9 +81,8 @@ void DevToolsEyeDropper::DetachFromHost() {
if (!host_)
return;
host_->RemoveMouseEventCallback(mouse_event_callback_);
- content::CursorInfo cursor_info;
- cursor_info.type = ui::CursorType::kPointer;
- host_->SetCursor(cursor_info);
+ ui::Cursor cursor(ui::mojom::CursorType::kPointer);
+ host_->SetCursor(cursor);
video_capturer_.reset();
host_ = nullptr;
}
@@ -115,8 +115,8 @@ void DevToolsEyeDropper::ResetFrame() {
}
bool DevToolsEyeDropper::HandleMouseEvent(const blink::WebMouseEvent& event) {
- last_cursor_x_ = event.PositionInWidget().x;
- last_cursor_y_ = event.PositionInWidget().y;
+ last_cursor_x_ = event.PositionInWidget().x();
+ last_cursor_y_ = event.PositionInWidget().y();
if (frame_.drawsNothing())
return true;
@@ -254,13 +254,12 @@ void DevToolsEyeDropper::UpdateCursor() {
paint.setAntiAlias(true);
canvas.drawCircle(kCursorSize / 2, kCursorSize / 2, kDiameter / 2, paint);
- content::CursorInfo cursor_info;
- cursor_info.type = ui::CursorType::kCustom;
- cursor_info.image_scale_factor = device_scale_factor;
- cursor_info.custom_image = result;
- cursor_info.hotspot = gfx::Point(kHotspotOffset * device_scale_factor,
- kHotspotOffset * device_scale_factor);
- host_->SetCursor(cursor_info);
+ ui::Cursor cursor(ui::mojom::CursorType::kCustom);
+ cursor.set_image_scale_factor(device_scale_factor);
+ cursor.set_custom_bitmap(result);
+ cursor.set_custom_hotspot(gfx::Point(kHotspotOffset * device_scale_factor,
+ kHotspotOffset * device_scale_factor));
+ host_->SetCursor(cursor);
}
void DevToolsEyeDropper::OnFrameCaptured(
diff --git a/chromium/chrome/browser/devtools/devtools_eye_dropper.h b/chromium/chrome/browser/devtools/devtools_eye_dropper.h
index e032ee05c8c..1db457ee152 100644
--- a/chromium/chrome/browser/devtools/devtools_eye_dropper.h
+++ b/chromium/chrome/browser/devtools/devtools_eye_dropper.h
@@ -51,6 +51,7 @@ class DevToolsEyeDropper : public content::WebContentsObserver,
mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
callbacks) override;
void OnStopped() override;
+ void OnLog(const std::string& /*message*/) override {}
EyeDropperCallback callback_;
SkBitmap frame_;
diff --git a/chromium/chrome/browser/devtools/devtools_file_helper.cc b/chromium/chrome/browser/devtools/devtools_file_helper.cc
index 30c088b5c98..1b441f5cc4d 100644
--- a/chromium/chrome/browser/devtools/devtools_file_helper.cc
+++ b/chromium/chrome/browser/devtools/devtools_file_helper.cc
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/value_conversions.h"
#include "chrome/browser/browser_process.h"
@@ -54,6 +55,7 @@ namespace {
static const char kRootName[] = "<root>";
static const char kPermissionDenied[] = "<permission denied>";
+static const char kSelectionCancelled[] = "<selection cancelled>";
base::LazyInstance<base::FilePath>::Leaky
g_last_save_path = LAZY_INSTANCE_INITIALIZER;
@@ -219,8 +221,8 @@ DevToolsFileHelper::DevToolsFileHelper(WebContents* web_contents,
: web_contents_(web_contents),
profile_(profile),
delegate_(delegate),
- file_task_runner_(base::CreateSequencedTaskRunner(
- {base::ThreadPool(), base::MayBlock()})) {
+ file_task_runner_(
+ base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})) {
pref_change_registrar_.Init(profile_->GetPrefs());
}
@@ -312,7 +314,7 @@ void DevToolsFileHelper::AddFileSystem(
Bind(&DevToolsFileHelper::InnerAddFileSystem, weak_factory_.GetWeakPtr(),
show_info_bar_callback, type),
Bind(&DevToolsFileHelper::FailedToAddFileSystem,
- weak_factory_.GetWeakPtr(), kPermissionDenied),
+ weak_factory_.GetWeakPtr(), kSelectionCancelled),
web_contents_);
select_file_dialog->Show(ui::SelectFileDialog::SELECT_FOLDER,
base::FilePath());
diff --git a/chromium/chrome/browser/devtools/devtools_file_system_indexer.cc b/chromium/chrome/browser/devtools/devtools_file_system_indexer.cc
index 9e97b8e3d52..edfb536146d 100644
--- a/chromium/chrome/browser/devtools/devtools_file_system_indexer.cc
+++ b/chromium/chrome/browser/devtools/devtools_file_system_indexer.cc
@@ -19,7 +19,7 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/lazy_task_runner.h"
+#include "base/task/lazy_thread_pool_task_runner.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
@@ -43,9 +43,9 @@ using std::set;
base::SequencedTaskRunner* impl_task_runner() {
constexpr base::TaskTraits kBlockingTraits = {
- base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT};
- static base::LazySequencedTaskRunner s_sequenced_task_task_runner =
- LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(kBlockingTraits);
+ base::MayBlock(), base::TaskPriority::BEST_EFFORT};
+ static base::LazyThreadPoolSequencedTaskRunner s_sequenced_task_task_runner =
+ LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(kBlockingTraits);
return s_sequenced_task_task_runner.Get().get();
}
diff --git a/chromium/chrome/browser/devtools/devtools_file_watcher.cc b/chromium/chrome/browser/devtools/devtools_file_watcher.cc
index d0445ad346e..520315666e1 100644
--- a/chromium/chrome/browser/devtools/devtools_file_watcher.cc
+++ b/chromium/chrome/browser/devtools/devtools_file_watcher.cc
@@ -18,7 +18,7 @@
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/stringprintf.h"
-#include "base/task/lazy_task_runner.h"
+#include "base/task/lazy_thread_pool_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
@@ -225,9 +225,9 @@ void DevToolsFileWatcher::SharedFileWatcher::DispatchNotifications() {
namespace {
base::SequencedTaskRunner* impl_task_runner() {
constexpr base::TaskTraits kImplTaskTraits = {
- base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT};
- static base::LazySequencedTaskRunner s_file_task_runner =
- LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER(kImplTaskTraits);
+ base::MayBlock(), base::TaskPriority::BEST_EFFORT};
+ static base::LazyThreadPoolSequencedTaskRunner s_file_task_runner =
+ LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(kImplTaskTraits);
return s_file_task_runner.Get().get();
}
} // namespace
diff --git a/chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc
index 12f139b5b20..77b07b55303 100644
--- a/chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chromium/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -39,9 +39,11 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/lifetime/application_lifetime.h"
+#include "chrome/browser/lifetime/browser_shutdown.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/policy/developer_tools_policy_handler.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_list.h"
@@ -53,14 +55,16 @@
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/test_chrome_web_ui_controller_factory.h"
#include "chrome/test/base/ui_test_utils.h"
-#include "components/app_modal/javascript_app_modal_dialog.h"
-#include "components/app_modal/native_app_modal_dialog.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
#include "components/autofill/content/browser/content_autofill_driver_factory.h"
#include "components/autofill/core/browser/autofill_experiments.h"
#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_manager_test_delegate.h"
#include "components/autofill/core/common/autofill_features.h"
+#include "components/javascript_dialogs/app_modal_dialog_controller.h"
+#include "components/javascript_dialogs/app_modal_dialog_view.h"
+#include "components/keep_alive_registry/keep_alive_registry.h"
+#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/policy_constants.h"
@@ -100,7 +104,7 @@
#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
-#include "third_party/blink/public/platform/web_input_event.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/gl/gl_switches.h"
#include "url/gurl.h"
@@ -109,8 +113,6 @@
#include "chromeos/constants/chromeos_switches.h"
#endif
-using app_modal::JavaScriptAppModalDialog;
-using app_modal::NativeAppModalDialog;
using content::BrowserThread;
using content::DevToolsAgentHost;
using content::DevToolsAgentHostObserver;
@@ -118,6 +120,7 @@ using content::NavigationController;
using content::RenderFrameHost;
using content::WebContents;
using extensions::Extension;
+using javascript_dialogs::AppModalDialogView;
namespace {
@@ -394,20 +397,21 @@ class DevToolsBeforeUnloadTest: public DevToolsSanityTest {
}
void AcceptModalDialog() {
- NativeAppModalDialog* native_dialog = GetDialog();
- native_dialog->AcceptAppModalDialog();
+ AppModalDialogView* view = GetDialog();
+ view->AcceptAppModalDialog();
}
void CancelModalDialog() {
- NativeAppModalDialog* native_dialog = GetDialog();
- native_dialog->CancelAppModalDialog();
+ AppModalDialogView* view = GetDialog();
+ view->CancelAppModalDialog();
}
- NativeAppModalDialog* GetDialog() {
- JavaScriptAppModalDialog* dialog = ui_test_utils::WaitForAppModalDialog();
- NativeAppModalDialog* native_dialog = dialog->native_dialog();
- EXPECT_TRUE(native_dialog);
- return native_dialog;
+ AppModalDialogView* GetDialog() {
+ javascript_dialogs::AppModalDialogController* dialog =
+ ui_test_utils::WaitForAppModalDialog();
+ AppModalDialogView* view = dialog->view();
+ EXPECT_TRUE(view);
+ return view;
}
};
@@ -829,7 +833,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestShowScriptsTab) {
// hadn't been shown by the moment inspected paged refreshed.
// @see http://crbug.com/26312
// This test is flaky on windows and linux asan. See https://crbug.com/1013003
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
#define MAYBE_TestScriptsTabIsPopulatedOnInspectedPageRefresh \
DISABLED_TestScriptsTabIsPopulatedOnInspectedPageRefresh
#else
@@ -878,7 +882,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
// Now that we know the panel is loaded, switch to it.
SwitchToExtensionPanel(window_, extension, "iframe_panel");
- content::WaitForLoadStop(main_web_contents());
+ EXPECT_TRUE(content::WaitForLoadStop(main_web_contents()));
std::vector<RenderFrameHost*> rfhs = main_web_contents()->GetAllFrames();
EXPECT_EQ(7U, rfhs.size());
@@ -1053,7 +1057,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
// different from the extension's background page, are rendered in their own
// processes and not in the devtools process or the extension's process.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
- DISABLED_HttpIframeInDevToolsExtensionDevtools) {
+ HttpIframeInDevToolsExtensionDevtools) {
ASSERT_TRUE(embedded_test_server()->Start());
// Install the dynamically-generated extension.
@@ -1819,23 +1823,13 @@ class MAYBE_DevToolsReattachAfterCrashTest : public DevToolsSanityTest {
}
};
-// Crashes on Win. http://crbug.com/1025369
-#if defined(OS_WIN)
-#define MAYBE_TestReattachAfterCrashOnTimeline \
- DISABLED_TestReattachAfterCrashOnTimeline
-#define MAYBE_TestReattachAfterCrashOnNetwork \
- DISABLED_TestReattachAfterCrashOnNetwork
-#else
-#define MAYBE_TestReattachAfterCrashOnTimeline TestReattachAfterCrashOnTimeline
-#define MAYBE_TestReattachAfterCrashOnNetwork TestReattachAfterCrashOnNetwork
-#endif
IN_PROC_BROWSER_TEST_F(MAYBE_DevToolsReattachAfterCrashTest,
- MAYBE_TestReattachAfterCrashOnTimeline) {
+ TestReattachAfterCrashOnTimeline) {
RunTestWithPanel("timeline");
}
IN_PROC_BROWSER_TEST_F(MAYBE_DevToolsReattachAfterCrashTest,
- MAYBE_TestReattachAfterCrashOnNetwork) {
+ TestReattachAfterCrashOnNetwork) {
RunTestWithPanel("network");
}
@@ -1858,7 +1852,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, SecondTabAfterDevTools) {
browser(), spawned_test_server()->GetURL(kDebuggerTestPage),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB |
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
WebContents* second = browser()->tab_strip_model()->GetActiveWebContents();
scoped_refptr<content::DevToolsAgentHost> agent(
@@ -2284,7 +2278,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestOpenInNewTabFilter) {
TabStripModel* tabs = browser()->tab_strip_model();
int i = 0;
- for (const std::pair<const std::string, const std::string> pair : tests) {
+ for (const std::pair<const std::string, const std::string>& pair : tests) {
bindings_delegate_->OpenInNewTab(pair.first);
i++;
@@ -2351,7 +2345,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsSanityTest, InspectElement) {
navigation_manager.WaitForNavigationFinished();
navigation_manager_iframe.WaitForNavigationFinished();
- content::WaitForLoadStop(tab);
+ EXPECT_TRUE(content::WaitForLoadStop(tab));
std::vector<RenderFrameHost*> frames = GetInspectedTab()->GetAllFrames();
ASSERT_EQ(2u, frames.size());
@@ -2368,6 +2362,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsSanityTest, InspectElement) {
}
IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, BrowserCloseWithBeforeUnload) {
+ EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsOriginRegistered(
+ KeepAliveOrigin::REMOTE_DEBUGGING));
ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
ASSERT_TRUE(content::ExecuteScript(
@@ -2380,6 +2376,30 @@ IN_PROC_BROWSER_TEST_F(InProcessBrowserTest, BrowserCloseWithBeforeUnload) {
ui_test_utils::WaitForBrowserToClose(browser());
}
+class KeepAliveDevToolsTest : public InProcessBrowserTest {
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitchASCII(switches::kRemoteDebuggingPort, "0");
+ command_line->AppendSwitch(switches::kNoStartupWindow);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(KeepAliveDevToolsTest, KeepsAliveUntilBrowserClose) {
+ EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
+ EXPECT_TRUE(BrowserList::GetInstance()->empty());
+ EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+ EXPECT_TRUE(KeepAliveRegistry::GetInstance()->IsOriginRegistered(
+ KeepAliveOrigin::REMOTE_DEBUGGING));
+ chrome::NewEmptyWindow(ProfileManager::GetLastUsedProfile());
+ EXPECT_FALSE(BrowserList::GetInstance()->empty());
+ BrowserHandler handler(nullptr, std::string());
+ handler.Close();
+ ui_test_utils::WaitForBrowserToClose();
+ EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive());
+ EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsOriginRegistered(
+ KeepAliveOrigin::REMOTE_DEBUGGING));
+}
+
class DevToolsPolicyTest : public InProcessBrowserTest {
protected:
DevToolsPolicyTest() {
@@ -2395,7 +2415,7 @@ class DevToolsPolicyTest : public InProcessBrowserTest {
IN_PROC_BROWSER_TEST_F(DevToolsPolicyTest, OpenBlackListedDevTools) {
base::ListValue blacklist;
- blacklist.AppendString("chrome-devtools://*");
+ blacklist.AppendString("devtools://*");
policy::PolicyMap policies;
policies.Set(policy::key::kURLBlacklist, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
@@ -2435,7 +2455,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsSanityTest,
navigation_manager.WaitForNavigationFinished();
navigation_manager_iframe.WaitForNavigationFinished();
- content::WaitForLoadStop(tab);
+ EXPECT_TRUE(content::WaitForLoadStop(tab));
for (auto* frame : GetInspectedTab()->GetAllFrames()) {
content::WaitForHitTestData(frame);
diff --git a/chromium/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc b/chromium/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
index 08f6eeead21..edd506a4872 100644
--- a/chromium/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
+++ b/chromium/chrome/browser/devtools/devtools_sanity_interactive_browsertest.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
#include "chrome/test/base/in_process_browser_test.h"
+#include "ui/display/types/display_constants.h"
#if defined(OS_MACOSX)
#include "ui/base/test/scoped_fake_nswindow_fullscreen.h"
@@ -220,7 +221,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsManagerDelegateTest, ExitFullscreenWindow) {
ui::test::ScopedFakeNSWindowFullscreen faker;
#endif
browser()->window()->GetExclusiveAccessContext()->EnterFullscreen(
- GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE);
+ GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE, display::kInvalidDisplayId);
#if defined(OS_MACOSX)
faker.FinishTransition();
#endif
diff --git a/chromium/chrome/browser/devtools/devtools_ui_bindings.cc b/chromium/chrome/browser/devtools/devtools_ui_bindings.cc
index 8c98889eef8..a90e1cca42f 100644
--- a/chromium/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chromium/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -99,6 +99,8 @@ static const char kTitleFormat[] = "DevTools - %s";
static const char kDevToolsActionTakenHistogram[] = "DevTools.ActionTaken";
static const char kDevToolsPanelShownHistogram[] = "DevTools.PanelShown";
+static const char kDevToolsKeyboardShortcutFiredHistogram[] =
+ "DevTools.KeyboardShortcutFired";
static const char kRemotePageActionInspect[] = "inspect";
static const char kRemotePageActionReload[] = "reload";
@@ -123,13 +125,13 @@ typedef std::vector<DevToolsUIBindings*> DevToolsUIBindingsList;
base::LazyInstance<DevToolsUIBindingsList>::Leaky
g_devtools_ui_bindings_instances = LAZY_INSTANCE_INITIALIZER;
-std::unique_ptr<base::DictionaryValue> CreateFileSystemValue(
+base::DictionaryValue CreateFileSystemValue(
DevToolsFileHelper::FileSystem file_system) {
- auto file_system_value = std::make_unique<base::DictionaryValue>();
- file_system_value->SetString("type", file_system.type);
- file_system_value->SetString("fileSystemName", file_system.file_system_name);
- file_system_value->SetString("rootURL", file_system.root_url);
- file_system_value->SetString("fileSystemPath", file_system.file_system_path);
+ base::DictionaryValue file_system_value;
+ file_system_value.SetString("type", file_system.type);
+ file_system_value.SetString("fileSystemName", file_system.file_system_name);
+ file_system_value.SetString("rootURL", file_system.root_url);
+ file_system_value.SetString("fileSystemPath", file_system.file_system_path);
return file_system_value;
}
@@ -213,6 +215,7 @@ std::unique_ptr<base::DictionaryValue> BuildObjectForResponse(
}
response->SetInteger("statusCode", responseCode);
response->SetInteger("netError", net_error);
+ response->SetString("netErrorName", net::ErrorToString(net_error));
auto headers = std::make_unique<base::DictionaryValue>();
size_t iterator = 0;
@@ -321,9 +324,9 @@ std::string SanitizeFrontendQueryParam(
const std::string& key,
const std::string& value) {
// Convert boolean flags to true.
- if (key == "can_dock" || key == "debugFrontend" || key == "experiments" ||
- key == "isSharedWorker" || key == "v8only" || key == "remoteFrontend" ||
- key == "nodeFrontend" || key == "hasOtherClients" || key == "uiDevTools")
+ if (key == "can_dock" || key == "debugFrontend" || key == "isSharedWorker" ||
+ key == "v8only" || key == "remoteFrontend" || key == "nodeFrontend" ||
+ key == "hasOtherClients" || key == "uiDevTools")
return "true";
// Pass connection endpoints as is.
@@ -478,11 +481,10 @@ class DevToolsUIBindings::NetworkResourceLoader
} else {
chunkValue = base::Value(chunk);
}
- base::Value id(stream_id_);
- base::Value encodedValue(encoded);
- bindings_->CallClientFunction("DevToolsAPI.streamWrite", &id, &chunkValue,
- &encodedValue);
+ bindings_->CallClientMethod("DevToolsAPI", "streamWrite",
+ base::Value(stream_id_), chunkValue,
+ base::Value(encoded));
std::move(resume).Run();
}
@@ -707,27 +709,35 @@ void DevToolsUIBindings::HandleMessageFromDevToolsFrontend(
}
// content::DevToolsAgentHostClient implementation --------------------------
+// There is a sibling implementation of DevToolsAgentHostClient in
+// content/shell/browser/shell_devtools_bindings.cc
+// that is used in layout tests, which only use content_shell.
+// The two implementations needs to be kept in sync wrt. the interface they
+// provide to the DevTools front-end.
+
void DevToolsUIBindings::DispatchProtocolMessage(
- content::DevToolsAgentHost* agent_host, const std::string& message) {
+ content::DevToolsAgentHost* agent_host,
+ base::span<const uint8_t> message) {
DCHECK(agent_host == agent_host_.get());
if (!frontend_host_)
return;
- if (message.length() < kMaxMessageChunkSize) {
- std::string param;
- base::EscapeJSONString(message, true, &param);
- base::string16 javascript =
- base::UTF8ToUTF16("DevToolsAPI.dispatchMessage(" + param + ");");
- web_contents_->GetMainFrame()->ExecuteJavaScript(javascript,
- base::NullCallback());
+ base::StringPiece message_sp(reinterpret_cast<const char*>(message.data()),
+ message.size());
+ if (message_sp.length() < kMaxMessageChunkSize) {
+ CallClientMethod("DevToolsAPI", "dispatchMessage", base::Value(message_sp));
return;
}
- base::Value total_size(static_cast<int>(message.length()));
- for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) {
- base::Value message_value(message.substr(pos, kMaxMessageChunkSize));
- CallClientFunction("DevToolsAPI.dispatchMessageChunk",
- &message_value, pos ? NULL : &total_size, NULL);
+ for (size_t pos = 0; pos < message_sp.length(); pos += kMaxMessageChunkSize) {
+ base::Value message_value(message_sp.substr(pos, kMaxMessageChunkSize));
+ if (pos == 0) {
+ CallClientMethod("DevToolsAPI", "dispatchMessageChunk", message_value,
+ base::Value(static_cast<int>(message_sp.length())));
+
+ } else {
+ CallClientMethod("DevToolsAPI", "dispatchMessageChunk", message_value);
+ }
}
}
@@ -740,9 +750,13 @@ void DevToolsUIBindings::AgentHostClosed(
void DevToolsUIBindings::SendMessageAck(int request_id,
const base::Value* arg) {
- base::Value id_value(request_id);
- CallClientFunction("DevToolsAPI.embedderMessageAck",
- &id_value, arg, nullptr);
+ if (arg) {
+ CallClientMethod("DevToolsAPI", "embedderMessageAck",
+ base::Value(request_id), *arg);
+ } else {
+ CallClientMethod("DevToolsAPI", "embedderMessageAck",
+ base::Value(request_id));
+ }
}
void DevToolsUIBindings::InnerAttach() {
@@ -839,7 +853,7 @@ void DevToolsUIBindings::LoadNetworkResource(const DispatchCallback& callback,
resource_request.url = gurl;
// TODO(caseq): this preserves behavior of URLFetcher-based implementation.
// We really need to pass proper first party origin from the front-end.
- resource_request.site_for_cookies = gurl;
+ resource_request.site_for_cookies = net::SiteForCookies::FromUrl(gurl);
resource_request.headers.AddHeadersFromString(headers);
NetworkResourceLoader::URLLoaderFactoryHolder url_loader_factory;
@@ -910,13 +924,10 @@ void DevToolsUIBindings::AppendToFile(const std::string& url,
void DevToolsUIBindings::RequestFileSystems() {
CHECK(IsValidFrontendURL(web_contents_->GetURL()) && frontend_host_);
- std::vector<DevToolsFileHelper::FileSystem> file_systems =
- file_helper_->GetFileSystems();
base::ListValue file_systems_value;
- for (size_t i = 0; i < file_systems.size(); ++i)
- file_systems_value.Append(CreateFileSystemValue(file_systems[i]));
- CallClientFunction("DevToolsAPI.fileSystemsLoaded",
- &file_systems_value, NULL, NULL);
+ for (auto const& file_system : file_helper_->GetFileSystems())
+ file_systems_value.Append(CreateFileSystemValue(file_system));
+ CallClientMethod("DevToolsAPI", "fileSystemsLoaded", file_systems_value);
}
void DevToolsUIBindings::AddFileSystem(const std::string& type) {
@@ -955,9 +966,7 @@ void DevToolsUIBindings::IndexPath(
base::Optional<base::Value> parsed_excluded_folders =
base::JSONReader::Read(excluded_folders_message);
if (parsed_excluded_folders && parsed_excluded_folders->is_list()) {
- const std::vector<base::Value>& folder_paths =
- parsed_excluded_folders->GetList();
- for (const base::Value& folder_path : folder_paths) {
+ for (const base::Value& folder_path : parsed_excluded_folders->GetList()) {
if (folder_path.is_string())
excluded_folders.push_back(folder_path.GetString());
}
@@ -1083,13 +1092,11 @@ void DevToolsUIBindings::DevicesDiscoveryConfigUpdated() {
->FindPreference(prefs::kDevToolsTCPDiscoveryConfig)
->GetValue()
->CreateDeepCopy());
- CallClientFunction("DevToolsAPI.devicesDiscoveryConfigChanged", &config,
- nullptr, nullptr);
+ CallClientMethod("DevToolsAPI", "devicesDiscoveryConfigChanged", config);
}
void DevToolsUIBindings::SendPortForwardingStatus(const base::Value& status) {
- CallClientFunction("DevToolsAPI.devicesPortForwardingStatusChanged", &status,
- nullptr, nullptr);
+ CallClientMethod("DevToolsAPI", "devicesPortForwardingStatusChanged", status);
}
void DevToolsUIBindings::SetDevicesUpdatesEnabled(bool enabled) {
@@ -1208,8 +1215,10 @@ void DevToolsUIBindings::SetOpenNewWindowForPopups(bool value) {
void DevToolsUIBindings::DispatchProtocolMessageFromDevToolsFrontend(
const std::string& message) {
- if (agent_host_.get())
- agent_host_->DispatchProtocolMessage(this, message);
+ if (!agent_host_)
+ return;
+ agent_host_->DispatchProtocolMessage(
+ this, base::as_bytes(base::make_span(message)));
}
void DevToolsUIBindings::RecordEnumeratedHistogram(const std::string& name,
@@ -1229,6 +1238,8 @@ void DevToolsUIBindings::RecordEnumeratedHistogram(const std::string& name,
UMA_HISTOGRAM_EXACT_LINEAR(name, sample, boundary_value);
else if (name == kDevToolsPanelShownHistogram)
UMA_HISTOGRAM_EXACT_LINEAR(name, sample, boundary_value);
+ else if (name == kDevToolsKeyboardShortcutFiredHistogram)
+ UMA_HISTOGRAM_EXACT_LINEAR(name, sample, boundary_value);
else
frontend_host_->BadMessageRecieved();
}
@@ -1279,53 +1290,44 @@ void DevToolsUIBindings::JsonReceived(const DispatchCallback& callback,
}
void DevToolsUIBindings::DeviceCountChanged(int count) {
- base::Value value(count);
- CallClientFunction("DevToolsAPI.deviceCountUpdated", &value, NULL,
- NULL);
+ CallClientMethod("DevToolsAPI", "deviceCountUpdated", base::Value(count));
}
void DevToolsUIBindings::DevicesUpdated(
const std::string& source,
const base::ListValue& targets) {
- CallClientFunction("DevToolsAPI.devicesUpdated", &targets, NULL,
- NULL);
+ CallClientMethod("DevToolsAPI", "devicesUpdated", targets);
}
void DevToolsUIBindings::FileSavedAs(const std::string& url,
const std::string& file_system_path) {
- base::Value url_value(url);
- base::Value file_system_path_value(file_system_path);
- CallClientFunction("DevToolsAPI.savedURL", &url_value,
- &file_system_path_value, NULL);
+ CallClientMethod("DevToolsAPI", "savedURL", base::Value(url),
+ base::Value(file_system_path));
}
void DevToolsUIBindings::CanceledFileSaveAs(const std::string& url) {
- base::Value url_value(url);
- CallClientFunction("DevToolsAPI.canceledSaveURL",
- &url_value, NULL, NULL);
+ CallClientMethod("DevToolsAPI", "canceledSaveURL", base::Value(url));
}
void DevToolsUIBindings::AppendedTo(const std::string& url) {
- base::Value url_value(url);
- CallClientFunction("DevToolsAPI.appendedToURL", &url_value, NULL,
- NULL);
+ CallClientMethod("DevToolsAPI", "appendedToURL", base::Value(url));
}
void DevToolsUIBindings::FileSystemAdded(
const std::string& error,
const DevToolsFileHelper::FileSystem* file_system) {
- base::Value error_value(error);
- std::unique_ptr<base::DictionaryValue> file_system_value(
- file_system ? CreateFileSystemValue(*file_system) : nullptr);
- CallClientFunction("DevToolsAPI.fileSystemAdded", &error_value,
- file_system_value.get(), NULL);
+ if (file_system) {
+ CallClientMethod("DevToolsAPI", "fileSystemAdded", base::Value(error),
+ CreateFileSystemValue(*file_system));
+ } else {
+ CallClientMethod("DevToolsAPI", "fileSystemAdded", base::Value(error));
+ }
}
void DevToolsUIBindings::FileSystemRemoved(
const std::string& file_system_path) {
- base::Value file_system_path_value(file_system_path);
- CallClientFunction("DevToolsAPI.fileSystemRemoved",
- &file_system_path_value, NULL, NULL);
+ CallClientMethod("DevToolsAPI", "fileSystemRemoved",
+ base::Value(file_system_path));
}
void DevToolsUIBindings::FilePathsChanged(
@@ -1355,8 +1357,8 @@ void DevToolsUIBindings::FilePathsChanged(
removed.AppendString(removed_paths[removed_index++]);
--budget;
}
- CallClientFunction("DevToolsAPI.fileSystemFilesChangedAddedRemoved",
- &changed, &added, &removed);
+ CallClientMethod("DevToolsAPI", "fileSystemFilesChangedAddedRemoved",
+ changed, added, removed);
}
}
@@ -1365,33 +1367,25 @@ void DevToolsUIBindings::IndexingTotalWorkCalculated(
const std::string& file_system_path,
int total_work) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::Value request_id_value(request_id);
- base::Value file_system_path_value(file_system_path);
- base::Value total_work_value(total_work);
- CallClientFunction("DevToolsAPI.indexingTotalWorkCalculated",
- &request_id_value, &file_system_path_value,
- &total_work_value);
+ CallClientMethod("DevToolsAPI", "indexingTotalWorkCalculated",
+ base::Value(request_id), base::Value(file_system_path),
+ base::Value(total_work));
}
void DevToolsUIBindings::IndexingWorked(int request_id,
const std::string& file_system_path,
int worked) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::Value request_id_value(request_id);
- base::Value file_system_path_value(file_system_path);
- base::Value worked_value(worked);
- CallClientFunction("DevToolsAPI.indexingWorked", &request_id_value,
- &file_system_path_value, &worked_value);
+ CallClientMethod("DevToolsAPI", "indexingWorked", base::Value(request_id),
+ base::Value(file_system_path), base::Value(worked));
}
void DevToolsUIBindings::IndexingDone(int request_id,
const std::string& file_system_path) {
indexing_jobs_.erase(request_id);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::Value request_id_value(request_id);
- base::Value file_system_path_value(file_system_path);
- CallClientFunction("DevToolsAPI.indexingDone", &request_id_value,
- &file_system_path_value, NULL);
+ CallClientMethod("DevToolsAPI", "indexingDone", base::Value(request_id),
+ base::Value(file_system_path));
}
void DevToolsUIBindings::SearchCompleted(
@@ -1400,13 +1394,10 @@ void DevToolsUIBindings::SearchCompleted(
const std::vector<std::string>& file_paths) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::ListValue file_paths_value;
- for (auto it(file_paths.begin()); it != file_paths.end(); ++it) {
- file_paths_value.AppendString(*it);
- }
- base::Value request_id_value(request_id);
- base::Value file_system_path_value(file_system_path);
- CallClientFunction("DevToolsAPI.searchCompleted", &request_id_value,
- &file_system_path_value, &file_paths_value);
+ for (auto const& file_path : file_paths)
+ file_paths_value.AppendString(file_path);
+ CallClientMethod("DevToolsAPI", "searchCompleted", base::Value(request_id),
+ base::Value(file_system_path), file_paths_value);
}
void DevToolsUIBindings::ShowDevToolsInfoBar(
@@ -1429,8 +1420,14 @@ void DevToolsUIBindings::AddDevToolsExtensionsToClient() {
for (const scoped_refptr<const extensions::Extension>& extension :
registry->enabled_extensions()) {
if (extensions::chrome_manifest_urls::GetDevToolsPage(extension.get())
- .is_empty())
+ .is_empty()) {
continue;
+ }
+ GURL url =
+ extensions::chrome_manifest_urls::GetDevToolsPage(extension.get());
+ const bool is_extension_url = url.SchemeIs(extensions::kExtensionScheme) &&
+ url.host_piece() == extension->id();
+ CHECK(is_extension_url || url.SchemeIsHTTPOrHTTPS());
// Each devtools extension will need to be able to run in the devtools
// process. Grant the devtools process the ability to request URLs from the
@@ -1441,10 +1438,7 @@ void DevToolsUIBindings::AddDevToolsExtensionsToClient() {
std::unique_ptr<base::DictionaryValue> extension_info(
new base::DictionaryValue());
- extension_info->SetString(
- "startPage",
- extensions::chrome_manifest_urls::GetDevToolsPage(extension.get())
- .spec());
+ extension_info->SetString("startPage", url.spec());
extension_info->SetString("name", extension->name());
extension_info->SetBoolean("exposeExperimentalAPIs",
extension->permissions_data()->HasAPIPermission(
@@ -1452,8 +1446,7 @@ void DevToolsUIBindings::AddDevToolsExtensionsToClient() {
results.Append(std::move(extension_info));
}
- CallClientFunction("DevToolsAPI.addExtensions",
- &results, NULL, NULL);
+ CallClientMethod("DevToolsAPI", "addExtensions", results);
}
void DevToolsUIBindings::RegisterExtensionsAPI(const std::string& origin,
@@ -1483,23 +1476,24 @@ bool DevToolsUIBindings::IsAttachedTo(content::DevToolsAgentHost* agent_host) {
return agent_host_.get() == agent_host;
}
-void DevToolsUIBindings::CallClientFunction(const std::string& function_name,
- const base::Value* arg1,
- const base::Value* arg2,
- const base::Value* arg3) {
+void DevToolsUIBindings::CallClientMethod(const std::string& object_name,
+ const std::string& method_name,
+ const base::Value& arg1,
+ const base::Value& arg2,
+ const base::Value& arg3) {
// If we're not exposing bindings, we shouldn't call functions either.
if (!frontend_host_)
return;
- std::string javascript = function_name + "(";
- if (arg1) {
+ std::string javascript = object_name + "." + method_name + "(";
+ if (!arg1.is_none()) {
std::string json;
- base::JSONWriter::Write(*arg1, &json);
+ base::JSONWriter::Write(arg1, &json);
javascript.append(json);
- if (arg2) {
- base::JSONWriter::Write(*arg2, &json);
+ if (!arg2.is_none()) {
+ base::JSONWriter::Write(arg2, &json);
javascript.append(", ").append(json);
- if (arg3) {
- base::JSONWriter::Write(*arg3, &json);
+ if (!arg3.is_none()) {
+ base::JSONWriter::Write(arg3, &json);
javascript.append(", ").append(json);
}
}
diff --git a/chromium/chrome/browser/devtools/devtools_ui_bindings.h b/chromium/chrome/browser/devtools/devtools_ui_bindings.h
index cc7e57e6c2e..b3e3ad1d0bc 100644
--- a/chromium/chrome/browser/devtools/devtools_ui_bindings.h
+++ b/chromium/chrome/browser/devtools/devtools_ui_bindings.h
@@ -80,10 +80,11 @@ class DevToolsUIBindings : public DevToolsEmbedderMessageDispatcher::Delegate,
// Takes ownership over the |delegate|.
void SetDelegate(Delegate* delegate);
- void CallClientFunction(const std::string& function_name,
- const base::Value* arg1,
- const base::Value* arg2,
- const base::Value* arg3);
+ void CallClientMethod(const std::string& object_name,
+ const std::string& method_name,
+ const base::Value& arg1 = {},
+ const base::Value& arg2 = {},
+ const base::Value& arg3 = {});
void AttachTo(const scoped_refptr<content::DevToolsAgentHost>& agent_host);
void Detach();
bool IsAttachedTo(content::DevToolsAgentHost* agent_host);
@@ -93,7 +94,7 @@ class DevToolsUIBindings : public DevToolsEmbedderMessageDispatcher::Delegate,
// content::DevToolsAgentHostClient implementation.
void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
- const std::string& message) override;
+ base::span<const uint8_t> message) override;
void AgentHostClosed(content::DevToolsAgentHost* agent_host) override;
// DevToolsEmbedderMessageDispatcher::Delegate implementation.
diff --git a/chromium/chrome/browser/devtools/devtools_ui_bindings_unittest.cc b/chromium/chrome/browser/devtools/devtools_ui_bindings_unittest.cc
index 2e27ec76906..3561a499b17 100644
--- a/chromium/chrome/browser/devtools/devtools_ui_bindings_unittest.cc
+++ b/chromium/chrome/browser/devtools/devtools_ui_bindings_unittest.cc
@@ -19,14 +19,14 @@ TEST_F(DevToolsUIBindingsTest, SanitizeFrontendURL) {
"devtools://devtools/bundled/devtools.html#hash"},
{"devtools://devtools/some/random/path",
"devtools://devtools/some/random/path"},
- {"devtools://devtools/bundled/devtools.html?experiments=true",
- "devtools://devtools/bundled/devtools.html?experiments=true"},
+ {"devtools://devtools/bundled/devtools.html?debugFrontend=true",
+ "devtools://devtools/bundled/devtools.html?debugFrontend=true"},
{"devtools://devtools/bundled/devtools.html"
- "?some-flag=flag&v8only=true&experiments=false&debugFrontend=a"
+ "?some-flag=flag&v8only=true&debugFrontend=a"
"&another-flag=another-flag&can_dock=false&isSharedWorker=notreally"
"&remoteFrontend=sure",
"devtools://devtools/bundled/devtools.html"
- "?v8only=true&experiments=true&debugFrontend=true"
+ "?v8only=true&debugFrontend=true"
"&can_dock=true&isSharedWorker=true&remoteFrontend=true"},
{"devtools://devtools/?ws=any-value-is-fine",
"devtools://devtools/?ws=any-value-is-fine"},
@@ -81,13 +81,13 @@ TEST_F(DevToolsUIBindingsTest, SanitizeFrontendURL) {
"devtools://devtools/?remoteFrontendUrl="
"https%3A%2F%2Fchrome-devtools-frontend.appspot.com%2Fserve_rev"
"%2Frev%2Finspector.html#hash"},
- {"devtools://devtools/?experiments=whatever&remoteFrontendUrl="
+ {"devtools://devtools/?remoteFrontendUrl="
"https://chrome-devtools-frontend.appspot.com/serve_rev/"
- "@12345/devtools.html%3Fws%3Danyvalue%26experiments%3Dlikely"
+ "@12345/devtools.html%3Fws%3Danyvalue"
"&unencoded=value&debugFrontend=true",
- "devtools://devtools/?experiments=true&remoteFrontendUrl="
+ "devtools://devtools/?remoteFrontendUrl="
"https%3A%2F%2Fchrome-devtools-frontend.appspot.com%2Fserve_rev"
- "%2F%4012345%2Fdevtools.html%3Fws%3Danyvalue%26experiments%3Dtrue"
+ "%2F%4012345%2Fdevtools.html%3Fws%3Danyvalue"
"&debugFrontend=true"},
{"devtools://devtools/?remoteFrontendUrl="
"https://chrome-devtools-frontend.appspot.com/serve_rev/"
diff --git a/chromium/chrome/browser/devtools/devtools_window.cc b/chromium/chrome/browser/devtools/devtools_window.cc
index 283e61c374d..3063ba32c4b 100644
--- a/chromium/chrome/browser/devtools/devtools_window.cc
+++ b/chromium/chrome/browser/devtools/devtools_window.cc
@@ -23,7 +23,6 @@
#include "chrome/browser/file_select_helper.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/task_manager/web_contents_tags.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
@@ -37,10 +36,11 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
-#include "components/app_modal/javascript_dialog_manager.h"
-#include "components/performance_manager/performance_manager_tab_helper.h"
+#include "components/javascript_dialogs/app_modal_dialog_manager.h"
+#include "components/performance_manager/embedder/performance_manager_registry.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/scoped_user_pref_update.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "components/zoom/page_zoom.h"
@@ -63,8 +63,8 @@
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "net/base/escape.h"
-#include "third_party/blink/public/platform/web_gesture_event.h"
-#include "third_party/blink/public/platform/web_input_event.h"
+#include "third_party/blink/public/common/input/web_gesture_event.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/public_buildflags.h"
#include "ui/base/page_transition_types.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -221,8 +221,6 @@ GURL DecorateFrontendURL(const GURL& base_url) {
((frontend_url.find("?") == std::string::npos) ? "?" : "&") +
"dockSide=undocked"); // TODO(dgozman): remove this support in M38.
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kEnableDevToolsExperiments))
- url_string += "&experiments=true";
if (command_line->HasSwitch(switches::kDevToolsFlags)) {
url_string += "&" + command_line->GetSwitchValueASCII(
@@ -317,8 +315,8 @@ bool DevToolsEventForwarder::ForwardEvent(
static_cast<ui::DomCode>(event.dom_code)));
event_data.SetIntKey("keyCode", key_code);
event_data.SetIntKey("modifiers", modifiers);
- devtools_window_->bindings_->CallClientFunction(
- "DevToolsAPI.keyEventUnhandled", &event_data, NULL, NULL);
+ devtools_window_->bindings_->CallClientMethod(
+ "DevToolsAPI", "keyEventUnhandled", event_data);
return true;
}
@@ -775,8 +773,7 @@ void DevToolsWindow::UpdateInspectedWebContents(
std::make_unique<ObserverWithAccessor>(new_web_contents);
bindings_->AttachTo(
content::DevToolsAgentHost::GetOrCreateFor(new_web_contents));
- bindings_->CallClientFunction("DevToolsAPI.reattachMainTarget", nullptr,
- nullptr, nullptr);
+ bindings_->CallClientMethod("DevToolsAPI", "reattachMainTarget");
}
void DevToolsWindow::ScheduleShow(const DevToolsToggleAction& action) {
@@ -962,8 +959,8 @@ DevToolsWindow::DevToolsWindow(FrontendType frontend_type,
zoom::ZoomController::CreateForWebContents(main_web_contents_);
zoom::ZoomController::FromWebContents(main_web_contents_)
->SetShowsNotificationBubble(false);
- performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
- main_web_contents_);
+ performance_manager::PerformanceManagerRegistry::GetInstance()
+ ->CreatePageNodeForWebContents(main_web_contents_);
g_devtools_window_instances.Get().push_back(this);
@@ -1276,7 +1273,7 @@ bool DevToolsWindow::HandleKeyboardEvent(
content::JavaScriptDialogManager* DevToolsWindow::GetJavaScriptDialogManager(
WebContents* source) {
- return app_modal::JavaScriptDialogManager::GetInstance();
+ return javascript_dialogs::AppModalDialogManager::GetInstance();
}
content::ColorChooser* DevToolsWindow::OpenColorChooser(
@@ -1429,8 +1426,7 @@ void DevToolsWindow::ColorPickedInEyeDropper(int r, int g, int b, int a) {
color.SetInteger("g", g);
color.SetInteger("b", b);
color.SetInteger("a", a);
- bindings_->CallClientFunction("DevToolsAPI.eyeDropperPickedColor", &color,
- nullptr, nullptr);
+ bindings_->CallClientMethod("DevToolsAPI", "eyeDropperPickedColor", color);
}
void DevToolsWindow::InspectedContentsClosing() {
@@ -1490,12 +1486,12 @@ void DevToolsWindow::OnLoadCompleted() {
// First seed inspected tab id for extension APIs.
WebContents* inspected_web_contents = GetInspectedWebContents();
if (inspected_web_contents) {
- SessionTabHelper* session_tab_helper =
- SessionTabHelper::FromWebContents(inspected_web_contents);
+ sessions::SessionTabHelper* session_tab_helper =
+ sessions::SessionTabHelper::FromWebContents(inspected_web_contents);
if (session_tab_helper) {
- base::Value tabId(session_tab_helper->session_id().id());
- bindings_->CallClientFunction("DevToolsAPI.setInspectedTabId",
- &tabId, NULL, NULL);
+ bindings_->CallClientMethod(
+ "DevToolsAPI", "setInspectedTabId",
+ base::Value(session_tab_helper->session_id().id()));
}
}
@@ -1562,8 +1558,7 @@ BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() {
void DevToolsWindow::DoAction(const DevToolsToggleAction& action) {
switch (action.type()) {
case DevToolsToggleAction::kInspect:
- bindings_->CallClientFunction("DevToolsAPI.enterInspectElementMode", NULL,
- NULL, NULL);
+ bindings_->CallClientMethod("DevToolsAPI", "enterInspectElementMode");
break;
case DevToolsToggleAction::kShowElementsPanel:
@@ -1578,11 +1573,10 @@ void DevToolsWindow::DoAction(const DevToolsToggleAction& action) {
const DevToolsToggleAction::RevealParams* params =
action.params();
CHECK(params);
- base::Value url_value(params->url);
- base::Value line_value(static_cast<int>(params->line_number));
- base::Value column_value(static_cast<int>(params->column_number));
- bindings_->CallClientFunction("DevToolsAPI.revealSourceLine",
- &url_value, &line_value, &column_value);
+ bindings_->CallClientMethod(
+ "DevToolsAPI", "revealSourceLine", base::Value(params->url),
+ base::Value(static_cast<int>(params->line_number)),
+ base::Value(static_cast<int>(params->column_number)));
break;
}
default:
@@ -1613,18 +1607,17 @@ void DevToolsWindow::LoadCompleted() {
Show(action_on_load_);
action_on_load_ = DevToolsToggleAction::NoOp();
if (!load_completed_callback_.is_null()) {
- load_completed_callback_.Run();
- load_completed_callback_ = base::Closure();
+ std::move(load_completed_callback_).Run();
}
}
-void DevToolsWindow::SetLoadCompletedCallback(const base::Closure& closure) {
+void DevToolsWindow::SetLoadCompletedCallback(base::OnceClosure closure) {
if (life_stage_ == kLoadCompleted || life_stage_ == kClosing) {
if (!closure.is_null())
- closure.Run();
+ std::move(closure).Run();
return;
}
- load_completed_callback_ = closure;
+ load_completed_callback_ = std::move(closure);
}
bool DevToolsWindow::ForwardKeyboardEvent(
@@ -1637,9 +1630,8 @@ bool DevToolsWindow::ReloadInspectedWebContents(bool bypass_cache) {
WebContents* wc = GetInspectedWebContents();
if (!wc || wc->GetCrashedStatus() != base::TERMINATION_STATUS_STILL_RUNNING)
return false;
- base::Value bypass_cache_value(bypass_cache);
- bindings_->CallClientFunction("DevToolsAPI.reloadInspectedPage",
- &bypass_cache_value, nullptr, nullptr);
+ bindings_->CallClientMethod("DevToolsAPI", "reloadInspectedPage",
+ base::Value(bypass_cache));
return true;
}
diff --git a/chromium/chrome/browser/devtools/devtools_window.h b/chromium/chrome/browser/devtools/devtools_window.h
index 9e51720ba60..0d607938f2e 100644
--- a/chromium/chrome/browser/devtools/devtools_window.h
+++ b/chromium/chrome/browser/devtools/devtools_window.h
@@ -132,7 +132,7 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate,
// Sets closure to be called after load is done. If already loaded, calls
// closure immediately.
- void SetLoadCompletedCallback(const base::Closure& closure);
+ void SetLoadCompletedCallback(base::OnceClosure closure);
// Forwards an unhandled keyboard event to the DevTools frontend.
bool ForwardKeyboardEvent(const content::NativeWebKeyboardEvent& event);
@@ -412,7 +412,7 @@ class DevToolsWindow : public DevToolsUIBindings::Delegate,
// True if we're in the process of handling a beforeunload event originating
// from the inspected webcontents, see InterceptPageBeforeUnload for details.
bool intercepted_page_beforeunload_;
- base::Closure load_completed_callback_;
+ base::OnceClosure load_completed_callback_;
base::OnceClosure close_callback_;
bool ready_for_test_;
base::OnceClosure ready_for_test_callback_;
diff --git a/chromium/chrome/browser/devtools/global_confirm_info_bar.cc b/chromium/chrome/browser/devtools/global_confirm_info_bar.cc
index 106733e746e..f26872e3867 100644
--- a/chromium/chrome/browser/devtools/global_confirm_info_bar.cc
+++ b/chromium/chrome/browser/devtools/global_confirm_info_bar.cc
@@ -28,18 +28,18 @@ class GlobalConfirmInfoBar::DelegateProxy : public ConfirmInfoBarDelegate {
// ConfirmInfoBarDelegate overrides
infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override;
+ base::string16 GetLinkText() const override;
+ GURL GetLinkURL() const override;
+ bool LinkClicked(WindowOpenDisposition disposition) override;
+ void InfoBarDismissed() override;
base::string16 GetMessageText() const override;
gfx::ElideBehavior GetMessageElideBehavior() const override;
int GetButtons() const override;
base::string16 GetButtonLabel(InfoBarButton button) const override;
bool Accept() override;
bool Cancel() override;
- base::string16 GetLinkText() const override;
- GURL GetLinkURL() const override;
- bool LinkClicked(WindowOpenDisposition disposition) override;
- void InfoBarDismissed() override;
- infobars::InfoBar* info_bar_;
+ infobars::InfoBar* info_bar_ = nullptr;
base::WeakPtr<GlobalConfirmInfoBar> global_info_bar_;
DISALLOW_COPY_AND_ASSIGN(DelegateProxy);
@@ -47,12 +47,9 @@ class GlobalConfirmInfoBar::DelegateProxy : public ConfirmInfoBarDelegate {
GlobalConfirmInfoBar::DelegateProxy::DelegateProxy(
base::WeakPtr<GlobalConfirmInfoBar> global_info_bar)
- : info_bar_(nullptr),
- global_info_bar_(global_info_bar) {
-}
+ : global_info_bar_(global_info_bar) {}
-GlobalConfirmInfoBar::DelegateProxy::~DelegateProxy() {
-}
+GlobalConfirmInfoBar::DelegateProxy::~DelegateProxy() = default;
infobars::InfoBarDelegate::InfoBarIdentifier
GlobalConfirmInfoBar::DelegateProxy::GetIdentifier() const {
@@ -60,6 +57,33 @@ GlobalConfirmInfoBar::DelegateProxy::GetIdentifier() const {
: INVALID;
}
+base::string16 GlobalConfirmInfoBar::DelegateProxy::GetLinkText() const {
+ return global_info_bar_ ? global_info_bar_->delegate_->GetLinkText()
+ : base::string16();
+}
+
+GURL GlobalConfirmInfoBar::DelegateProxy::GetLinkURL() const {
+ return global_info_bar_ ? global_info_bar_->delegate_->GetLinkURL() : GURL();
+}
+
+bool GlobalConfirmInfoBar::DelegateProxy::LinkClicked(
+ WindowOpenDisposition disposition) {
+ return global_info_bar_ &&
+ global_info_bar_->delegate_->LinkClicked(disposition);
+}
+
+void GlobalConfirmInfoBar::DelegateProxy::InfoBarDismissed() {
+ base::WeakPtr<GlobalConfirmInfoBar> info_bar = global_info_bar_;
+ // See comments in GlobalConfirmInfoBar::DelegateProxy::Accept().
+ if (info_bar) {
+ info_bar->OnInfoBarRemoved(info_bar_, false);
+ info_bar->delegate_->InfoBarDismissed();
+ }
+ // Could be destroyed after this point.
+ if (info_bar)
+ info_bar->Close();
+}
+
base::string16 GlobalConfirmInfoBar::DelegateProxy::GetMessageText() const {
return global_info_bar_ ? global_info_bar_->delegate_->GetMessageText()
: base::string16();
@@ -74,7 +98,7 @@ GlobalConfirmInfoBar::DelegateProxy::GetMessageElideBehavior() const {
int GlobalConfirmInfoBar::DelegateProxy::GetButtons() const {
return global_info_bar_ ? global_info_bar_->delegate_->GetButtons()
- : 0;
+ : BUTTON_NONE;
}
base::string16 GlobalConfirmInfoBar::DelegateProxy::GetButtonLabel(
@@ -113,34 +137,6 @@ bool GlobalConfirmInfoBar::DelegateProxy::Cancel() {
return true;
}
-base::string16 GlobalConfirmInfoBar::DelegateProxy::GetLinkText() const {
- return global_info_bar_ ? global_info_bar_->delegate_->GetLinkText()
- : base::string16();
-}
-
-GURL GlobalConfirmInfoBar::DelegateProxy::GetLinkURL() const {
- return global_info_bar_ ? global_info_bar_->delegate_->GetLinkURL()
- : GURL();
-}
-
-bool GlobalConfirmInfoBar::DelegateProxy::LinkClicked(
- WindowOpenDisposition disposition) {
- return global_info_bar_ ?
- global_info_bar_->delegate_->LinkClicked(disposition) : false;
-}
-
-void GlobalConfirmInfoBar::DelegateProxy::InfoBarDismissed() {
- base::WeakPtr<GlobalConfirmInfoBar> info_bar = global_info_bar_;
- // See comments in GlobalConfirmInfoBar::DelegateProxy::Accept().
- if (info_bar) {
- info_bar->OnInfoBarRemoved(info_bar_, false);
- info_bar->delegate_->InfoBarDismissed();
- }
- // Could be destroyed after this point.
- if (info_bar)
- info_bar->Close();
-}
-
void GlobalConfirmInfoBar::DelegateProxy::Detach() {
global_info_bar_.reset();
}
@@ -150,9 +146,9 @@ void GlobalConfirmInfoBar::DelegateProxy::Detach() {
// static
base::WeakPtr<GlobalConfirmInfoBar> GlobalConfirmInfoBar::Show(
std::unique_ptr<ConfirmInfoBarDelegate> delegate) {
- GlobalConfirmInfoBar* info_bar =
- new GlobalConfirmInfoBar(std::move(delegate));
- return info_bar->weak_factory_.GetWeakPtr();
+ // Owns itself, deleted by Close().
+ auto* infobar = new GlobalConfirmInfoBar(std::move(delegate));
+ return infobar->weak_factory_.GetWeakPtr();
}
void GlobalConfirmInfoBar::Close() {
@@ -161,9 +157,7 @@ void GlobalConfirmInfoBar::Close() {
GlobalConfirmInfoBar::GlobalConfirmInfoBar(
std::unique_ptr<ConfirmInfoBarDelegate> delegate)
- : delegate_(std::move(delegate)),
- browser_tab_strip_tracker_(this, nullptr, nullptr),
- is_closing_(false) {
+ : delegate_(std::move(delegate)) {
browser_tab_strip_tracker_.Init();
}
@@ -196,7 +190,7 @@ void GlobalConfirmInfoBar::TabChangedAt(content::WebContents* web_contents,
void GlobalConfirmInfoBar::OnInfoBarRemoved(infobars::InfoBar* info_bar,
bool animate) {
// Do not process alien infobars.
- for (auto it : proxies_) {
+ for (const auto& it : proxies_) {
if (it.second->info_bar_ == info_bar) {
OnManagerShuttingDown(info_bar->owner());
break;
@@ -218,8 +212,8 @@ void GlobalConfirmInfoBar::MaybeAddInfoBar(content::WebContents* web_contents) {
if (base::Contains(proxies_, infobar_service))
return;
- std::unique_ptr<GlobalConfirmInfoBar::DelegateProxy> proxy(
- new GlobalConfirmInfoBar::DelegateProxy(weak_factory_.GetWeakPtr()));
+ auto proxy = std::make_unique<GlobalConfirmInfoBar::DelegateProxy>(
+ weak_factory_.GetWeakPtr());
GlobalConfirmInfoBar::DelegateProxy* proxy_ptr = proxy.get();
infobars::InfoBar* added_bar = infobar_service->AddInfoBar(
infobar_service->CreateConfirmInfoBar(std::move(proxy)));
diff --git a/chromium/chrome/browser/devtools/global_confirm_info_bar.h b/chromium/chrome/browser/devtools/global_confirm_info_bar.h
index 82afbd73967..ca10c39a340 100644
--- a/chromium/chrome/browser/devtools/global_confirm_info_bar.h
+++ b/chromium/chrome/browser/devtools/global_confirm_info_bar.h
@@ -56,11 +56,11 @@ class GlobalConfirmInfoBar : public TabStripModelObserver,
std::unique_ptr<ConfirmInfoBarDelegate> delegate_;
std::map<infobars::InfoBarManager*, DelegateProxy*> proxies_;
- BrowserTabStripTracker browser_tab_strip_tracker_;
+ BrowserTabStripTracker browser_tab_strip_tracker_{this, nullptr};
// Indicates if the global infobar is currently in the process of shutting
// down.
- bool is_closing_;
+ bool is_closing_ = false;
base::WeakPtrFactory<GlobalConfirmInfoBar> weak_factory_{this};
diff --git a/chromium/chrome/browser/devtools/inspector_protocol_config.json b/chromium/chrome/browser/devtools/inspector_protocol_config.json
index 7c39573e78b..83d16426da2 100644
--- a/chromium/chrome/browser/devtools/inspector_protocol_config.json
+++ b/chromium/chrome/browser/devtools/inspector_protocol_config.json
@@ -8,9 +8,9 @@
"options": [
{
"domain": "Page",
- "include": [ "enable", "disable", "setAdBlockingEnabled", "getInstallabilityErrors" ],
+ "include": [ "enable", "disable", "setAdBlockingEnabled", "getInstallabilityErrors", "getManifestIcons" ],
"include_events": [],
- "async": ["getInstallabilityErrors"]
+ "async": ["getInstallabilityErrors", "getManifestIcons"]
},
{
"domain": "Browser",
diff --git a/chromium/chrome/browser/devtools/protocol/browser_handler.cc b/chromium/chrome/browser/devtools/protocol/browser_handler.cc
index 371df65890b..3ba37138d18 100644
--- a/chromium/chrome/browser/devtools/protocol/browser_handler.cc
+++ b/chromium/chrome/browser/devtools/protocol/browser_handler.cc
@@ -20,6 +20,7 @@
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
+#include "ui/display/types/display_constants.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_png_rep.h"
@@ -79,10 +80,10 @@ Response BrowserHandler::GetWindowForTarget(
auto host =
content::DevToolsAgentHost::GetForId(target_id.fromMaybe(target_id_));
if (!host)
- return Response::Error("No target with given id");
+ return Response::ServerError("No target with given id");
content::WebContents* web_contents = host->GetWebContents();
if (!web_contents)
- return Response::Error("No web contents in the target");
+ return Response::ServerError("No web contents in the target");
Browser* browser = nullptr;
for (auto* b : *BrowserList::GetInstance()) {
@@ -91,12 +92,12 @@ Response BrowserHandler::GetWindowForTarget(
browser = b;
}
if (!browser)
- return Response::Error("Browser window not found");
+ return Response::ServerError("Browser window not found");
BrowserWindow* window = browser->window();
*out_window_id = browser->session_id().id();
*out_bounds = GetBrowserWindowBounds(window);
- return Response::OK();
+ return Response::Success();
}
Response BrowserHandler::GetWindowBounds(
@@ -104,16 +105,20 @@ Response BrowserHandler::GetWindowBounds(
std::unique_ptr<protocol::Browser::Bounds>* out_bounds) {
BrowserWindow* window = GetBrowserWindow(window_id);
if (!window)
- return Response::Error("Browser window not found");
+ return Response::ServerError("Browser window not found");
*out_bounds = GetBrowserWindowBounds(window);
- return Response::OK();
+ return Response::Success();
}
Response BrowserHandler::Close() {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce([]() { chrome::ExitIgnoreUnloadHandlers(); }));
- return Response::OK();
+ base::PostTask(
+ FROM_HERE, {content::BrowserThread::UI}, base::BindOnce([]() {
+ if (ChromeDevToolsManagerDelegate::GetInstance())
+ ChromeDevToolsManagerDelegate::GetInstance()->BrowserCloseRequested();
+ chrome::ExitIgnoreUnloadHandlers();
+ }));
+ return Response::Success();
}
Response BrowserHandler::SetWindowBounds(
@@ -121,7 +126,7 @@ Response BrowserHandler::SetWindowBounds(
std::unique_ptr<protocol::Browser::Bounds> window_bounds) {
BrowserWindow* window = GetBrowserWindow(window_id);
if (!window)
- return Response::Error("Browser window not found");
+ return Response::ServerError("Browser window not found");
gfx::Rect bounds = window->GetBounds();
const bool set_bounds = window_bounds->HasLeft() || window_bounds->HasTop() ||
window_bounds->HasWidth() ||
@@ -135,29 +140,29 @@ Response BrowserHandler::SetWindowBounds(
const std::string window_state = window_bounds->GetWindowState("normal");
if (set_bounds && window_state != "normal") {
- return Response::Error(
+ return Response::ServerError(
"The 'minimized', 'maximized' and 'fullscreen' states cannot be "
"combined with 'left', 'top', 'width' or 'height'");
}
if (window_state == "fullscreen") {
if (window->IsMinimized()) {
- return Response::Error(
+ return Response::ServerError(
"To make minimized window fullscreen, "
"restore it to normal state first.");
}
window->GetExclusiveAccessContext()->EnterFullscreen(
- GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE);
+ GURL(), EXCLUSIVE_ACCESS_BUBBLE_TYPE_NONE, display::kInvalidDisplayId);
} else if (window_state == "maximized") {
if (window->IsMinimized() || window->IsFullscreen()) {
- return Response::Error(
+ return Response::ServerError(
"To maximize a minimized or fullscreen "
"window, restore it to normal state first.");
}
window->Maximize();
} else if (window_state == "minimized") {
if (window->IsFullscreen()) {
- return Response::Error(
+ return Response::ServerError(
"To minimize a fullscreen window, restore it to normal "
"state first.");
}
@@ -175,7 +180,7 @@ Response BrowserHandler::SetWindowBounds(
NOTREACHED();
}
- return Response::OK();
+ return Response::Success();
}
protocol::Response BrowserHandler::SetDockTile(
@@ -186,5 +191,5 @@ protocol::Response BrowserHandler::SetDockTile(
reps.emplace_back(image.fromJust().bytes(), 1);
DevToolsDockTile::Update(label.fromMaybe(std::string()),
!reps.empty() ? gfx::Image(reps) : gfx::Image());
- return Response::OK();
+ return Response::Success();
}
diff --git a/chromium/chrome/browser/devtools/protocol/cast_handler.cc b/chromium/chrome/browser/devtools/protocol/cast_handler.cc
index bccebb6efd1..77d6839f04b 100644
--- a/chromium/chrome/browser/devtools/protocol/cast_handler.cc
+++ b/chromium/chrome/browser/devtools/protocol/cast_handler.cc
@@ -10,10 +10,10 @@
#include "chrome/browser/media/router/media_router.h"
#include "chrome/browser/media/router/media_router_factory.h"
#include "chrome/browser/media/router/presentation/presentation_service_delegate_impl.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/media_router/media_router_ui_helper.h"
#include "chrome/common/media_router/media_source.h"
#include "chrome/common/media_router/mojom/media_router.mojom.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/web_contents.h"
@@ -89,7 +89,7 @@ Response CastHandler::SetSinkToUse(const std::string& in_sink_name) {
->set_start_presentation_cb(
base::BindRepeating(&CastHandler::StartPresentation,
weak_factory_.GetWeakPtr(), in_sink_name));
- return Response::OK();
+ return Response::Success();
}
void CastHandler::StartTabMirroring(
@@ -98,7 +98,7 @@ void CastHandler::StartTabMirroring(
EnsureInitialized();
const media_router::MediaSink::Id& sink_id = GetSinkIdByName(in_sink_name);
if (sink_id.empty()) {
- callback->sendFailure(Response::Error("Sink not found"));
+ callback->sendFailure(Response::ServerError("Sink not found"));
return;
}
@@ -119,19 +119,19 @@ Response CastHandler::StopCasting(const std::string& in_sink_name) {
EnsureInitialized();
const media_router::MediaSink::Id& sink_id = GetSinkIdByName(in_sink_name);
if (sink_id.empty())
- return Response::Error("Sink not found");
+ return Response::ServerError("Sink not found");
const MediaRoute::Id& route_id = GetRouteIdForSink(sink_id);
if (route_id.empty())
- return Response::Error("Route not found");
+ return Response::ServerError("Route not found");
router_->TerminateRoute(route_id);
initiated_routes_.erase(route_id);
- return Response::OK();
+ return Response::Success();
}
Response CastHandler::Enable(protocol::Maybe<std::string> in_presentation_url) {
EnsureInitialized();
StartObservingForSinks(std::move(in_presentation_url));
- return Response::OK();
+ return Response::Success();
}
Response CastHandler::Disable() {
@@ -140,7 +140,7 @@ Response CastHandler::Disable() {
issues_observer_.reset();
for (const MediaRoute::Id& route_id : initiated_routes_)
router_->TerminateRoute(route_id);
- return Response::OK();
+ return Response::Success();
}
void CastHandler::OnResultsUpdated(
@@ -217,7 +217,7 @@ MediaRoute::Id CastHandler::GetRouteIdForSink(
void CastHandler::StartObservingForSinks(
protocol::Maybe<std::string> presentation_url) {
media_router::MediaSource mirroring_source(media_router::MediaSource::ForTab(
- SessionTabHelper::IdForTab(web_contents_).id()));
+ sessions::SessionTabHelper::IdForTab(web_contents_).id()));
query_result_manager_->SetSourcesForCastMode(
media_router::MediaCastMode::TAB_MIRROR, {mirroring_source},
url::Origin::Create(GURL()));
@@ -266,7 +266,7 @@ void CastHandler::OnTabMirroringStarted(
initiated_routes_.insert(result.route()->media_route_id());
callback->sendSuccess();
} else {
- callback->sendFailure(Response::Error(result.error()));
+ callback->sendFailure(Response::ServerError(result.error()));
}
}
diff --git a/chromium/chrome/browser/devtools/protocol/cast_handler_unittest.cc b/chromium/chrome/browser/devtools/protocol/cast_handler_unittest.cc
index bfbfef61e01..c42720ba8f7 100644
--- a/chromium/chrome/browser/devtools/protocol/cast_handler_unittest.cc
+++ b/chromium/chrome/browser/devtools/protocol/cast_handler_unittest.cc
@@ -9,10 +9,10 @@
#include "chrome/browser/media/router/media_router_factory.h"
#include "chrome/browser/media/router/media_sinks_observer.h"
#include "chrome/browser/media/router/test/mock_media_router.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/common/media_router/media_sink.h"
#include "chrome/common/media_router/media_source.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/sessions/content/session_tab_helper.h"
using testing::_;
using testing::DoAll;
@@ -34,13 +34,11 @@ const media_router::MediaSink sink1(kSinkId1,
const media_router::MediaSink sink2(kSinkId2,
kSinkName2,
media_router::SinkIconType::CAST);
-const media_router::MediaRoute route1(
- kRouteId1,
- media_router::MediaSource("https://example.com/"),
- kSinkId1,
- "",
- true,
- true);
+media_router::MediaRoute Route1() {
+ return media_router::MediaRoute(
+ kRouteId1, media_router::MediaSource("https://example.com/"), kSinkId1,
+ "", true, true);
+}
class MockStartTabMirroringCallback
: public CastHandler::StartTabMirroringCallback {
@@ -95,7 +93,7 @@ class CastHandlerTest : public ChromeRenderViewHostTestHarness {
TEST_F(CastHandlerTest, SetSinkToUse) {
sinks_observer_->OnSinksUpdated({sink1, sink2}, {});
- EXPECT_TRUE(handler_->SetSinkToUse(kSinkName1).isSuccess());
+ EXPECT_TRUE(handler_->SetSinkToUse(kSinkName1).IsSuccess());
const std::string presentation_url("https://example.com/");
content::PresentationRequest request(content::GlobalFrameRoutingId(),
@@ -123,17 +121,18 @@ TEST_F(CastHandlerTest, StartTabMirroring) {
// Make |router_| return a successful result. |callback| should be notified of
// the success.
- EXPECT_CALL(*router_, CreateRouteInternal(
- media_router::MediaSource::ForTab(
- SessionTabHelper::IdForTab(web_contents()).id())
- .id(),
- kSinkId1, _, _, _, _, _))
+ EXPECT_CALL(*router_,
+ CreateRouteInternal(
+ media_router::MediaSource::ForTab(
+ sessions::SessionTabHelper::IdForTab(web_contents()).id())
+ .id(),
+ kSinkId1, _, _, _, _, _))
.WillOnce(
WithArg<4>([](media_router::MediaRouteResponseCallback& callback) {
std::move(callback).Run(
media_router::mojom::RoutePresentationConnectionPtr(),
media_router::RouteRequestResult(
- std::make_unique<media_router::MediaRoute>(route1), "id",
+ std::make_unique<media_router::MediaRoute>(Route1()), "id",
"", media_router::RouteRequestResult::OK));
}));
EXPECT_CALL(*callback_ptr, sendSuccess());
@@ -153,15 +152,14 @@ TEST_F(CastHandlerTest, StartTabMirroringWithInvalidName) {
TEST_F(CastHandlerTest, StopCasting) {
sinks_observer_->OnSinksUpdated({sink1, sink2}, {});
- routes_observer_->OnRoutesUpdated({route1}, {});
+ routes_observer_->OnRoutesUpdated({Route1()}, {});
EXPECT_CALL(*router_, TerminateRoute(kRouteId1));
- EXPECT_TRUE(handler_->StopCasting(kSinkName1).isSuccess());
+ EXPECT_TRUE(handler_->StopCasting(kSinkName1).IsSuccess());
}
TEST_F(CastHandlerTest, StopCastingWithInvalidName) {
sinks_observer_->OnSinksUpdated({sink1, sink2}, {});
- routes_observer_->OnRoutesUpdated({route1}, {});
+ routes_observer_->OnRoutesUpdated({Route1()}, {});
// Attempting to stop casting to a sink without a route should fail.
- EXPECT_EQ(protocol::Response::kError,
- handler_->StopCasting(kSinkName2).status());
+ EXPECT_TRUE(handler_->StopCasting(kSinkName2).IsError());
}
diff --git a/chromium/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
index dba87a8f64a..854e317df26 100644
--- a/chromium/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/chrome/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -7,6 +7,7 @@
#include "base/base64.h"
#include "base/callback.h"
+#include "base/containers/span.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/values.h"
@@ -43,8 +44,10 @@ class DevToolsProtocolTest : public InProcessBrowserTest,
// DevToolsAgentHostClient interface
void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
- const std::string& message) override {
- auto parsed_message = base::JSONReader::Read(message);
+ base::span<const uint8_t> message) override {
+ base::StringPiece message_str(reinterpret_cast<const char*>(message.data()),
+ message.size());
+ auto parsed_message = base::JSONReader::Read(message_str);
auto id = parsed_message->FindIntPath("id");
if (id) {
// TODO: implement handling of results from method calls (when needed).
@@ -72,7 +75,8 @@ class DevToolsProtocolTest : public InProcessBrowserTest,
command.SetKey(kMethodParam, base::Value(method));
std::string json_command;
base::JSONWriter::Write(command, &json_command);
- agent_host_->DispatchProtocolMessage(this, json_command);
+ agent_host_->DispatchProtocolMessage(
+ this, base::as_bytes(base::make_span(json_command)));
}
void RunLoopUpdatingQuitClosure() {
@@ -137,7 +141,7 @@ class DevToolsProtocolTest : public InProcessBrowserTest,
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
VisibleSecurityStateChangedNeutralState) {
ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
- content::WaitForLoadStop(web_contents());
+ EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
Attach();
SendCommand("Security.enable");
diff --git a/chromium/chrome/browser/devtools/protocol/page_handler.cc b/chromium/chrome/browser/devtools/protocol/page_handler.cc
index 5dcd7d129d7..edbb2dea06c 100644
--- a/chromium/chrome/browser/devtools/protocol/page_handler.cc
+++ b/chromium/chrome/browser/devtools/protocol/page_handler.cc
@@ -6,6 +6,7 @@
#include "chrome/browser/installable/installable_manager.h"
#include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h"
+#include "ui/gfx/image/image.h"
PageHandler::PageHandler(content::WebContents* web_contents,
protocol::UberDispatcher* dispatcher)
@@ -44,9 +45,9 @@ protocol::Response PageHandler::Disable() {
protocol::Response PageHandler::SetAdBlockingEnabled(bool enabled) {
if (!enabled_)
- return protocol::Response::Error("Page domain is disabled.");
+ return protocol::Response::ServerError("Page domain is disabled.");
ToggleAdBlocking(enabled);
- return protocol::Response::OK();
+ return protocol::Response::Success();
}
void PageHandler::GetInstallabilityErrors(
@@ -57,7 +58,7 @@ void PageHandler::GetInstallabilityErrors(
: nullptr;
if (!manager) {
callback->sendFailure(
- protocol::Response::Error("Unable to fetch errors for target"));
+ protocol::Response::ServerError("Unable to fetch errors for target"));
return;
}
manager->GetAllErrors(base::BindOnce(&PageHandler::GotInstallabilityErrors,
@@ -67,7 +68,55 @@ void PageHandler::GetInstallabilityErrors(
// static
void PageHandler::GotInstallabilityErrors(
std::unique_ptr<GetInstallabilityErrorsCallback> callback,
- std::vector<std::string> errors) {
+ std::vector<content::InstallabilityError> installability_errors) {
+ auto result_installability_errors =
+ std::make_unique<protocol::Array<protocol::Page::InstallabilityError>>();
+ for (const auto& installability_error : installability_errors) {
+ auto installability_error_arguments = std::make_unique<
+ protocol::Array<protocol::Page::InstallabilityErrorArgument>>();
+ for (const auto& error_argument :
+ installability_error.installability_error_arguments) {
+ installability_error_arguments->emplace_back(
+ protocol::Page::InstallabilityErrorArgument::Create()
+ .SetName(error_argument.name)
+ .SetValue(error_argument.value)
+ .Build());
+ }
+ result_installability_errors->emplace_back(
+ protocol::Page::InstallabilityError::Create()
+ .SetErrorId(installability_error.error_id)
+ .SetErrorArguments(std::move(installability_error_arguments))
+ .Build());
+ }
callback->sendSuccess(
- std::make_unique<protocol::Array<std::string>>(std::move(errors)));
+ std::move(result_installability_errors));
+}
+
+void PageHandler::GetManifestIcons(
+ std::unique_ptr<GetManifestIconsCallback> callback) {
+ InstallableManager* manager =
+ web_contents() ? InstallableManager::FromWebContents(web_contents())
+ : nullptr;
+
+ if (!manager) {
+ callback->sendFailure(
+ protocol::Response::ServerError("Unable to fetch icons for target"));
+ return;
+ }
+
+ manager->GetPrimaryIcon(
+ base::BindOnce(&PageHandler::GotManifestIcons, std::move(callback)));
+}
+
+void PageHandler::GotManifestIcons(
+ std::unique_ptr<GetManifestIconsCallback> callback,
+ const SkBitmap* primary_icon) {
+ protocol::Maybe<protocol::Binary> primaryIconAsBinary;
+
+ if (primary_icon && !primary_icon->empty()) {
+ primaryIconAsBinary = std::move(protocol::Binary::fromRefCounted(
+ gfx::Image::CreateFrom1xBitmap(*primary_icon).As1xPNGBytes()));
+ }
+
+ callback->sendSuccess(std::move(primaryIconAsBinary));
}
diff --git a/chromium/chrome/browser/devtools/protocol/page_handler.h b/chromium/chrome/browser/devtools/protocol/page_handler.h
index 42251937243..a69b871c276 100644
--- a/chromium/chrome/browser/devtools/protocol/page_handler.h
+++ b/chromium/chrome/browser/devtools/protocol/page_handler.h
@@ -10,9 +10,12 @@
#include "content/public/browser/web_contents_observer.h"
namespace content {
+struct InstallabilityError;
class WebContents;
}
+class SkBitmap;
+
class PageHandler : public protocol::Page::Backend,
public content::WebContentsObserver {
public:
@@ -29,10 +32,17 @@ class PageHandler : public protocol::Page::Backend,
void GetInstallabilityErrors(
std::unique_ptr<GetInstallabilityErrorsCallback> callback) override;
+ void GetManifestIcons(
+ std::unique_ptr<GetManifestIconsCallback> callback) override;
+
private:
static void GotInstallabilityErrors(
std::unique_ptr<GetInstallabilityErrorsCallback> callback,
- std::vector<std::string> errors);
+ std::vector<content::InstallabilityError> installability_errors);
+
+ static void GotManifestIcons(
+ std::unique_ptr<GetManifestIconsCallback> callback,
+ const SkBitmap* primary_icon);
bool enabled_ = false;
diff --git a/chromium/chrome/browser/devtools/protocol/target_handler.cc b/chromium/chrome/browser/devtools/protocol/target_handler.cc
index 6947f168e23..87601179264 100644
--- a/chromium/chrome/browser/devtools/protocol/target_handler.cc
+++ b/chromium/chrome/browser/devtools/protocol/target_handler.cc
@@ -51,7 +51,7 @@ protocol::Response TargetHandler::SetRemoteLocations(
locations) {
remote_locations_.clear();
if (!locations)
- return protocol::Response::OK();
+ return protocol::Response::Success();
for (const auto& location : *locations) {
remote_locations_.insert(
@@ -62,7 +62,7 @@ protocol::Response TargetHandler::SetRemoteLocations(
ChromeDevToolsManagerDelegate::GetInstance();
if (delegate)
delegate->UpdateDeviceDiscovery();
- return protocol::Response::OK();
+ return protocol::Response::Success();
}
protocol::Response TargetHandler::CreateTarget(
@@ -80,7 +80,7 @@ protocol::Response TargetHandler::CreateTarget(
profile =
DevToolsBrowserContextManager::GetInstance().GetProfileById(profile_id);
if (!profile) {
- return protocol::Response::Error(
+ return protocol::Response::ServerError(
"Failed to find browser context with id " + profile_id);
}
}
@@ -103,7 +103,7 @@ protocol::Response TargetHandler::CreateTarget(
bool explicit_old_window = !new_window.fromMaybe(true);
if (explicit_old_window && !target_browser) {
- return protocol::Response::Error(
+ return protocol::Response::ServerError(
"Failed to open new tab - "
"no browser is open");
}
@@ -114,10 +114,10 @@ protocol::Response TargetHandler::CreateTarget(
create_in_background, target_browser);
Navigate(&params);
if (!params.navigated_or_inserted_contents)
- return protocol::Response::Error("Failed to open a new tab");
+ return protocol::Response::ServerError("Failed to open a new tab");
*out_target_id = content::DevToolsAgentHost::GetOrCreateFor(
params.navigated_or_inserted_contents)
->GetId();
- return protocol::Response::OK();
+ return protocol::Response::Success();
}
diff --git a/chromium/chrome/browser/devtools/protocol/target_handler.h b/chromium/chrome/browser/devtools/protocol/target_handler.h
index d6bdb5fa73f..3960e0ce69e 100644
--- a/chromium/chrome/browser/devtools/protocol/target_handler.h
+++ b/chromium/chrome/browser/devtools/protocol/target_handler.h
@@ -10,7 +10,7 @@
#include "base/memory/weak_ptr.h"
#include "chrome/browser/devtools/protocol/forward.h"
#include "chrome/browser/devtools/protocol/target.h"
-#include "chrome/browser/media/router/presentation/independent_otr_profile_manager.h"
+#include "chrome/browser/profiles/independent_otr_profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "net/base/host_port_pair.h"
diff --git a/chromium/chrome/browser/devtools/protocol/window_manager_handler.cc b/chromium/chrome/browser/devtools/protocol/window_manager_handler.cc
index 3e8fce9c9ab..2c1df6bd831 100644
--- a/chromium/chrome/browser/devtools/protocol/window_manager_handler.cc
+++ b/chromium/chrome/browser/devtools/protocol/window_manager_handler.cc
@@ -18,13 +18,13 @@ WindowManagerHandler::~WindowManagerHandler() = default;
protocol::Response WindowManagerHandler::EnterOverviewMode() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
bool success = ash::Shell::Get()->overview_controller()->StartOverview();
- return success ? protocol::Response::OK()
- : protocol::Response::Error("Overview failed");
+ return success ? protocol::Response::Success()
+ : protocol::Response::ServerError("Overview failed");
}
protocol::Response WindowManagerHandler::ExitOverviewMode() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
bool success = ash::Shell::Get()->overview_controller()->EndOverview();
- return success ? protocol::Response::OK()
- : protocol::Response::Error("Overview failed");
+ return success ? protocol::Response::Success()
+ : protocol::Response::ServerError("Overview failed");
}
diff --git a/chromium/chrome/browser/downgrade/buildflags.gni b/chromium/chrome/browser/downgrade/buildflags.gni
new file mode 100644
index 00000000000..ec184e76aee
--- /dev/null
+++ b/chromium/chrome/browser/downgrade/buildflags.gni
@@ -0,0 +1,9 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+
+declare_args() {
+ enable_downgrade_processing = !is_android && !is_chromeos
+}
diff --git a/chromium/chrome/browser/download/android/BUILD.gn b/chromium/chrome/browser/download/android/BUILD.gn
index da1ddbdfe8d..ee05a9b017e 100644
--- a/chromium/chrome/browser/download/android/BUILD.gn
+++ b/chromium/chrome/browser/download/android/BUILD.gn
@@ -5,17 +5,18 @@
import("//build/config/android/rules.gni")
android_library("java") {
- java_files = [
+ sources = [
"java/src/org/chromium/chrome/browser/download/DirectoryOption.java",
"java/src/org/chromium/chrome/browser/download/DownloadConstants.java",
+ "java/src/org/chromium/chrome/browser/download/DownloadDelegateImpl.java",
"java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java",
"java/src/org/chromium/chrome/browser/download/DownloadFileProvider.java",
"java/src/org/chromium/chrome/browser/download/DownloadFilter.java",
"java/src/org/chromium/chrome/browser/download/DownloadInfo.java",
"java/src/org/chromium/chrome/browser/download/DownloadManagerBridge.java",
+ "java/src/org/chromium/chrome/browser/download/DownloadStartupUtils.java",
"java/src/org/chromium/chrome/browser/download/DownloadStatus.java",
"java/src/org/chromium/chrome/browser/download/MediaStoreHelper.java",
- "java/src/org/chromium/chrome/browser/download/DownloadStartupUtils.java",
"java/src/org/chromium/chrome/browser/download/MimeUtils.java",
"java/src/org/chromium/chrome/browser/download/UriUtils.java",
]
@@ -24,10 +25,13 @@ android_library("java") {
"//base:base_java",
"//base:jni_java",
"//chrome/browser/util:java",
+ "//components/download/internal/common:internal_java",
"//components/download/public/common:public_java",
+ "//components/embedder_support/android:util_java",
+ "//components/feed/core/shared_prefs:feed_shared_prefs",
"//components/offline_items_collection/core:core_java",
"//content/public/android:content_java",
- "//third_party/android_deps:com_android_support_support_compat_java",
+ "//third_party/android_deps:androidx_core_core_java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
@@ -45,9 +49,9 @@ generate_jni("jni_headers") {
android_library("download_java_tests") {
testonly = true
- java_files = [
- "javatests/src/org/chromium/chrome/browser/download/MimeUtilsTest.java",
+ sources = [
"javatests/src/org/chromium/chrome/browser/download/DownloadFileProviderTest.java",
+ "javatests/src/org/chromium/chrome/browser/download/MimeUtilsTest.java",
]
deps = [
@@ -59,3 +63,63 @@ android_library("download_java_tests") {
"//third_party/mockito:mockito_java",
]
}
+
+android_resources("java_resources") {
+ sources = [
+ "java/res/drawable/async_image_view_unavailable.xml",
+ "java/res/drawable/async_image_view_waiting.xml",
+ "java/res/drawable/circular_progress_bar_background_large.xml",
+ "java/res/drawable/circular_progress_bar_background_small.xml",
+ "java/res/drawable/circular_progress_bar_determinate_large.xml",
+ "java/res/drawable/circular_progress_bar_determinate_small.xml",
+ "java/res/drawable/circular_progress_bar_indeterminate_large.xml",
+ "java/res/drawable/circular_progress_bar_indeterminate_small.xml",
+ "java/res/drawable/circular_progress_bar_pause_tiny.xml",
+ "java/res/drawable/circular_progress_bar_resume_tiny.xml",
+ "java/res/drawable/circular_progress_bar_retry_tiny.xml",
+ "java/res/drawable/group_card_footer_curved_border.xml",
+ "java/res/drawable/group_card_header_curved_border.xml",
+ "java/res/drawable/group_card_item_border.xml",
+ "java/res/layout/confirm_oma_download.xml",
+ "java/res/layout/download_home_tabs.xml",
+ "java/res/layout/download_home_toolbar.xml",
+ "java/res/layout/download_location_dialog.xml",
+ "java/res/layout/download_location_preference.xml",
+ "java/res/layout/download_location_preference_item.xml",
+ "java/res/layout/download_location_spinner_dropdown_item.xml",
+ "java/res/layout/download_location_spinner_item.xml",
+ "java/res/layout/download_manager_audio.xml",
+ "java/res/layout/download_manager_card_divider_bottom.xml",
+ "java/res/layout/download_manager_card_divider_middle.xml",
+ "java/res/layout/download_manager_card_divider_top.xml",
+ "java/res/layout/download_manager_card_footer.xml",
+ "java/res/layout/download_manager_card_header.xml",
+ "java/res/layout/download_manager_generic_item.xml",
+ "java/res/layout/download_manager_image_item.xml",
+ "java/res/layout/download_manager_in_progress_image_item.xml",
+ "java/res/layout/download_manager_in_progress_item.xml",
+ "java/res/layout/download_manager_in_progress_video_item.xml",
+ "java/res/layout/download_manager_pagination_header.xml",
+ "java/res/layout/download_manager_prefetch_article.xml",
+ "java/res/layout/download_manager_prefetch_grouped_item.xml",
+ "java/res/layout/download_manager_section_header.xml",
+ "java/res/layout/download_manager_video_item.xml",
+ "java/res/layout/download_rename_custom_dialog.xml",
+ "java/res/layout/download_rename_extension_custom_dialog.xml",
+ "java/res/layout/download_storage_summary.xml",
+ "java/res/layout/downloads_empty_view.xml",
+ "java/res/menu/download_manager_menu.xml",
+ "java/res/values-v17/attrs.xml",
+ "java/res/values-v17/ids.xml",
+ "java/res/values-v17/styles.xml",
+ ]
+ deps = [
+ "//chrome/browser/ui/android/strings:ui_strings_grd",
+ "//components/browser_ui/modaldialog/android:java_resources",
+ "//components/browser_ui/strings/android:browser_ui_strings_grd",
+ "//components/browser_ui/styles/android:java_resources",
+ "//components/browser_ui/widget/android:java_resources",
+ "//ui/android:ui_java_resources",
+ ]
+ custom_package = "org.chromium.chrome.download"
+}
diff --git a/chromium/chrome/browser/engagement/BUILD.gn b/chromium/chrome/browser/engagement/BUILD.gn
index 19652962467..2744f704fc7 100644
--- a/chromium/chrome/browser/engagement/BUILD.gn
+++ b/chromium/chrome/browser/engagement/BUILD.gn
@@ -5,11 +5,7 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "site_engagement_details.mojom",
- ]
+ sources = [ "site_engagement_details.mojom" ]
- public_deps = [
- "//url/mojom:url_mojom_gurl",
- ]
+ public_deps = [ "//url/mojom:url_mojom_gurl" ]
}
diff --git a/chromium/chrome/browser/extensions/BUILD.gn b/chromium/chrome/browser/extensions/BUILD.gn
index 9d69db7aa10..60cc5af9997 100644
--- a/chromium/chrome/browser/extensions/BUILD.gn
+++ b/chromium/chrome/browser/extensions/BUILD.gn
@@ -181,6 +181,8 @@ jumbo_static_library("extensions") {
"api/i18n/i18n_api.h",
"api/identity/extension_token_key.cc",
"api/identity/extension_token_key.h",
+ "api/identity/gaia_remote_consent_flow.cc",
+ "api/identity/gaia_remote_consent_flow.h",
"api/identity/gaia_web_auth_flow.cc",
"api/identity/gaia_web_auth_flow.h",
"api/identity/identity_api.cc",
@@ -197,6 +199,8 @@ jumbo_static_library("extensions") {
"api/identity/identity_launch_web_auth_flow_function.h",
"api/identity/identity_mint_queue.cc",
"api/identity/identity_mint_queue.h",
+ "api/identity/identity_private_api.cc",
+ "api/identity/identity_private_api.h",
"api/identity/identity_remove_cached_auth_token_function.cc",
"api/identity/identity_remove_cached_auth_token_function.h",
"api/identity/web_auth_flow.cc",
@@ -269,6 +273,8 @@ jumbo_static_library("extensions") {
"api/omnibox/omnibox_api.h",
"api/page_capture/page_capture_api.cc",
"api/page_capture/page_capture_api.h",
+ "api/passwords_private/password_check_delegate.cc",
+ "api/passwords_private/password_check_delegate.h",
"api/passwords_private/passwords_private_api.cc",
"api/passwords_private/passwords_private_api.h",
"api/passwords_private/passwords_private_delegate.h",
@@ -282,6 +288,8 @@ jumbo_static_library("extensions") {
"api/passwords_private/passwords_private_event_router_factory.h",
"api/passwords_private/passwords_private_utils.cc",
"api/passwords_private/passwords_private_utils.h",
+ "api/passwords_private/test_passwords_private_delegate.cc",
+ "api/passwords_private/test_passwords_private_delegate.h",
"api/permissions/permissions_api.cc",
"api/permissions/permissions_api.h",
"api/permissions/permissions_api_helpers.cc",
@@ -414,8 +422,6 @@ jumbo_static_library("extensions") {
"api/webstore_private/extension_install_status.h",
"api/webstore_private/webstore_private_api.cc",
"api/webstore_private/webstore_private_api.h",
- "app_data_migrator.cc",
- "app_data_migrator.h",
"blacklist.cc",
"blacklist.h",
"blacklist_check.cc",
@@ -466,8 +472,6 @@ jumbo_static_library("extensions") {
"chrome_extensions_browser_client.h",
"chrome_extensions_browser_interface_binders.cc",
"chrome_extensions_browser_interface_binders.h",
- "chrome_extensions_interface_registration.cc",
- "chrome_extensions_interface_registration.h",
"chrome_kiosk_delegate.h",
"chrome_process_manager_delegate.cc",
"chrome_process_manager_delegate.h",
@@ -611,6 +615,8 @@ jumbo_static_library("extensions") {
"external_provider_impl.h",
"external_registry_loader_win.cc",
"external_registry_loader_win.h",
+ "forced_extensions/installation_metrics.cc",
+ "forced_extensions/installation_metrics.h",
"forced_extensions/installation_reporter.cc",
"forced_extensions/installation_reporter.h",
"forced_extensions/installation_reporter_factory.cc",
@@ -626,6 +632,8 @@ jumbo_static_library("extensions") {
"install_gate.h",
"install_observer.cc",
"install_observer.h",
+ "install_prompt_permissions.cc",
+ "install_prompt_permissions.h",
"install_signer.cc",
"install_signer.h",
"install_tracker.cc",
@@ -660,8 +668,6 @@ jumbo_static_library("extensions") {
"permissions_based_management_policy_provider.h",
"permissions_updater.cc",
"permissions_updater.h",
- "plugin_manager.cc",
- "plugin_manager.h",
"policy_extension_reinstaller.cc",
"policy_extension_reinstaller.h",
"policy_handlers.cc",
@@ -766,9 +772,9 @@ jumbo_static_library("extensions") {
"//chrome/browser/extensions/api:api_registration",
"//chrome/common",
"//chrome/common/extensions/api",
- "//components/safe_browsing:csd_proto",
- "//components/safe_browsing:webprotect_proto",
- "//components/safe_browsing/db:util",
+ "//components/safe_browsing/core:csd_proto",
+ "//components/safe_browsing/core:webprotect_proto",
+ "//components/safe_browsing/core/db:util",
"//components/signin/core/browser",
"//content/public/browser",
"//mojo/public/cpp/bindings",
@@ -788,6 +794,7 @@ jumbo_static_library("extensions") {
"//chrome/browser:theme_properties",
"//chrome/browser/devtools",
"//chrome/browser/engagement:mojo_bindings",
+ "//chrome/browser/image_decoder",
"//chrome/browser/media/router",
"//chrome/browser/media/router/discovery",
"//chrome/browser/resource_coordinator:mojo_bindings",
@@ -797,13 +804,11 @@ jumbo_static_library("extensions") {
"//chrome/common/extensions/api:extensions_features",
"//chrome/common/safe_browsing:proto",
"//chrome/services/removable_storage_writer/public/mojom",
- "//components/app_modal",
"//components/autofill/content/browser",
"//components/bookmarks/browser",
"//components/bookmarks/managed",
"//components/browser_sync",
"//components/browsing_data/core",
- "//components/bubble",
"//components/content_settings/core/browser",
"//components/cookie_config:cookie_config",
"//components/crx_file",
@@ -812,12 +817,14 @@ jumbo_static_library("extensions") {
"//components/download/content/public",
"//components/download/public/common:public",
"//components/drive",
+ "//components/embedder_support",
"//components/favicon/content",
"//components/feedback",
"//components/gcm_driver",
"//components/guest_view/browser",
"//components/history/core/browser",
"//components/infobars/core",
+ "//components/javascript_dialogs",
"//components/keyed_service/content",
"//components/language/core/browser",
"//components/language/core/common",
@@ -826,11 +833,14 @@ jumbo_static_library("extensions") {
"//components/net_log",
"//components/omnibox/browser",
"//components/onc",
+ "//components/page_load_metrics/browser:browser",
"//components/password_manager/core/browser",
"//components/password_manager/core/browser:affiliation",
+ "//components/password_manager/core/browser/leak_detection",
"//components/payments/core",
"//components/pdf/browser",
"//components/performance_manager",
+ "//components/permissions",
"//components/policy:generated",
"//components/policy/core/browser",
"//components/pref_registry",
@@ -838,10 +848,11 @@ jumbo_static_library("extensions") {
"//components/rappor",
"//components/resources",
"//components/safe_browsing:buildflags",
- "//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/content/web_ui:web_ui",
+ "//components/safe_browsing/core:csd_proto",
+ "//components/safe_browsing/core:features",
+ "//components/safe_browsing/core/common:safe_browsing_prefs",
+ "//components/safe_browsing/core/db:database_manager",
"//components/search_engines",
"//components/services/patch/content",
"//components/services/unzip/content",
@@ -885,8 +896,6 @@ jumbo_static_library("extensions") {
"//services/audio/public/cpp",
"//services/data_decoder/public/cpp",
"//services/device/public/mojom",
- "//services/identity/public/cpp:cpp_types",
- "//services/identity/public/mojom",
"//services/network/public/mojom",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
@@ -921,6 +930,16 @@ jumbo_static_library("extensions") {
"//url",
]
+ if (enable_autofill_assistant_api) {
+ sources += [
+ "api/autofill_assistant_private/autofill_assistant_private_api.cc",
+ "api/autofill_assistant_private/autofill_assistant_private_api.h",
+ "api/autofill_assistant_private/extension_access_token_fetcher.cc",
+ "api/autofill_assistant_private/extension_access_token_fetcher.h",
+ ]
+ deps += [ "//components/autofill_assistant/browser" ]
+ }
+
if (is_chromeos) {
sources += [
"api/certificate_provider/certificate_provider_api.cc",
@@ -1032,6 +1051,8 @@ jumbo_static_library("extensions") {
"api/enterprise_reporting_private/chrome_desktop_report_request_helper.h",
"api/enterprise_reporting_private/device_info_fetcher.cc",
"api/enterprise_reporting_private/device_info_fetcher.h",
+ "api/enterprise_reporting_private/device_info_fetcher_linux.cc",
+ "api/enterprise_reporting_private/device_info_fetcher_linux.h",
"api/enterprise_reporting_private/device_info_fetcher_mac.h",
"api/enterprise_reporting_private/device_info_fetcher_mac.mm",
"api/enterprise_reporting_private/device_info_fetcher_win.cc",
@@ -1058,6 +1079,9 @@ jumbo_static_library("extensions") {
if (is_posix) {
sources += [ "api/messaging/native_process_launcher_posix.cc" ]
}
+ if (use_gio) {
+ configs += [ "//build/linux:gio_config" ]
+ }
}
if (use_x11) {
@@ -1146,6 +1170,13 @@ jumbo_static_library("extensions") {
]
}
+ if (enable_plugins) {
+ sources += [
+ "plugin_manager.cc",
+ "plugin_manager.h",
+ ]
+ }
+
if (enable_print_preview && !is_chromeos) {
sources += [
"api/cloud_print_private/cloud_print_private_api.cc",
diff --git a/chromium/chrome/browser/extensions/api/BUILD.gn b/chromium/chrome/browser/extensions/api/BUILD.gn
index 0200a00b204..82da6124bc6 100644
--- a/chromium/chrome/browser/extensions/api/BUILD.gn
+++ b/chromium/chrome/browser/extensions/api/BUILD.gn
@@ -22,6 +22,7 @@ function_registration("api_registration") {
deps = [
# Different APIs include headers from these targets.
"//chrome/common:mojo_bindings",
+ "//components/zoom",
"//content/public/browser",
"//extensions/browser",
diff --git a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
index 8d66064324e..3cc1dec8191 100644
--- a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc
@@ -112,7 +112,8 @@ void ActivityLogAPI::OnExtensionActivity(scoped_refptr<Action> activity) {
EventRouter::Get(browser_context_)->BroadcastEvent(std::move(event));
}
-bool ActivityLogPrivateGetExtensionActivitiesFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+ActivityLogPrivateGetExtensionActivitiesFunction::Run() {
std::unique_ptr<activity_log_private::GetExtensionActivities::Params> params(
activity_log_private::GetExtensionActivities::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
@@ -153,20 +154,15 @@ bool ActivityLogPrivateGetExtensionActivitiesFunction::RunAsync() {
days_ago = *filter.days_ago;
// Call the ActivityLog.
- ActivityLog* activity_log = ActivityLog::GetInstance(GetProfile());
+ ActivityLog* activity_log = ActivityLog::GetInstance(browser_context());
DCHECK(activity_log);
activity_log->GetFilteredActions(
- extension_id,
- action_type,
- api_call,
- page_url,
- arg_url,
- days_ago,
- base::Bind(
+ extension_id, action_type, api_call, page_url, arg_url, days_ago,
+ base::BindOnce(
&ActivityLogPrivateGetExtensionActivitiesFunction::OnLookupCompleted,
this));
- return true;
+ return RespondLater();
}
void ActivityLogPrivateGetExtensionActivitiesFunction::OnLookupCompleted(
@@ -177,12 +173,11 @@ void ActivityLogPrivateGetExtensionActivitiesFunction::OnLookupCompleted(
result_arr.push_back(activity->ConvertToExtensionActivity());
// Populate the return object.
- std::unique_ptr<ActivityResultSet> result_set(new ActivityResultSet);
- result_set->activities = std::move(result_arr);
- results_ = activity_log_private::GetExtensionActivities::Results::Create(
- *result_set);
-
- SendResponse(true);
+ ActivityResultSet result_set;
+ result_set.activities = std::move(result_arr);
+ Respond(ArgumentList(
+ activity_log_private::GetExtensionActivities::Results::Create(
+ result_set)));
}
ExtensionFunction::ResponseAction
diff --git a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h
index afee1976650..07a3dbf51aa 100644
--- a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h
+++ b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h
@@ -13,9 +13,9 @@
#include "base/synchronization/lock.h"
#include "chrome/browser/extensions/activity_log/activity_actions.h"
#include "chrome/browser/extensions/activity_log/activity_log.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_function.h"
namespace extensions {
@@ -65,7 +65,7 @@ void
// The implementation of activityLogPrivate.getExtensionActivities
class ActivityLogPrivateGetExtensionActivitiesFunction
- : public ChromeAsyncExtensionFunction {
+ : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("activityLogPrivate.getExtensionActivities",
ACTIVITYLOGPRIVATE_GETEXTENSIONACTIVITIES)
@@ -74,7 +74,7 @@ class ActivityLogPrivateGetExtensionActivitiesFunction
~ActivityLogPrivateGetExtensionActivitiesFunction() override {}
// ExtensionFunction:
- bool RunAsync() override;
+ ResponseAction Run() override;
private:
void OnLookupCompleted(
diff --git a/chromium/chrome/browser/extensions/api/alarms/alarms_apitest.cc b/chromium/chrome/browser/extensions/api/alarms/alarms_apitest.cc
new file mode 100644
index 00000000000..3601f29123e
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/alarms/alarms_apitest.cc
@@ -0,0 +1,82 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/common/api/test.h"
+#include "extensions/test/extension_test_message_listener.h"
+#include "extensions/test/result_catcher.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+using extensions::ResultCatcher;
+
+namespace extensions {
+
+class AlarmsApiTest : public ExtensionApiTest {
+ public:
+ void SetUpOnMainThread() override {
+ ExtensionApiTest::SetUpOnMainThread();
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ }
+
+ static std::unique_ptr<base::ListValue> BuildEventArguments(
+ const bool last_message) {
+ api::test::OnMessage::Info info;
+ info.data = "";
+ info.last_message = last_message;
+ return api::test::OnMessage::Create(info);
+ }
+};
+
+// Tests that an alarm created by an extension with incognito split mode is
+// only triggered in the browser context it was created in.
+IN_PROC_BROWSER_TEST_F(AlarmsApiTest, IncognitoSplit) {
+ // We need 2 ResultCatchers because we'll be running the same test in both
+ // regular and incognito mode.
+ Profile* incognito_profile = browser()->profile()->GetOffTheRecordProfile();
+ ResultCatcher catcher_incognito;
+ catcher_incognito.RestrictToBrowserContext(incognito_profile);
+ ResultCatcher catcher;
+ catcher.RestrictToBrowserContext(browser()->profile());
+ EventRouter* event_router = EventRouter::Get(incognito_profile);
+
+ ExtensionTestMessageListener listener("ready: false", false);
+
+ ExtensionTestMessageListener listener_incognito("ready: true", false);
+
+ ASSERT_TRUE(LoadExtensionIncognito(
+ test_data_dir_.AppendASCII("alarms").AppendASCII("split")));
+
+ EXPECT_TRUE(listener.WaitUntilSatisfied());
+ EXPECT_TRUE(listener_incognito.WaitUntilSatisfied());
+
+ // Open incognito window.
+ OpenURLOffTheRecord(browser()->profile(), GURL("about:blank"));
+
+ event_router->BroadcastEvent(std::make_unique<Event>(
+ events::FOR_TEST, api::test::OnMessage::kEventName,
+ BuildEventArguments(true)));
+
+ EXPECT_TRUE(catcher.GetNextResult());
+ EXPECT_TRUE(catcher_incognito.GetNextResult());
+}
+
+// Tests that the behavior for an alarm created in incognito context should be
+// the same if incognito is in spanning mode.
+IN_PROC_BROWSER_TEST_F(AlarmsApiTest, IncognitoSpanning) {
+ ResultCatcher catcher;
+ catcher.RestrictToBrowserContext(browser()->profile());
+
+ ASSERT_TRUE(LoadExtensionIncognito(
+ test_data_dir_.AppendASCII("alarms").AppendASCII("spanning")));
+
+ // Open incognito window.
+ OpenURLOffTheRecord(browser()->profile(), GURL("about:blank"));
+
+ EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/autofill_assistant_private/OWNERS b/chromium/chrome/browser/extensions/api/autofill_assistant_private/OWNERS
new file mode 100644
index 00000000000..ed6d5f01bfd
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/autofill_assistant_private/OWNERS
@@ -0,0 +1 @@
+file://components/autofill_assistant/OWNERS
diff --git a/chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.cc b/chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.cc
new file mode 100644
index 00000000000..83041ce1abf
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.cc
@@ -0,0 +1,421 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/no_destructor.h"
+#include "base/time/default_tick_clock.h"
+#include "base/values.h"
+#include "chrome/browser/autofill/personal_data_manager_factory.h"
+#include "chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h"
+#include "chrome/browser/extensions/chrome_extension_function_details.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "extensions/browser/event_router_factory.h"
+
+namespace extensions {
+namespace {
+content::WebContents* GetActiveWebContents(ExtensionFunction* function) {
+ // TODO(crbug.com/1015753): GetCurrentBrowser is not deterministic and needs
+ // to be replaced with an explicit tabID passed to the create(...) extension
+ // function.
+ return ChromeExtensionFunctionDetails(function)
+ .GetCurrentBrowser()
+ ->tab_strip_model()
+ ->GetActiveWebContents();
+}
+} // namespace
+
+AutofillAssistantPrivateCreateFunction::
+ AutofillAssistantPrivateCreateFunction() = default;
+
+AutofillAssistantPrivateCreateFunction::
+ ~AutofillAssistantPrivateCreateFunction() = default;
+
+ExtensionFunction::ResponseAction
+AutofillAssistantPrivateCreateFunction::Run() {
+ auto* web_contents = GetActiveWebContents(this);
+ CHECK(web_contents);
+ AutofillAssistantPrivateAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->CreateAutofillAssistantController(web_contents);
+
+ // TODO(crbug.com/1015753): Add unittests and check that no arguments are
+ // returned!
+ return RespondNow(NoArguments());
+}
+
+AutofillAssistantPrivateStartFunction::AutofillAssistantPrivateStartFunction() =
+ default;
+
+AutofillAssistantPrivateStartFunction::
+ ~AutofillAssistantPrivateStartFunction() = default;
+
+ExtensionFunction::ResponseAction AutofillAssistantPrivateStartFunction::Run() {
+ std::unique_ptr<api::autofill_assistant_private::Start::Params> params =
+ api::autofill_assistant_private::Start::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ // TODO(crbug.com/1015753): Populate parameters from params.
+ std::map<std::string, std::string> parameters;
+
+ bool ok = AutofillAssistantPrivateAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->StartAutofillAssistantController(std::move(parameters));
+
+ if (!ok) {
+ return RespondNow(Error("Starting requires a valid controller!"));
+ }
+ return RespondNow(NoArguments());
+}
+
+AutofillAssistantPrivatePerformActionFunction::
+ AutofillAssistantPrivatePerformActionFunction() = default;
+
+AutofillAssistantPrivatePerformActionFunction::
+ ~AutofillAssistantPrivatePerformActionFunction() = default;
+
+ExtensionFunction::ResponseAction
+AutofillAssistantPrivatePerformActionFunction::Run() {
+ std::unique_ptr<api::autofill_assistant_private::PerformAction::Params>
+ parameters =
+ api::autofill_assistant_private::PerformAction::Params::Create(
+ *args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters.get());
+
+ bool ok = AutofillAssistantPrivateAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->PerformAction(parameters->index);
+ if (!ok) {
+ return RespondNow(Error("performAction requires a valid controller!"));
+ }
+ return RespondNow(NoArguments());
+}
+
+AutofillAssistantPrivateProvideUserDataFunction::
+ AutofillAssistantPrivateProvideUserDataFunction() = default;
+
+AutofillAssistantPrivateProvideUserDataFunction::
+ ~AutofillAssistantPrivateProvideUserDataFunction() = default;
+
+ExtensionFunction::ResponseAction
+AutofillAssistantPrivateProvideUserDataFunction::Run() {
+ AutofillAssistantPrivateAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->ProvideUserData();
+
+ return RespondNow(NoArguments());
+}
+
+AutofillAssistantPrivateEventRouter::AutofillAssistantPrivateEventRouter(
+ autofill_assistant::Controller* controller,
+ content::BrowserContext* browser_context)
+ : controller_(controller), browser_context_(browser_context) {
+ DCHECK_NE(nullptr, controller);
+ controller_->AddObserver(this);
+}
+
+AutofillAssistantPrivateEventRouter::~AutofillAssistantPrivateEventRouter() {}
+
+void AutofillAssistantPrivateEventRouter::OnUserActionsChanged(
+ const std::vector<autofill_assistant::UserAction>& user_actions) {
+ if (!HasEventListenerForEvent(
+ api::autofill_assistant_private::OnActionsChanged::kEventName))
+ return;
+
+ std::vector<api::autofill_assistant_private::ActionObject> actions;
+ actions.reserve(user_actions.size());
+ for (size_t i = 0; i < user_actions.size(); ++i) {
+ actions.emplace_back();
+ actions.back().name = user_actions[i].chip().text;
+ actions.back().index = i;
+ }
+
+ std::unique_ptr<base::ListValue> args(
+ api::autofill_assistant_private::OnActionsChanged::Create(actions));
+
+ std::unique_ptr<Event> extension_event = std::make_unique<Event>(
+ events::AUTOFILL_ASSISTANT_PRIVATE_ON_ACTIONS_CHANGED,
+ api::autofill_assistant_private::OnActionsChanged::kEventName,
+ std::move(args));
+ EventRouter::Get(browser_context_)
+ ->BroadcastEvent(std::move(extension_event));
+}
+
+void AutofillAssistantPrivateEventRouter::OnStatusMessageChanged(
+ const std::string& message) {
+ if (!HasEventListenerForEvent(
+ api::autofill_assistant_private::OnStatusMessageChanged::kEventName))
+ return;
+
+ std::unique_ptr<base::ListValue> args(
+ api::autofill_assistant_private::OnStatusMessageChanged::Create(message));
+
+ std::unique_ptr<Event> extension_event(new Event(
+ events::AUTOFILL_ASSISTANT_PRIVATE_ON_STATUS_MESSAGE_CHANGED,
+ api::autofill_assistant_private::OnStatusMessageChanged::kEventName,
+ std::move(args)));
+ EventRouter::Get(browser_context_)
+ ->BroadcastEvent(std::move(extension_event));
+}
+
+void AutofillAssistantPrivateEventRouter::OnStateChanged(
+ autofill_assistant::AutofillAssistantState new_state) {}
+
+void AutofillAssistantPrivateEventRouter::OnBubbleMessageChanged(
+ const std::string& message) {}
+
+void AutofillAssistantPrivateEventRouter::CloseCustomTab() {}
+
+void AutofillAssistantPrivateEventRouter::OnCollectUserDataOptionsChanged(
+ const autofill_assistant::CollectUserDataOptions* options) {}
+
+void AutofillAssistantPrivateEventRouter::OnUserDataChanged(
+ const autofill_assistant::UserData* state,
+ autofill_assistant::UserData::FieldChange field_change) {}
+
+void AutofillAssistantPrivateEventRouter::OnDetailsChanged(
+ const autofill_assistant::Details* details) {}
+
+void AutofillAssistantPrivateEventRouter::OnInfoBoxChanged(
+ const autofill_assistant::InfoBox* info_box) {}
+
+void AutofillAssistantPrivateEventRouter::OnProgressChanged(int progress) {}
+
+void AutofillAssistantPrivateEventRouter::OnProgressVisibilityChanged(
+ bool visible) {}
+
+void AutofillAssistantPrivateEventRouter::OnTouchableAreaChanged(
+ const autofill_assistant::RectF& visual_viewport,
+ const std::vector<autofill_assistant::RectF>& touchable_areas,
+ const std::vector<autofill_assistant::RectF>& restricted_areas) {}
+
+void AutofillAssistantPrivateEventRouter::OnViewportModeChanged(
+ autofill_assistant::ViewportMode mode) {}
+
+void AutofillAssistantPrivateEventRouter::OnPeekModeChanged(
+ autofill_assistant::ConfigureBottomSheetProto::PeekMode peek_mode) {}
+
+void AutofillAssistantPrivateEventRouter::OnOverlayColorsChanged(
+ const autofill_assistant::UiDelegate::OverlayColors& colors) {}
+
+void AutofillAssistantPrivateEventRouter::OnFormChanged(
+ const autofill_assistant::FormProto* form,
+ const autofill_assistant::FormProto::Result* result) {}
+
+void AutofillAssistantPrivateEventRouter::OnClientSettingsChanged(
+ const autofill_assistant::ClientSettings& settings) {}
+
+void AutofillAssistantPrivateEventRouter::OnGenericUserInterfaceChanged(
+ const autofill_assistant::GenericUserInterfaceProto* generic_ui) {}
+
+void AutofillAssistantPrivateEventRouter::OnExpandBottomSheet() {}
+
+void AutofillAssistantPrivateEventRouter::OnCollapseBottomSheet() {}
+
+bool AutofillAssistantPrivateEventRouter::HasEventListenerForEvent(
+ const char* event_name) {
+ return EventRouter::Get(browser_context_)->HasEventListener(event_name);
+}
+
+// static
+BrowserContextKeyedAPIFactory<AutofillAssistantPrivateAPI>*
+AutofillAssistantPrivateAPI::GetFactoryInstance() {
+ static base::NoDestructor<
+ BrowserContextKeyedAPIFactory<AutofillAssistantPrivateAPI>>
+ instance;
+ return instance.get();
+}
+
+template <>
+void BrowserContextKeyedAPIFactory<
+ AutofillAssistantPrivateAPI>::DeclareFactoryDependencies() {
+ DependsOn(EventRouterFactory::GetInstance());
+}
+
+AutofillAssistantPrivateAPI::AutofillAssistantPrivateAPI(
+ content::BrowserContext* context)
+ : browser_context_(context) {
+ access_token_fetcher_ = std::make_unique<ExtensionAccessTokenFetcher>(
+ IdentityManagerFactory::GetForProfile(
+ Profile::FromBrowserContext(browser_context_)));
+}
+
+AutofillAssistantPrivateAPI::~AutofillAssistantPrivateAPI() {
+ access_token_fetcher_.reset();
+}
+
+void AutofillAssistantPrivateAPI::CreateAutofillAssistantController(
+ content::WebContents* web_contents) {
+ if (active_autofill_assistant_) {
+ DestroyActiveAutofillAssistant();
+ }
+
+ CreateActiveAutofillAssistant(web_contents);
+}
+
+bool AutofillAssistantPrivateAPI::StartAutofillAssistantController(
+ std::map<std::string, std::string> parameters) {
+ if (!active_autofill_assistant_)
+ return false;
+
+ // TODO(crbug.com/1015753): Remove the hard coded parameter and use |params|
+ // instead. The url usually comes from an Android intent data URL and is
+ // logged as the trigger deep link. This does not fully translate to the
+ // extension use case and needs more thought. For now we pass in a dummy URL.
+ parameters["DETAILS_SHOW_INITIAL"] = "false";
+ const std::string url = "http://localhost:8080/test.html";
+
+ auto context = autofill_assistant::TriggerContext::Create(parameters, "");
+ active_autofill_assistant_->controller->Start(GURL(url), std::move(context));
+ return true;
+}
+
+bool AutofillAssistantPrivateAPI::PerformAction(int index) {
+ if (!active_autofill_assistant_)
+ return false;
+ active_autofill_assistant_->controller->PerformUserAction(index);
+ return true;
+}
+
+bool AutofillAssistantPrivateAPI::ProvideUserData() {
+ if (!active_autofill_assistant_)
+ return false;
+
+ auto* controller = active_autofill_assistant_->controller.get();
+
+ // TODO(crbug.com/1015753): Plumb the hard coded user data to the idl
+ // interface definition and expose it to the extension.
+ // Note that the set of empty profiles provided here is currently not
+ // sufficient for a working e2e flow.
+ auto shipping = std::make_unique<autofill::AutofillProfile>();
+ // TBD: set some shipping fields.
+ controller->SetShippingAddress(std::move(shipping));
+ auto contact = std::make_unique<autofill::AutofillProfile>();
+ controller->SetContactInfo(std::move(contact));
+
+ auto billing = std::make_unique<autofill::AutofillProfile>();
+ auto card = std::make_unique<autofill::CreditCard>();
+ card->set_billing_address_id(billing->guid());
+
+ controller->SetCreditCard(std::move(card), std::move(billing));
+ controller->SetTermsAndConditions(
+ autofill_assistant::TermsAndConditionsState::ACCEPTED);
+ return true;
+}
+
+void AutofillAssistantPrivateAPI::AttachUI() {}
+
+void AutofillAssistantPrivateAPI::DestroyUI() {}
+
+std::string AutofillAssistantPrivateAPI::GetApiKey() const {
+ // TODO(crbug.com/1015753): Use chromium's keys and also consider the
+ // autofill-assistant-key here to override that particular key.
+ return "invalid";
+}
+
+std::string AutofillAssistantPrivateAPI::GetAccountEmailAddress() const {
+ return "joe@example.com";
+}
+
+autofill_assistant::AccessTokenFetcher*
+AutofillAssistantPrivateAPI::GetAccessTokenFetcher() {
+ return access_token_fetcher_.get();
+}
+
+autofill::PersonalDataManager*
+AutofillAssistantPrivateAPI::GetPersonalDataManager() const {
+ return autofill::PersonalDataManagerFactory::GetForProfile(
+ Profile::FromBrowserContext(browser_context_));
+}
+
+password_manager::PasswordManagerClient*
+AutofillAssistantPrivateAPI::GetPasswordManagerClient() const {
+ // TODO(crbug.com/1015753): Support credential leak flows.
+ return nullptr;
+}
+
+autofill_assistant::WebsiteLoginFetcher*
+AutofillAssistantPrivateAPI::GetWebsiteLoginFetcher() const {
+ return nullptr;
+}
+
+std::string AutofillAssistantPrivateAPI::GetServerUrl() const {
+ // TODO(crbug.com/1015753): Consider the autofill-assistant-url for endpoint
+ // overrides and share the kDefaultAutofillAssistantServerUrl to expose it
+ // here.
+ return "https://automate-pa.googleapis.com";
+}
+
+std::string AutofillAssistantPrivateAPI::GetLocale() const {
+ return "en-us";
+}
+
+std::string AutofillAssistantPrivateAPI::GetCountryCode() const {
+ return "us";
+}
+
+autofill_assistant::DeviceContext
+AutofillAssistantPrivateAPI::GetDeviceContext() const {
+ return autofill_assistant::DeviceContext();
+}
+
+void AutofillAssistantPrivateAPI::Shutdown(
+ autofill_assistant::Metrics::DropOutReason reason) {}
+
+// Note that this method implements autofill_assistant::Client and simply
+// forwards the web_contents associated with the controller. There is no reason
+// to use this method in this context.
+// TODO(crbug.com/1015753): Revisit the interfaces used for this extension API
+// and introduce new, more concise ones if needed.
+content::WebContents* AutofillAssistantPrivateAPI::GetWebContents() const {
+ if (!active_autofill_assistant_)
+ return nullptr;
+ return active_autofill_assistant_->controller->GetWebContents();
+}
+
+void AutofillAssistantPrivateAPI::Shutdown() {
+ if (active_autofill_assistant_)
+ DestroyActiveAutofillAssistant();
+}
+
+AutofillAssistantPrivateAPI::ActiveAutofillAssistant::
+ ActiveAutofillAssistant() {}
+AutofillAssistantPrivateAPI::ActiveAutofillAssistant::
+ ~ActiveAutofillAssistant() {}
+
+void AutofillAssistantPrivateAPI::CreateActiveAutofillAssistant(
+ content::WebContents* web_contents) {
+ active_autofill_assistant_ = std::make_unique<ActiveAutofillAssistant>();
+ // TODO(crbug.com/1015753): Make sure web_contents going away is properly
+ // handled by the controller. And if so, clean up state here.
+ active_autofill_assistant_->controller =
+ std::make_unique<autofill_assistant::Controller>(
+ web_contents, this, base::DefaultTickClock::GetInstance(),
+ std::move(service_));
+ active_autofill_assistant_->event_router =
+ std::make_unique<AutofillAssistantPrivateEventRouter>(
+ active_autofill_assistant_->controller.get(), browser_context_);
+}
+
+void AutofillAssistantPrivateAPI::DestroyActiveAutofillAssistant() {
+ // The event router has a reference to controller, so that is being cleaned up
+ // first.
+ active_autofill_assistant_->event_router.reset();
+ active_autofill_assistant_->controller.reset();
+ active_autofill_assistant_.reset();
+}
+
+void AutofillAssistantPrivateAPI::SetService(
+ std::unique_ptr<autofill_assistant::Service> service) {
+ DCHECK_EQ(nullptr, service_);
+ service_ = std::move(service);
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h b/chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h
new file mode 100644
index 00000000000..d047699de6c
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h
@@ -0,0 +1,248 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_ASSISTANT_PRIVATE_AUTOFILL_ASSISTANT_PRIVATE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_ASSISTANT_PRIVATE_AUTOFILL_ASSISTANT_PRIVATE_API_H_
+
+#include <string>
+
+#include "chrome/common/extensions/api/autofill_assistant_private.h"
+#include "components/autofill_assistant/browser/client.h"
+#include "components/autofill_assistant/browser/controller.h"
+#include "components/autofill_assistant/browser/controller_observer.h"
+#include "components/autofill_assistant/browser/service.h"
+#include "extensions/browser/browser_context_keyed_api_factory.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_function.h"
+
+namespace extensions {
+
+class AutofillAssistantPrivateCreateFunction : public ExtensionFunction {
+ public:
+ AutofillAssistantPrivateCreateFunction();
+ DECLARE_EXTENSION_FUNCTION("autofillAssistantPrivate.create",
+ AUTOFILLASSISTANTPRIVATE_CREATE)
+
+ AutofillAssistantPrivateCreateFunction(
+ const AutofillAssistantPrivateCreateFunction&) = delete;
+ AutofillAssistantPrivateCreateFunction& operator=(
+ const AutofillAssistantPrivateCreateFunction&) = delete;
+
+ protected:
+ ~AutofillAssistantPrivateCreateFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+};
+
+class AutofillAssistantPrivateStartFunction : public ExtensionFunction {
+ public:
+ AutofillAssistantPrivateStartFunction();
+ DECLARE_EXTENSION_FUNCTION("autofillAssistantPrivate.start",
+ AUTOFILLASSISTANTPRIVATE_START)
+
+ AutofillAssistantPrivateStartFunction(
+ const AutofillAssistantPrivateStartFunction&) = delete;
+ AutofillAssistantPrivateStartFunction& operator=(
+ const AutofillAssistantPrivateStartFunction&) = delete;
+
+ protected:
+ ~AutofillAssistantPrivateStartFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+};
+
+class AutofillAssistantPrivateGetStateFunction : public ExtensionFunction {
+ public:
+ AutofillAssistantPrivateGetStateFunction();
+ DECLARE_EXTENSION_FUNCTION("autofillAssistantPrivate.getState",
+ AUTOFILLASSISTANTPRIVATE_GETSTATE)
+
+ AutofillAssistantPrivateGetStateFunction(
+ const AutofillAssistantPrivateGetStateFunction&) = delete;
+ AutofillAssistantPrivateGetStateFunction& operator=(
+ const AutofillAssistantPrivateGetStateFunction&) = delete;
+
+ protected:
+ ~AutofillAssistantPrivateGetStateFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+};
+
+class AutofillAssistantPrivatePerformActionFunction : public ExtensionFunction {
+ public:
+ AutofillAssistantPrivatePerformActionFunction();
+ DECLARE_EXTENSION_FUNCTION("autofillAssistantPrivate.performAction",
+ AUTOFILLASSISTANTPRIVATE_PERFORMACTION)
+
+ AutofillAssistantPrivatePerformActionFunction(
+ const AutofillAssistantPrivatePerformActionFunction&) = delete;
+ AutofillAssistantPrivatePerformActionFunction& operator=(
+ const AutofillAssistantPrivatePerformActionFunction&) = delete;
+
+ protected:
+ ~AutofillAssistantPrivatePerformActionFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+};
+
+class AutofillAssistantPrivateProvideUserDataFunction
+ : public ExtensionFunction {
+ public:
+ AutofillAssistantPrivateProvideUserDataFunction();
+ DECLARE_EXTENSION_FUNCTION("autofillAssistantPrivate.provideUserData",
+ AUTOFILLASSISTANTPRIVATE_PROVIDEUSERDATA)
+
+ AutofillAssistantPrivateProvideUserDataFunction(
+ const AutofillAssistantPrivateProvideUserDataFunction&) = delete;
+ AutofillAssistantPrivateProvideUserDataFunction& operator=(
+ const AutofillAssistantPrivateProvideUserDataFunction&) = delete;
+
+ protected:
+ ~AutofillAssistantPrivateProvideUserDataFunction() override;
+
+ // ExtensionFunction:
+ ResponseAction Run() override;
+};
+
+class AutofillAssistantPrivateEventRouter
+ : public autofill_assistant::ControllerObserver {
+ public:
+ AutofillAssistantPrivateEventRouter(
+ autofill_assistant::Controller* controller,
+ content::BrowserContext* browser_context);
+ ~AutofillAssistantPrivateEventRouter() override;
+
+ AutofillAssistantPrivateEventRouter(
+ const AutofillAssistantPrivateEventRouter&) = delete;
+ AutofillAssistantPrivateEventRouter& operator=(
+ const AutofillAssistantPrivateEventRouter&) = delete;
+
+ // autofill_assistant::ControllerObserver:
+ void OnUserActionsChanged(
+ const std::vector<autofill_assistant::UserAction>& user_actions) override;
+ void OnStatusMessageChanged(const std::string& message) override;
+ // TODO(crbug.com/1015753): Expose more notifications as needed here.
+ void OnStateChanged(
+ autofill_assistant::AutofillAssistantState new_state) override;
+ void OnBubbleMessageChanged(const std::string& message) override;
+ void CloseCustomTab() override;
+ void OnCollectUserDataOptionsChanged(
+ const autofill_assistant::CollectUserDataOptions* options) override;
+ void OnUserDataChanged(
+ const autofill_assistant::UserData* state,
+ autofill_assistant::UserData::FieldChange field_change) override;
+ void OnDetailsChanged(const autofill_assistant::Details* details) override;
+ void OnInfoBoxChanged(const autofill_assistant::InfoBox* info_box) override;
+ void OnProgressChanged(int progress) override;
+ void OnProgressVisibilityChanged(bool visible) override;
+ void OnTouchableAreaChanged(
+ const autofill_assistant::RectF& visual_viewport,
+ const std::vector<autofill_assistant::RectF>& touchable_areas,
+ const std::vector<autofill_assistant::RectF>& restricted_areas) override;
+ void OnViewportModeChanged(autofill_assistant::ViewportMode mode) override;
+ void OnPeekModeChanged(autofill_assistant::ConfigureBottomSheetProto::PeekMode
+ peek_mode) override;
+ void OnOverlayColorsChanged(
+ const autofill_assistant::UiDelegate::OverlayColors& colors) override;
+ void OnFormChanged(
+ const autofill_assistant::FormProto* form,
+ const autofill_assistant::FormProto::Result* result) override;
+ void OnClientSettingsChanged(
+ const autofill_assistant::ClientSettings& settings) override;
+ void OnGenericUserInterfaceChanged(
+ const autofill_assistant::GenericUserInterfaceProto* generic_ui) override;
+
+ void OnExpandBottomSheet() override;
+ void OnCollapseBottomSheet() override;
+
+ private:
+ bool HasEventListenerForEvent(const char* event_name);
+
+ // |controller_|'s lifetime and this object are managed by the
+ // AutofillAssistantPrivateAPI, and |controller_| is guaranteed to be alive
+ // while this object is around.
+ autofill_assistant::Controller* controller_;
+ content::BrowserContext* browser_context_;
+};
+
+class AutofillAssistantPrivateAPI : public BrowserContextKeyedAPI,
+ public autofill_assistant::Client {
+ public:
+ static BrowserContextKeyedAPIFactory<AutofillAssistantPrivateAPI>*
+ GetFactoryInstance();
+
+ explicit AutofillAssistantPrivateAPI(content::BrowserContext* context);
+ ~AutofillAssistantPrivateAPI() override;
+
+ AutofillAssistantPrivateAPI(const AutofillAssistantPrivateAPI&) = delete;
+ AutofillAssistantPrivateAPI& operator=(const AutofillAssistantPrivateAPI&) =
+ delete;
+
+ void CreateAutofillAssistantController(content::WebContents* web_contents);
+ bool StartAutofillAssistantController(
+ std::map<std::string, std::string> params);
+ // Relay a selected action to the autofill assistant controller.
+ bool PerformAction(int index);
+ // Provides user data to the controller.
+ // TODO(crbug.com/1015753): Flesh this out to let the extension pass in user
+ // data.
+ bool ProvideUserData();
+
+ // autofill_assistant::Client:
+ void AttachUI() override;
+ void DestroyUI() override;
+ std::string GetApiKey() const override;
+ std::string GetAccountEmailAddress() const override;
+ autofill_assistant::AccessTokenFetcher* GetAccessTokenFetcher() override;
+ autofill::PersonalDataManager* GetPersonalDataManager() const override;
+ password_manager::PasswordManagerClient* GetPasswordManagerClient()
+ const override;
+ autofill_assistant::WebsiteLoginFetcher* GetWebsiteLoginFetcher()
+ const override;
+ std::string GetServerUrl() const override;
+ std::string GetLocale() const override;
+ std::string GetCountryCode() const override;
+ autofill_assistant::DeviceContext GetDeviceContext() const override;
+ void Shutdown(autofill_assistant::Metrics::DropOutReason reason) override;
+ content::WebContents* GetWebContents() const override;
+
+ // BrowserContextKeyedAPI:
+ void Shutdown() override;
+
+ // Used to inject a mock backend service in tests.
+ void SetService(std::unique_ptr<autofill_assistant::Service> service);
+
+ private:
+ friend class BrowserContextKeyedAPIFactory<AutofillAssistantPrivateAPI>;
+
+ // BrowserContextKeyedAPI:
+ static const char* service_name() { return "AutofillAssistantPrivateAPI"; }
+ static const bool kServiceIsNULLWhileTesting = true;
+
+ void CreateActiveAutofillAssistant(content::WebContents* web_contents);
+ void DestroyActiveAutofillAssistant();
+
+ content::BrowserContext* browser_context_;
+ std::unique_ptr<autofill_assistant::Service> service_;
+
+ // This struct ties the lifecycle of the event router and the controller
+ // together. That way event are only dispatched when both are alive.
+ struct ActiveAutofillAssistant {
+ ActiveAutofillAssistant();
+ ~ActiveAutofillAssistant();
+
+ std::unique_ptr<autofill_assistant::Controller> controller;
+ std::unique_ptr<AutofillAssistantPrivateEventRouter> event_router;
+ };
+ std::unique_ptr<ActiveAutofillAssistant> active_autofill_assistant_;
+ std::unique_ptr<autofill_assistant::AccessTokenFetcher> access_token_fetcher_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_ASSISTANT_PRIVATE_AUTOFILL_ASSISTANT_PRIVATE_API_H_
diff --git a/chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_apitest.cc b/chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_apitest.cc
new file mode 100644
index 00000000000..d2b7d290bdb
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_apitest.cc
@@ -0,0 +1,96 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/macros.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/api/autofill_assistant_private/autofill_assistant_private_api.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/common/extensions/api/autofill_assistant_private.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/autofill_assistant/browser/mock_service.h"
+#include "components/autofill_assistant/browser/service.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "content/public/test/test_utils.h"
+#include "extensions/common/switches.h"
+#include "net/dns/mock_host_resolver.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace extensions {
+
+namespace {
+
+using autofill_assistant::ActionsResponseProto;
+using autofill_assistant::MockService;
+using autofill_assistant::SupportedScriptProto;
+using autofill_assistant::SupportsScriptResponseProto;
+using autofill_assistant::TellProto;
+using base::test::RunOnceCallback;
+using testing::_;
+using testing::NiceMock;
+using testing::StrEq;
+
+// TODO(crbug.com/1015753): We have to split some of these tests up due to the
+// MockService being owned by the controller. If we were to run two tests that
+// create a controller in the same browser test, the mock service is lost and a
+// real ServiceImpl is used. This is an issue in the architecture of the
+// controller and service and should be changed to avoid this issue.
+class AutofillAssistantPrivateApiTest : public ExtensionApiTest {
+ public:
+ AutofillAssistantPrivateApiTest() = default;
+
+ void SetUpOnMainThread() override {
+ ExtensionApiTest::SetUpOnMainThread();
+
+ auto service = std::make_unique<NiceMock<MockService>>();
+ mock_service_ = service.get();
+
+ AutofillAssistantPrivateAPI::GetFactoryInstance()
+ ->Get(browser()->profile())
+ ->SetService(std::move(service));
+
+ // Prepare the mock service to return two scripts when asked.
+ SupportsScriptResponseProto scripts_proto;
+ SupportedScriptProto* script = scripts_proto.add_scripts();
+ script->set_path("some/path");
+ script->mutable_presentation()->mutable_chip()->set_text("Action 0");
+ SupportedScriptProto* script1 = scripts_proto.add_scripts();
+ script1->set_path("some/path");
+ script1->mutable_presentation()->mutable_chip()->set_text("Action 1");
+ std::string scripts_output;
+ scripts_proto.SerializeToString(&scripts_output);
+ ON_CALL(*mock_service_, OnGetScriptsForUrl(_, _, _))
+ .WillByDefault(RunOnceCallback<2>(true, scripts_output));
+
+ // Always return a script with a single tell action.
+ ActionsResponseProto actions_proto;
+ TellProto* tell_action = actions_proto.add_actions()->mutable_tell();
+ tell_action->set_message("This is a test status.");
+ std::string actions_output;
+ actions_proto.SerializeToString(&actions_output);
+ ON_CALL(*mock_service_, OnGetActions(StrEq("some/path"), _, _, _, _, _))
+ .WillByDefault(RunOnceCallback<5>(true, actions_output));
+
+ // We never return more additional actions.
+ ON_CALL(*mock_service_, OnGetNextActions(_, _, _, _, _))
+ .WillByDefault(RunOnceCallback<4>(true, ""));
+ }
+
+ private:
+ std::unique_ptr<MockService> service_;
+ MockService* mock_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillAssistantPrivateApiTest);
+};
+
+IN_PROC_BROWSER_TEST_F(AutofillAssistantPrivateApiTest, DefaultTest) {
+ ui_test_utils::NavigateToURL(browser(), GURL("chrome://version"));
+ EXPECT_TRUE(
+ RunComponentExtensionTestWithArg("autofill_assistant_private", "default"))
+ << message_;
+}
+
+} // namespace
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.cc b/chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.cc
new file mode 100644
index 00000000000..04d1c0131a3
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.cc
@@ -0,0 +1,63 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h"
+
+#include "base/callback.h"
+#include "components/signin/public/identity_manager/access_token_fetcher.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/scope_set.h"
+#include "google_apis/gaia/gaia_constants.h"
+
+namespace extensions {
+
+ExtensionAccessTokenFetcher::ExtensionAccessTokenFetcher(
+ signin::IdentityManager* identity_manager)
+ : identity_manager_(identity_manager) {}
+
+ExtensionAccessTokenFetcher::~ExtensionAccessTokenFetcher() = default;
+
+void ExtensionAccessTokenFetcher::FetchAccessToken(
+ base::OnceCallback<void(bool, const std::string&)> callback) {
+ // TODO(b/143736397): Use a more flexible logic to pick this account.
+ auto account_info = identity_manager_->GetPrimaryAccountInfo();
+
+ callback_ = std::move(callback);
+ signin::ScopeSet scopes;
+ scopes.insert(GaiaConstants::kGoogleUserInfoProfile);
+ auto mode = signin::AccessTokenFetcher::Mode::kImmediate;
+ access_token_fetcher_ = identity_manager_->CreateAccessTokenFetcherForAccount(
+ account_info.account_id,
+ /*consumer_name=*/"AccessTokenFetcher", scopes,
+ base::BindOnce(&ExtensionAccessTokenFetcher::OnCompleted,
+ // It is safe to use base::Unretained as
+ // |this| owns |access_token_fetcher_|.
+ base::Unretained(this)),
+ mode);
+}
+
+void ExtensionAccessTokenFetcher::InvalidateAccessToken(
+ const std::string& access_token) {
+ // TODO(b/143736397) Implement this by providing the data required for
+ // RemoveAccessTokenFromCache?
+}
+
+void ExtensionAccessTokenFetcher::OnCompleted(
+ GoogleServiceAuthError error,
+ signin::AccessTokenInfo access_token_info) {
+ access_token_fetcher_.reset();
+
+ if (!callback_)
+ return;
+
+ if (error.state() == GoogleServiceAuthError::NONE) {
+ std::move(callback_).Run(true, access_token_info.token);
+ } else {
+ VLOG(2) << "Access token fetching failed with error state " << error.state()
+ << " and message " << error.ToString();
+ std::move(callback_).Run(false, "");
+ }
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h b/chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h
new file mode 100644
index 00000000000..f94060e1862
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_ASSISTANT_PRIVATE_EXTENSION_ACCESS_TOKEN_FETCHER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_ASSISTANT_PRIVATE_EXTENSION_ACCESS_TOKEN_FETCHER_H_
+
+#include "components/autofill_assistant/browser/access_token_fetcher.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+
+namespace extensions {
+
+// A class that fetches tokens as needed for requests to Autofill Assistant
+// backends. This is an implementation provided to a service in the AA
+// component.
+class ExtensionAccessTokenFetcher
+ : public autofill_assistant::AccessTokenFetcher {
+ public:
+ explicit ExtensionAccessTokenFetcher(
+ signin::IdentityManager* identity_manager);
+ ~ExtensionAccessTokenFetcher() override;
+
+ // AccessTokenFetcher:
+ void FetchAccessToken(
+ base::OnceCallback<void(bool, const std::string&)> callback) override;
+ void InvalidateAccessToken(const std::string& access_token) override;
+
+ private:
+ void OnCompleted(GoogleServiceAuthError error,
+ signin::AccessTokenInfo access_token_info);
+
+ signin::IdentityManager* identity_manager_;
+ std::unique_ptr<signin::AccessTokenFetcher> access_token_fetcher_;
+ base::OnceCallback<void(bool, const std::string&)> callback_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_ASSISTANT_PRIVATE_EXTENSION_ACCESS_TOKEN_FETCHER_H_
diff --git a/chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher_unittest.cc b/chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher_unittest.cc
new file mode 100644
index 00000000000..1719cf43522
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher_unittest.cc
@@ -0,0 +1,58 @@
+// 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 "chrome/browser/extensions/api/autofill_assistant_private/extension_access_token_fetcher.h"
+
+#include "base/test/gmock_callback_support.h"
+#include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+class ExtensionAccessTokenFetcherTest : public testing::Test {
+ public:
+ ExtensionAccessTokenFetcherTest() = default;
+ ~ExtensionAccessTokenFetcherTest() override = default;
+
+ void SetUp() override {
+ identity_test_env_.MakePrimaryAccountAvailable("primary@example.com");
+ }
+
+ void TearDown() override {}
+
+ protected:
+ // The environment needs to be the first member to be initialized.
+ base::test::TaskEnvironment task_environment_;
+
+ signin::IdentityTestEnvironment identity_test_env_;
+};
+
+TEST_F(ExtensionAccessTokenFetcherTest, SuccessfulAccessTokenFetch) {
+ base::MockCallback<base::OnceCallback<void(bool, const std::string&)>>
+ callback;
+ EXPECT_CALL(callback, Run(true, "access_token"));
+
+ ExtensionAccessTokenFetcher fetcher(identity_test_env_.identity_manager());
+ fetcher.FetchAccessToken(callback.Get());
+
+ identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken(
+ "access_token", base::Time::Max());
+}
+
+TEST_F(ExtensionAccessTokenFetcherTest, FailedAccessTokenFetch) {
+ base::MockCallback<base::OnceCallback<void(bool, const std::string&)>>
+ callback;
+ EXPECT_CALL(callback, Run(false, ""));
+
+ ExtensionAccessTokenFetcher fetcher(identity_test_env_.identity_manager());
+ fetcher.FetchAccessToken(callback.Get());
+
+ identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ GoogleServiceAuthError::FromConnectionError(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/OWNERS b/chromium/chrome/browser/extensions/api/autofill_private/OWNERS
index aa215c7d505..e123d19737f 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/autofill_private/OWNERS
@@ -1 +1,5 @@
-stevenjb@chromium.org
+file://chrome/browser/resources/settings/OWNERS
+
+jdoerrie@chromium.org
+
+# COMPONENT: UI>Settings
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
index 49b4da3c607..450445fb776 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/extensions/api/autofill_private/autofill_private_api.h"
#include <stddef.h>
+#include <memory>
#include <utility>
#include "base/guid.h"
@@ -44,8 +45,9 @@ static const char kErrorDataUnavailable[] = "Autofill data unavailable.";
// any of the rest of the list, then the item (at |index|) is removed. The
// comparison of phone number values is done on normalized versions of the phone
// number values.
-void RemoveDuplicatePhoneNumberAtIndex(
- size_t index, const std::string& country_code, base::ListValue* list) {
+void RemoveDuplicatePhoneNumberAtIndex(size_t index,
+ const std::string& country_code,
+ base::ListValue* list) {
base::string16 new_value;
if (!list->GetString(index, &new_value)) {
NOTREACHED() << "List should have a value at index " << index;
@@ -63,8 +65,8 @@ void RemoveDuplicatePhoneNumberAtIndex(
NOTREACHED() << "List should have a value at index " << i;
continue;
}
- is_duplicate = autofill::i18n::PhoneNumbersMatch(
- new_value, existing_value, country_code, app_locale);
+ is_duplicate = autofill::i18n::PhoneNumbersMatch(new_value, existing_value,
+ country_code, app_locale);
}
if (is_duplicate)
@@ -103,7 +105,7 @@ ExtensionFunction::ResponseAction AutofillPrivateSaveAddressFunction::Run() {
autofill::PersonalDataManager* personal_data =
autofill::PersonalDataManagerFactory::GetForProfile(
- chrome_details_.GetProfile());
+ chrome_details_.GetProfile());
if (!personal_data || !personal_data->IsDataLoaded())
return RespondNow(Error(kErrorDataUnavailable));
@@ -134,51 +136,43 @@ ExtensionFunction::ResponseAction AutofillPrivateSaveAddressFunction::Run() {
}
if (address->company_name) {
- profile.SetRawInfo(
- autofill::COMPANY_NAME,
- base::UTF8ToUTF16(*address->company_name));
+ profile.SetRawInfo(autofill::COMPANY_NAME,
+ base::UTF8ToUTF16(*address->company_name));
}
if (address->address_lines) {
- profile.SetRawInfo(
- autofill::ADDRESS_HOME_STREET_ADDRESS,
- base::UTF8ToUTF16(*address->address_lines));
+ profile.SetRawInfo(autofill::ADDRESS_HOME_STREET_ADDRESS,
+ base::UTF8ToUTF16(*address->address_lines));
}
if (address->address_level1) {
- profile.SetRawInfo(
- autofill::ADDRESS_HOME_STATE,
- base::UTF8ToUTF16(*address->address_level1));
+ profile.SetRawInfo(autofill::ADDRESS_HOME_STATE,
+ base::UTF8ToUTF16(*address->address_level1));
}
if (address->address_level2) {
- profile.SetRawInfo(
- autofill::ADDRESS_HOME_CITY,
- base::UTF8ToUTF16(*address->address_level2));
+ profile.SetRawInfo(autofill::ADDRESS_HOME_CITY,
+ base::UTF8ToUTF16(*address->address_level2));
}
if (address->address_level3) {
- profile.SetRawInfo(
- autofill::ADDRESS_HOME_DEPENDENT_LOCALITY,
- base::UTF8ToUTF16(*address->address_level3));
+ profile.SetRawInfo(autofill::ADDRESS_HOME_DEPENDENT_LOCALITY,
+ base::UTF8ToUTF16(*address->address_level3));
}
if (address->postal_code) {
- profile.SetRawInfo(
- autofill::ADDRESS_HOME_ZIP,
- base::UTF8ToUTF16(*address->postal_code));
+ profile.SetRawInfo(autofill::ADDRESS_HOME_ZIP,
+ base::UTF8ToUTF16(*address->postal_code));
}
if (address->sorting_code) {
- profile.SetRawInfo(
- autofill::ADDRESS_HOME_SORTING_CODE,
- base::UTF8ToUTF16(*address->sorting_code));
+ profile.SetRawInfo(autofill::ADDRESS_HOME_SORTING_CODE,
+ base::UTF8ToUTF16(*address->sorting_code));
}
if (address->country_code) {
- profile.SetRawInfo(
- autofill::ADDRESS_HOME_COUNTRY,
- base::UTF8ToUTF16(*address->country_code));
+ profile.SetRawInfo(autofill::ADDRESS_HOME_COUNTRY,
+ base::UTF8ToUTF16(*address->country_code));
}
if (address->phone_numbers) {
@@ -244,7 +238,7 @@ AutofillPrivateGetAddressComponentsFunction::
~AutofillPrivateGetAddressComponentsFunction() {}
ExtensionFunction::ResponseAction
- AutofillPrivateGetAddressComponentsFunction::Run() {
+AutofillPrivateGetAddressComponentsFunction::Run() {
std::unique_ptr<api::autofill_private::GetAddressComponents::Params>
parameters =
api::autofill_private::GetAddressComponents::Params::Create(*args_);
@@ -312,7 +306,7 @@ ExtensionFunction::ResponseAction AutofillPrivateSaveCreditCardFunction::Run() {
autofill::PersonalDataManager* personal_data =
autofill::PersonalDataManagerFactory::GetForProfile(
- chrome_details_.GetProfile());
+ chrome_details_.GetProfile());
if (!personal_data || !personal_data->IsDataLoaded())
return RespondNow(Error(kErrorDataUnavailable));
@@ -339,21 +333,18 @@ ExtensionFunction::ResponseAction AutofillPrivateSaveCreditCardFunction::Run() {
}
if (card->card_number) {
- credit_card.SetRawInfo(
- autofill::CREDIT_CARD_NUMBER,
- base::UTF8ToUTF16(*card->card_number));
+ credit_card.SetRawInfo(autofill::CREDIT_CARD_NUMBER,
+ base::UTF8ToUTF16(*card->card_number));
}
if (card->expiration_month) {
- credit_card.SetRawInfo(
- autofill::CREDIT_CARD_EXP_MONTH,
- base::UTF8ToUTF16(*card->expiration_month));
+ credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_MONTH,
+ base::UTF8ToUTF16(*card->expiration_month));
}
if (card->expiration_year) {
- credit_card.SetRawInfo(
- autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR,
- base::UTF8ToUTF16(*card->expiration_year));
+ credit_card.SetRawInfo(autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR,
+ base::UTF8ToUTF16(*card->expiration_year));
}
if (use_existing_card) {
@@ -381,7 +372,7 @@ ExtensionFunction::ResponseAction AutofillPrivateRemoveEntryFunction::Run() {
autofill::PersonalDataManager* personal_data =
autofill::PersonalDataManagerFactory::GetForProfile(
- chrome_details_.GetProfile());
+ chrome_details_.GetProfile());
if (!personal_data || !personal_data->IsDataLoaded())
return RespondNow(Error(kErrorDataUnavailable));
@@ -397,7 +388,7 @@ AutofillPrivateValidatePhoneNumbersFunction::
~AutofillPrivateValidatePhoneNumbersFunction() {}
ExtensionFunction::ResponseAction
- AutofillPrivateValidatePhoneNumbersFunction::Run() {
+AutofillPrivateValidatePhoneNumbersFunction::Run() {
std::unique_ptr<api::autofill_private::ValidatePhoneNumbers::Params>
parameters =
api::autofill_private::ValidatePhoneNumbers::Params::Create(*args_);
@@ -431,7 +422,7 @@ ExtensionFunction::ResponseAction AutofillPrivateMaskCreditCardFunction::Run() {
autofill::PersonalDataManager* personal_data =
autofill::PersonalDataManagerFactory::GetForProfile(
- chrome_details_.GetProfile());
+ chrome_details_.GetProfile());
if (!personal_data || !personal_data->IsDataLoaded())
return RespondNow(Error(kErrorDataUnavailable));
@@ -566,4 +557,25 @@ AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction::Run() {
parameters->enabled);
return RespondNow(NoArguments());
}
+
+////////////////////////////////////////////////////////////////////////////////
+// AutofillPrivateGetUpiIdListFunction
+
+AutofillPrivateGetUpiIdListFunction::AutofillPrivateGetUpiIdListFunction() =
+ default;
+
+AutofillPrivateGetUpiIdListFunction::~AutofillPrivateGetUpiIdListFunction() =
+ default;
+
+ExtensionFunction::ResponseAction AutofillPrivateGetUpiIdListFunction::Run() {
+ autofill::PersonalDataManager* personal_data =
+ autofill::PersonalDataManagerFactory::GetForProfile(
+ chrome_details_.GetProfile());
+ DCHECK(personal_data && personal_data->IsDataLoaded());
+
+ return RespondNow(
+ ArgumentList(api::autofill_private::GetUpiIdList::Results::Create(
+ personal_data->GetUpiIds())));
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
index 0594f1421d6..64e55183c8a 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
+++ b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
@@ -229,6 +229,24 @@ class AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction
AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction);
};
+class AutofillPrivateGetUpiIdListFunction : public ExtensionFunction {
+ public:
+ AutofillPrivateGetUpiIdListFunction();
+ DECLARE_EXTENSION_FUNCTION("autofillPrivate.getUpiIdList",
+ AUTOFILLPRIVATE_GETUPIIDLIST)
+
+ protected:
+ ~AutofillPrivateGetUpiIdListFunction() override;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+
+ private:
+ ChromeExtensionFunctionDetails chrome_details_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetUpiIdListFunction);
+};
+
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_PRIVATE_AUTOFILL_PRIVATE_API_H_
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc
index da953b0e667..e38e8d02d4b 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_apitest.cc
@@ -31,9 +31,8 @@ class AutofillPrivateApiTest : public ExtensionApiTest {
protected:
bool RunAutofillSubtest(const std::string& subtest) {
- return RunExtensionSubtest("autofill_private",
- "main.html?" + subtest,
- kFlagLoadAsComponent);
+ return RunExtensionSubtest("autofill_private", "main.html?" + subtest,
+ kFlagNone, kFlagLoadAsComponent);
}
private:
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.cc b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.cc
index 4126e95675e..b21d4cdaf46 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.cc
+++ b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.cc
@@ -53,8 +53,4 @@ bool AutofillPrivateEventRouterFactory::
return true;
}
-bool AutofillPrivateEventRouterFactory::ServiceIsNULLWhileTesting() const {
- return false;
-}
-
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.h b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.h
index 861c769550a..5856e3b1b87 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.h
+++ b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.h
@@ -32,7 +32,6 @@ class AutofillPrivateEventRouterFactory
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
bool ServiceIsCreatedWithBrowserContext() const override;
- bool ServiceIsNULLWhileTesting() const override;
private:
friend struct base::DefaultSingletonTraits<AutofillPrivateEventRouterFactory>;
diff --git a/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc b/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc
index 8ad2aef4ca4..75ccc7c7c83 100644
--- a/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -11,7 +11,6 @@
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
@@ -448,6 +447,12 @@ IN_PROC_BROWSER_TEST_F(AutomationApiTestWithDeviceScaleFactor, HitTest) {
<< message_;
}
+IN_PROC_BROWSER_TEST_F(AutomationApiTest, Position) {
+ StartEmbeddedTestServer();
+ ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop", "position.html"))
+ << message_;
+}
+
#endif // defined(OS_CHROMEOS)
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc b/chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc
index ceb98f41dde..0a50f70f364 100644
--- a/chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.cc
@@ -24,11 +24,17 @@
#include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
#endif
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_helper_bridge.h"
+#endif
+
namespace extensions {
-ChromeAutomationInternalApiDelegate::ChromeAutomationInternalApiDelegate() {}
+ChromeAutomationInternalApiDelegate::ChromeAutomationInternalApiDelegate() =
+ default;
-ChromeAutomationInternalApiDelegate::~ChromeAutomationInternalApiDelegate() {}
+ChromeAutomationInternalApiDelegate::~ChromeAutomationInternalApiDelegate() =
+ default;
bool ChromeAutomationInternalApiDelegate::CanRequestAutomation(
const Extension* extension,
@@ -72,6 +78,18 @@ content::WebContents* ChromeAutomationInternalApiDelegate::GetActiveWebContents(
->GetActiveWebContents();
}
+bool ChromeAutomationInternalApiDelegate::EnableTree(
+ const ui::AXTreeID& tree_id) {
+#if defined(OS_CHROMEOS)
+ arc::ArcAccessibilityHelperBridge* bridge =
+ arc::ArcAccessibilityHelperBridge::GetForBrowserContext(
+ GetActiveUserContext());
+ if (bridge)
+ return bridge->RefreshTreeIfInActiveWindow(tree_id);
+#endif
+ return false;
+}
+
void ChromeAutomationInternalApiDelegate::EnableDesktop() {
#if defined(USE_AURA)
AutomationManagerAura::GetInstance()->Enable();
diff --git a/chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h b/chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h
index f2bdc737969..35e114b60f4 100644
--- a/chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h
+++ b/chromium/chrome/browser/extensions/api/automation_internal/chrome_automation_internal_api_delegate.h
@@ -27,6 +27,7 @@ class ChromeAutomationInternalApiDelegate
int GetTabId(content::WebContents* contents) override;
content::WebContents* GetActiveWebContents(
ExtensionFunction* function) override;
+ bool EnableTree(const ui::AXTreeID& tree_id) override;
void EnableDesktop() override;
ui::AXTreeID GetAXTreeID() override;
void SetEventBundleSink(ui::AXEventBundleSink* sink) override;
diff --git a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
index d0c59bb4cc4..ee42b5b5de6 100644
--- a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
@@ -513,7 +513,7 @@ bool BookmarkManagerPrivateGetSubtreeFunction::RunOnReady() {
bookmark_api_helpers::AddNodeFoldersOnly(managed, node, &nodes, true);
else
bookmark_api_helpers::AddNode(managed, node, &nodes, true);
- results_ = GetSubtree::Results::Create(nodes);
+ SetResultList(GetSubtree::Results::Create(nodes));
return true;
}
diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
index e3cebde37c3..9f93b617fb2 100644
--- a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
+++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
@@ -21,6 +21,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/bookmarks/bookmark_html_writer.h"
@@ -440,7 +441,7 @@ bool BookmarksGetFunction::RunOnReady() {
bookmark_api_helpers::AddNode(managed, node, &nodes, false);
}
- results_ = api::bookmarks::Get::Results::Create(nodes);
+ SetResultList(api::bookmarks::Get::Results::Create(nodes));
return true;
}
@@ -459,7 +460,7 @@ bool BookmarksGetChildrenFunction::RunOnReady() {
&nodes, false);
}
- results_ = api::bookmarks::GetChildren::Results::Create(nodes);
+ SetResultList(api::bookmarks::GetChildren::Results::Create(nodes));
return true;
}
@@ -481,7 +482,7 @@ bool BookmarksGetRecentFunction::RunOnReady() {
&tree_nodes, false);
}
- results_ = api::bookmarks::GetRecent::Results::Create(tree_nodes);
+ SetResultList(api::bookmarks::GetRecent::Results::Create(tree_nodes));
return true;
}
@@ -491,7 +492,7 @@ bool BookmarksGetTreeFunction::RunOnReady() {
BookmarkModelFactory::GetForBrowserContext(GetProfile())->root_node();
bookmark_api_helpers::AddNode(GetManagedBookmarkService(), node, &nodes,
true);
- results_ = api::bookmarks::GetTree::Results::Create(nodes);
+ SetResultList(api::bookmarks::GetTree::Results::Create(nodes));
return true;
}
@@ -507,7 +508,7 @@ bool BookmarksGetSubTreeFunction::RunOnReady() {
std::vector<BookmarkTreeNode> nodes;
bookmark_api_helpers::AddNode(GetManagedBookmarkService(), node, &nodes,
true);
- results_ = api::bookmarks::GetSubTree::Results::Create(nodes);
+ SetResultList(api::bookmarks::GetSubTree::Results::Create(nodes));
return true;
}
@@ -547,7 +548,7 @@ bool BookmarksSearchFunction::RunOnReady() {
for (const BookmarkNode* node : nodes)
bookmark_api_helpers::AddNode(managed, node, &tree_nodes, false);
- results_ = api::bookmarks::Search::Results::Create(tree_nodes);
+ SetResultList(api::bookmarks::Search::Results::Create(tree_nodes));
return true;
}
@@ -597,7 +598,7 @@ bool BookmarksCreateFunction::RunOnReady() {
BookmarkTreeNode ret = bookmark_api_helpers::GetBookmarkTreeNode(
GetManagedBookmarkService(), node, false, false);
- results_ = api::bookmarks::Create::Results::Create(ret);
+ SetResultList(api::bookmarks::Create::Results::Create(ret));
return true;
}
@@ -651,7 +652,7 @@ bool BookmarksMoveFunction::RunOnReady() {
BookmarkTreeNode tree_node = bookmark_api_helpers::GetBookmarkTreeNode(
GetManagedBookmarkService(), node, false, false);
- results_ = api::bookmarks::Move::Results::Create(tree_node);
+ SetResultList(api::bookmarks::Move::Results::Create(tree_node));
return true;
}
@@ -704,7 +705,7 @@ bool BookmarksUpdateFunction::RunOnReady() {
BookmarkTreeNode tree_node = bookmark_api_helpers::GetBookmarkTreeNode(
GetManagedBookmarkService(), node, false, false);
- results_ = api::bookmarks::Update::Results::Create(tree_node);
+ SetResultList(api::bookmarks::Update::Results::Create(tree_node));
return true;
}
@@ -793,9 +794,9 @@ bool BookmarksExportFunction::RunOnReady() {
// extensions use user gesture for export, so use USER_VISIBLE priority.
// GetDefaultFilepathForBookmarkExport() might have to touch filesystem
// (stat or access, for example), so this requires IO.
- base::PostTaskAndReplyWithResult(
+ base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&GetDefaultFilepathForBookmarkExport),
base::BindOnce(&BookmarksIOFunction::ShowSelectFileDialog, this,
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
index f21ccfe51bc..755ee8a39c6 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
@@ -16,6 +16,7 @@
#include "base/bind_helpers.h"
#include "base/stl_util.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/time/time.h"
#include "chrome/browser/extensions/api/braille_display_private/brlapi_connection.h"
@@ -171,9 +172,8 @@ void BrailleControllerImpl::StartConnecting() {
}
if (!sequenced_task_runner_) {
- sequenced_task_runner_ =
- base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE});
+ sequenced_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
}
// Only try to connect after we've started to watch the
@@ -315,10 +315,9 @@ void BrailleControllerImpl::DispatchKeys() {
void BrailleControllerImpl::DispatchKeyEvent(std::unique_ptr<KeyEvent> event) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&BrailleControllerImpl::DispatchKeyEvent,
- base::Unretained(this), base::Passed(&event)));
+ base::PostTask(FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&BrailleControllerImpl::DispatchKeyEvent,
+ base::Unretained(this), std::move(event)));
return;
}
VLOG(1) << "Dispatching key event: " << *event->ToValue();
@@ -333,7 +332,7 @@ void BrailleControllerImpl::DispatchOnDisplayStateChanged(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(
&BrailleControllerImpl::DispatchOnDisplayStateChanged,
- base::Unretained(this), base::Passed(&new_state)))) {
+ base::Unretained(this), std::move(new_state)))) {
NOTREACHED();
}
return;
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc b/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc
index aa4e913a4fc..a827864971b 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.cc
@@ -24,7 +24,7 @@ const int kAllDots = BRLAPI_DOT1 | BRLAPI_DOT2 | BRLAPI_DOT3 | BRLAPI_DOT4 |
const brlapi_keyCode_t kMaxLatin1KeySym = 0xff;
// Range of function keys that we support.
-// See ui/events/keycodes/dom/keycode_converter_data.inc for the list of all
+// See ui/events/keycodes/dom/dom_code_data.inc for the list of all
// key codes.
const brlapi_keyCode_t kMinFunctionKey = BRLAPI_KEY_SYM_FUNCTION;
const brlapi_keyCode_t kMaxFunctionKey = BRLAPI_KEY_SYM_FUNCTION + 23;
@@ -42,7 +42,7 @@ void MapModifierFlags(brlapi_keyCode_t code, KeyEvent* event) {
// Maps a brlapi keysym, which is similar to an X keysym into the
// provided event.
-// See ui/events/keycodes/dom/keycode_converter_data.cc for the full
+// See ui/events/keycodes/dom/dom_code_data.cc for the full
// list of key codes.
void MapKeySym(brlapi_keyCode_t code, KeyEvent* event) {
brlapi_keyCode_t key_sym = code & BRLAPI_KEY_CODE_MASK;
diff --git a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
index e73cd3f3032..0e1126ecea4 100644
--- a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
+++ b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
@@ -13,11 +13,10 @@
#include "base/bind.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
-#include "chrome/browser/plugins/plugin_data_remover_helper.h"
-#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/account_reconcilor_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
@@ -27,6 +26,7 @@
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "components/browsing_data/core/pref_names.h"
+#include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -36,9 +36,14 @@
#include "extensions/common/extension.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-using content::BrowserThread;
-using browsing_data::ClearBrowsingDataTab;
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "chrome/browser/plugins/plugin_data_remover_helper.h"
+#include "chrome/browser/plugins/plugin_prefs.h"
+#endif
+
using browsing_data::BrowsingDataType;
+using browsing_data::ClearBrowsingDataTab;
+using content::BrowserThread;
namespace extension_browsing_data_api_constants {
// Parameter name keys.
@@ -347,20 +352,24 @@ bool BrowsingDataRemoverFunction::RunAsync() {
return false;
}
+#if BUILDFLAG(ENABLE_PLUGINS)
if (removal_mask_ &
ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA) {
// If we're being asked to remove plugin data, check whether it's actually
// supported.
- PostTask(FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- base::TaskPriority::USER_VISIBLE},
- base::BindOnce(
- &BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported,
- this, PluginPrefs::GetForProfile(GetProfile())));
+ base::ThreadPool::PostTask(
+ FROM_HERE,
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(
+ &BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported,
+ this, PluginPrefs::GetForProfile(GetProfile())));
} else {
StartRemoving();
}
+#else
+ StartRemoving();
+#endif
// Will finish asynchronously.
return true;
@@ -372,6 +381,7 @@ bool BrowsingDataRemoverFunction::IsPauseSyncAllowed() {
return true;
}
+#if BUILDFLAG(ENABLE_PLUGINS)
void BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported(
scoped_refptr<PluginPrefs> plugin_prefs) {
if (!PluginDataRemoverHelper::IsSupported(plugin_prefs.get()))
@@ -381,6 +391,7 @@ void BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported(
FROM_HERE, {BrowserThread::UI},
base::BindOnce(&BrowsingDataRemoverFunction::StartRemoving, this));
}
+#endif
void BrowsingDataRemoverFunction::StartRemoving() {
Profile* profile = GetProfile();
diff --git a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
index 2a588cf744e..2ea463c3eab 100644
--- a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
+++ b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
@@ -9,7 +9,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_BROWSING_DATA_BROWSING_DATA_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_BROWSING_DATA_BROWSING_DATA_API_H_
-#include <string>
+#include <memory>
#include <vector>
#include "base/scoped_observer.h"
@@ -18,6 +18,7 @@
#include "components/signin/core/browser/account_reconcilor.h"
#include "content/public/browser/browsing_data_filter_builder.h"
#include "content/public/browser/browsing_data_remover.h"
+#include "ppapi/buildflags/buildflags.h"
class PluginPrefs;
class PrefService;
@@ -123,10 +124,12 @@ class BrowsingDataRemoverFunction
// pausing Sync would prevent the data from being deleted on the server.
virtual bool IsPauseSyncAllowed();
+#if BUILDFLAG(ENABLE_PLUGINS)
// Updates the removal bitmask according to whether removing plugin data is
// supported or not.
void CheckRemovingPluginDataSupported(
scoped_refptr<PluginPrefs> plugin_prefs);
+#endif
// Parse the developer-provided |origin_types| object into |origin_type_mask|
// that can be used with the BrowsingDataRemover.
diff --git a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_unittest.cc b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_unittest.cc
index c10602fe117..c25e5885e8e 100644
--- a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_unittest.cc
@@ -68,11 +68,15 @@ class BrowsingDataApiTest : public ExtensionServiceTestBase {
browser_window_.reset();
ExtensionServiceTestBase::TearDown();
}
- const base::Time& GetBeginTime() { return remover_->GetLastUsedBeginTime(); }
+ const base::Time& GetBeginTime() {
+ return remover_->GetLastUsedBeginTimeForTesting();
+ }
- int GetRemovalMask() { return remover_->GetLastUsedRemovalMask(); }
+ int GetRemovalMask() { return remover_->GetLastUsedRemovalMaskForTesting(); }
- int GetOriginTypeMask() { return remover_->GetLastUsedOriginTypeMask(); }
+ int GetOriginTypeMask() {
+ return remover_->GetLastUsedOriginTypeMaskForTesting();
+ }
int GetAsMask(const base::DictionaryValue* dict,
std::string path,
diff --git a/chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc b/chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc
index f4910e3e87e..a7d906040eb 100644
--- a/chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc
@@ -131,11 +131,11 @@ class TestPatternReceiver : public media::cast::InProcessReceiver {
void WaitForExpectedTonesAndColors() {
base::RunLoop run_loop;
cast_env()->PostTask(
- media::cast::CastEnvironment::MAIN,
- FROM_HERE,
- base::Bind(&TestPatternReceiver::NotifyOnceObservedAllTonesAndColors,
- base::Unretained(this),
- media::BindToCurrentLoop(run_loop.QuitClosure())));
+ media::cast::CastEnvironment::MAIN, FROM_HERE,
+ base::BindOnce(
+ &TestPatternReceiver::NotifyOnceObservedAllTonesAndColors,
+ base::Unretained(this),
+ media::BindToCurrentLoop(run_loop.QuitClosure())));
run_loop.Run();
}
diff --git a/chromium/chrome/browser/extensions/api/certificate_provider/OWNERS b/chromium/chrome/browser/extensions/api/certificate_provider/OWNERS
index 325f7c3fcd6..6835e98ab3e 100644
--- a/chromium/chrome/browser/extensions/api/certificate_provider/OWNERS
+++ b/chromium/chrome/browser/extensions/api/certificate_provider/OWNERS
@@ -1 +1,3 @@
emaxx@chromium.org
+
+# COMPONENT: Enterprise
diff --git a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
index 4530f54ea05..0d9b2566c56 100644
--- a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
+++ b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
@@ -20,7 +20,7 @@
#include "chrome/browser/chromeos/certificate_provider/security_token_pin_dialog_host.h"
#include "chrome/common/extensions/api/certificate_provider.h"
#include "chrome/common/extensions/api/certificate_provider_internal.h"
-#include "chromeos/constants/security_token_pin_types.h"
+#include "chromeos/components/security_token_pin/constants.h"
#include "extensions/browser/quota_service.h"
#include "net/cert/x509_certificate.h"
#include "net/ssl/ssl_private_key.h"
@@ -29,8 +29,8 @@
namespace api_cp = extensions::api::certificate_provider;
namespace api_cpi = extensions::api::certificate_provider_internal;
-using PinCodeType = chromeos::SecurityTokenPinCodeType;
-using PinErrorLabel = chromeos::SecurityTokenPinErrorLabel;
+using PinCodeType = chromeos::security_token_pin::CodeType;
+using PinErrorLabel = chromeos::security_token_pin::ErrorLabel;
namespace {
@@ -160,6 +160,10 @@ CertificateProviderInternalReportCertificatesFunction::Run() {
rejected_certificates.push_back(input_cert_info.certificate);
}
+ // TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
+ VLOG(1) << "Certificates provided by extension " << extension()->id() << ": "
+ << cert_infos.size() << ", rejected " << rejected_certificates.size();
+
if (service->SetCertificatesProvidedByExtension(
extension_id(), params->request_id, cert_infos)) {
return RespondNow(ArgumentList(
@@ -248,6 +252,10 @@ CertificateProviderStopPinRequestFunction::Run() {
api_cp::RequestPin::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
+ // TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
+ VLOG(1) << "Handling PIN stop request from extension " << extension()->id()
+ << " error " << params->details.error_type;
+
chromeos::CertificateProviderService* const service =
chromeos::CertificateProviderServiceFactory::GetForBrowserContext(
browser_context());
@@ -259,9 +267,14 @@ CertificateProviderStopPinRequestFunction::Run() {
if (!dialog_closed) {
// This might happen if the user closed the dialog while extension was
// processing the input.
+ // TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
+ VLOG(1) << "PIN stop request failed: "
+ << kCertificateProviderNoActiveDialog;
return RespondNow(Error(kCertificateProviderNoActiveDialog));
}
+ // TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
+ VLOG(1) << "PIN stop request succeeded";
return RespondNow(NoArguments());
}
@@ -275,20 +288,24 @@ CertificateProviderStopPinRequestFunction::Run() {
base::BindOnce(
&CertificateProviderStopPinRequestFunction::OnPinRequestStopped,
this));
+ std::string error_result;
switch (stop_request_result) {
case chromeos::PinDialogManager::StopPinRequestResult::kNoActiveDialog:
- return RespondNow(Error(kCertificateProviderNoActiveDialog));
+ error_result = kCertificateProviderNoActiveDialog;
+ break;
case chromeos::PinDialogManager::StopPinRequestResult::kNoUserInput:
- return RespondNow(Error(kCertificateProviderNoUserInput));
+ error_result = kCertificateProviderNoUserInput;
+ break;
case chromeos::PinDialogManager::StopPinRequestResult::kSuccess:
return RespondLater();
}
-
- NOTREACHED();
- return RespondLater();
+ // TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
+ VLOG(1) << "PIN stop request failed: " << error_result;
+ return RespondNow(Error(error_result));
}
void CertificateProviderStopPinRequestFunction::OnPinRequestStopped() {
+ VLOG(1) << "PIN stop request succeeded";
Respond(NoArguments());
}
@@ -316,14 +333,16 @@ void CertificateProviderRequestPinFunction::GetQuotaLimitHeuristics(
api::certificate_provider::kMaxClosedDialogsPerMinute - 1,
base::TimeDelta::FromMinutes(1)};
heuristics->push_back(std::make_unique<QuotaService::TimedLimit>(
- short_limit_config, new RequestPinExceptFirstQuotaBucketMapper,
+ short_limit_config,
+ std::make_unique<RequestPinExceptFirstQuotaBucketMapper>(),
"MAX_PIN_DIALOGS_CLOSED_PER_MINUTE"));
QuotaLimitHeuristic::Config long_limit_config = {
api::certificate_provider::kMaxClosedDialogsPer10Minutes - 1,
base::TimeDelta::FromMinutes(10)};
heuristics->push_back(std::make_unique<QuotaService::TimedLimit>(
- long_limit_config, new RequestPinExceptFirstQuotaBucketMapper,
+ long_limit_config,
+ std::make_unique<RequestPinExceptFirstQuotaBucketMapper>(),
"MAX_PIN_DIALOGS_CLOSED_PER_10_MINUTES"));
}
@@ -358,6 +377,12 @@ ExtensionFunction::ResponseAction CertificateProviderRequestPinFunction::Run() {
attempts_left = *params->details.attempts_left;
}
+ // TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
+ VLOG(1) << "Starting PIN request from extension " << extension()->id()
+ << " signRequestId " << params->details.sign_request_id << " type "
+ << params->details.request_type << " error "
+ << params->details.error_type << " attempts " << attempts_left;
+
const chromeos::PinDialogManager::RequestPinResult result =
service->pin_dialog_manager()->RequestPin(
extension()->id(), extension()->name(),
@@ -365,19 +390,23 @@ ExtensionFunction::ResponseAction CertificateProviderRequestPinFunction::Run() {
attempts_left,
base::BindOnce(
&CertificateProviderRequestPinFunction::OnInputReceived, this));
+ std::string error_result;
switch (result) {
case chromeos::PinDialogManager::RequestPinResult::kSuccess:
return RespondLater();
case chromeos::PinDialogManager::RequestPinResult::kInvalidId:
- return RespondNow(Error(kCertificateProviderInvalidId));
+ error_result = kCertificateProviderInvalidId;
+ break;
case chromeos::PinDialogManager::RequestPinResult::kOtherFlowInProgress:
- return RespondNow(Error(kCertificateProviderOtherFlowInProgress));
+ error_result = kCertificateProviderOtherFlowInProgress;
+ break;
case chromeos::PinDialogManager::RequestPinResult::kDialogDisplayedAlready:
- return RespondNow(Error(kCertificateProviderPreviousDialogActive));
+ error_result = kCertificateProviderPreviousDialogActive;
+ break;
}
-
- NOTREACHED();
- return RespondNow(Error(kCertificateProviderPreviousDialogActive));
+ // TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
+ VLOG(1) << "PIN request failed: " << error_result;
+ return RespondNow(Error(error_result));
}
void CertificateProviderRequestPinFunction::OnInputReceived(
@@ -388,9 +417,14 @@ void CertificateProviderRequestPinFunction::OnInputReceived(
browser_context());
DCHECK(service);
if (!value.empty()) {
+ // TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
+ VLOG(1) << "PIN request succeeded";
api::certificate_provider::PinResponseDetails details;
details.user_input = std::make_unique<std::string>(value);
create_results->Append(details.ToValue());
+ } else {
+ // TODO(crbug.com/1046860): Remove logging after stabilizing the feature.
+ VLOG(1) << "PIN request canceled";
}
Respond(ArgumentList(std::move(create_results)));
diff --git a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
index 1de2320a536..cd8eddd1672 100644
--- a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
@@ -24,6 +24,7 @@
#include "chrome/browser/chromeos/ui/request_pin_view.h"
#include "chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/policy/core/browser/browser_policy_connector.h"
@@ -36,6 +37,10 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "crypto/rsa_private_key.h"
+#include "extensions/browser/disable_reason.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/common/extension.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
@@ -171,6 +176,8 @@ class CertificateProviderRequestPinTest : public CertificateProviderApiTest {
CertificateProviderApiTest::TearDownOnMainThread();
}
+ std::string pin_request_extension_id() const { return extension_->id(); }
+
void AddFakeSignRequest(int sign_request_id) {
cert_provider_service_->pin_dialog_manager()->AddSignRequestId(
extension_->id(), sign_request_id, {});
@@ -662,3 +669,49 @@ IN_PROC_BROWSER_TEST_F(CertificateProviderRequestPinTest,
EXPECT_TRUE(SendCommand("IncrementRequestId"));
}
}
+
+// Test that disabling the extension closes its PIN dialog.
+IN_PROC_BROWSER_TEST_F(CertificateProviderRequestPinTest, ExtensionDisable) {
+ AddFakeSignRequest(kFakeSignRequestId);
+ NavigateTo("operated.html");
+
+ EXPECT_TRUE(SendCommandAndWaitForMessage("Request", "request1:begun"));
+ EXPECT_TRUE(GetActivePinDialogView());
+
+ extensions::TestExtensionRegistryObserver registry_observer(
+ extensions::ExtensionRegistry::Get(profile()),
+ pin_request_extension_id());
+ extensions::ExtensionSystem::Get(profile())
+ ->extension_service()
+ ->DisableExtension(pin_request_extension_id(),
+ extensions::disable_reason::DISABLE_USER_ACTION);
+ registry_observer.WaitForExtensionUnloaded();
+ // Let the events from the extensions subsystem propagate to the code that
+ // manages the PIN dialog.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(GetActivePinDialogView());
+}
+
+// Test that reloading the extension closes its PIN dialog.
+IN_PROC_BROWSER_TEST_F(CertificateProviderRequestPinTest, ExtensionReload) {
+ AddFakeSignRequest(kFakeSignRequestId);
+ NavigateTo("operated.html");
+
+ EXPECT_TRUE(SendCommandAndWaitForMessage("Request", "request1:begun"));
+ EXPECT_TRUE(GetActivePinDialogView());
+
+ // Create a second browser, in order to suppress Chrome shutdown logic when
+ // reloading the extension (as the tab with the extension's file gets closed).
+ CreateBrowser(profile());
+
+ // Trigger the chrome.runtime.reload() call from the extension.
+ extensions::TestExtensionRegistryObserver registry_observer(
+ extensions::ExtensionRegistry::Get(profile()),
+ pin_request_extension_id());
+ EXPECT_TRUE(SendCommand("Reload"));
+ registry_observer.WaitForExtensionUnloaded();
+ registry_observer.WaitForExtensionLoaded();
+
+ EXPECT_FALSE(GetActivePinDialogView());
+}
diff --git a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc
index 10b8986f9d6..0e8e1376aab 100644
--- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -43,10 +43,11 @@
#include "chrome/browser/search/instant_service_factory.h"
#include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h"
#include "chrome/browser/ui/webui/devtools_ui.h"
+#include "chrome/common/buildflags.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/webui_url_constants.h"
#include "components/pdf/browser/pdf_web_contents_helper.h"
-#include "components/performance_manager/performance_manager_tab_helper.h"
+#include "components/performance_manager/embedder/performance_manager_registry.h"
#include "components/performance_manager/public/performance_manager.h"
#include "components/signin/core/browser/signin_header_helper.h"
#include "content/public/browser/browser_context.h"
@@ -54,6 +55,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
+#include "extensions/browser/api/management/supervised_user_service_delegate.h"
#include "extensions/browser/api/system_display/display_info_provider.h"
#include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
#include "extensions/browser/api/web_request/web_request_info.h"
@@ -76,9 +78,15 @@
#include "chrome/browser/printing/printing_init.h"
#endif
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+// TODO(https://crbug.com/1060801): Here and elsewhere, possibly switch build
+// flag to #if defined(OS_CHROMEOS)
+#include "chrome/browser/supervised_user/supervised_user_service_management_api_delegate.h"
+#endif
+
namespace extensions {
-ChromeExtensionsAPIClient::ChromeExtensionsAPIClient() {}
+ChromeExtensionsAPIClient::ChromeExtensionsAPIClient() = default;
ChromeExtensionsAPIClient::~ChromeExtensionsAPIClient() {}
@@ -108,9 +116,9 @@ void ChromeExtensionsAPIClient::AttachWebContentsHelpers(
extensions::ChromeExtensionWebContentsObserver::CreateForWebContents(
web_contents);
- if (performance_manager::PerformanceManager::IsAvailable()) {
- performance_manager::PerformanceManagerTabHelper::CreateForWebContents(
- web_contents);
+ if (auto* performance_manager_registry =
+ performance_manager::PerformanceManagerRegistry::GetInstance()) {
+ performance_manager_registry->CreatePageNodeForWebContents(web_contents);
}
}
@@ -137,8 +145,9 @@ bool ChromeExtensionsAPIClient::ShouldHideBrowserNetworkRequest(
// But we do still need to protect some sensitive sub-frame navigation
// requests.
// Exclude main frame navigation requests.
- bool is_browser_request = request.render_process_id == -1 &&
- request.type != content::ResourceType::kMainFrame;
+ bool is_browser_request =
+ request.render_process_id == -1 &&
+ request.type != blink::mojom::ResourceType::kMainFrame;
// Hide requests made by the Devtools frontend.
bool is_sensitive_request =
@@ -334,6 +343,15 @@ ManagementAPIDelegate* ChromeExtensionsAPIClient::CreateManagementAPIDelegate()
return new ChromeManagementAPIDelegate;
}
+std::unique_ptr<SupervisedUserServiceDelegate>
+ChromeExtensionsAPIClient::CreateSupervisedUserServiceDelegate() const {
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+ return std::make_unique<SupervisedUserServiceManagementAPIDelegate>();
+#else
+ return nullptr;
+#endif
+}
+
std::unique_ptr<DisplayInfoProvider>
ChromeExtensionsAPIClient::CreateDisplayInfoProvider() const {
return CreateChromeDisplayInfoProvider();
diff --git a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h
index f5ff000a8c4..a9498af9053 100644
--- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h
+++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h
@@ -67,6 +67,9 @@ class ChromeExtensionsAPIClient : public ExtensionsAPIClient {
std::unique_ptr<VirtualKeyboardDelegate> CreateVirtualKeyboardDelegate(
content::BrowserContext* browser_context) const override;
ManagementAPIDelegate* CreateManagementAPIDelegate() const override;
+ std::unique_ptr<SupervisedUserServiceDelegate>
+ CreateSupervisedUserServiceDelegate() const override;
+
std::unique_ptr<DisplayInfoProvider> CreateDisplayInfoProvider()
const override;
MetricsPrivateDelegate* GetMetricsPrivateDelegate() override;
diff --git a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client_unittest.cc b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client_unittest.cc
index 7948a83f6dc..ec45c707845 100644
--- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client_unittest.cc
@@ -38,7 +38,7 @@ TEST_F(ChromeExtensionsAPIClientTest, ShouldHideResponseHeader) {
TEST_F(ChromeExtensionsAPIClientTest, ShouldHideBrowserNetworkRequest) {
ChromeExtensionsAPIClient client;
- auto create_params = [](content::ResourceType type) {
+ auto create_params = [](blink::mojom::ResourceType type) {
WebRequestInfoInitParams request_params;
request_params.url = GURL("https://example.com/script.js");
request_params.initiator =
@@ -52,16 +52,16 @@ TEST_F(ChromeExtensionsAPIClientTest, ShouldHideBrowserNetworkRequest) {
// not be visible to extensions.
EXPECT_TRUE(client.ShouldHideBrowserNetworkRequest(
nullptr /* context */,
- WebRequestInfo(create_params(content::ResourceType::kScript))));
+ WebRequestInfo(create_params(blink::mojom::ResourceType::kScript))));
// Main frame requests should always be visible to extensions.
EXPECT_FALSE(client.ShouldHideBrowserNetworkRequest(
nullptr /* context */,
- WebRequestInfo(create_params(content::ResourceType::kMainFrame))));
+ WebRequestInfo(create_params(blink::mojom::ResourceType::kMainFrame))));
// Similar requests made by the renderer should be visible to extensions.
WebRequestInfoInitParams params =
- create_params(content::ResourceType::kScript);
+ create_params(blink::mojom::ResourceType::kScript);
params.render_process_id = 2;
EXPECT_FALSE(client.ShouldHideBrowserNetworkRequest(
nullptr /* context */, WebRequestInfo(std::move(params))));
diff --git a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc
index a00d71d51b3..9b31666f327 100644
--- a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc
@@ -124,7 +124,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionCloudPrintPrivateApiTest,
CloudPrintHostedIncognito) {
GURL page_url = GetTestServerURL(
"enable_chrome_connector/cloud_print_incognito_failure_tests.html");
- ASSERT_TRUE(RunPageTest(page_url.spec(), kFlagUseIncognito));
+ ASSERT_TRUE(RunPageTest(page_url.spec(), kFlagNone, kFlagUseIncognito));
}
#endif // !defined(OS_CHROMEOS)
diff --git a/chromium/chrome/browser/extensions/api/commands/command_service.cc b/chromium/chrome/browser/extensions/api/commands/command_service.cc
index 67601761cf7..fbb6db74270 100644
--- a/chromium/chrome/browser/extensions/api/commands/command_service.cc
+++ b/chromium/chrome/browser/extensions/api/commands/command_service.cc
@@ -19,7 +19,6 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/accelerator_utils.h"
#include "chrome/common/extensions/api/commands/commands_handler.h"
-#include "chrome/common/extensions/manifest_handlers/ui_overrides_handler.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/scoped_user_pref_update.h"
@@ -132,23 +131,6 @@ CommandService* CommandService::Get(content::BrowserContext* context) {
return BrowserContextKeyedAPIFactory<CommandService>::Get(context);
}
-// static
-bool CommandService::RemovesBookmarkShortcut(const Extension* extension) {
- return UIOverrides::RemovesBookmarkShortcut(extension) &&
- (extension->permissions_data()->HasAPIPermission(
- APIPermission::kBookmarkManagerPrivate) ||
- FeatureSwitch::enable_override_bookmarks_ui()->IsEnabled());
-}
-
-// static
-bool CommandService::RemovesBookmarkAllTabsShortcut(
- const Extension* extension) {
- return UIOverrides::RemovesBookmarkAllTabsShortcut(extension) &&
- (extension->permissions_data()->HasAPIPermission(
- APIPermission::kBookmarkManagerPrivate) ||
- FeatureSwitch::enable_override_bookmarks_ui()->IsEnabled());
-}
-
bool CommandService::GetBrowserActionCommand(const std::string& extension_id,
QueryType type,
Command* command,
@@ -419,14 +401,6 @@ bool CommandService::GetSuggestedExtensionCommand(
return false;
}
-bool CommandService::RequestsBookmarkShortcutOverride(
- const Extension* extension) const {
- return RemovesBookmarkShortcut(extension) &&
- GetSuggestedExtensionCommand(
- extension->id(),
- chrome::GetPrimaryChromeAcceleratorForBookmarkTab(), nullptr);
-}
-
void CommandService::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
@@ -572,22 +546,10 @@ bool CommandService::CanAutoAssign(const Command &command,
return false;
return (command.accelerator().key_code() >= ui::VKEY_0 &&
command.accelerator().key_code() <= ui::VKEY_9);
- } else {
- // Not a global command, check if Chrome shortcut and whether
- // we can override it.
- if (command.accelerator() ==
- chrome::GetPrimaryChromeAcceleratorForBookmarkTab() &&
- CommandService::RemovesBookmarkShortcut(extension)) {
- // If this check fails it either means we have an API to override a
- // key that isn't a ChromeAccelerator (and the API can therefore be
- // deprecated) or the IsChromeAccelerator isn't consistently
- // returning true for all accelerators.
- DCHECK(chrome::IsChromeAccelerator(command.accelerator(), profile_));
- return true;
- }
-
- return !chrome::IsChromeAccelerator(command.accelerator(), profile_);
}
+
+ // Not a global command, check if the command is a Chrome shortcut.
+ return !chrome::IsChromeAccelerator(command.accelerator());
}
void CommandService::UpdateExtensionSuggestedCommandPrefs(
diff --git a/chromium/chrome/browser/extensions/api/commands/command_service.h b/chromium/chrome/browser/extensions/api/commands/command_service.h
index 73251ed8ebc..0c7f057d493 100644
--- a/chromium/chrome/browser/extensions/api/commands/command_service.h
+++ b/chromium/chrome/browser/extensions/api/commands/command_service.h
@@ -94,14 +94,6 @@ class CommandService : public BrowserContextKeyedAPI,
// Convenience method to get the CommandService for a profile.
static CommandService* Get(content::BrowserContext* context);
- // Returns true if |extension| is permitted to and does remove the bookmark
- // shortcut key.
- static bool RemovesBookmarkShortcut(const Extension* extension);
-
- // Returns true if |extension| is permitted to and does remove the bookmark
- // all tabs shortcut key.
- static bool RemovesBookmarkAllTabsShortcut(const Extension* extension);
-
// Gets the command (if any) for the browser action of an extension given
// its |extension_id|. The function consults the master list to see if
// the command is active. Returns false if the extension has no browser
@@ -181,10 +173,6 @@ class CommandService : public BrowserContextKeyedAPI,
const ui::Accelerator& accelerator,
Command* command) const;
- // Returns true if |extension| requests to override the bookmark shortcut key
- // and should be allowed to do so.
- bool RequestsBookmarkShortcutOverride(const Extension* extension) const;
-
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc
index 8895ee152cf..cd71b0bd21c 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc
@@ -6,8 +6,8 @@
#include <memory>
#include <set>
+#include <string>
#include <utility>
-#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
@@ -24,10 +24,7 @@
#include "chrome/browser/extensions/api/content_settings/content_settings_store.h"
#include "chrome/browser/extensions/api/preference/preference_api_constants.h"
#include "chrome/browser/extensions/api/preference/preference_helpers.h"
-#include "chrome/browser/plugins/plugin_finder.h"
-#include "chrome/browser/plugins/plugin_installer.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/content_settings.h"
#include "components/content_settings/core/browser/content_settings_info.h"
@@ -36,16 +33,21 @@
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
+#include "components/permissions/features.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/plugin_service.h"
#include "content/public/common/webplugininfo.h"
#include "extensions/browser/extension_prefs_scope.h"
#include "extensions/browser/extension_util.h"
#include "extensions/common/error_utils.h"
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "chrome/browser/plugins/plugin_finder.h"
+#include "chrome/browser/plugins/plugin_installer.h"
+#include "content/public/browser/plugin_service.h"
+#endif
+
using content::BrowserThread;
-using content::PluginService;
namespace Clear = extensions::api::content_settings::ContentSetting::Clear;
namespace Get = extensions::api::content_settings::ContentSetting::Get;
@@ -267,7 +269,8 @@ ContentSettingsContentSettingSetFunction::Run() {
if (primary_pattern != secondary_pattern &&
secondary_pattern != ContentSettingsPattern::Wildcard() &&
!info->website_settings_info()->SupportsEmbeddedExceptions() &&
- base::FeatureList::IsEnabled(::features::kPermissionDelegation)) {
+ base::FeatureList::IsEnabled(
+ permissions::features::kPermissionDelegation)) {
static const char kUnsupportedEmbeddedException[] =
"Embedded patterns are not supported for this setting.";
return RespondNow(Error(kUnsupportedEmbeddedException));
@@ -311,24 +314,29 @@ ContentSettingsContentSettingSetFunction::Run() {
return RespondNow(NoArguments());
}
-bool ContentSettingsContentSettingGetResourceIdentifiersFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+ContentSettingsContentSettingGetResourceIdentifiersFunction::Run() {
ContentSettingsType content_type;
EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_.get(), &content_type));
if (content_type != ContentSettingsType::PLUGINS) {
- SendResponse(true);
- return true;
+ return RespondNow(NoArguments());
}
- PluginService::GetInstance()->GetPlugins(base::BindOnce(
+#if BUILDFLAG(ENABLE_PLUGINS)
+ content::PluginService::GetInstance()->GetPlugins(base::BindOnce(
&ContentSettingsContentSettingGetResourceIdentifiersFunction::
OnGotPlugins,
this));
- return true;
+#endif
+
+ return RespondLater();
}
+#if BUILDFLAG(ENABLE_PLUGINS)
void ContentSettingsContentSettingGetResourceIdentifiersFunction::OnGotPlugins(
const std::vector<content::WebPluginInfo>& plugins) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
PluginFinder* finder = PluginFinder::GetInstance();
std::set<std::string> group_identifiers;
std::unique_ptr<base::ListValue> list(new base::ListValue());
@@ -346,13 +354,8 @@ void ContentSettingsContentSettingGetResourceIdentifiersFunction::OnGotPlugins(
plugin_metadata->name());
list->Append(std::move(dict));
}
- SetResult(std::move(list));
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(
- &ContentSettingsContentSettingGetResourceIdentifiersFunction::
- SendResponse,
- this, true));
+ Respond(OneArgument(std::move(list)));
}
+#endif // BUILDFLAG(ENABLE_PLUGINS)
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.h b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.h
index be5d3208e9c..ffcadd63105 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.h
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.h
@@ -5,8 +5,11 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_CONTENT_SETTINGS_CONTENT_SETTINGS_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_CONTENT_SETTINGS_CONTENT_SETTINGS_API_H_
+#include <vector>
+
#include "base/gtest_prod_util.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
+#include "extensions/browser/extension_function.h"
+#include "ppapi/buildflags/buildflags.h"
namespace content {
struct WebPluginInfo;
@@ -48,7 +51,7 @@ class ContentSettingsContentSettingSetFunction : public ExtensionFunction {
};
class ContentSettingsContentSettingGetResourceIdentifiersFunction
- : public ChromeAsyncExtensionFunction {
+ : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("contentSettings.getResourceIdentifiers",
CONTENTSETTINGS_GETRESOURCEIDENTIFIERS)
@@ -57,15 +60,17 @@ class ContentSettingsContentSettingGetResourceIdentifiersFunction
~ContentSettingsContentSettingGetResourceIdentifiersFunction() override {}
// ExtensionFunction:
- bool RunAsync() override;
+ ResponseAction Run() override;
private:
FRIEND_TEST_ALL_PREFIXES(ExtensionApiTest,
ContentSettingsGetResourceIdentifiers);
+#if BUILDFLAG(ENABLE_PLUGINS)
// Callback method that gets executed when |plugins|
// are asynchronously fetched.
void OnGotPlugins(const std::vector<content::WebPluginInfo>& plugins);
+#endif
};
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
index 308fb92d2e1..9c180fc96bf 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
@@ -20,13 +20,13 @@
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
+#include "components/permissions/features.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/plugin_service.h"
@@ -335,8 +335,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest, IncognitoIsolation) {
// Run extension, set all permissions to allow, and check if they are changed.
EXPECT_TRUE(RunExtensionSubtest("content_settings/incognitoisolation",
- "test.html?allow",
- kFlagUseIncognito | kFlagEnableIncognito))
+ "test.html?allow", kFlagEnableIncognito,
+ kFlagUseIncognito))
<< message_;
// Get content settings after running extension to ensure nothing is changed.
@@ -345,8 +345,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest, IncognitoIsolation) {
// Run extension, set all permissions to block, and check if they are changed.
EXPECT_TRUE(RunExtensionSubtest("content_settings/incognitoisolation",
- "test.html?block",
- kFlagUseIncognito | kFlagEnableIncognito))
+ "test.html?block", kFlagEnableIncognito,
+ kFlagUseIncognito))
<< message_;
// Get content settings after running extension to ensure nothing is changed.
@@ -395,7 +395,8 @@ class ExtensionContentSettingsApiTestWithPermissionDelegationDisabled
: public ExtensionContentSettingsApiTest {
public:
ExtensionContentSettingsApiTestWithPermissionDelegationDisabled() {
- feature_list_.InitAndDisableFeature(features::kPermissionDelegation);
+ feature_list_.InitAndDisableFeature(
+ permissions::features::kPermissionDelegation);
}
private:
@@ -406,7 +407,8 @@ class ExtensionContentSettingsApiTestWithPermissionDelegationEnabled
: public ExtensionContentSettingsApiTest {
public:
ExtensionContentSettingsApiTestWithPermissionDelegationEnabled() {
- feature_list_.InitAndEnableFeature(features::kPermissionDelegation);
+ feature_list_.InitAndEnableFeature(
+ permissions::features::kPermissionDelegation);
}
private:
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.cc
index 73db87ef55b..3b60b83250b 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.cc
@@ -17,7 +17,6 @@
#include "base/values.h"
#include "chrome/browser/extensions/api/content_settings/content_settings_api_constants.h"
#include "chrome/browser/extensions/api/content_settings/content_settings_helpers.h"
-#include "chrome/common/chrome_features.h"
#include "components/content_settings/core/browser/content_settings_info.h"
#include "components/content_settings/core/browser/content_settings_origin_identifier_value_map.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
@@ -25,6 +24,7 @@
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/content_settings/core/browser/website_settings_info.h"
#include "components/content_settings/core/common/content_settings_utils.h"
+#include "components/permissions/features.h"
#include "content/public/browser/browser_thread.h"
using content::BrowserThread;
@@ -370,7 +370,8 @@ void ContentSettingsStore::SetExtensionContentSettingFromList(
if (primary_pattern != secondary_pattern &&
secondary_pattern != ContentSettingsPattern::Wildcard() &&
!info->website_settings_info()->SupportsEmbeddedExceptions() &&
- base::FeatureList::IsEnabled(::features::kPermissionDelegation)) {
+ base::FeatureList::IsEnabled(
+ permissions::features::kPermissionDelegation)) {
// Some types may have had embedded exceptions written even though they
// aren't supported. This will implicitly delete these old settings from
// the pref store when it is written back.
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_store_unittest.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_store_unittest.cc
index 982640c0f1d..ec02e12ba9a 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_store_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_store_unittest.cc
@@ -11,12 +11,12 @@
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/content_settings/content_settings_api_constants.h"
-#include "chrome/common/chrome_features.h"
#include "components/content_settings/core/browser/content_settings_registry.h"
#include "components/content_settings/core/browser/content_settings_rule.h"
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/content_settings/core/common/content_settings_utils.h"
#include "components/content_settings/core/test/content_settings_test_utils.h"
+#include "components/permissions/features.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -335,7 +335,7 @@ TEST_F(ContentSettingsStoreTest, RemoveEmbedded) {
{
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(
- ::features::kPermissionDelegation);
+ permissions::features::kPermissionDelegation);
store()->SetExtensionContentSettingFromList(ext_id, &pref_list,
kExtensionPrefsScopeRegular);
@@ -354,7 +354,8 @@ TEST_F(ContentSettingsStoreTest, RemoveEmbedded) {
{
base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(::features::kPermissionDelegation);
+ scoped_feature_list.InitAndEnableFeature(
+ permissions::features::kPermissionDelegation);
store()->SetExtensionContentSettingFromList(ext_id, &pref_list,
kExtensionPrefsScopeRegular);
diff --git a/chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc b/chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
index a7766c8ef4b..52acc9c128d 100644
--- a/chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
@@ -16,8 +16,8 @@
#include "chrome/common/extensions/api/context_menus.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/version_info/channel.h"
+#include "content/public/browser/context_menu_params.h"
#include "content/public/browser/render_frame_host.h"
-#include "content/public/common/context_menu_params.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/common/scoped_worker_based_extensions_channel.h"
#include "extensions/test/result_catcher.h"
@@ -136,7 +136,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ContextMenus) {
IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ServiceWorkerContextMenus) {
ScopedWorkerBasedExtensionsChannel worker_channel_override;
ASSERT_TRUE(RunExtensionTestWithFlags("context_menus/event_page",
- kFlagRunAsServiceWorkerBasedExtension))
+ kFlagRunAsServiceWorkerBasedExtension,
+ kFlagNone))
<< message_;
}
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc b/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc
index e30f454b5b3..8e0a716fe26 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc
@@ -447,7 +447,7 @@ ExtensionFunction::ResponseAction CookiesSetFunction::Run() {
net::CookieOptions options;
options.set_include_httponly();
options.set_same_site_cookie_context(
- net::CookieOptions::SameSiteCookieContext::SAME_SITE_STRICT);
+ net::CookieOptions::SameSiteCookieContext::MakeInclusive());
DCHECK(!url_.is_empty() && url_.is_valid());
cookie_manager->SetCanonicalCookie(
*cc, url_.scheme(), options,
diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_api.h b/chromium/chrome/browser/extensions/api/cookies/cookies_api.h
index 0761d5333fb..d6b171b5f04 100644
--- a/chromium/chrome/browser/extensions/api/cookies/cookies_api.h
+++ b/chromium/chrome/browser/extensions/api/cookies/cookies_api.h
@@ -14,11 +14,11 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/common/extensions/api/cookies.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_function.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/cookies/canonical_cookie.h"
@@ -26,6 +26,8 @@
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "url/gurl.h"
+class Profile;
+
namespace extensions {
// Observes CookieManager Mojo messages and routes them as events to the
diff --git a/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc b/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc
index 0a4dc66eb5e..204f0bd2e17 100644
--- a/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc
@@ -13,14 +13,18 @@
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/permissions/attestation_permission_request.h"
-#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
+#include "components/page_load_metrics/browser/metrics_web_contents_observer.h"
+#include "components/permissions/permission_request_manager.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
#include "crypto/sha2.h"
#include "device/fido/features.h"
+#include "extensions/browser/extension_api_frame_id_map.h"
#include "extensions/common/error_utils.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "url/origin.h"
@@ -29,6 +33,10 @@
#include "device/fido/win/webauthn_api.h"
#endif // defined(OS_WIN)
+namespace extensions {
+
+namespace api {
+
namespace {
// U2FAttestationPromptResult enumerates events related to attestation prompts.
@@ -86,11 +94,20 @@ void RecordAttestationEvent(U2FAttestationPromptResult event) {
event);
}
-} // namespace
-
-namespace extensions {
+content::RenderFrameHost* RenderFrameHostForTabAndFrameId(
+ content::BrowserContext* const browser_context,
+ const int tab_id,
+ const int frame_id) {
+ content::WebContents* web_contents = nullptr;
+ if (!ExtensionTabUtil::GetTabById(tab_id, browser_context,
+ /*include_incognito=*/true,
+ &web_contents)) {
+ return nullptr;
+ }
+ return ExtensionApiFrameIdMap::GetRenderFrameHostById(web_contents, frame_id);
+}
-namespace api {
+} // namespace
void CryptotokenRegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
@@ -206,6 +223,12 @@ CryptotokenPrivateCanAppIdGetAttestationFunction::Run() {
return RespondNow(OneArgument(std::make_unique<base::Value>(true)));
}
+ // If the origin is blocked, reject attestation.
+ if (device::DoesMatchWebAuthAttestationBlockedDomains(
+ url::Origin::Create(origin_url))) {
+ return RespondNow(OneArgument(std::make_unique<base::Value>(false)));
+ }
+
// If prompting is disabled, allow attestation because that is the historical
// behavior.
if (!base::FeatureList::IsEnabled(
@@ -241,8 +264,8 @@ CryptotokenPrivateCanAppIdGetAttestationFunction::Run() {
return RespondNow(Error("cannot find specified tab"));
}
- PermissionRequestManager* permission_request_manager =
- PermissionRequestManager::FromWebContents(web_contents);
+ permissions::PermissionRequestManager* permission_request_manager =
+ permissions::PermissionRequestManager::FromWebContents(web_contents);
if (!permission_request_manager) {
return RespondNow(Error("no PermissionRequestManager"));
}
@@ -262,5 +285,40 @@ void CryptotokenPrivateCanAppIdGetAttestationFunction::Complete(bool result) {
Respond(OneArgument(std::make_unique<base::Value>(result)));
}
+ExtensionFunction::ResponseAction
+CryptotokenPrivateRecordRegisterRequestFunction::Run() {
+ auto params =
+ cryptotoken_private::RecordRegisterRequest::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ content::RenderFrameHost* frame = RenderFrameHostForTabAndFrameId(
+ browser_context(), params->tab_id, params->frame_id);
+ if (!frame) {
+ return RespondNow(Error("cannot find specified tab or frame"));
+ }
+
+ page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(
+ frame, page_load_metrics::mojom::PageLoadFeatures(
+ {blink::mojom::WebFeature::kU2FCryptotokenRegister}, {}, {}));
+ return RespondNow(NoArguments());
+}
+
+ExtensionFunction::ResponseAction
+CryptotokenPrivateRecordSignRequestFunction::Run() {
+ auto params = cryptotoken_private::RecordSignRequest::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ content::RenderFrameHost* frame = RenderFrameHostForTabAndFrameId(
+ browser_context(), params->tab_id, params->frame_id);
+ if (!frame) {
+ return RespondNow(Error("cannot find specified tab or frame"));
+ }
+
+ page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage(
+ frame, page_load_metrics::mojom::PageLoadFeatures(
+ {blink::mojom::WebFeature::kU2FCryptotokenSign}, {}, {}));
+ return RespondNow(NoArguments());
+}
+
} // namespace api
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h b/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h
index 9ac938c8b12..33e8072b5a6 100644
--- a/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h
+++ b/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h
@@ -63,6 +63,29 @@ class CryptotokenPrivateCanAppIdGetAttestationFunction
void Complete(bool result);
};
+class CryptotokenPrivateRecordRegisterRequestFunction
+ : public ExtensionFunction {
+ public:
+ CryptotokenPrivateRecordRegisterRequestFunction() = default;
+ DECLARE_EXTENSION_FUNCTION("cryptotokenPrivate.recordRegisterRequest",
+ CRYPTOTOKENPRIVATE_RECORDREGISTERREQUEST)
+
+ protected:
+ ~CryptotokenPrivateRecordRegisterRequestFunction() override = default;
+ ResponseAction Run() override;
+};
+
+class CryptotokenPrivateRecordSignRequestFunction : public ExtensionFunction {
+ public:
+ CryptotokenPrivateRecordSignRequestFunction() = default;
+ DECLARE_EXTENSION_FUNCTION("cryptotokenPrivate.recordSignRequest",
+ CRYPTOTOKENPRIVATE_RECORDSIGNREQUEST)
+
+ protected:
+ ~CryptotokenPrivateRecordSignRequestFunction() override = default;
+ ResponseAction Run() override;
+};
+
} // namespace api
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
index 092a999f02e..41925681ba1 100644
--- a/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
@@ -13,11 +13,12 @@
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/extensions/extension_api_unittest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
-#include "chrome/browser/permissions/permission_request_manager.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
-#include "chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
+#include "components/page_load_metrics/browser/page_load_metrics_test_waiter.h"
+#include "components/permissions/permission_request_manager.h"
+#include "components/permissions/test/mock_permission_prompt_factory.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "crypto/sha2.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/browser/extension_function_dispatcher.h"
@@ -154,6 +155,57 @@ TEST_F(CryptoTokenPrivateApiTest, IsAppIdHashInEnterpriseContext) {
EXPECT_FALSE(result);
}
+TEST_F(CryptoTokenPrivateApiTest, RecordRegisterRequest) {
+ const GURL url("https://example.com/signin");
+ AddTab(browser(), url);
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetWebContentsAt(0);
+ const int tab_id = sessions::SessionTabHelper::IdForTab(web_contents).id();
+
+ page_load_metrics::PageLoadMetricsTestWaiter web_feature_waiter(web_contents);
+ web_feature_waiter.AddWebFeatureExpectation(
+ blink::mojom::WebFeature::kU2FCryptotokenRegister);
+ // Force the metrics waiter to attach.
+ NavigateAndCommitActiveTab(url);
+
+ auto function = base::MakeRefCounted<
+ api::CryptotokenPrivateRecordRegisterRequestFunction>();
+ auto args = std::make_unique<base::ListValue>();
+ args->AppendInteger(tab_id);
+ args->AppendInteger(0 /* top-level frame */);
+ ASSERT_TRUE(extension_function_test_utils::RunFunction(
+ function.get(), base::ListValue::From(std::move(args)), browser(),
+ api_test_utils::NONE));
+ ASSERT_EQ(function->GetResultList()->GetSize(), 0u);
+
+ web_feature_waiter.Wait();
+}
+
+TEST_F(CryptoTokenPrivateApiTest, RecordSignRequest) {
+ const GURL url("https://example.com/signin");
+ AddTab(browser(), url);
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetWebContentsAt(0);
+ const int tab_id = sessions::SessionTabHelper::IdForTab(web_contents).id();
+
+ page_load_metrics::PageLoadMetricsTestWaiter web_feature_waiter(web_contents);
+ web_feature_waiter.AddWebFeatureExpectation(
+ blink::mojom::WebFeature::kU2FCryptotokenSign);
+ // Force the metrics waiter to attach.
+ NavigateAndCommitActiveTab(url);
+
+ auto function =
+ base::MakeRefCounted<api::CryptotokenPrivateRecordSignRequestFunction>();
+ auto args = std::make_unique<base::ListValue>();
+ args->AppendInteger(tab_id);
+ args->AppendInteger(0 /* top-level frame */);
+ ASSERT_TRUE(extension_function_test_utils::RunFunction(
+ function.get(), base::ListValue::From(std::move(args)), browser(),
+ api_test_utils::NONE));
+ ASSERT_EQ(function->GetResultList()->GetSize(), 0u);
+
+ web_feature_waiter.Wait();
+}
} // namespace
class CryptoTokenPermissionTest : public ExtensionApiUnittest {
@@ -171,10 +223,12 @@ class CryptoTokenPermissionTest : public ExtensionApiUnittest {
content::WebContents* web_contents =
browser()->tab_strip_model()->GetWebContentsAt(0);
- tab_id_ = SessionTabHelper::IdForTab(web_contents).id();
- PermissionRequestManager::CreateForWebContents(web_contents);
- prompt_factory_ = std::make_unique<MockPermissionPromptFactory>(
- PermissionRequestManager::FromWebContents(web_contents));
+ tab_id_ = sessions::SessionTabHelper::IdForTab(web_contents).id();
+ permissions::PermissionRequestManager::CreateForWebContents(web_contents);
+ prompt_factory_ =
+ std::make_unique<permissions::MockPermissionPromptFactory>(
+ permissions::PermissionRequestManager::FromWebContents(
+ web_contents));
}
void TearDown() override {
@@ -190,9 +244,9 @@ class CryptoTokenPermissionTest : public ExtensionApiUnittest {
// synchronous.
bool CanAppIdGetAttestation(
const std::string& app_id,
- PermissionRequestManager::AutoResponseType bubble_action,
+ permissions::PermissionRequestManager::AutoResponseType bubble_action,
bool* out_result) {
- if (bubble_action != PermissionRequestManager::NONE) {
+ if (bubble_action != permissions::PermissionRequestManager::NONE) {
prompt_factory_->set_response_type(bubble_action);
prompt_factory_->DocumentOnLoadCompletedInMainFrame();
}
@@ -218,16 +272,18 @@ class CryptoTokenPermissionTest : public ExtensionApiUnittest {
private:
base::test::ScopedFeatureList feature_list_;
int tab_id_ = -1;
- std::unique_ptr<MockPermissionPromptFactory> prompt_factory_;
+ std::unique_ptr<permissions::MockPermissionPromptFactory> prompt_factory_;
DISALLOW_COPY_AND_ASSIGN(CryptoTokenPermissionTest);
};
TEST_F(CryptoTokenPermissionTest, Prompt) {
- const std::vector<PermissionRequestManager::AutoResponseType> actions = {
- PermissionRequestManager::ACCEPT_ALL, PermissionRequestManager::DENY_ALL,
- PermissionRequestManager::DISMISS,
- };
+ const std::vector<permissions::PermissionRequestManager::AutoResponseType>
+ actions = {
+ permissions::PermissionRequestManager::ACCEPT_ALL,
+ permissions::PermissionRequestManager::DENY_ALL,
+ permissions::PermissionRequestManager::DISMISS,
+ };
for (const auto& action : actions) {
SCOPED_TRACE(action);
@@ -236,7 +292,8 @@ TEST_F(CryptoTokenPermissionTest, Prompt) {
ASSERT_TRUE(CanAppIdGetAttestation("https://test.com", action, &result));
// The result should only be positive if the user accepted the permissions
// prompt.
- EXPECT_EQ(action == PermissionRequestManager::ACCEPT_ALL, result);
+ EXPECT_EQ(action == permissions::PermissionRequestManager::ACCEPT_ALL,
+ result);
}
}
@@ -250,8 +307,8 @@ TEST_F(CryptoTokenPermissionTest, PolicyOverridesPrompt) {
// If an appId is configured by enterprise policy then attestation requests
// should be permitted without showing a prompt.
bool result = false;
- ASSERT_TRUE(CanAppIdGetAttestation(example_com,
- PermissionRequestManager::NONE, &result));
+ ASSERT_TRUE(CanAppIdGetAttestation(
+ example_com, permissions::PermissionRequestManager::NONE, &result));
EXPECT_TRUE(result);
}
diff --git a/chromium/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc b/chromium/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc
index b55ebba5d70..78af5ac1873 100644
--- a/chromium/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc
+++ b/chromium/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc
@@ -39,7 +39,7 @@ DataReductionProxyGetDataUsageFunction::Run() {
browser_context());
settings->data_reduction_proxy_service()
->compression_stats()
- ->GetHistoricalDataUsage(base::Bind(
+ ->GetHistoricalDataUsage(base::BindOnce(
&DataReductionProxyGetDataUsageFunction::ReplyWithDataUsage, this));
return RespondLater();
}
diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
index e0b5e36b092..496d13e881f 100644
--- a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
+++ b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -111,6 +111,14 @@ bool ExtensionCanAttachToURL(const Extension& extension,
return true;
}
+constexpr char kBrowserTargetId[] = "browser";
+
+constexpr char kPerfettoUIExtensionId[] = "lfmkphfpdbjijhpomgecfikhfohaoine";
+
+bool ExtensionMayAttachToBrowser(const Extension& extension) {
+ return extension.id() == kPerfettoUIExtensionId;
+}
+
} // namespace
// ExtensionDevToolsClientHost ------------------------------------------------
@@ -145,7 +153,7 @@ class ExtensionDevToolsClientHost : public content::DevToolsAgentHostClient,
// DevToolsAgentHostClient interface.
void AgentHostClosed(DevToolsAgentHost* agent_host) override;
void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
- const std::string& message) override;
+ base::span<const uint8_t> message) override;
bool MayAttachToURL(const GURL& url, bool is_webui) override;
bool MayAttachToBrowser() override;
bool MayReadLocalFiles() override;
@@ -266,9 +274,11 @@ void ExtensionDevToolsClientHost::SendMessageToBackend(
"params", command_params->additional_properties.CreateDeepCopy());
}
- std::string json_args;
- base::JSONWriter::Write(protocol_request, &json_args);
- agent_host_->DispatchProtocolMessage(this, json_args);
+ std::string json;
+ base::JSONWriter::Write(protocol_request, &json);
+
+ agent_host_->DispatchProtocolMessage(this,
+ base::as_bytes(base::make_span(json)));
}
void ExtensionDevToolsClientHost::InfoBarDismissed() {
@@ -314,15 +324,18 @@ void ExtensionDevToolsClientHost::Observe(
}
void ExtensionDevToolsClientHost::DispatchProtocolMessage(
- DevToolsAgentHost* agent_host, const std::string& message) {
+ DevToolsAgentHost* agent_host,
+ base::span<const uint8_t> message) {
DCHECK(agent_host == agent_host_.get());
if (!EventRouter::Get(profile_))
return;
+ base::StringPiece message_str(reinterpret_cast<const char*>(message.data()),
+ message.size());
std::unique_ptr<base::Value> result = base::JSONReader::ReadDeprecated(
- message, base::JSON_REPLACE_INVALID_CHARACTERS);
+ message_str, base::JSON_REPLACE_INVALID_CHARACTERS);
if (!result || !result->is_dict()) {
- LOG(ERROR) << "Tried to send invalid message to extension: " << message;
+ LOG(ERROR) << "Tried to send invalid message to extension: " << message_str;
return;
}
base::DictionaryValue* dictionary =
@@ -347,12 +360,12 @@ void ExtensionDevToolsClientHost::DispatchProtocolMessage(
EventRouter::Get(profile_)->DispatchEventToExtension(extension_id(),
std::move(event));
} else {
- DebuggerSendCommandFunction* function = pending_requests_[id].get();
- if (!function)
+ auto it = pending_requests_.find(id);
+ if (it == pending_requests_.end())
return;
- function->SendResponseBody(dictionary);
- pending_requests_.erase(id);
+ it->second->SendResponseBody(dictionary);
+ pending_requests_.erase(it);
}
}
@@ -368,7 +381,7 @@ bool ExtensionDevToolsClientHost::MayAttachToURL(const GURL& url,
}
bool ExtensionDevToolsClientHost::MayAttachToBrowser() {
- return false;
+ return ExtensionMayAttachToBrowser(*extension_);
}
bool ExtensionDevToolsClientHost::MayReadLocalFiles() {
@@ -385,46 +398,49 @@ DebuggerFunction::DebuggerFunction()
: client_host_(NULL) {
}
-DebuggerFunction::~DebuggerFunction() {
-}
+DebuggerFunction::~DebuggerFunction() = default;
-void DebuggerFunction::FormatErrorMessage(const std::string& format) {
- if (debuggee_.tab_id)
- error_ = ErrorUtils::FormatErrorMessage(
+std::string DebuggerFunction::FormatErrorMessage(const std::string& format) {
+ if (debuggee_.tab_id) {
+ return ErrorUtils::FormatErrorMessage(
format, debugger_api_constants::kTabTargetType,
base::NumberToString(*debuggee_.tab_id));
- else if (debuggee_.extension_id)
- error_ = ErrorUtils::FormatErrorMessage(
+ }
+ if (debuggee_.extension_id) {
+ return ErrorUtils::FormatErrorMessage(
format, debugger_api_constants::kBackgroundPageTargetType,
*debuggee_.extension_id);
- else
- error_ = ErrorUtils::FormatErrorMessage(
- format, debugger_api_constants::kOpaqueTargetType,
- *debuggee_.target_id);
+ }
+
+ return ErrorUtils::FormatErrorMessage(
+ format, debugger_api_constants::kOpaqueTargetType, *debuggee_.target_id);
}
-bool DebuggerFunction::InitAgentHost() {
+bool DebuggerFunction::InitAgentHost(std::string* error) {
if (debuggee_.tab_id) {
WebContents* web_contents = nullptr;
- bool result = ExtensionTabUtil::GetTabById(*debuggee_.tab_id, GetProfile(),
- include_incognito_information(),
- &web_contents);
+ bool result = ExtensionTabUtil::GetTabById(
+ *debuggee_.tab_id, browser_context(), include_incognito_information(),
+ &web_contents);
if (result && web_contents) {
// TODO(rdevlin.cronin) This should definitely be GetLastCommittedURL().
GURL url = web_contents->GetVisibleURL();
- if (!ExtensionCanAttachToURL(*extension(), url, GetProfile(), &error_))
+ if (!ExtensionCanAttachToURL(
+ *extension(), url, Profile::FromBrowserContext(browser_context()),
+ error)) {
return false;
+ }
agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents);
}
} else if (debuggee_.extension_id) {
ExtensionHost* extension_host =
- ProcessManager::Get(GetProfile())
+ ProcessManager::Get(browser_context())
->GetBackgroundHostForExtension(*debuggee_.extension_id);
if (extension_host) {
if (extension()->permissions_data()->IsRestrictedUrl(
- extension_host->GetURL(), &error_)) {
+ extension_host->GetURL(), error)) {
return false;
}
agent_host_ =
@@ -434,30 +450,50 @@ bool DebuggerFunction::InitAgentHost() {
agent_host_ = DevToolsAgentHost::GetForId(*debuggee_.target_id);
if (agent_host_.get()) {
if (extension()->permissions_data()->IsRestrictedUrl(
- agent_host_->GetURL(), &error_)) {
+ agent_host_->GetURL(), error)) {
agent_host_ = nullptr;
return false;
}
+ } else if (*debuggee_.target_id == kBrowserTargetId &&
+ ExtensionMayAttachToBrowser(*extension())) {
+ // TODO(caseq): get rid of the below code, browser agent host should
+ // really be a singleton.
+ // Re-use existing browser agent hosts.
+ const std::string& extension_id = extension()->id();
+ AttachedClientHosts& hosts = g_attached_client_hosts.Get();
+ auto it = std::find_if(
+ hosts.begin(), hosts.end(),
+ [&extension_id](ExtensionDevToolsClientHost* client_host) {
+ return client_host->extension_id() == extension_id &&
+ client_host->agent_host() &&
+ client_host->agent_host()->GetType() ==
+ DevToolsAgentHost::kTypeBrowser;
+ });
+ agent_host_ = it != hosts.end()
+ ? (*it)->agent_host()
+ : DevToolsAgentHost::CreateForBrowser(
+ nullptr /* tethering_task_runner */,
+ DevToolsAgentHost::CreateServerSocketCallback());
}
} else {
- error_ = debugger_api_constants::kInvalidTargetError;
+ *error = debugger_api_constants::kInvalidTargetError;
return false;
}
if (!agent_host_.get()) {
- FormatErrorMessage(debugger_api_constants::kNoTargetError);
+ *error = FormatErrorMessage(debugger_api_constants::kNoTargetError);
return false;
}
return true;
}
-bool DebuggerFunction::InitClientHost() {
- if (!InitAgentHost())
+bool DebuggerFunction::InitClientHost(std::string* error) {
+ if (!InitAgentHost(error))
return false;
client_host_ = FindClientHost();
if (!client_host_) {
- FormatErrorMessage(debugger_api_constants::kNotAttachedError);
+ *error = FormatErrorMessage(debugger_api_constants::kNotAttachedError);
return false;
}
@@ -483,98 +519,93 @@ ExtensionDevToolsClientHost* DebuggerFunction::FindClientHost() {
// DebuggerAttachFunction -----------------------------------------------------
-DebuggerAttachFunction::DebuggerAttachFunction() {
-}
+DebuggerAttachFunction::DebuggerAttachFunction() = default;
-DebuggerAttachFunction::~DebuggerAttachFunction() {
-}
+DebuggerAttachFunction::~DebuggerAttachFunction() = default;
-bool DebuggerAttachFunction::RunAsync() {
+ExtensionFunction::ResponseAction DebuggerAttachFunction::Run() {
std::unique_ptr<Attach::Params> params(Attach::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
CopyDebuggee(&debuggee_, params->target);
- if (!InitAgentHost())
- return false;
+ std::string error;
+ if (!InitAgentHost(&error))
+ return RespondNow(Error(error));
if (!DevToolsAgentHost::IsSupportedProtocolVersion(
params->required_version)) {
- error_ = ErrorUtils::FormatErrorMessage(
+ return RespondNow(Error(ErrorUtils::FormatErrorMessage(
debugger_api_constants::kProtocolVersionNotSupportedError,
- params->required_version);
- return false;
+ params->required_version)));
}
if (FindClientHost()) {
- FormatErrorMessage(debugger_api_constants::kAlreadyAttachedError);
- return false;
+ return RespondNow(Error(
+ FormatErrorMessage(debugger_api_constants::kAlreadyAttachedError)));
}
auto host = std::make_unique<ExtensionDevToolsClientHost>(
- GetProfile(), agent_host_.get(), extension(), debuggee_);
+ Profile::FromBrowserContext(browser_context()), agent_host_.get(),
+ extension(), debuggee_);
if (!host->Attach()) {
- error_ = debugger_api_constants::kRestrictedError;
- return false;
+ return RespondNow(Error(debugger_api_constants::kRestrictedError));
}
host.release(); // An attached client host manages its own lifetime.
- SendResponse(true);
- return true;
+ return RespondNow(NoArguments());
}
-
// DebuggerDetachFunction -----------------------------------------------------
-DebuggerDetachFunction::DebuggerDetachFunction() {
-}
+DebuggerDetachFunction::DebuggerDetachFunction() = default;
-DebuggerDetachFunction::~DebuggerDetachFunction() {
-}
+DebuggerDetachFunction::~DebuggerDetachFunction() = default;
-bool DebuggerDetachFunction::RunAsync() {
+ExtensionFunction::ResponseAction DebuggerDetachFunction::Run() {
std::unique_ptr<Detach::Params> params(Detach::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
CopyDebuggee(&debuggee_, params->target);
- if (!InitClientHost())
- return false;
+ std::string error;
+ if (!InitClientHost(&error))
+ return RespondNow(Error(error));
client_host_->RespondDetachedToPendingRequests();
client_host_->Close();
- SendResponse(true);
- return true;
+ return RespondNow(NoArguments());
}
-
// DebuggerSendCommandFunction ------------------------------------------------
-DebuggerSendCommandFunction::DebuggerSendCommandFunction() {
-}
+DebuggerSendCommandFunction::DebuggerSendCommandFunction() = default;
-DebuggerSendCommandFunction::~DebuggerSendCommandFunction() {
-}
+DebuggerSendCommandFunction::~DebuggerSendCommandFunction() = default;
-bool DebuggerSendCommandFunction::RunAsync() {
+ExtensionFunction::ResponseAction DebuggerSendCommandFunction::Run() {
std::unique_ptr<SendCommand::Params> params(
SendCommand::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
CopyDebuggee(&debuggee_, params->target);
- if (!InitClientHost())
- return false;
+ std::string error;
+ if (!InitClientHost(&error))
+ return RespondNow(Error(error));
client_host_->SendMessageToBackend(this, params->method,
params->command_params.get());
- return true;
+ if (did_respond())
+ return AlreadyResponded();
+ return RespondLater();
}
void DebuggerSendCommandFunction::SendResponseBody(
base::DictionaryValue* response) {
base::Value* error_body;
if (response->Get("error", &error_body)) {
- base::JSONWriter::Write(*error_body, &error_);
- SendResponse(false);
+ std::string error;
+ base::JSONWriter::Write(*error_body, &error);
+ Respond(Error(error));
return;
}
@@ -583,13 +614,11 @@ void DebuggerSendCommandFunction::SendResponseBody(
if (response->GetDictionary("result", &result_body))
result.additional_properties.Swap(result_body);
- results_ = SendCommand::Results::Create(result);
- SendResponse(true);
+ Respond(ArgumentList(SendCommand::Results::Create(result)));
}
void DebuggerSendCommandFunction::SendDetachedError() {
- error_ = debugger_api_constants::kDetachedWhileHandlingError;
- SendResponse(false);
+ Respond(Error(debugger_api_constants::kDetachedWhileHandlingError));
}
// DebuggerGetTargetsFunction -------------------------------------------------
@@ -644,27 +673,17 @@ std::unique_ptr<base::DictionaryValue> SerializeTarget(
} // namespace
-DebuggerGetTargetsFunction::DebuggerGetTargetsFunction() {
-}
+DebuggerGetTargetsFunction::DebuggerGetTargetsFunction() = default;
-DebuggerGetTargetsFunction::~DebuggerGetTargetsFunction() {
-}
+DebuggerGetTargetsFunction::~DebuggerGetTargetsFunction() = default;
-bool DebuggerGetTargetsFunction::RunAsync() {
+ExtensionFunction::ResponseAction DebuggerGetTargetsFunction::Run() {
content::DevToolsAgentHost::List list = DevToolsAgentHost::GetOrCreateAll();
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&DebuggerGetTargetsFunction::SendTargetList, this, list));
- return true;
-}
-
-void DebuggerGetTargetsFunction::SendTargetList(
- const content::DevToolsAgentHost::List& target_list) {
std::unique_ptr<base::ListValue> result(new base::ListValue());
- for (size_t i = 0; i < target_list.size(); ++i)
- result->Append(SerializeTarget(target_list[i]));
- SetResult(std::move(result));
- SendResponse(true);
+ for (size_t i = 0; i < list.size(); ++i)
+ result->Append(SerializeTarget(list[i]));
+
+ return RespondNow(OneArgument(std::move(result)));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_api.h b/chromium/chrome/browser/extensions/api/debugger/debugger_api.h
index dfb2a63c10a..7ec6ab61ba8 100644
--- a/chromium/chrome/browser/extensions/api/debugger/debugger_api.h
+++ b/chromium/chrome/browser/extensions/api/debugger/debugger_api.h
@@ -11,9 +11,9 @@
#include <string>
#include <vector>
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/common/extensions/api/debugger.h"
#include "content/public/browser/devtools_agent_host.h"
+#include "extensions/browser/extension_function.h"
using extensions::api::debugger::Debuggee;
@@ -26,15 +26,15 @@ class DictionaryValue;
namespace extensions {
class ExtensionDevToolsClientHost;
-class DebuggerFunction : public ChromeAsyncExtensionFunction {
+class DebuggerFunction : public ExtensionFunction {
protected:
DebuggerFunction();
~DebuggerFunction() override;
- void FormatErrorMessage(const std::string& format);
+ std::string FormatErrorMessage(const std::string& format);
- bool InitAgentHost();
- bool InitClientHost();
+ bool InitAgentHost(std::string* error);
+ bool InitClientHost(std::string* error);
ExtensionDevToolsClientHost* FindClientHost();
Debuggee debuggee_;
@@ -53,7 +53,7 @@ class DebuggerAttachFunction : public DebuggerFunction {
~DebuggerAttachFunction() override;
// ExtensionFunction:
- bool RunAsync() override;
+ ResponseAction Run() override;
};
// Implements the debugger.detach() extension function.
@@ -67,7 +67,7 @@ class DebuggerDetachFunction : public DebuggerFunction {
~DebuggerDetachFunction() override;
// ExtensionFunction:
- bool RunAsync() override;
+ ResponseAction Run() override;
};
// Implements the debugger.sendCommand() extension function.
@@ -83,7 +83,7 @@ class DebuggerSendCommandFunction : public DebuggerFunction {
~DebuggerSendCommandFunction() override;
// ExtensionFunction:
- bool RunAsync() override;
+ ResponseAction Run() override;
};
// Implements the debugger.getTargets() extension function.
@@ -97,10 +97,7 @@ class DebuggerGetTargetsFunction : public DebuggerFunction {
~DebuggerGetTargetsFunction() override;
// ExtensionFunction:
- bool RunAsync() override;
-
- private:
- void SendTargetList(const content::DevToolsAgentHost::List& target_list);
+ ResponseAction Run() override;
};
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc b/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc
index 9f6af1fa41b..ea248c27dce 100644
--- a/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc
@@ -15,13 +15,13 @@
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/infobars/core/infobar.h"
#include "components/infobars/core/infobar_delegate.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/extension_function.h"
#include "extensions/common/extension.h"
@@ -94,7 +94,7 @@ testing::AssertionResult DebuggerApiTest::RunAttachFunction(
browser()->tab_strip_model()->GetActiveWebContents();
// Attach by tabId.
- int tab_id = SessionTabHelper::IdForTab(web_contents).id();
+ int tab_id = sessions::SessionTabHelper::IdForTab(web_contents).id();
std::string debugee_by_tab = base::StringPrintf("{\"tabId\": %d}", tab_id);
testing::AssertionResult result =
RunAttachFunctionOnTarget(debugee_by_tab, expected_error);
@@ -201,7 +201,7 @@ IN_PROC_BROWSER_TEST_F(DebuggerApiTest,
}
IN_PROC_BROWSER_TEST_F(DebuggerApiTest, InfoBar) {
- int tab_id = SessionTabHelper::IdForTab(
+ int tab_id = sessions::SessionTabHelper::IdForTab(
browser()->tab_strip_model()->GetActiveWebContents())
.id();
scoped_refptr<DebuggerAttachFunction> attach_function;
@@ -211,7 +211,7 @@ IN_PROC_BROWSER_TEST_F(DebuggerApiTest, InfoBar) {
new Browser(Browser::CreateParams(profile(), true));
AddBlankTabAndShow(another_browser);
AddBlankTabAndShow(another_browser);
- int tab_id2 = SessionTabHelper::IdForTab(
+ int tab_id2 = sessions::SessionTabHelper::IdForTab(
another_browser->tab_strip_model()->GetActiveWebContents())
.id();
@@ -338,6 +338,19 @@ IN_PROC_BROWSER_TEST_F(DebuggerExtensionApiTest, Debugger) {
ASSERT_TRUE(RunExtensionTest("debugger")) << message_;
}
+// Tests that an extension is not allowed to inspect a worker through the
+// inspectWorker debugger command.
+// Regression test for https://crbug.com/1059577.
+IN_PROC_BROWSER_TEST_F(DebuggerExtensionApiTest,
+ DebuggerNotAllowedToInvokeInspectWorker) {
+ GURL url(embedded_test_server()->GetURL(
+ "/extensions/api_test/debugger_inspect_worker/inspected_page.html"));
+
+ EXPECT_TRUE(
+ RunExtensionTestWithArg("debugger_inspect_worker", url.spec().c_str()))
+ << message_;
+}
+
class SitePerProcessDebuggerExtensionApiTest : public DebuggerExtensionApiTest {
public:
void SetUpCommandLine(base::CommandLine* command_line) override {
diff --git a/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc b/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc
index b84087e0e01..05022dd0ba4 100644
--- a/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_features.h"
#include "extensions/browser/api/declarative/rules_registry_service.h"
#include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
#include "extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h"
@@ -119,6 +120,54 @@ class DeclarativeApiTest : public ExtensionApiTest {
}
};
+// Copied from origin_policy_browsertest.cc.
+const base::FilePath::CharType kDataRoot[] =
+ FILE_PATH_LITERAL("chrome/test/data/origin_policy_browsertest");
+
+class DeclarativeApiTestWithOriginPolicy : public DeclarativeApiTest {
+ protected:
+ base::string16 NavigateToAndReturnTitle(const char* url) {
+ EXPECT_TRUE(server());
+ ui_test_utils::NavigateToURL(browser(), GURL(server()->GetURL(url)));
+ base::string16 title;
+ ui_test_utils::GetCurrentTabTitle(browser(), &title);
+ return title;
+ }
+
+ private:
+ void SetUpInProcessBrowserTestFixture() override {
+ server_ = std::make_unique<net::test_server::EmbeddedTestServer>(
+ net::test_server::EmbeddedTestServer::TYPE_HTTPS);
+ server_->AddDefaultHandlers(base::FilePath(kDataRoot));
+ feature_list_.InitAndEnableFeature(features::kOriginPolicy);
+ EXPECT_TRUE(server()->Start());
+ DeclarativeApiTest::SetUpInProcessBrowserTestFixture();
+ }
+
+ void TearDownInProcessBrowserTestFixture() override { server_.reset(); }
+
+ net::test_server::EmbeddedTestServer* server() { return server_.get(); }
+
+ std::unique_ptr<net::test_server::EmbeddedTestServer> server_;
+ base::test::ScopedFeatureList feature_list_;
+};
+
+// Regression test for crbug.com/1047275.
+IN_PROC_BROWSER_TEST_F(DeclarativeApiTestWithOriginPolicy,
+ OriginPolicyEnabled) {
+ // Navigate to a page with an origin policy. It should load correctly.
+ EXPECT_EQ(base::ASCIIToUTF16("Page With Policy"),
+ NavigateToAndReturnTitle("/page-with-policy.html"));
+
+ // Load an extension that has the |declarativeWebRequest| permission.
+ ASSERT_TRUE(RunExtensionTest("declarative/api")) << message_;
+
+ // Future navigations to the page with the origin policy should still work,
+ // and not throw an interstitial.
+ EXPECT_EQ(base::ASCIIToUTF16("Page With Policy"),
+ NavigateToAndReturnTitle("/page-with-policy.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, DeclarativeApi) {
ASSERT_TRUE(RunExtensionTest("declarative/api")) << message_;
diff --git a/chromium/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc b/chromium/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc
index ae31311197c..8b25d8e15ff 100644
--- a/chromium/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative/rules_registry_service_unittest.cc
@@ -16,7 +16,6 @@
#include "components/version_info/version_info.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_browser_thread.h"
#include "extensions/browser/api/declarative/test_rules_registry.h"
#include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
#include "extensions/common/api/declarative/declarative_constants.h"
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
index b60f7e4cf42..e75b5e1c4df 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/chrome_content_rules_registry_unittest.cc
@@ -161,25 +161,23 @@ TEST_F(DeclarativeChromeContentRulesRegistryTest, ActiveRulesDoesntGrow) {
// Add a rule.
api::events::Rule rule;
- api::events::Rule::Populate(
- *base::test::ParseJsonDeprecated(
- "{\n"
- " \"id\": \"rule1\",\n"
- " \"priority\": 100,\n"
- " \"conditions\": [\n"
- " {\n"
- " \"instanceType\": \"declarativeContent.PageStateMatcher\",\n"
- " \"test_predicate\": []\n"
- " }],\n"
- " \"actions\": [\n"
- " { \"instanceType\": \"declarativeContent.ShowAction\" }\n"
- " ]\n"
- "}"),
- &rule);
+ api::events::Rule::Populate(base::test::ParseJson(R"({
+ "id": "rule1",
+ "priority": 100,
+ "conditions": [
+ {
+ "instanceType": "declarativeContent.PageStateMatcher",
+ "test_predicate": []
+ }],
+ "actions": [
+ {"instanceType": "declarativeContent.ShowAction"}
+ ]
+ })"),
+ &rule);
std::vector<const api::events::Rule*> rules({&rule});
- const Extension* extension = env()->MakeExtension(
- *base::test::ParseJsonDeprecated("{\"page_action\": {}}"));
+ const Extension* extension =
+ env()->MakeExtension(base::test::ParseJson("{\"page_action\": {}}"));
registry->AddRulesImpl(extension->id(), rules);
registry->DidFinishNavigation(tab.get(), &navigation_handle);
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/content_action.cc b/chromium/chrome/browser/extensions/api/declarative_content/content_action.cc
index 55c66774656..7365c7eba44 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/content_action.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/content_action.cc
@@ -18,7 +18,7 @@
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -375,8 +375,8 @@ void RequestContentScript::InstructRenderProcessToInject(
content::RenderFrameHost* render_frame_host = contents->GetMainFrame();
render_frame_host->Send(new ExtensionMsg_ExecuteDeclarativeScript(
render_frame_host->GetRoutingID(),
- SessionTabHelper::IdForTab(contents).id(), extension->id(), script_.id(),
- contents->GetLastCommittedURL()));
+ sessions::SessionTabHelper::IdForTab(contents).id(), extension->id(),
+ script_.id(), contents->GetLastCommittedURL()));
}
// static
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/content_action_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_content/content_action_unittest.cc
index 22351676669..00eb884a1e7 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/content_action_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/content_action_unittest.cc
@@ -33,7 +33,7 @@
namespace extensions {
namespace {
-using base::test::ParseJsonDeprecated;
+using base::test::ParseJson;
using testing::HasSubstr;
std::unique_ptr<base::DictionaryValue> SimpleManifest() {
@@ -60,7 +60,6 @@ class RequestContentScriptTest : public ExtensionServiceTestBase {
base::RunLoop().RunUntilIdle();
}
- Profile* profile() { return profile_.get(); }
const Extension* extension() { return extension_.get(); }
private:
@@ -75,27 +74,23 @@ TEST(DeclarativeContentActionTest, InvalidCreation) {
// Test wrong data type passed.
error.clear();
- result = ContentAction::Create(&profile, nullptr, *ParseJsonDeprecated("[]"),
- &error);
+ result = ContentAction::Create(&profile, nullptr, ParseJson("[]"), &error);
EXPECT_THAT(error, HasSubstr("missing instanceType"));
EXPECT_FALSE(result.get());
// Test missing instanceType element.
error.clear();
- result = ContentAction::Create(&profile, nullptr, *ParseJsonDeprecated("{}"),
- &error);
+ result = ContentAction::Create(&profile, nullptr, ParseJson("{}"), &error);
EXPECT_THAT(error, HasSubstr("missing instanceType"));
EXPECT_FALSE(result.get());
// Test wrong instanceType element.
error.clear();
- result = ContentAction::Create(
- &profile, nullptr,
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.UnknownType\",\n"
- "}"),
- &error);
+ result = ContentAction::Create(&profile, nullptr, ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.UnknownType",
+ })"),
+ &error);
EXPECT_THAT(error, HasSubstr("invalid instanceType"));
EXPECT_FALSE(result.get());
}
@@ -119,13 +114,12 @@ TEST(DeclarativeContentActionTest, ShowActionWithoutAction) {
TestingProfile profile;
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- &profile, extension.get(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.ShowAction\",\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(&profile, extension.get(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.ShowAction",
+ })"),
+ &error);
EXPECT_THAT(error, testing::HasSubstr("without an action"));
ASSERT_FALSE(result.get());
}
@@ -149,8 +143,7 @@ TEST_P(ParameterizedDeclarativeContentActionTest, ShowAction) {
TestingProfile profile;
std::unique_ptr<const ContentAction> result = ContentAction::Create(
nullptr, extension.get(),
- *ParseJsonDeprecated(
- R"({"instanceType": "declarativeContent.ShowAction"})"),
+ ParseJson(R"({"instanceType": "declarativeContent.ShowAction"})"),
&error);
EXPECT_TRUE(error.empty()) << error;
ASSERT_TRUE(result.get());
@@ -221,8 +214,8 @@ TEST(DeclarativeContentActionTest, SetIcon) {
.Set("imageData", DictionaryBuilder().Set("19", data64).Build())
.Build();
- const Extension* extension = env.MakeExtension(*ParseJsonDeprecated(
- "{\"page_action\": { \"default_title\": \"Extension\" } }"));
+ const Extension* extension = env.MakeExtension(
+ ParseJson(R"({"page_action": {"default_title": "Extension"}})"));
base::HistogramTester histogram_tester;
TestingProfile profile;
std::string error;
@@ -280,8 +273,8 @@ TEST(DeclarativeContentActionTest, SetInvisibleIcon) {
.Build();
// Expect an error and no instance to be created.
- const Extension* extension = env.MakeExtension(*ParseJsonDeprecated(
- R"({"page_action": {"default_title": "Extension"}})"));
+ const Extension* extension = env.MakeExtension(
+ ParseJson(R"({"page_action": {"default_title": "Extension"}})"));
base::HistogramTester histogram_tester;
TestingProfile profile;
std::string error;
@@ -302,15 +295,14 @@ TEST(DeclarativeContentActionTest, SetInvisibleIcon) {
TEST_F(RequestContentScriptTest, MissingScripts) {
Init();
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- profile(), extension(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
- " \"allFrames\": true,\n"
- " \"matchAboutBlank\": true\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(profile(), extension(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.RequestContentScript",
+ "allFrames": true,
+ "matchAboutBlank": true
+ })"),
+ &error);
EXPECT_THAT(error, testing::HasSubstr("Missing parameter is required"));
ASSERT_FALSE(result.get());
}
@@ -318,14 +310,13 @@ TEST_F(RequestContentScriptTest, MissingScripts) {
TEST_F(RequestContentScriptTest, CSS) {
Init();
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- profile(), extension(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
- " \"css\": [\"style.css\"]\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(profile(), extension(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.RequestContentScript",
+ "css": ["style.css"]
+ })"),
+ &error);
EXPECT_EQ("", error);
ASSERT_TRUE(result.get());
}
@@ -333,14 +324,13 @@ TEST_F(RequestContentScriptTest, CSS) {
TEST_F(RequestContentScriptTest, JS) {
Init();
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- profile(), extension(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
- " \"js\": [\"script.js\"]\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(profile(), extension(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.RequestContentScript",
+ "js": ["script.js"]
+ })"),
+ &error);
EXPECT_EQ("", error);
ASSERT_TRUE(result.get());
}
@@ -348,43 +338,40 @@ TEST_F(RequestContentScriptTest, JS) {
TEST_F(RequestContentScriptTest, CSSBadType) {
Init();
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- profile(), extension(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
- " \"css\": \"style.css\"\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(profile(), extension(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.RequestContentScript",
+ "css": "style.css"
+ })"),
+ &error);
ASSERT_FALSE(result.get());
}
TEST_F(RequestContentScriptTest, JSBadType) {
Init();
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- profile(), extension(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
- " \"js\": \"script.js\"\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(profile(), extension(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.RequestContentScript",
+ "js": "script.js"
+ })"),
+ &error);
ASSERT_FALSE(result.get());
}
TEST_F(RequestContentScriptTest, AllFrames) {
Init();
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- profile(), extension(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
- " \"js\": [\"script.js\"],\n"
- " \"allFrames\": true\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(profile(), extension(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.RequestContentScript",
+ "js": ["script.js"],
+ "allFrames": true
+ })"),
+ &error);
EXPECT_EQ("", error);
ASSERT_TRUE(result.get());
}
@@ -392,15 +379,14 @@ TEST_F(RequestContentScriptTest, AllFrames) {
TEST_F(RequestContentScriptTest, MatchAboutBlank) {
Init();
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- profile(), extension(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
- " \"js\": [\"script.js\"],\n"
- " \"matchAboutBlank\": true\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(profile(), extension(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.RequestContentScript",
+ "js": ["script.js"],
+ "matchAboutBlank": true
+ })"),
+ &error);
EXPECT_EQ("", error);
ASSERT_TRUE(result.get());
}
@@ -408,30 +394,28 @@ TEST_F(RequestContentScriptTest, MatchAboutBlank) {
TEST_F(RequestContentScriptTest, AllFramesBadType) {
Init();
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- profile(), extension(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
- " \"js\": [\"script.js\"],\n"
- " \"allFrames\": null\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(profile(), extension(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.RequestContentScript",
+ "js": ["script.js"],
+ "allFrames": null
+ })"),
+ &error);
ASSERT_FALSE(result.get());
}
TEST_F(RequestContentScriptTest, MatchAboutBlankBadType) {
Init();
std::string error;
- std::unique_ptr<const ContentAction> result = ContentAction::Create(
- profile(), extension(),
- *ParseJsonDeprecated(
- "{\n"
- " \"instanceType\": \"declarativeContent.RequestContentScript\",\n"
- " \"js\": [\"script.js\"],\n"
- " \"matchAboutBlank\": null\n"
- "}"),
- &error);
+ std::unique_ptr<const ContentAction> result =
+ ContentAction::Create(profile(), extension(), ParseJson(R"(
+ {
+ "instanceType": "declarativeContent.RequestContentScript",
+ "js": ["script.js"],
+ "matchAboutBlank": null
+ })"),
+ &error);
ASSERT_FALSE(result.get());
}
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc
index a53f33a7961..809b12858b6 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/content_condition_unittest.cc
@@ -81,11 +81,10 @@ TEST(DeclarativeContentConditionTest, UnknownPredicateName) {
std::string error;
std::unique_ptr<ContentCondition> condition = CreateContentCondition(
nullptr, std::map<std::string, ContentPredicateFactory*>(),
- *base::test::ParseJsonDeprecated(
- "{\n"
- " \"invalid\": \"foobar\",\n"
- " \"instanceType\": \"declarativeContent.PageStateMatcher\",\n"
- "}"),
+ base::test::ParseJson(R"({
+ "invalid": "foobar",
+ "instanceType": "declarativeContent.PageStateMatcher",
+ })"),
&error);
EXPECT_THAT(error, HasSubstr("Unknown condition attribute"));
EXPECT_FALSE(condition);
@@ -98,12 +97,10 @@ TEST(DeclarativeContentConditionTest,
predicate_factories["test_predicate"] = &factory;
std::string error;
std::unique_ptr<ContentCondition> condition = CreateContentCondition(
- nullptr, predicate_factories,
- *base::test::ParseJsonDeprecated(
- "{\n"
- " \"test_predicate\": \"\",\n"
- " \"instanceType\": \"declarativeContent.PageStateMatcher\",\n"
- "}"),
+ nullptr, predicate_factories, base::test::ParseJson(R"({
+ "test_predicate": "",
+ "instanceType": "declarativeContent.PageStateMatcher",
+ })"),
&error);
EXPECT_EQ("error message", error);
EXPECT_FALSE(condition);
@@ -116,13 +113,11 @@ TEST(DeclarativeContentConditionTest, AllSpecifiedPredicatesCreated) {
predicate_factories["test_predicate2"] = &factory2;
std::string error;
std::unique_ptr<ContentCondition> condition = CreateContentCondition(
- nullptr, predicate_factories,
- *base::test::ParseJsonDeprecated(
- "{\n"
- " \"test_predicate1\": {},\n"
- " \"test_predicate2\": [],\n"
- " \"instanceType\": \"declarativeContent.PageStateMatcher\",\n"
- "}"),
+ nullptr, predicate_factories, base::test::ParseJson(R"({
+ "test_predicate1": {},
+ "test_predicate2": [],
+ "instanceType": "declarativeContent.PageStateMatcher",
+ })"),
&error);
ASSERT_TRUE(condition);
ASSERT_EQ(1u, factory1.created_predicates().size());
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
index 778095d72b1..044dc6eaa3e 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
@@ -16,11 +16,11 @@
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "components/bookmarks/browser/bookmark_model.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/extension_registry.h"
@@ -508,7 +508,7 @@ void ParameterizedShowActionDeclarativeContentApiTest::TestShowAction(
browser()->tab_strip_model()->GetWebContentsAt(0);
NavigateInRenderer(tab, GURL("http://test/"));
- const int tab_id = SessionTabHelper::IdForTab(tab).id();
+ const int tab_id = sessions::SessionTabHelper::IdForTab(tab).id();
EXPECT_TRUE(action->GetIsVisible(tab_id));
// If an extension had no action specified in the manifest, it will get a
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
index b43cb47ab7b..4cff33757b9 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker.cc
@@ -283,8 +283,8 @@ std::vector<std::string> DeclarativeContentCssConditionTracker::
GetWatchedCssSelectors() const {
std::vector<std::string> selectors;
selectors.reserve(watched_css_selector_predicate_count_.size());
- for (const std::pair<std::string, int>& selector_pair :
- watched_css_selector_predicate_count_) {
+ for (const std::pair<const std::string, int>& selector_pair :
+ watched_css_selector_predicate_count_) {
selectors.push_back(selector_pair.first);
}
return selectors;
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc
index 0f5446c1def..b6c4337f0c8 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc
@@ -107,8 +107,8 @@ class DeclarativeContentCssConditionTrackerTest
void CreatePredicateImpl(const std::string& value,
std::unique_ptr<const ContentPredicate>* predicate) {
std::string error;
- *predicate = tracker_.CreatePredicate(
- nullptr, *base::test::ParseJsonDeprecated(value), &error);
+ *predicate =
+ tracker_.CreatePredicate(nullptr, base::test::ParseJson(value), &error);
EXPECT_EQ("", error);
ASSERT_TRUE(*predicate);
}
@@ -119,8 +119,8 @@ class DeclarativeContentCssConditionTrackerTest
TEST(DeclarativeContentCssPredicateTest, WrongCssDatatype) {
std::string error;
std::unique_ptr<DeclarativeContentCssPredicate> predicate =
- DeclarativeContentCssPredicate::Create(
- nullptr, *base::test::ParseJsonDeprecated("\"selector\""), &error);
+ DeclarativeContentCssPredicate::Create(nullptr, base::Value("selector"),
+ &error);
EXPECT_THAT(error, HasSubstr("invalid type"));
EXPECT_FALSE(predicate);
}
@@ -129,8 +129,7 @@ TEST(DeclarativeContentCssPredicateTest, CssPredicate) {
std::string error;
std::unique_ptr<DeclarativeContentCssPredicate> predicate =
DeclarativeContentCssPredicate::Create(
- nullptr, *base::test::ParseJsonDeprecated("[\"input\", \"a\"]"),
- &error);
+ nullptr, base::test::ParseJson("[\"input\", \"a\"]"), &error);
EXPECT_EQ("", error);
ASSERT_TRUE(predicate);
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc
index d8776afb347..cf7151f03ec 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc
@@ -13,7 +13,6 @@
#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/test/values_test_util.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/extensions/api/declarative_content/content_predicate_evaluator.h"
#include "chrome/browser/extensions/api/declarative_content/declarative_content_condition_tracker_test.h"
@@ -54,9 +53,7 @@ std::unique_ptr<DeclarativeContentIsBookmarkedPredicate> CreatePredicate(
std::string error;
std::unique_ptr<DeclarativeContentIsBookmarkedPredicate> predicate =
DeclarativeContentIsBookmarkedPredicate::Create(
- evaluator, extension,
- *base::test::ParseJsonDeprecated(is_bookmarked ? "true" : "false"),
- &error);
+ evaluator, extension, base::Value(is_bookmarked), &error);
EXPECT_EQ("", error);
EXPECT_TRUE(predicate);
EXPECT_EQ(is_bookmarked, predicate->is_bookmarked());
@@ -169,8 +166,7 @@ TEST(DeclarativeContentIsBookmarkedPredicateTest,
std::string error;
std::unique_ptr<DeclarativeContentIsBookmarkedPredicate> predicate =
DeclarativeContentIsBookmarkedPredicate::Create(
- nullptr, extension.get(), *base::test::ParseJsonDeprecated("true"),
- &error);
+ nullptr, extension.get(), base::Value(true), &error);
EXPECT_THAT(error, HasSubstr("requires 'bookmarks' permission"));
EXPECT_FALSE(predicate);
}
@@ -183,7 +179,7 @@ TEST(DeclarativeContentIsBookmarkedPredicateTest,
std::string error;
std::unique_ptr<DeclarativeContentIsBookmarkedPredicate> predicate =
DeclarativeContentIsBookmarkedPredicate::Create(
- nullptr, extension.get(), *base::test::ParseJsonDeprecated("[]"),
+ nullptr, extension.get(), base::Value(base::Value::Type::LIST),
&error);
EXPECT_THAT(error, HasSubstr("invalid type"));
EXPECT_FALSE(predicate);
diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc
new file mode 100644
index 00000000000..c054ff4fef0
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc
@@ -0,0 +1,309 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/declarative_net_request/action_tracker.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/test/simple_test_clock.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/time/time.h"
+#include "chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h"
+#include "chrome/browser/extensions/chrome_test_extension_loader.h"
+#include "extensions/browser/api/web_request/web_request_info.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_util.h"
+#include "extensions/common/api/declarative_net_request.h"
+#include "extensions/common/api/declarative_net_request/constants.h"
+#include "extensions/common/api/declarative_net_request/test_utils.h"
+#include "extensions/common/constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
+#include "url/gurl.h"
+
+namespace extensions {
+namespace declarative_net_request {
+
+namespace dnr_api = api::declarative_net_request;
+
+namespace {
+
+constexpr char kJSONRulesFilename[] = "rules_file.json";
+
+constexpr int64_t kNavigationId = 1;
+
+class ActionTrackerTest : public DNRTestBase {
+ public:
+ ActionTrackerTest() = default;
+ ActionTrackerTest(const ActionTrackerTest& other) = delete;
+ ActionTrackerTest& operator=(const ActionTrackerTest& other) = delete;
+
+ void SetUp() override {
+ DNRTestBase::SetUp();
+ action_tracker_ = std::make_unique<ActionTracker>(browser_context());
+ }
+
+ protected:
+ using RequestActionType = RequestAction::Type;
+
+ // Helper to load an extension. |flags| is a bitmask of ConfigFlag to
+ // configure the extension.
+ void LoadExtension(const std::string& extension_dirname, unsigned flags) {
+ base::FilePath extension_dir =
+ temp_dir().GetPath().AppendASCII(extension_dirname);
+
+ // Create extension directory.
+ ASSERT_TRUE(base::CreateDirectory(extension_dir));
+ TestRulesetInfo info = {kJSONRulesFilename, base::ListValue()};
+ WriteManifestAndRuleset(
+ extension_dir, info,
+ std::vector<std::string>({URLPattern::kAllUrlsPattern}), flags);
+
+ last_loaded_extension_ =
+ CreateExtensionLoader()->LoadExtension(extension_dir);
+ ASSERT_TRUE(last_loaded_extension_);
+
+ ExtensionRegistry::Get(browser_context())
+ ->AddEnabled(last_loaded_extension_);
+ }
+
+ // Helper to create a RequestAction for the given |extension_id|.
+ RequestAction CreateRequestAction(const ExtensionId& extension_id) {
+ return RequestAction(RequestActionType::BLOCK, kMinValidID,
+ kDefaultPriority, dnr_api::SOURCE_TYPE_MANIFEST,
+ extension_id);
+ }
+
+ // Returns renderer-initiated request params for the given |url|.
+ WebRequestInfoInitParams GetRequestParamsForURL(
+ base::StringPiece url,
+ blink::mojom::ResourceType type,
+ int tab_id) {
+ const int kRendererId = 1;
+ WebRequestInfoInitParams info;
+ info.url = GURL(url);
+ info.type = type;
+ info.render_process_id = kRendererId;
+ info.frame_data.tab_id = tab_id;
+
+ if (type == blink::mojom::ResourceType::kMainFrame) {
+ info.navigation_id = kNavigationId;
+ info.is_navigation_request = true;
+ }
+
+ return info;
+ }
+
+ const Extension* last_loaded_extension() const {
+ return last_loaded_extension_.get();
+ }
+
+ ActionTracker* action_tracker() { return action_tracker_.get(); }
+
+ private:
+ scoped_refptr<const Extension> last_loaded_extension_;
+ std::unique_ptr<ActionTracker> action_tracker_;
+};
+
+// Test that rules matched will be recorded for extensions with the
+// declarativeNetRequestFeedback or activeTab permission.
+TEST_P(ActionTrackerTest, GetMatchedRulesNoPermission) {
+ // Load an extension with the declarativeNetRequestFeedback permission.
+ ASSERT_NO_FATAL_FAILURE(LoadExtension(
+ "test_extension", ConfigFlag::kConfig_HasFeedbackPermission));
+ const Extension* extension_1 = last_loaded_extension();
+
+ // Load an extension without the declarativeNetRequestFeedback permission.
+ ASSERT_NO_FATAL_FAILURE(
+ LoadExtension("test_extension_2", ConfigFlag::kConfig_None));
+ const Extension* extension_2 = last_loaded_extension();
+
+ // Load an extension without the declarativeNetRequestFeedback permission but
+ // with the activeTab permission.
+ ASSERT_NO_FATAL_FAILURE(
+ LoadExtension("test_extension_3", ConfigFlag::kConfig_HasActiveTab));
+ const Extension* extension_3 = last_loaded_extension();
+
+ const int tab_id = 1;
+
+ // Record a rule match for a main-frame navigation request.
+ WebRequestInfo request_1(GetRequestParamsForURL(
+ "http://one.com", blink::mojom::ResourceType::kMainFrame, tab_id));
+
+ // Record a rule match for a non-navigation request.
+ WebRequestInfo request_2(GetRequestParamsForURL(
+ "http://one.com", blink::mojom::ResourceType::kSubResource, tab_id));
+
+ // Assume a rule is matched for |request_1| and |request_2| for all three
+ // extensions.
+ for (const Extension* extension : {extension_1, extension_2, extension_3}) {
+ action_tracker()->OnRuleMatched(CreateRequestAction(extension->id()),
+ request_1);
+ action_tracker()->OnRuleMatched(CreateRequestAction(extension->id()),
+ request_2);
+ }
+
+ // No need to trim non-active rules because all requests are from active tabs.
+ const bool trim_non_active_rules = false;
+
+ // For |extension_1|, one rule match should be recorded for |rules_tracked_|
+ // and one for |pending_navigation_actions_|.
+ EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest(
+ extension_1->id(), tab_id, trim_non_active_rules));
+ EXPECT_EQ(1, action_tracker()->GetPendingRuleCountForTest(extension_1->id(),
+ kNavigationId));
+
+ // Since |extension_2| does not have the feedback permission, no rule matches
+ // should be recorded.
+ EXPECT_EQ(0, action_tracker()->GetMatchedRuleCountForTest(
+ extension_2->id(), tab_id, trim_non_active_rules));
+ EXPECT_EQ(0, action_tracker()->GetPendingRuleCountForTest(extension_2->id(),
+ kNavigationId));
+
+ // While |extension_3| does not have the feedback permission, it does have the
+ // activeTab permission and therefore rule matches should be recorded.
+ EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest(
+ extension_3->id(), tab_id, trim_non_active_rules));
+ EXPECT_EQ(1, action_tracker()->GetPendingRuleCountForTest(extension_3->id(),
+ kNavigationId));
+
+ // Clean up the internal state of |action_tracker_|.
+ action_tracker()->ClearPendingNavigation(kNavigationId);
+ action_tracker()->ClearTabData(tab_id);
+}
+
+// Test that rules associated with a non-active tab past their lifetime will be
+// removed, and not returned by getMatchedRules
+TEST_P(ActionTrackerTest, GetMatchedRulesLifespan) {
+ base::SimpleTestClock clock_;
+ clock_.SetNow(base::Time::Now());
+ action_tracker()->SetClockForTests(&clock_);
+
+ // Load an extension with the declarativeNetRequestFeedback permission.
+ ASSERT_NO_FATAL_FAILURE(LoadExtension(
+ "test_extension", ConfigFlag::kConfig_HasFeedbackPermission));
+ const Extension* extension_1 = last_loaded_extension();
+
+ const int tab_id = 1;
+
+ // Record a rule match for a non-navigation request.
+ WebRequestInfo request_1(GetRequestParamsForURL(
+ "http://one.com", blink::mojom::ResourceType::kSubResource, tab_id));
+ action_tracker()->OnRuleMatched(CreateRequestAction(extension_1->id()),
+ request_1);
+
+ // Half life of a matched rule associated with a non-active tab, with 50ms
+ // added.
+ base::TimeDelta half_life = (ActionTracker::kNonActiveTabRuleLifespan / 2) +
+ base::TimeDelta::FromMilliseconds(50);
+
+ // Advance the clock by half of the lifespan of a matched rule for the unknown
+ // tab ID.
+ clock_.Advance(half_life);
+
+ // Record another rule match.
+ action_tracker()->OnRuleMatched(CreateRequestAction(extension_1->id()),
+ request_1);
+
+ // Close the tab with |tab_id|.
+ action_tracker()->ClearTabData(tab_id);
+
+ // Since some requests are not from an active tab, and the rule count for the
+ // unknown tab will be queried, we should emulate the getMatchedRules API call
+ // and trim non-active rules.
+ const bool trim_non_active_rules = true;
+
+ // Both rules should now be attributed to the unknown tab ID since the tab in
+ // which they were matched is no longer active.
+ EXPECT_EQ(2, action_tracker()->GetMatchedRuleCountForTest(
+ extension_1->id(), extension_misc::kUnknownTabId,
+ trim_non_active_rules));
+
+ // Advance the clock so one of the matched rules will be older than the
+ // lifespan for rules not associated with an active tab.
+ clock_.Advance(half_life);
+
+ // Rules not attributed to an active tab have a fixed lifespan,
+ // so only one rule should be returned.
+ EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest(
+ extension_1->id(), extension_misc::kUnknownTabId,
+ trim_non_active_rules));
+
+ // Advance the clock so both rules will be older than the matched rule
+ // lifespan.
+ clock_.Advance(ActionTracker::kNonActiveTabRuleLifespan);
+
+ // Since both rules are older than the lifespan, they should be cleared and no
+ // rules are returned.
+ EXPECT_EQ(0, action_tracker()->GetMatchedRuleCountForTest(
+ extension_1->id(), extension_misc::kUnknownTabId,
+ trim_non_active_rules));
+
+ action_tracker()->SetClockForTests(nullptr);
+}
+
+// Test that matched rules not associated with an active tab will be
+// automatically cleaned up by a recurring task.
+TEST_P(ActionTrackerTest, RulesClearedOnTimer) {
+ scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner =
+ base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+ base::Time::Now(), base::TimeTicks::Now());
+ // Mock the clock and the timer. Clock is used to check whether the rule
+ // should be removed and the timer is used to set up a recurrent task to clean
+ // up old rules.
+ action_tracker()->SetClockForTests(mock_time_task_runner->GetMockClock());
+
+ auto mock_trim_timer = std::make_unique<base::RetainingOneShotTimer>(
+ mock_time_task_runner->GetMockTickClock());
+
+ mock_trim_timer->SetTaskRunner(mock_time_task_runner);
+ action_tracker()->SetTimerForTest(std::move(mock_trim_timer));
+
+ // Load an extension with the declarativeNetRequestFeedback permission.
+ ASSERT_NO_FATAL_FAILURE(LoadExtension(
+ "test_extension", ConfigFlag::kConfig_HasFeedbackPermission));
+ const Extension* extension_1 = last_loaded_extension();
+
+ // Record a rule match for |extension_1| for the unknown tab.
+ WebRequestInfo request_1(GetRequestParamsForURL(
+ "http://one.com", blink::mojom::ResourceType::kSubResource,
+ extension_misc::kUnknownTabId));
+ action_tracker()->OnRuleMatched(CreateRequestAction(extension_1->id()),
+ request_1);
+
+ // Since this test explicitly tests that the recurring task will remove
+ // non-active rules, ensure that calls to GetmatchedRuleCountForTest will not
+ // remove non-active rules.
+ const bool trim_non_active_rules = false;
+
+ // Verify that the rule has been matched.
+ EXPECT_EQ(1, action_tracker()->GetMatchedRuleCountForTest(
+ extension_1->id(), extension_misc::kUnknownTabId,
+ trim_non_active_rules));
+
+ // Advance the clock by more than the lifespan of a rule through
+ // |mock_time_task_runner|.
+ mock_time_task_runner->FastForwardBy(
+ ActionTracker::kNonActiveTabRuleLifespan +
+ base::TimeDelta::FromSeconds(1));
+
+ // Verify that the rule has been cleared by the recurring task.
+ EXPECT_EQ(0, action_tracker()->GetMatchedRuleCountForTest(
+ extension_1->id(), extension_misc::kUnknownTabId,
+ trim_non_active_rules));
+
+ // Reset the ActionTracker's state.
+ action_tracker()->SetClockForTests(nullptr);
+ action_tracker()->SetTimerForTest(
+ std::make_unique<base::RetainingOneShotTimer>());
+}
+
+INSTANTIATE_TEST_SUITE_P(All,
+ ActionTrackerTest,
+ ::testing::Values(ExtensionLoadType::PACKED,
+ ExtensionLoadType::UNPACKED));
+
+} // namespace
+} // namespace declarative_net_request
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc
index 7aead9b18bd..4ac0fec5fe2 100644
--- a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc
@@ -47,14 +47,6 @@ class DeclarativeNetRequestAPItest : public extensions::ExtensionApiTest {
DISALLOW_COPY_AND_ASSIGN(DeclarativeNetRequestAPItest);
};
-IN_PROC_BROWSER_TEST_F(DeclarativeNetRequestAPItest, PageAllowingAPI) {
- ASSERT_TRUE(RunExtensionTest("page_allowing_api")) << message_;
-}
-
-IN_PROC_BROWSER_TEST_F(DeclarativeNetRequestAPItest, ExtensionWithNoRuleset) {
- ASSERT_TRUE(RunExtensionTest("extension_with_no_ruleset")) << message_;
-}
-
IN_PROC_BROWSER_TEST_F(DeclarativeNetRequestAPItest, DynamicRules) {
ASSERT_TRUE(RunExtensionTest("dynamic_rules")) << message_;
}
@@ -70,4 +62,8 @@ IN_PROC_BROWSER_TEST_F(DeclarativeNetRequestAPItest,
ASSERT_TRUE(RunExtensionTest("on_rules_matched_debug")) << message_;
}
+IN_PROC_BROWSER_TEST_F(DeclarativeNetRequestAPItest, GetMatchedRules) {
+ ASSERT_TRUE(RunExtensionTest("get_matched_rules")) << message_;
+}
+
} // namespace
diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
index a07adf5cd77..214ce9ff122 100644
--- a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -21,14 +21,19 @@
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
+#include "base/sequence_checker.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/simple_test_clock.h"
#include "base/threading/thread_restrictions.h"
+#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "chrome/browser/extensions/active_tab_permission_granter.h"
#include "chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
@@ -38,6 +43,7 @@
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/load_error_reporter.h"
#include "chrome/browser/extensions/scripting_permissions_modifier.h"
+#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
#include "chrome/browser/profiles/profile.h"
@@ -62,7 +68,9 @@
#include "content/public/test/simple_url_loader_test_helper.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
+#include "extensions/browser/api/declarative_net_request/action_tracker.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
+#include "extensions/browser/api/declarative_net_request/declarative_net_request_api.h"
#include "extensions/browser/api/declarative_net_request/rules_monitor_service.h"
#include "extensions/browser/api/declarative_net_request/ruleset_manager.h"
#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
@@ -107,9 +115,9 @@ namespace extensions {
namespace declarative_net_request {
namespace {
+namespace dnr_api = api::declarative_net_request;
+
constexpr char kJSONRulesFilename[] = "rules_file.json";
-const base::FilePath::CharType kJSONRulesetFilepath[] =
- FILE_PATH_LITERAL("rules_file.json");
// Returns true if |window.scriptExecuted| is true for the given frame.
bool WasFrameWithScriptLoaded(content::RenderFrameHost* rfh) {
@@ -125,11 +133,14 @@ bool WasFrameWithScriptLoaded(content::RenderFrameHost* rfh) {
// Used to monitor requests that reach the RulesetManager.
class URLRequestMonitor : public RulesetManager::TestObserver {
public:
- explicit URLRequestMonitor(GURL url) : url_(std::move(url)) {}
+ explicit URLRequestMonitor(RulesetManager* manager, GURL url)
+ : manager_(manager), url_(std::move(url)) {
+ manager_->SetObserverForTest(this);
+ }
+ ~URLRequestMonitor() override { manager_->SetObserverForTest(nullptr); }
- // This is called from both the UI and IO thread. Clients should ensure
- // there's no race.
bool GetAndResetRequestSeen(bool new_val) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool return_val = request_seen_;
request_seen_ = new_val;
return return_val;
@@ -139,12 +150,15 @@ class URLRequestMonitor : public RulesetManager::TestObserver {
// RulesetManager::TestObserver implementation.
void OnEvaluateRequest(const WebRequestInfo& request,
bool is_incognito_context) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (request.url == url_)
GetAndResetRequestSeen(true);
}
+ RulesetManager* const manager_;
GURL url_;
bool request_seen_ = false;
+ SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(URLRequestMonitor);
};
@@ -153,76 +167,46 @@ class URLRequestMonitor : public RulesetManager::TestObserver {
// a certain count.
class RulesetCountWaiter : public RulesetManager::TestObserver {
public:
- RulesetCountWaiter() = default;
+ explicit RulesetCountWaiter(RulesetManager* manager)
+ : manager_(manager), current_count_(manager_->GetMatcherCountForTest()) {
+ manager_->SetObserverForTest(this);
+ }
+ ~RulesetCountWaiter() override { manager_->SetObserverForTest(nullptr); }
void WaitForRulesetCount(size_t count) {
- {
- base::AutoLock lock(lock_);
- ASSERT_FALSE(expected_count_);
- if (current_count_ == count)
- return;
- expected_count_ = count;
- run_loop_ = std::make_unique<base::RunLoop>();
- }
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ ASSERT_FALSE(expected_count_);
+ if (current_count_ == count)
+ return;
+ expected_count_ = count;
+ run_loop_ = std::make_unique<base::RunLoop>();
run_loop_->Run();
}
private:
// RulesetManager::TestObserver implementation.
void OnRulesetCountChanged(size_t count) override {
- base::AutoLock lock(lock_);
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
current_count_ = count;
if (expected_count_ != count)
return;
ASSERT_TRUE(run_loop_.get());
- // The run-loop has either started or a task on the UI thread to start it is
- // underway. RunLoop::Quit is thread-safe and should post a task to the UI
- // thread to quit the run-loop.
run_loop_->Quit();
expected_count_.reset();
}
- // Accessed on both the UI and IO threads. Access is synchronized using
- // |lock_|.
+ RulesetManager* const manager_;
size_t current_count_ = 0;
base::Optional<size_t> expected_count_;
std::unique_ptr<base::RunLoop> run_loop_;
-
- base::Lock lock_;
+ SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(RulesetCountWaiter);
};
-// Helper to set (and reset on destruction) the given
-// RulesetManager::TestObserver on the IO thread. Lifetime of |observer| should
-// be managed by clients.
-class ScopedRulesetManagerTestObserver {
- public:
- ScopedRulesetManagerTestObserver(RulesetManager::TestObserver* observer,
- content::BrowserContext* browser_context)
- : browser_context_(browser_context) {
- SetRulesetManagerTestObserver(observer);
- }
-
- ~ScopedRulesetManagerTestObserver() {
- SetRulesetManagerTestObserver(nullptr);
- }
-
- private:
- void SetRulesetManagerTestObserver(RulesetManager::TestObserver* observer) {
- declarative_net_request::RulesMonitorService::Get(browser_context_)
- ->ruleset_manager()
- ->SetObserverForTest(observer);
- }
-
- content::BrowserContext* browser_context_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedRulesetManagerTestObserver);
-};
-
// Helper to wait for warnings thrown for a given extension.
class WarningServiceObserver : public WarningService::Observer {
public:
@@ -324,6 +308,10 @@ class DeclarativeNetRequestBrowserTest
->GetPageType();
}
+ RulesetManager* ruleset_manager() {
+ return RulesMonitorService::Get(profile())->ruleset_manager();
+ }
+
content::PageType GetPageType() const { return GetPageType(browser()); }
std::string GetPageBody() const {
@@ -335,10 +323,7 @@ class DeclarativeNetRequestBrowserTest
return result;
}
- // Sets whether the extension should have a background script.
- void set_has_background_script(bool has_background_script) {
- has_background_script_ = has_background_script;
- }
+ void set_config_flags(unsigned flags) { flags_ = flags; }
// Loads an extension with the given declarative |rules| in the given
// |directory|. Generates a fatal failure if the extension failed to load.
@@ -353,9 +338,8 @@ class DeclarativeNetRequestBrowserTest
base::FilePath extension_dir = temp_dir_.GetPath().AppendASCII(directory);
EXPECT_TRUE(base::CreateDirectory(extension_dir));
- WriteManifestAndRuleset(extension_dir, kJSONRulesetFilepath,
- kJSONRulesFilename, rules, hosts,
- has_background_script_);
+ TestRulesetInfo info = {kJSONRulesFilename, std::move(*ToListValue(rules))};
+ WriteManifestAndRuleset(extension_dir, info, hosts, flags_);
background_page_ready_listener_->Reset();
const Extension* extension = nullptr;
@@ -387,10 +371,10 @@ class DeclarativeNetRequestBrowserTest
"Extensions.DeclarativeNetRequest.LoadRulesetResult",
RulesetMatcher::kLoadSuccess /*sample*/, 1 /*count*/);
- EXPECT_TRUE(HasValidIndexedRuleset(*extension, profile()));
+ EXPECT_TRUE(AreAllIndexedStaticRulesetsValid(*extension, profile()));
// Wait for the background page to load if needed.
- if (has_background_script_)
+ if (flags_ & kConfig_HasBackgroundScript)
WaitForBackgroundScriptToLoad(extension->id());
// Ensure no load errors were reported.
@@ -414,47 +398,6 @@ class DeclarativeNetRequestBrowserTest
return !WasFrameWithScriptLoaded(GetMainFrame());
}
- void AddAllowedPages(const ExtensionId& extension_id,
- const std::vector<std::string>& patterns) {
- UpdateAllowedPages(extension_id, patterns, "addAllowedPages");
- }
-
- void RemoveAllowedPages(const ExtensionId& extension_id,
- const std::vector<std::string>& patterns) {
- UpdateAllowedPages(extension_id, patterns, "removeAllowedPages");
- }
-
- // Verifies that the result of getAllowedPages call is the same as
- // |expected_patterns|.
- void VerifyGetAllowedPages(const ExtensionId& extension_id,
- const std::set<std::string>& expected_patterns) {
- static constexpr char kScript[] = R"(
- chrome.declarativeNetRequest.getAllowedPages(function(patterns) {
- window.domAutomationController.send(chrome.runtime.lastError
- ? 'error'
- : JSON.stringify(patterns));
- });
- )";
-
- const std::string result =
- ExecuteScriptInBackgroundPage(extension_id, kScript);
- ASSERT_NE("error", result);
-
- // Parse |result| as a list and deserialize it to a set of strings.
- std::unique_ptr<base::Value> value =
- JSONStringValueDeserializer(result).Deserialize(
- nullptr /*error_code*/, nullptr /*error_message*/);
- ASSERT_TRUE(value);
- ASSERT_TRUE(value->is_list());
- std::set<std::string> patterns;
- for (const auto& pattern_value : value->GetList()) {
- ASSERT_TRUE(pattern_value.is_string());
- patterns.insert(pattern_value.GetString());
- }
-
- EXPECT_EQ(expected_patterns, patterns);
- }
-
void AddDynamicRules(const ExtensionId& extension_id,
const std::vector<TestRule>& rules) {
static constexpr char kScript[] = R"(
@@ -526,6 +469,76 @@ class DeclarativeNetRequestBrowserTest
navigation_observer.Wait();
}
+ // Calls getMatchedRules for |extension_id| and optionally, the |tab_id| and
+ // returns comma separated pairs of rule_id and tab_id, with each pair
+ // delimited by '|'. Matched Rules are sorted in ascending order by ruleId,
+ // and ties are resolved by the tabId (in ascending order.)
+ // E.g. "<rule_1>,<tab_1>|<rule_2>,<tab_2>|<rule_3>,<tab_3>"
+ std::string GetRuleAndTabIdsMatched(const ExtensionId& extension_id,
+ base::Optional<int> tab_id) {
+ const char kGetMatchedRulesScript[] = R"(
+ chrome.declarativeNetRequest.getMatchedRules({%s}, (rules) => {
+ // |ruleAndTabIds| is a list of `${ruleId},${tabId}`
+ var ruleAndTabIds = rules.rulesMatchedInfo.map(rule => {
+ return [rule.rule.ruleId, rule.tabId];
+ }).sort((a, b) => {
+ // Sort ascending by rule ID, and resolve ties by tab ID.
+ const idDiff = a.ruleId - b.ruleId;
+ return (idDiff != 0) ? idDiff : a.tabId - b.tabId;
+ }).map(ruleAndTabId => ruleAndTabId.join());
+
+ // Join the comma separated (ruleId,tabId) pairs with '|'.
+ window.domAutomationController.send(ruleAndTabIds.join('|'));
+ });
+ )";
+
+ std::string tab_id_param =
+ tab_id ? base::StringPrintf("tabId: %d", *tab_id) : "";
+ return ExecuteScriptInBackgroundPage(
+ extension_id,
+ base::StringPrintf(kGetMatchedRulesScript, tab_id_param.c_str()),
+ browsertest_util::ScriptUserActivation::kDontActivate);
+ }
+
+ // Calls getMatchedRules for |extension_id| and optionally, |tab_id| and
+ // |timestamp|. Returns the matched rule count for rules more recent than
+ // |timestamp| if specified, and are associated with the tab specified by
+ // |tab_id| or all tabs if |tab_id| is not specified. |script_user_activation|
+ // specifies if the call should be treated as a user gesture. Returns any API
+ // error if the call fails.
+ std::string GetMatchedRuleCount(
+ const ExtensionId& extension_id,
+ base::Optional<int> tab_id,
+ base::Optional<base::Time> timestamp,
+ browsertest_util::ScriptUserActivation script_user_activation =
+ browsertest_util::ScriptUserActivation::kDontActivate) {
+ const char kGetMatchedRulesScript[] = R"(
+ chrome.declarativeNetRequest.getMatchedRules(%s, (rules) => {
+ if (chrome.runtime.lastError) {
+ window.domAutomationController.send(chrome.runtime.lastError.message);
+ return;
+ }
+
+ var rule_count = rules.rulesMatchedInfo.length;
+ window.domAutomationController.send(rule_count.toString());
+ });
+ )";
+
+ double timestamp_in_js =
+ timestamp.has_value() ? timestamp->ToJsTimeIgnoringNull() : 0;
+
+ std::string param_string =
+ tab_id.has_value()
+ ? base::StringPrintf("{tabId: %d, minTimeStamp: %f}", *tab_id,
+ timestamp_in_js)
+ : base::StringPrintf("{minTimeStamp: %f}", timestamp_in_js);
+
+ return ExecuteScriptInBackgroundPage(
+ extension_id,
+ base::StringPrintf(kGetMatchedRulesScript, param_string.c_str()),
+ script_user_activation);
+ }
+
std::set<GURL> GetAndResetRequestsToServer() {
base::AutoLock lock(requests_to_server_lock_);
std::set<GURL> results = requests_to_server_;
@@ -541,30 +554,8 @@ class DeclarativeNetRequestBrowserTest
requests_to_server_.insert(request.GetURL());
}
- void UpdateAllowedPages(const ExtensionId& extension_id,
- const std::vector<std::string>& patterns,
- const std::string& function_name) {
- static constexpr char kScript[] = R"(
- chrome.declarativeNetRequest.%s(%s, function() {
- window.domAutomationController.send(chrome.runtime.lastError
- ? 'error'
- : 'success');
- });
- )";
-
- // Serialize |patterns| to JSON.
- std::unique_ptr<base::ListValue> list = ToListValue(patterns);
- std::string json_string;
- ASSERT_TRUE(JSONStringValueSerializer(&json_string).Serialize(*list));
-
- EXPECT_EQ("success", ExecuteScriptInBackgroundPage(
- extension_id,
- base::StringPrintf(kScript, function_name.c_str(),
- json_string.c_str())));
- }
-
base::ScopedTempDir temp_dir_;
- bool has_background_script_ = false;
+ unsigned flags_ = ConfigFlag::kConfig_None;
std::unique_ptr<ExtensionTestMessageListener> background_page_ready_listener_;
// Requests observed by the EmbeddedTestServer. This is accessed on both the
@@ -933,6 +924,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowBlock) {
rule.id = id++;
rule.condition->url_filter = base::StringPrintf("num=%d|", i);
rule.condition->resource_types = std::vector<std::string>({"main_frame"});
+ rule.priority = 1;
rules.push_back(rule);
}
@@ -943,6 +935,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowBlock) {
rule.condition->url_filter = base::StringPrintf("num=%d|", i);
rule.condition->resource_types = std::vector<std::string>({"main_frame"});
rule.action->type = std::string("allow");
+ rule.priority = 2;
rules.push_back(rule);
}
@@ -967,7 +960,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowBlock) {
// Tests allowing rules for redirects.
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowRedirect) {
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
const GURL static_redirect_url = embedded_test_server()->GetURL(
"example.com", base::StringPrintf("/pages_with_script/page2.html"));
@@ -979,20 +972,21 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowRedirect) {
struct {
std::string url_filter;
int id;
+ int priority;
std::string action_type;
base::Optional<std::string> redirect_url;
} rules_data[] = {
- {"google.com", 1, "redirect", static_redirect_url.spec()},
- {"num=1|", 2, "allow", base::nullopt},
- {"1|", 3, "redirect", dynamic_redirect_url.spec()},
- {"num=21|", 4, "allow", base::nullopt},
+ {"google.com", 1, 1, "redirect", static_redirect_url.spec()},
+ {"num=1|", 2, 3, "allow", base::nullopt},
+ {"1|", 3, 4, "redirect", dynamic_redirect_url.spec()},
+ {"num=3|", 4, 2, "allow", base::nullopt},
};
std::vector<TestRule> rules;
for (const auto& rule_data : rules_data) {
TestRule rule = CreateGenericRule();
rule.id = rule_data.id;
- rule.priority = kMinValidPriority;
+ rule.priority = rule_data.priority;
rule.condition->url_filter = rule_data.url_filter;
rule.condition->resource_types = std::vector<std::string>({"main_frame"});
rule.action->type = rule_data.action_type;
@@ -1024,6 +1018,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowRedirect) {
} static_test_cases[] = {
{get_url(0), static_redirect_url},
{get_url(1), get_url(1)},
+ {get_url(3), static_redirect_url},
};
for (const auto& test_case : static_test_cases) {
@@ -1037,18 +1032,18 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowRedirect) {
EXPECT_EQ(test_case.expected_final_url, final_url);
}
- // Now add dynamic rules. These should override static rules in priority.
+ // Now add dynamic rules. These should share the priority space with static
+ // rules.
const ExtensionId& extension_id = last_loaded_extension_id();
ASSERT_NO_FATAL_FAILURE(AddDynamicRules(extension_id, dynamic_rules));
- // Test that rules follow the priority of: dynamic allow > dynamic redirect >
- // static allow > static redirect.
+ // Test that dynamic and static rules are in the same priority space.
struct {
GURL initial_url;
GURL expected_final_url;
} dynamic_test_cases[] = {
{get_url(1), dynamic_redirect_url},
- {get_url(21), get_url(21)},
+ {get_url(3), get_url(3)},
};
for (const auto& test_case : dynamic_test_cases) {
@@ -1067,7 +1062,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowRedirect) {
// enabled.
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
Enable_Disable_Reload_Uninstall) {
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
// Block all main frame requests to "index.html".
TestRule rule = CreateGenericRule();
@@ -1245,15 +1240,16 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, BlockAndRedirect) {
struct {
std::string url_filter;
int id;
+ int priority;
std::string action_type;
base::Optional<std::string> redirect_url;
} rules_data[] = {
- {"example.com", 1, "redirect", get_url_for_host("yahoo.com")},
- {"yahoo.com", 2, "redirect", get_url_for_host("google.com")},
- {"abc.com", 3, "redirect", get_url_for_host("def.com")},
- {"def.com", 4, "block", base::nullopt},
- {"def.com", 5, "redirect", get_url_for_host("xyz.com")},
- {"ghi*", 6, "redirect", get_url_for_host("ghijk.com")},
+ {"example.com", 1, 1, "redirect", get_url_for_host("yahoo.com")},
+ {"yahoo.com", 2, 1, "redirect", get_url_for_host("google.com")},
+ {"abc.com", 3, 1, "redirect", get_url_for_host("def.com")},
+ {"def.com", 4, 2, "block", base::nullopt},
+ {"def.com", 5, 1, "redirect", get_url_for_host("xyz.com")},
+ {"ghi*", 6, 1, "redirect", get_url_for_host("ghijk.com")},
};
// Load the extension.
@@ -1262,7 +1258,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, BlockAndRedirect) {
TestRule rule = CreateGenericRule();
rule.condition->url_filter = rule_data.url_filter;
rule.id = rule_data.id;
- rule.priority = kMinValidPriority;
+ rule.priority = rule_data.priority;
rule.condition->resource_types = std::vector<std::string>({"main_frame"});
rule.action->type = rule_data.action_type;
rule.action->redirect.emplace();
@@ -1411,7 +1407,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, UpgradeRules) {
// TODO(crbug.com/985104): Add a https test server to display https pages
// so this redirect rule can be removed.
{"|https*", 3, 6, "redirect", google_url.spec()},
- {"exact.com", 4, 1, "block", base::nullopt},
+ {"exact.com", 4, 5, "block", base::nullopt},
};
// Load the extension.
@@ -1564,7 +1560,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
// directory won't be persisted across browser restarts.
ASSERT_EQ(ExtensionLoadType::PACKED, GetParam());
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
// Block all main frame requests to "index.html".
TestRule rule = CreateGenericRule();
@@ -1606,8 +1602,8 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, RendererCacheCleared) {
// Set-up an observer for RulesetMatcher to monitor requests to
// script.js.
URLRequestMonitor script_monitor(
+ ruleset_manager(),
embedded_test_server()->GetURL("example.com", "/cached/script.js"));
- ScopedRulesetManagerTestObserver scoped_observer(&script_monitor, profile());
GURL url = embedded_test_server()->GetURL(
"example.com", "/cached/page_with_cacheable_script.html");
@@ -1730,233 +1726,6 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
EXPECT_EQ(content::PAGE_TYPE_NORMAL, GetPageType());
}
-// Tests the page allowing API.
-IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
- PRE_PageAllowingAPI_PersistedAcrossSessions) {
- // This is not tested for unpacked extensions since the unpacked extension
- // directory won't be persisted across browser sessions.
- ASSERT_EQ(ExtensionLoadType::PACKED, GetParam());
-
- set_has_background_script(true);
- LoadExtensionWithRules({});
-
- const Extension* dnr_extension = extension_registry()->GetExtensionById(
- last_loaded_extension_id(), extensions::ExtensionRegistry::ENABLED);
- ASSERT_TRUE(dnr_extension);
- EXPECT_EQ("Test extension", dnr_extension->name());
-
- constexpr char kGoogleDotCom[] = "https://www.google.com/";
-
- // Allow |kGoogleDotCom|.
- AddAllowedPages(dnr_extension->id(), {kGoogleDotCom});
-
- // Ensure that the page was allowed.
- VerifyGetAllowedPages(dnr_extension->id(), {kGoogleDotCom});
-}
-
-// Tests that the pages allowed using the page allowing API are
-// persisted across browser sessions.
-IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
- PageAllowingAPI_PersistedAcrossSessions) {
- // This is not tested for unpacked extensions since the unpacked extension
- // directory won't be persisted across browser sessions.
- ASSERT_EQ(ExtensionLoadType::PACKED, GetParam());
-
- // Retrieve the extension installed in the previous browser session.
- ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
- const Extension* dnr_extension = nullptr;
- for (const scoped_refptr<const Extension>& extension :
- registry->enabled_extensions()) {
- if (extension->name() == "Test extension") {
- dnr_extension = extension.get();
- break;
- }
- }
- ASSERT_TRUE(dnr_extension);
-
- // Ensure the background page is ready before dispatching the script to it.
- WaitForBackgroundScriptToLoad(dnr_extension->id());
-
- constexpr char kGoogleDotCom[] = "https://www.google.com/";
-
- VerifyGetAllowedPages(dnr_extension->id(), {kGoogleDotCom});
-
- // Remove |kGoogleDotCom| from the set of allowed pages.
- RemoveAllowedPages(dnr_extension->id(), {kGoogleDotCom});
-
- VerifyGetAllowedPages(dnr_extension->id(), {});
-}
-
-// Tests that the page allowing API performs pattern matching correctly.
-IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
- PageAllowingAPI_Patterns) {
- // Load an extension which blocks requests to "script.js".
- set_has_background_script(true);
- std::vector<TestRule> rules;
- TestRule rule = CreateGenericRule();
- rule.condition->url_filter = std::string("script.js");
- rules.push_back(rule);
- ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(rules));
-
- // We'll be allowing these patterns subsequently.
- const std::vector<std::string> allowed_page_patterns = {
- "http://google.com:*/pages_with_script/page*.html",
- "http://*/*index.html",
- "http://example.com:*/pages_with_script/page2.html"};
-
- struct TestCase {
- std::string hostname;
- std::string path;
- bool expect_script_allowed_with_rules;
- } test_cases[] = {
- {"yahoo.com", "/pages_with_script/page.html", false},
- {"yahoo.com", "/pages_with_script/index.html", true},
- {"example.com", "/pages_with_script/page.html", false},
- {"example.com", "/pages_with_script/page2.html", true},
- {"google.com", "/pages_with_script/page.html", true},
- {"google.com", "/pages_with_script/page2.html", true},
- };
-
- const GURL script_url =
- embedded_test_server()->GetURL("/pages_with_script/script.js");
- auto verify_script_load = [this, script_url](bool expect_script_load) {
- // The page should have loaded correctly.
- EXPECT_EQ(content::PAGE_TYPE_NORMAL, GetPageType());
- EXPECT_EQ(expect_script_load, WasFrameWithScriptLoaded(GetMainFrame()));
-
- // The EmbeddedTestServer sees requests after the hostname has been
- // resolved.
- bool did_see_script_request =
- base::Contains(GetAndResetRequestsToServer(), script_url);
- EXPECT_EQ(expect_script_load, did_see_script_request);
- };
-
- // "script.js" should have been blocked for all pages initially.
- for (const auto& test_case : test_cases) {
- GURL url =
- embedded_test_server()->GetURL(test_case.hostname, test_case.path);
- SCOPED_TRACE(base::StringPrintf("Testing %s with no page allowing rules",
- url.spec().c_str()));
-
- ui_test_utils::NavigateToURL(browser(), url);
-
- verify_script_load(false);
- }
-
- // Now allow |allowed_page_patterns| and ensure the test expectations
- // are met.
- AddAllowedPages(last_loaded_extension_id(), allowed_page_patterns);
- for (const auto& test_case : test_cases) {
- GURL url =
- embedded_test_server()->GetURL(test_case.hostname, test_case.path);
- SCOPED_TRACE(base::StringPrintf("Testing %s with page allowing rules",
- url.spec().c_str()));
-
- ui_test_utils::NavigateToURL(browser(), url);
-
- verify_script_load(test_case.expect_script_allowed_with_rules);
- }
-
- // Now remove the |allowed_page_patterns| and ensure that all requests to
- // "script.js" are blocked again.
- RemoveAllowedPages(last_loaded_extension_id(), allowed_page_patterns);
- for (const auto& test_case : test_cases) {
- GURL url =
- embedded_test_server()->GetURL(test_case.hostname, test_case.path);
- SCOPED_TRACE(base::StringPrintf(
- "Testing %s with all page allowing rules removed", url.spec().c_str()));
-
- ui_test_utils::NavigateToURL(browser(), url);
-
- verify_script_load(false);
- }
-}
-
-// Tests the page allowing API for subresource requests.
-IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
- PageAllowingAPI_Resources) {
- // Load an extension which blocks all requests.
- set_has_background_script(true);
- std::vector<TestRule> rules;
-
- // This blocks all subresource requests. By default the main-frame resource
- // type is excluded.
- TestRule rule = CreateGenericRule();
- rule.id = kMinValidID;
- rule.condition->url_filter = std::string("*");
- rules.push_back(rule);
-
- // Also block main frame requests.
- rule.id = kMinValidID + 1;
- rule.condition->resource_types = std::vector<std::string>({"main_frame"});
- rules.push_back(rule);
-
- ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(rules));
-
- const GURL url = embedded_test_server()->GetURL("/allowing_api.html");
-
- auto verify_page_load = [this](bool expect_load) {
- EXPECT_EQ(expect_load, WasFrameWithScriptLoaded(GetMainFrame()));
- EXPECT_EQ(
- expect_load ? content::PAGE_TYPE_NORMAL : content::PAGE_TYPE_ERROR,
- GetPageType());
-
- // We will be loading "allowing_api.html" for the test. The following
- // lists the set of requests we expect to see if the page is loaded.
- static const std::vector<std::string> page_resources_path = {
- // Main frame request.
- "/allowing_api.html",
-
- // Main frame subrources.
- "/subresources/style.css", "/subresources/script.js",
- "/subresources/image.png", "/subresources/ping.mp3",
- "/child_frame_with_subresources.html",
-
- // Child frame subresources.
- "/iframe_subresources/style.css", "/iframe_subresources/script.js",
- "/iframe_subresources/image.png", "/iframe_subresources/ping.mp3",
- "/iframe_subresources/subframe.html",
- };
-
- const std::set<GURL> requests_seen = GetAndResetRequestsToServer();
-
- for (const auto& path : page_resources_path) {
- GURL expected_request_url = embedded_test_server()->GetURL(path);
-
- // Request to |expected_requested_url| should be seen by the server iff we
- // expect the page to load.
- if (expect_load) {
- EXPECT_TRUE(base::Contains(requests_seen, expected_request_url))
- << expected_request_url.spec()
- << " was not requested from the server.";
- } else {
- EXPECT_FALSE(base::Contains(requests_seen, expected_request_url))
- << expected_request_url.spec() << " request seen unexpectedly.";
- }
- }
- };
-
- // Initially the request for the page should be blocked. No request should
- // reach the server.
- ui_test_utils::NavigateToURL(browser(), url);
- verify_page_load(false /*expect_load*/);
-
- // Next we allow |url|. All requests with |url| as the top level frame
- // should be allowed.
- AddAllowedPages(last_loaded_extension_id(), {url.spec()});
-
- // Ensure that no requests made by the page load are blocked.
- ui_test_utils::NavigateToURL(browser(), url);
- verify_page_load(true /*expect_load*/);
-
- // Remove |url| from allowed pages.
- RemoveAllowedPages(last_loaded_extension_id(), {url.spec()});
-
- // Ensure that requests are blocked.
- ui_test_utils::NavigateToURL(browser(), url);
- verify_page_load(false /*expect_load*/);
-}
-
// Ensures that any <img> elements blocked by the API are collapsed.
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, ImageCollapsed) {
// Loads a page with an image and returns whether the image was collapsed.
@@ -2061,11 +1830,9 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
CorruptedIndexedRuleset) {
// Set-up an observer for RulesetMatcher to monitor the number of extension
// rulesets.
- RulesetCountWaiter ruleset_count_waiter;
- ScopedRulesetManagerTestObserver scoped_observer(&ruleset_count_waiter,
- profile());
+ RulesetCountWaiter ruleset_count_waiter(ruleset_manager());
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
// Load an extension which blocks all main-frame requests to "google.com".
TestRule rule = CreateGenericRule();
@@ -2089,7 +1856,9 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
const Extension* extension = extension_registry()->GetExtensionById(
extension_id, ExtensionRegistry::ENABLED);
- RulesetSource static_source = RulesetSource::CreateStatic(*extension);
+ std::vector<RulesetSource> static_sources =
+ RulesetSource::CreateStatic(*extension);
+ ASSERT_EQ(1u, static_sources.size());
RulesetSource dynamic_source =
RulesetSource::CreateDynamic(profile(), *extension);
@@ -2133,7 +1902,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
// Test static ruleset re-indexing.
{
SCOPED_TRACE("Static ruleset corruption");
- corrupt_file_for_checksum_mismatch(static_source.indexed_path());
+ corrupt_file_for_checksum_mismatch(static_sources[0].indexed_path());
base::HistogramTester tester;
test_extension_works_after_reload();
@@ -2180,7 +1949,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
{
SCOPED_TRACE("Static and dynamic ruleset corruption");
corrupt_file_for_checksum_mismatch(dynamic_source.indexed_path());
- corrupt_file_for_checksum_mismatch(static_source.indexed_path());
+ corrupt_file_for_checksum_mismatch(static_sources[0].indexed_path());
base::HistogramTester tester;
test_extension_works_after_reload();
@@ -2213,11 +1982,18 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
declarative_net_request::RulesMonitorService::Get(profile());
EXPECT_TRUE(rules_monitor_service->HasRegisteredRuleset(extension_id));
+ const Extension* extension = extension_registry()->GetExtensionById(
+ last_loaded_extension_id(), ExtensionRegistry::ENABLED);
+ ASSERT_TRUE(extension);
+
+ std::vector<RulesetSource> sources = RulesetSource::CreateStatic(*extension);
+ ASSERT_EQ(1u, sources.size());
+
// Mimic extension prefs corruption by overwriting the indexed ruleset
// checksum.
const int kInvalidRulesetChecksum = -1;
- ExtensionPrefs::Get(profile())->SetDNRRulesetChecksum(
- extension_id, kInvalidRulesetChecksum);
+ ExtensionPrefs::Get(profile())->SetDNRStaticRulesetChecksum(
+ extension_id, sources[0].id(), kInvalidRulesetChecksum);
TestExtensionRegistryObserver registry_observer(
ExtensionRegistry::Get(profile()), extension_id);
@@ -2255,13 +2031,11 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// version is not the same as one used by Chrome.
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
ReindexOnRulesetVersionMismatch) {
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
// Set up an observer for RulesetMatcher to monitor the number of extension
// rulesets.
- RulesetCountWaiter ruleset_count_waiter;
- ScopedRulesetManagerTestObserver scoped_observer(&ruleset_count_waiter,
- profile());
+ RulesetCountWaiter ruleset_count_waiter(ruleset_manager());
TestRule rule = CreateGenericRule();
rule.condition->url_filter = std::string("*");
@@ -2489,7 +2263,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// Tests the dynamic rule support.
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, DynamicRules) {
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
// Add an extension which blocks main-frame requests to "yahoo.com".
TestRule block_static_rule = CreateGenericRule();
@@ -2590,9 +2364,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// Set up an observer for RulesetMatcher to monitor the number of extension
// rulesets.
- RulesetCountWaiter ruleset_count_waiter;
- ScopedRulesetManagerTestObserver scoped_observer(&ruleset_count_waiter,
- profile());
+ RulesetCountWaiter ruleset_count_waiter(ruleset_manager());
EXPECT_FALSE(
ExtensionWebRequestEventRouter::GetInstance()->HasAnyExtraHeadersListener(
@@ -2704,6 +2476,12 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, Redirect) {
// of actions taken on requests matching the extension's ruleset.
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
ActionsMatchedCountAsBadgeText) {
+ // Load the extension with a background script so scripts can be run from its
+ // generated background page. Also grant the feedback permission for the
+ // extension so it has access to the getMatchedRules API function.
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript |
+ ConfigFlag::kConfig_HasFeedbackPermission);
+
auto get_url_for_host = [this](std::string hostname) {
return embedded_test_server()->GetURL(hostname,
"/pages_with_script/index.html");
@@ -2770,9 +2548,8 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
std::string expected_badge_text;
bool has_referrer_header;
} test_cases[] = {
- // zzz.com does not match any rules, but we should still display 0 as the
- // badge text as the preference is on.
- {"zzz.com", "0", false},
+ // zzz.com does not match any rules, so no badge text should be displayed.
+ {"zzz.com", "", false},
// abc.com is blocked by a matching rule and should increment the badge
// text.
{"abc.com", "1", false},
@@ -2794,9 +2571,10 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
ui_test_utils::NavigateToURL(browser(), page_url);
ASSERT_TRUE(WasFrameWithScriptLoaded(GetMainFrame()));
- // Verify that the badge text is 0 when navigation finishes.
+ // Verify that the badge text is empty when navigation finishes because no
+ // actions have been matched.
int first_tab_id = ExtensionTabUtil::GetTabId(web_contents());
- EXPECT_EQ("0", action->GetDisplayBadgeText(first_tab_id));
+ EXPECT_EQ("", action->GetDisplayBadgeText(first_tab_id));
for (const auto& test_case : test_cases) {
GURL url = test_case.has_referrer_header
@@ -2814,16 +2592,45 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
const GURL second_tab_url = get_url_for_host("nomatch.com");
ui_test_utils::NavigateToURLWithDisposition(
browser(), second_tab_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
ASSERT_EQ(2, browser()->tab_strip_model()->count());
ASSERT_TRUE(browser()->tab_strip_model()->IsTabSelected(1));
int second_tab_id = ExtensionTabUtil::GetTabId(web_contents());
- EXPECT_EQ("0", action->GetDisplayBadgeText(second_tab_id));
+ EXPECT_EQ("", action->GetDisplayBadgeText(second_tab_id));
// Verify that the badge text for the first tab is unaffected.
EXPECT_EQ(first_tab_badge_text, action->GetDisplayBadgeText(first_tab_id));
+
+ // Verify that the correct rules are returned via getMatchedRules.
+ auto get_matched_rule_ids = [this](int tab_id) {
+ const char kGetMatchedRulesScript[] = R"(
+ chrome.declarativeNetRequest.getMatchedRules({tabId: %d}, (rules) => {
+ var ruleIds =
+ rules.rulesMatchedInfo.map(rule => rule.rule.ruleId).sort();
+ window.domAutomationController.send(ruleIds.join());
+ });
+ )";
+
+ return ExecuteScriptInBackgroundPage(
+ last_loaded_extension_id(),
+ base::StringPrintf(kGetMatchedRulesScript, tab_id),
+ browsertest_util::ScriptUserActivation::kDontActivate);
+ };
+
+ DeclarativeNetRequestGetMatchedRulesFunction::
+ set_disable_throttling_for_tests(true);
+
+ // Four rules should be matched on the tab with |first_tab_id|:
+ // - the block rule for abc.com (ruleId = 1)
+ // - the redirect rule for def.com (ruleId = 2)
+ // - the removeHeaders rule for jkl.com (ruleId = 3)
+ // - the allow rule for abcd.com (ruleId = 5)
+ EXPECT_EQ("1,2,3,5", get_matched_rule_ids(first_tab_id));
+
+ // No rule should be matched on the tab with |second_tab_id|.
+ EXPECT_EQ("", get_matched_rule_ids(second_tab_id));
}
// Ensure web request events are still dispatched even if DNR blocks/redirects
@@ -2831,7 +2638,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, WebRequestEvents) {
// Load the extension with a background script so scripts can be run from its
// generated background page.
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
TestRule rule = CreateGenericRule();
rule.condition->url_filter = "||example.com";
@@ -2880,7 +2687,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, WebRequestEvents) {
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, WebRequestPriority) {
// Load the extension with a background script so scripts can be run from its
// generated background page.
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
GURL url = embedded_test_server()->GetURL("example.com",
"/pages_with_script/index.html");
@@ -2948,10 +2755,17 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// Load the extension with a background script so scripts can be run from its
// generated background page.
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
+ TestRule rule = CreateGenericRule();
+ rule.condition->url_filter = "abc.com";
+ rule.id = kMinValidID;
+ rule.condition->resource_types = std::vector<std::string>({"main_frame"});
+ rule.action->type = "block";
+
+ std::vector<TestRule> rules({rule});
ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(
- {}, "test_extension", {URLPattern::kAllUrlsPattern}));
+ {rules}, "test_extension", {URLPattern::kAllUrlsPattern}));
const ExtensionId& extension_id = last_loaded_extension_id();
const Extension* dnr_extension = extension_registry()->GetExtensionById(
@@ -2965,9 +2779,8 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
action->SetBadgeText(ExtensionAction::kDefaultTabId, default_badge_text);
const GURL page_url = embedded_test_server()->GetURL(
- "norulesmatched.com", "/pages_with_script/index.html");
+ "abc.com", "/pages_with_script/index.html");
ui_test_utils::NavigateToURL(browser(), page_url);
- ASSERT_TRUE(WasFrameWithScriptLoaded(GetMainFrame()));
// The preference is initially turned off. Both the visible badge text and the
// badge text queried by the extension using getBadgeText() should return the
@@ -2987,8 +2800,8 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
EXPECT_EQ(declarative_net_request::kActionCountPlaceholderBadgeText,
queried_badge_text);
- // The displayed badge text should show "0" as no actions have been matched.
- EXPECT_EQ("0", action->GetDisplayBadgeText(first_tab_id));
+ // One action was matched, and this should be reflected in the badge text.
+ EXPECT_EQ("1", action->GetDisplayBadgeText(first_tab_id));
SetActionsAsBadgeText(extension_id, false);
// Switching the preference off should cause the extension queried badge text
@@ -3012,10 +2825,17 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
ActionCountPreferenceMultipleWindows) {
// Load the extension with a background script so scripts can be run from its
// generated background page.
- set_has_background_script(true);
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript);
+ TestRule rule = CreateGenericRule();
+ rule.condition->url_filter = "abc.com";
+ rule.id = kMinValidID;
+ rule.condition->resource_types = std::vector<std::string>({"main_frame"});
+ rule.action->type = "block";
+
+ std::vector<TestRule> rules({rule});
ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(
- {}, "test_extension", {URLPattern::kAllUrlsPattern}));
+ {rules}, "test_extension", {URLPattern::kAllUrlsPattern}));
const ExtensionId& extension_id = last_loaded_extension_id();
const Extension* dnr_extension = extension_registry()->GetExtensionById(
@@ -3026,9 +2846,8 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
->GetExtensionAction(*dnr_extension);
const GURL page_url = embedded_test_server()->GetURL(
- "norulesmatched.com", "/pages_with_script/index.html");
+ "abc.com", "/pages_with_script/index.html");
ui_test_utils::NavigateToURL(browser(), page_url);
- ASSERT_TRUE(WasFrameWithScriptLoaded(GetMainFrame()));
int first_browser_tab_id = ExtensionTabUtil::GetTabId(web_contents());
EXPECT_EQ("", extension_action->GetDisplayBadgeText(first_browser_tab_id));
@@ -3037,7 +2856,6 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// to |page_url|.
Browser* second_browser = CreateBrowser(profile());
ui_test_utils::NavigateToURL(second_browser, page_url);
- ASSERT_TRUE(WasFrameWithScriptLoaded(GetMainFrame(second_browser)));
content::WebContents* second_browser_contents =
second_browser->tab_strip_model()->GetActiveWebContents();
@@ -3053,15 +2871,16 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
SetActionsAsBadgeText(extension_id, true);
// Wait until ExtensionActionAPI::NotifyChange is called, then perform a
- // sanity check on the browser action's badge text.
+ // sanity check that one action was matched, and this is reflected in the
+ // badge text.
test_api_observer.Wait();
- EXPECT_EQ("0", extension_action->GetDisplayBadgeText(first_browser_tab_id));
+ EXPECT_EQ("1", extension_action->GetDisplayBadgeText(first_browser_tab_id));
// The badge text for the second browser window should also update to the
// matched action count because the second browser shares the same browser
// context as the first.
- EXPECT_EQ("0", extension_action->GetDisplayBadgeText(second_browser_tab_id));
+ EXPECT_EQ("1", extension_action->GetDisplayBadgeText(second_browser_tab_id));
}
// Test that the action matched badge text for an extension is visible in an
@@ -3096,15 +2915,12 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
ExtensionActionManager::Get(incognito_contents->GetBrowserContext())
->GetExtensionAction(*dnr_extension);
- // TODO(crbug.com/992251): This should be a "1" after the main-frame
- // navigation case is fixed.
- EXPECT_EQ("0", incognito_action->GetDisplayBadgeText(
+ EXPECT_EQ("1", incognito_action->GetDisplayBadgeText(
ExtensionTabUtil::GetTabId(incognito_contents)));
}
// Test that the actions matched badge text for an extension will be reset
// when a main-frame navigation finishes.
-// TODO(crbug.com/992251): Edit this test to add more main-frame cases.
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
ActionsMatchedCountAsBadgeTextMainFrame) {
auto get_url_for_host = [this](std::string hostname) {
@@ -3112,6 +2928,10 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
"/pages_with_script/index.html");
};
+ auto get_set_cookie_url = [this](std::string hostname) {
+ return embedded_test_server()->GetURL(hostname, "/set-cookie?a=b");
+ };
+
struct {
std::string url_filter;
int id;
@@ -3119,11 +2939,23 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
std::string action_type;
std::vector<std::string> resource_types;
base::Optional<std::string> redirect_url;
+ base::Optional<std::vector<std::string>> remove_headers_list;
} rules_data[] = {
{"abc.com", 1, 1, "block", std::vector<std::string>({"script"}),
- base::nullopt},
- {"def.com", 2, 1, "redirect", std::vector<std::string>({"main_frame"}),
- get_url_for_host("abc.com").spec()},
+ base::nullopt, base::nullopt},
+ {"||def.com", 2, 1, "redirect", std::vector<std::string>({"main_frame"}),
+ get_url_for_host("abc.com").spec(), base::nullopt},
+ {"gotodef.com", 3, 1, "redirect",
+ std::vector<std::string>({"main_frame"}),
+ get_url_for_host("def.com").spec(), base::nullopt},
+ {"ghi.com", 4, 1, "block", std::vector<std::string>({"main_frame"}),
+ base::nullopt, base::nullopt},
+ {"gotosetcookie.com", 5, 1, "redirect",
+ std::vector<std::string>({"main_frame"}),
+ get_set_cookie_url("setcookie.com").spec(), base::nullopt},
+ {"setcookie.com", 6, 1, "removeHeaders",
+ std::vector<std::string>({"main_frame"}), base::nullopt,
+ std::vector<std::string>({"setCookie"})},
};
// Load the extension.
@@ -3137,6 +2969,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
rule.action->type = rule_data.action_type;
rule.action->redirect.emplace();
rule.action->redirect->url = rule_data.redirect_url;
+ rule.action->remove_headers_list = rule_data.remove_headers_list;
rules.push_back(rule);
}
@@ -3157,14 +2990,26 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
std::string frame_hostname;
std::string expected_badge_text;
} test_cases[] = {
+ // The request to ghi.com should be blocked, so the badge text should be 1
+ // once navigation finishes.
+ {"ghi.com", "1"},
// The script on get_url_for_host("abc.com") matches with a rule and
// should increment the badge text.
{"abc.com", "1"},
- // No rules match, so the badge text should be 0 once navigation finishes.
- {"nomatch.com", "0"},
+ // No rules match, so there should be no badge text once navigation
+ // finishes.
+ {"nomatch.com", ""},
// The request to def.com will redirect to get_url_for_host("abc.com") and
// the script on abc.com should match with a rule.
- {"def.com", "1"},
+ {"def.com", "2"},
+ // Same as the above test, except with an additional redirect from
+ // gotodef.com to def.com caused by a rule match. Therefore the badge text
+ // should be 3.
+ {"gotodef.com", "3"},
+ // The request to gotosetcookie.com will match with a rule and redirect to
+ // setcookie.com. The Set-Cookie header on setcookie.com will also match
+ // with a rule and get removed. Therefore the badge text should be 2.
+ {"gotosetcookie.com", "2"},
};
int first_tab_id = ExtensionTabUtil::GetTabId(web_contents());
@@ -3259,7 +3104,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
} test_cases[] = {
// This request only has a Set-Cookie header. Only the badge text for the
// extension with a remove Set-Cookie header rule should be incremented.
- {get_set_cookie_url("example.com"), false, "1", "0"},
+ {get_set_cookie_url("example.com"), false, "1", ""},
// This request only has a Referer header. Only the badge text for the
// extension with a remove Referer header rule should be incremented.
{get_referer_url("example.com"), true, "1", "1"},
@@ -3280,8 +3125,8 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
ASSERT_TRUE(WasFrameWithScriptLoaded(GetMainFrame()));
int first_tab_id = ExtensionTabUtil::GetTabId(web_contents());
- EXPECT_EQ("0", extension_1_action->GetDisplayBadgeText(first_tab_id));
- EXPECT_EQ("0", extension_2_action->GetDisplayBadgeText(first_tab_id));
+ EXPECT_EQ("", extension_1_action->GetDisplayBadgeText(first_tab_id));
+ EXPECT_EQ("", extension_2_action->GetDisplayBadgeText(first_tab_id));
for (const auto& test_case : test_cases) {
SCOPED_TRACE(base::StringPrintf("Testing URL: %s, using referrer: %s",
@@ -3302,8 +3147,12 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
OnRuleMatchedDebugAvailability) {
// Load the extension with a background script so scripts can be run from its
- // generated background page.
- set_has_background_script(true);
+ // generated background page. Also grant the feedback permission for the
+ // extension so it can have access to the onRuleMatchedDebug event when
+ // unpacked.
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript |
+ ConfigFlag::kConfig_HasFeedbackPermission);
+
ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(
{}, "test_extension", {URLPattern::kAllUrlsPattern}));
@@ -3330,8 +3179,10 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Unpacked,
ASSERT_EQ(ExtensionLoadType::UNPACKED, GetParam());
// Load the extension with a background script so scripts can be run from its
- // generated background page.
- set_has_background_script(true);
+ // generated background page. Also grant the feedback permission for the
+ // extension so it has access to the onRuleMatchedDebug event.
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript |
+ ConfigFlag::kConfig_HasFeedbackPermission);
auto create_remove_headers_rule =
[](int id, const std::string& url_filter,
@@ -3402,6 +3253,580 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Unpacked,
EXPECT_EQ("1,2", matched_rule_ids);
}
+// Test that getMatchedRules returns the correct rules when called by different
+// extensions with rules matched by requests initiated from different tabs.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
+ GetMatchedRulesMultipleTabs) {
+ // Load the extension with a background script so scripts can be run from its
+ // generated background page. Also grant the feedback permission for the
+ // extension so it has access to the getMatchedRules API function.
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript |
+ ConfigFlag::kConfig_HasFeedbackPermission);
+
+ DeclarativeNetRequestGetMatchedRulesFunction::
+ set_disable_throttling_for_tests(true);
+
+ // Sub-frames are used for navigations instead of the main-frame to allow
+ // multiple requests to be made without triggering a main-frame navigation,
+ // which would move rules attributed to the previous main-frame to the unknown
+ // tab ID.
+ const std::string kFrameName1 = "frame1";
+ const GURL page_url = embedded_test_server()->GetURL(
+ "nomatch.com", "/page_with_two_frames.html");
+
+ auto get_url_for_host = [this](std::string hostname) {
+ return embedded_test_server()->GetURL(hostname,
+ "/pages_with_script/index.html");
+ };
+
+ auto create_block_rule = [](int id, const std::string& url_filter) {
+ TestRule rule = CreateGenericRule();
+ rule.id = id;
+ rule.condition->url_filter = url_filter;
+ rule.condition->resource_types = std::vector<std::string>({"sub_frame"});
+ rule.action->type = "block";
+ return rule;
+ };
+
+ TestRule abc_rule = create_block_rule(kMinValidID, "abc.com");
+ TestRule def_rule = create_block_rule(kMinValidID + 1, "def.com");
+
+ ASSERT_NO_FATAL_FAILURE(
+ LoadExtensionWithRules({abc_rule}, "extension_1", {}));
+ auto extension_1_id = last_loaded_extension_id();
+
+ ASSERT_NO_FATAL_FAILURE(
+ LoadExtensionWithRules({def_rule}, "extension_2", {}));
+ auto extension_2_id = last_loaded_extension_id();
+
+ ui_test_utils::NavigateToURL(browser(), page_url);
+ ASSERT_TRUE(WasFrameWithScriptLoaded(GetMainFrame()));
+ const int first_tab_id = ExtensionTabUtil::GetTabId(web_contents());
+
+ // Navigate to abc.com. The rule from |extension_1| should match for
+ // |first_tab_id|.
+ NavigateFrame(kFrameName1, get_url_for_host("abc.com"));
+
+ // Navigate to abc.com. The rule from |extension_2| should match for
+ // |first_tab_id|.
+ NavigateFrame(kFrameName1, get_url_for_host("def.com"));
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), page_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
+
+ ASSERT_EQ(2, browser()->tab_strip_model()->count());
+ ASSERT_TRUE(browser()->tab_strip_model()->IsTabSelected(1));
+
+ ui_test_utils::NavigateToURL(browser(), page_url);
+ ASSERT_TRUE(WasFrameWithScriptLoaded(GetMainFrame()));
+ const int second_tab_id = ExtensionTabUtil::GetTabId(web_contents());
+
+ // Navigate to abc.com from the second tab. The rule from |extension_1| should
+ // match for |second_tab_id|.
+ NavigateFrame(kFrameName1, get_url_for_host("abc.com"));
+
+ int abc_id = *abc_rule.id;
+ int def_id = *def_rule.id;
+
+ struct {
+ ExtensionId extension_id;
+ base::Optional<int> tab_id;
+ std::string expected_rule_and_tab_ids;
+ } test_cases[] = {
+ // No rules should be matched for |extension_1| and the unknown tab ID.
+ {extension_1_id, extension_misc::kUnknownTabId, ""},
+
+ // No filter is specified for |extension_1|, therefore two MatchedRuleInfo
+ // should be returned:
+ // (abc_id, first_tab_id) and (abc_id, second_tab_id)
+ {extension_1_id, base::nullopt,
+ base::StringPrintf("%d,%d|%d,%d", abc_id, first_tab_id, abc_id,
+ second_tab_id)},
+
+ // Filtering by tab_id = |first_tab_id| should return one MatchedRuleInfo:
+ // (abc_id, first_tab_id)
+ {extension_1_id, first_tab_id,
+ base::StringPrintf("%d,%d", abc_id, first_tab_id)},
+
+ // Filtering by tab_id = |second_tab_id| should return one
+ // MatchedRuleInfo: (abc_id, second_tab_id)
+ {extension_1_id, second_tab_id,
+ base::StringPrintf("%d,%d", abc_id, second_tab_id)},
+
+ // For |extension_2|, filtering by tab_id = |first_tab_id| should return
+ // one MatchedRuleInfo: (def_id, first_tab_id)
+ {extension_2_id, first_tab_id,
+ base::StringPrintf("%d,%d", def_id, first_tab_id)},
+
+ // Since no rules from |extension_2| was matched for the second tab,
+ // getMatchedRules should not return any rules.
+ {extension_2_id, second_tab_id, ""}};
+
+ for (const auto& test_case : test_cases) {
+ if (test_case.tab_id) {
+ SCOPED_TRACE(base::StringPrintf(
+ "Testing getMatchedRules for tab %d and extension %s",
+ *test_case.tab_id, test_case.extension_id.c_str()));
+ } else {
+ SCOPED_TRACE(base::StringPrintf(
+ "Testing getMatchedRules for all tabs and extension %s",
+ test_case.extension_id.c_str()));
+ }
+
+ std::string actual_rule_and_tab_ids =
+ GetRuleAndTabIdsMatched(test_case.extension_id, test_case.tab_id);
+ EXPECT_EQ(test_case.expected_rule_and_tab_ids, actual_rule_and_tab_ids);
+ }
+
+ // Close the second tab opened.
+ browser()->tab_strip_model()->CloseSelectedTabs();
+
+ ASSERT_EQ(1, browser()->tab_strip_model()->count());
+ ASSERT_TRUE(browser()->tab_strip_model()->IsTabSelected(0));
+
+ std::string actual_rule_and_tab_ids =
+ GetRuleAndTabIdsMatched(extension_1_id, base::nullopt);
+
+ // The matched rule info for the second tab should have its tab ID changed to
+ // the unknown tab ID after the second tab has been closed.
+ EXPECT_EQ(
+ base::StringPrintf("%d,%d|%d,%d", abc_id, extension_misc::kUnknownTabId,
+ abc_id, first_tab_id),
+ actual_rule_and_tab_ids);
+}
+
+// Test that rules matched for main-frame navigations are attributed will be
+// reset when a main-frame navigation finishes.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
+ GetMatchedRulesMainFrame) {
+ // Load the extension with a background script so scripts can be run from its
+ // generated background page. Also grant the feedback permission for the
+ // extension so it has access to the getMatchedRules API function.
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript |
+ ConfigFlag::kConfig_HasFeedbackPermission);
+
+ DeclarativeNetRequestGetMatchedRulesFunction::
+ set_disable_throttling_for_tests(true);
+
+ const std::string test_host = "abc.com";
+ GURL page_url = embedded_test_server()->GetURL(
+ test_host, "/pages_with_script/index.html");
+
+ TestRule rule = CreateGenericRule();
+ rule.id = kMinValidID;
+ rule.condition->url_filter = test_host;
+ rule.condition->resource_types = std::vector<std::string>({"main_frame"});
+ rule.action->type = "block";
+
+ ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules({rule}, "extension_1", {}));
+
+ // Navigate to abc.com.
+ ui_test_utils::NavigateToURL(browser(), page_url);
+ std::string actual_rule_and_tab_ids =
+ GetRuleAndTabIdsMatched(last_loaded_extension_id(), base::nullopt);
+
+ // Since the block rule for abc.com is matched for the main-frame navigation
+ // request, it should be attributed to the current tab.
+ const int first_tab_id = ExtensionTabUtil::GetTabId(web_contents());
+ std::string expected_rule_and_tab_ids =
+ base::StringPrintf("%d,%d", *rule.id, first_tab_id);
+
+ EXPECT_EQ(expected_rule_and_tab_ids, actual_rule_and_tab_ids);
+
+ // Navigate to abc.com again.
+ ui_test_utils::NavigateToURL(browser(), page_url);
+ actual_rule_and_tab_ids =
+ GetRuleAndTabIdsMatched(last_loaded_extension_id(), base::nullopt);
+
+ // The same block rule is matched for this navigation request, and should be
+ // attributed to the current tab. Since the main-frame for which the older
+ // matched rule is associated with is no longer active, the older matched
+ // rule's tab ID should be changed to the unknown tab ID.
+ expected_rule_and_tab_ids =
+ base::StringPrintf("%d,%d|%d,%d", *rule.id, extension_misc::kUnknownTabId,
+ *rule.id, first_tab_id);
+
+ EXPECT_EQ(expected_rule_and_tab_ids, actual_rule_and_tab_ids);
+
+ // Navigate to nomatch,com.
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL(
+ "nomatch.com", "/pages_with_script/index.html"));
+
+ // No rules should be matched for the navigation request to nomatch.com and
+ // all rules previously attributed to |first_tab_id| should now be attributed
+ // to the unknown tab ID as a result of the navigation. Therefore
+ // GetMatchedRules should return no matched rules.
+ actual_rule_and_tab_ids =
+ GetRuleAndTabIdsMatched(last_loaded_extension_id(), first_tab_id);
+ EXPECT_EQ("", actual_rule_and_tab_ids);
+}
+
+// Test that getMatchedRules only returns rules more recent than the provided
+// timestamp.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
+ GetMatchedRulesTimestampFiltering) {
+ base::Time start_time = base::Time::Now();
+
+ base::SimpleTestClock clock_;
+ clock_.SetNow(start_time);
+ auto* rules_monitor_service =
+ declarative_net_request::RulesMonitorService::Get(profile());
+ rules_monitor_service->action_tracker().SetClockForTests(&clock_);
+
+ // Load the extension with a background script so scripts can be run from its
+ // generated background page. Also grant the feedback permission for the
+ // extension so it has access to the getMatchedRules API function.
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript |
+ ConfigFlag::kConfig_HasFeedbackPermission);
+
+ DeclarativeNetRequestGetMatchedRulesFunction::
+ set_disable_throttling_for_tests(true);
+
+ const std::string kFrameName1 = "frame1";
+ const GURL page_url = embedded_test_server()->GetURL(
+ "nomatch.com", "/page_with_two_frames.html");
+
+ const std::string example_host = "example.com";
+ const GURL sub_frame_url = embedded_test_server()->GetURL(
+ example_host, "/pages_with_script/index.html");
+
+ TestRule rule = CreateGenericRule();
+ rule.id = kMinValidID;
+ rule.condition->url_filter = example_host;
+ rule.condition->resource_types = std::vector<std::string>({"sub_frame"});
+ rule.action->type = "block";
+
+ ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules({rule}, "extension_1", {}));
+ const ExtensionId& extension_id = last_loaded_extension_id();
+ ui_test_utils::NavigateToURL(browser(), page_url);
+
+ // Using subframes here to make requests without triggering main-frame
+ // navigations. This request will match with the block rule for example.com at
+ // |start_time|.
+ NavigateFrame(kFrameName1, sub_frame_url);
+
+ const char getMatchedRuleTimestampScript[] = R"(
+ chrome.declarativeNetRequest.getMatchedRules((rules) => {
+ var rule_count = rules.rulesMatchedInfo.length;
+ var timestamp = rule_count === 1 ?
+ rules.rulesMatchedInfo[0].timeStamp.toString() : '';
+
+ window.domAutomationController.send(timestamp);
+ });
+ )";
+
+ std::string timestamp_string = ExecuteScriptInBackgroundPage(
+ extension_id, getMatchedRuleTimestampScript,
+ browsertest_util::ScriptUserActivation::kDontActivate);
+
+ double matched_rule_timestamp;
+ ASSERT_TRUE(base::StringToDouble(timestamp_string, &matched_rule_timestamp));
+
+ // Verify that the rule was matched at |start_time|.
+ EXPECT_DOUBLE_EQ(start_time.ToJsTimeIgnoringNull(), matched_rule_timestamp);
+
+ // Advance the clock to capture a timestamp after when the first request was
+ // made.
+ clock_.Advance(base::TimeDelta::FromMilliseconds(100));
+ base::Time timestamp_1 = clock_.Now();
+ clock_.Advance(base::TimeDelta::FromMilliseconds(100));
+
+ // Navigate to example.com again. This should cause |rule| to be matched.
+ NavigateFrame(kFrameName1, sub_frame_url);
+
+ // Advance the clock to capture a timestamp after when the second request was
+ // made.
+ clock_.Advance(base::TimeDelta::FromMilliseconds(100));
+ base::Time timestamp_2 = clock_.Now();
+
+ int first_tab_id = ExtensionTabUtil::GetTabId(web_contents());
+
+ // Two rules should be matched on |first_tab_id|.
+ std::string rule_count = GetMatchedRuleCount(extension_id, first_tab_id,
+ base::nullopt /* timestamp */);
+ EXPECT_EQ("2", rule_count);
+
+ // Only one rule should be matched on |first_tab_id| after |timestamp_1|.
+ rule_count = GetMatchedRuleCount(extension_id, first_tab_id, timestamp_1);
+ EXPECT_EQ("1", rule_count);
+
+ // No rules should be matched on |first_tab_id| after |timestamp_2|.
+ rule_count = GetMatchedRuleCount(extension_id, first_tab_id, timestamp_2);
+ EXPECT_EQ("0", rule_count);
+
+ rules_monitor_service->action_tracker().SetClockForTests(nullptr);
+}
+
+// Test that getMatchedRules will only return matched rules for individual tabs
+// where activeTab is granted.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
+ GetMatchedRulesActiveTab) {
+ // Load the extension with a background script so scripts can be run from its
+ // generated background page.
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript |
+ ConfigFlag::kConfig_HasActiveTab);
+
+ DeclarativeNetRequestGetMatchedRulesFunction::
+ set_disable_throttling_for_tests(true);
+
+ const std::string test_host = "abc.com";
+ GURL page_url = embedded_test_server()->GetURL(
+ test_host, "/pages_with_script/index.html");
+
+ TestRule rule = CreateGenericRule();
+ rule.id = kMinValidID;
+ rule.condition->url_filter = test_host;
+ rule.condition->resource_types = std::vector<std::string>({"main_frame"});
+ rule.action->type = "block";
+
+ ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules({rule}, "extension_1", {}));
+ const ExtensionId& extension_id = last_loaded_extension_id();
+
+ // Navigate to |page_url| which will cause |rule| to be matched.
+ ui_test_utils::NavigateToURL(browser(), page_url);
+
+ int first_tab_id = ExtensionTabUtil::GetTabId(web_contents());
+
+ // Open a new tab and navigate to |page_url| which will cause |rule| to be
+ // matched.
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), page_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
+
+ ASSERT_EQ(2, browser()->tab_strip_model()->count());
+ ASSERT_TRUE(browser()->tab_strip_model()->IsTabSelected(1));
+
+ TabHelper* tab_helper = TabHelper::FromWebContents(web_contents());
+ ASSERT_TRUE(tab_helper);
+
+ // Get the ActiveTabPermissionGranter for the second tab.
+ ActiveTabPermissionGranter* active_tab_granter =
+ tab_helper->active_tab_permission_granter();
+ ASSERT_TRUE(active_tab_granter);
+
+ const Extension* dnr_extension = extension_registry()->GetExtensionById(
+ extension_id, extensions::ExtensionRegistry::ENABLED);
+
+ // Grant the activeTab permission for the second tab.
+ active_tab_granter->GrantIfRequested(dnr_extension);
+
+ int second_tab_id = ExtensionTabUtil::GetTabId(web_contents());
+
+ // Calling getMatchedRules with no tab ID specified should result in an error
+ // since the extension does not have the feedback permission.
+ EXPECT_EQ(declarative_net_request::kErrorGetMatchedRulesMissingPermissions,
+ GetMatchedRuleCount(extension_id, base::nullopt /* tab_id */,
+ base::nullopt /* timestamp */));
+
+ // Calling getMatchedRules for a tab without the activeTab permission granted
+ // should result in an error.
+ EXPECT_EQ(declarative_net_request::kErrorGetMatchedRulesMissingPermissions,
+ GetMatchedRuleCount(extension_id, first_tab_id,
+ base::nullopt /* timestamp */));
+
+ // Calling getMatchedRules for a tab with the activeTab permission granted
+ // should return the rules matched for that tab.
+ EXPECT_EQ("1", GetMatchedRuleCount(extension_id, second_tab_id,
+ base::nullopt /* timestamp */));
+}
+
+// Test that getMatchedRules will not be throttled if the call is associated
+// with a user gesture.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
+ GetMatchedRulesNoThrottlingIfUserGesture) {
+ // Load the extension with a background script so scripts can be run from its
+ // generated background page. Also grant the feedback permission for the
+ // extension so it has access to the getMatchedRules API function.
+ set_config_flags(ConfigFlag::kConfig_HasBackgroundScript |
+ ConfigFlag::kConfig_HasFeedbackPermission);
+
+ // Ensure that GetMatchedRules is being throttled.
+ DeclarativeNetRequestGetMatchedRulesFunction::
+ set_disable_throttling_for_tests(false);
+
+ ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules({}));
+ const ExtensionId& extension_id = last_loaded_extension_id();
+
+ auto get_matched_rules_count = [this, &extension_id](bool user_gesture) {
+ auto user_gesture_setting =
+ user_gesture ? browsertest_util::ScriptUserActivation::kActivate
+ : browsertest_util::ScriptUserActivation::kDontActivate;
+
+ return GetMatchedRuleCount(extension_id, base::nullopt /* tab_id */,
+ base::nullopt /* timestamp */,
+ user_gesture_setting);
+ };
+
+ // Call getMatchedRules without a user gesture, until the quota is reached.
+ // None of these calls should return an error.
+ for (int i = 1; i <= dnr_api::MAX_GETMATCHEDRULES_CALLS_PER_INTERVAL; ++i) {
+ SCOPED_TRACE(base::StringPrintf(
+ "Testing getMatchedRules call without user gesture %d of %d", i,
+ dnr_api::MAX_GETMATCHEDRULES_CALLS_PER_INTERVAL));
+ EXPECT_EQ("0", get_matched_rules_count(false));
+ }
+
+ // Calling getMatchedRules without a user gesture should return an error after
+ // the quota has been reached.
+ EXPECT_EQ(
+ "This request exceeds the MAX_GETMATCHEDRULES_CALLS_PER_INTERVAL quota.",
+ get_matched_rules_count(false));
+
+ // Calling getMatchedRules with a user gesture should not return an error even
+ // after the quota has been reached.
+ EXPECT_EQ("0", get_matched_rules_count(true));
+}
+
+// Tests the allowAllRequests action.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, AllowAllRequests) {
+ struct RuleData {
+ int id;
+ int priority;
+ std::string action_type;
+ std::string url_filter;
+ bool is_regex_rule;
+ base::Optional<std::vector<std::string>> resource_types;
+ };
+
+ auto run_test = [this](const GURL& page_url,
+ const std::vector<RuleData>& rule_data,
+ const std::vector<std::string>& paths_seen,
+ const std::vector<std::string>& paths_not_seen) {
+ std::vector<TestRule> test_rules;
+ for (const auto& rule : rule_data) {
+ TestRule test_rule = CreateGenericRule();
+ test_rule.id = rule.id;
+ test_rule.priority = rule.priority;
+ test_rule.action->type = rule.action_type;
+ test_rule.condition->url_filter.reset();
+ if (rule.is_regex_rule)
+ test_rule.condition->regex_filter = rule.url_filter;
+ else
+ test_rule.condition->url_filter = rule.url_filter;
+ test_rule.condition->resource_types = rule.resource_types;
+ test_rules.push_back(test_rule);
+ }
+
+ ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(test_rules));
+
+ ui_test_utils::NavigateToURL(browser(), page_url);
+
+ const std::set<GURL> requests_seen = GetAndResetRequestsToServer();
+
+ for (const auto& path : paths_seen) {
+ GURL expected_request_url = embedded_test_server()->GetURL(path);
+ EXPECT_TRUE(base::Contains(requests_seen, expected_request_url))
+ << expected_request_url.spec()
+ << " was not requested from the server.";
+ }
+
+ for (const auto& path : paths_not_seen) {
+ GURL expected_request_url = embedded_test_server()->GetURL(path);
+ EXPECT_FALSE(base::Contains(requests_seen, expected_request_url))
+ << expected_request_url.spec() << " request seen unexpectedly.";
+ }
+
+ UninstallExtension(last_loaded_extension_id());
+ };
+
+ // This page causes the following requests.
+ GURL page_url = embedded_test_server()->GetURL("example.com",
+ "/page_with_two_frames.html");
+ std::vector<std::string> requests = {
+ {"/page_with_two_frames.html"}, // 0
+ {"/subresources/script.js"}, // 1
+ {"/child_frame.html?frame=1"}, // 2
+ {"/subresources/script.js?frameId=1"}, // 3
+ {"/child_frame.html?frame=2"}, // 4
+ {"/subresources/script.js?frameId=2"}, // 5
+ };
+
+ {
+ SCOPED_TRACE("Testing case 1");
+ std::vector<RuleData> rule_data = {
+ {1, 4, "allowAllRequests", "page_with_two_frames\\.html", true,
+ std::vector<std::string>({"main_frame"})},
+ {2, 3, "block", "script.js|", false},
+ {3, 5, "block", "script.js?frameId=1", false},
+ {4, 3, "block", "script\\.js?frameId=2", true}};
+ // Requests:
+ // -/page_with_two_frames.html (Matching rule=1)
+ // -/subresources/script.js (Matching rule=[1,2] Winner=1)
+ // -/child_frame.html?frame=1 (Matching Rule=1)
+ // -/subresources/script.js?frameId=1 (Matching Rule=[1,3] Winner=3)
+ // -/child_frame.html?frame=2 (Matching Rule=1)
+ // -/subresources/script.js?frameId=2 (Matching Rule=1,4 Winner=1)
+ // Hence only requests[3] is blocked.
+ run_test(page_url, rule_data,
+ {requests[0], requests[1], requests[2], requests[4], requests[5]},
+ {requests[3]});
+ }
+
+ {
+ SCOPED_TRACE("Testing case 2");
+ std::vector<RuleData> rule_data = {
+ {1, 4, "allowAllRequests", "page_with_two_frames.html", false,
+ std::vector<std::string>({"main_frame"})},
+ {2, 5, "block", "script\\.js", true},
+ {3, 6, "allowAllRequests", "child_frame.html", false,
+ std::vector<std::string>({"sub_frame"})},
+ {4, 7, "block", "frame=1", true}};
+
+ // Requests:
+ // -/page_with_two_frames.html (Matching rule=1)
+ // -/subresources/script.js (Matching rule=[1,2] Winner=2, Blocked)
+ // -/child_frame.html?frame=1 (Matching Rule=[1,3,4] Winner=4, Blocked)
+ // -/subresources/script.js?frameId=1 (Source Frame was blocked)
+ // -/child_frame.html?frame=2 (Matching Rule=[1,3] Winner=3)
+ // -/subresources/script.js?frameId=2 (Matching Rule=[1,2,3] Winner=3)
+ run_test(page_url, rule_data, {requests[0], requests[4], requests[5]},
+ {requests[1], requests[2], requests[3]});
+ }
+
+ {
+ SCOPED_TRACE("Testing case 3");
+ std::vector<RuleData> rule_data = {
+ {1, 1, "allowAllRequests", "page_with_two_frames.html", false,
+ std::vector<std::string>({"main_frame"})},
+ {2, 5, "block", ".*", true},
+ };
+
+ // Requests:
+ // -/page_with_two_frames.html (Matching rule=1)
+ // -/subresources/script.js (Matching rule=[1,2] Winner=2)
+ // -/child_frame.html?frame=1 (Matching Rule=[1,2] Winner=2)
+ // -/subresources/script.js?frameId=1 (Source Frame was blocked)
+ // -/child_frame.html?frame=2 (Matching Rule=[1,2] Winner=2)
+ // -/subresources/script.js?frameId=2 (Source frame was blocked)
+ // Hence only the main-frame request goes through.
+ run_test(page_url, rule_data, {requests[0]},
+ {requests[1], requests[2], requests[3], requests[4], requests[5]});
+ }
+ {
+ SCOPED_TRACE("Testing case 4");
+ std::vector<RuleData> rule_data = {
+ {1, 6, "allowAllRequests", "page_with_two_frames\\.html", true,
+ std::vector<std::string>({"main_frame"})},
+ {2, 5, "block", "*", false},
+ };
+
+ // Requests:
+ // -/page_with_two_frames.html (Matching rule=1)
+ // -/subresources/script.js (Matching rule=[1,2] Winner=1)
+ // -/child_frame.html?frame=1 (Matching Rule=[1,2] Winner=1)
+ // -/subresources/script.js?frameId=1 (Matching Rule=[1,2] Winner=1)
+ // -/child_frame.html?frame=2 (Matching Rule=[1,2] Winner=1)
+ // -/subresources/script.js?frameId=2 (Matching Rule=[1,2] Winner=1)
+ // Hence all requests go through.
+ run_test(page_url, rule_data,
+ {requests[0], requests[1], requests[2], requests[3], requests[4],
+ requests[5]},
+ {});
+ }
+}
+
// Test fixture to verify that host permissions for the request url and the
// request initiator are properly checked when redirecting requests. Loads an
// example.com url with four sub-frames named frame_[1..4] from hosts
diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
index 4169d058110..6284bd6c2a0 100644
--- a/chromium/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc
@@ -3,13 +3,16 @@
// found in the LICENSE file.
#include <stddef.h>
+#include <functional>
#include <string>
+#include <utility>
#include <vector>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/memory/ref_counted.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -37,30 +40,50 @@ namespace declarative_net_request {
namespace {
constexpr char kJSONRulesFilename[] = "rules_file.json";
-const base::FilePath::CharType kJSONRulesetFilepath[] =
- FILE_PATH_LITERAL("rules_file.json");
-// Fixure testing that declarative rules corresponding to the Declarative Net
-// Request API are correctly indexed, for both packed and unpacked
-// extensions.
-class RuleIndexingTest : public DNRTestBase {
+constexpr char kLargeRegexFilter[] = ".{512}x";
+
+namespace dnr_api = extensions::api::declarative_net_request;
+
+std::string GetParseError(ParseResult result, int rule_id) {
+ ParseInfo info;
+ info.SetError(result, &rule_id);
+ return info.error();
+}
+
+std::string GetErrorWithFilename(
+ const std::string& error,
+ const std::string& filename = kJSONRulesFilename) {
+ return base::StringPrintf("%s: %s", filename.c_str(), error.c_str());
+}
+
+InstallWarning GetLargeRegexWarning(
+ int rule_id,
+ const std::string& filename = kJSONRulesFilename) {
+ return InstallWarning(ErrorUtils::FormatErrorMessage(
+ GetErrorWithFilename(kErrorRegexTooLarge, filename),
+ base::NumberToString(rule_id), kRegexFilterKey),
+ manifest_keys::kDeclarativeNetRequestKey,
+ manifest_keys::kDeclarativeRuleResourcesKey);
+}
+
+// Base test fixture to test indexing of rulesets.
+class RuleIndexingTestBase : public DNRTestBase {
public:
- RuleIndexingTest() {}
+ RuleIndexingTestBase() = default;
// DNRTestBase override.
void SetUp() override {
DNRTestBase::SetUp();
loader_ = CreateExtensionLoader();
- }
-
- protected:
- void AddRule(const TestRule& rule) { rules_list_.push_back(rule); }
+ extension_dir_ =
+ temp_dir().GetPath().Append(FILE_PATH_LITERAL("test_extension"));
- // This takes precedence over the AddRule method.
- void SetRules(std::unique_ptr<base::Value> rules) {
- rules_value_ = std::move(rules);
+ // Create extension directory.
+ ASSERT_TRUE(base::CreateDirectory(extension_dir_));
}
+ protected:
// Loads the extension and verifies the indexed ruleset location and histogram
// counts.
void LoadAndExpectSuccess(size_t expected_indexed_rules_count) {
@@ -75,7 +98,8 @@ class RuleIndexingTest : public DNRTestBase {
extension_ = loader_->LoadExtension(extension_dir_);
ASSERT_TRUE(extension_.get());
- EXPECT_TRUE(HasValidIndexedRuleset(*extension_, browser_context()));
+ EXPECT_TRUE(
+ AreAllIndexedStaticRulesetsValid(*extension_, browser_context()));
// Ensure no load errors were reported.
EXPECT_TRUE(error_reporter()->GetErrors()->empty());
@@ -89,10 +113,11 @@ class RuleIndexingTest : public DNRTestBase {
}
}
- void LoadAndExpectError(const std::string& expected_error) {
+ void LoadAndExpectError(const std::string& expected_error,
+ const std::string& filename) {
// The error should be prepended with the JSON filename.
- std::string error_with_filename = base::StringPrintf(
- "%s: %s", kJSONRulesFilename, expected_error.c_str());
+ std::string error_with_filename =
+ GetErrorWithFilename(expected_error, filename);
base::HistogramTester tester;
WriteExtensionData();
@@ -118,88 +143,106 @@ class RuleIndexingTest : public DNRTestBase {
tester.ExpectTotalCount(kManifestRulesCountHistogram, 0u);
}
+ ChromeTestExtensionLoader* extension_loader() { return loader_.get(); }
+
+ const Extension* extension() const { return extension_.get(); }
+
+ const base::FilePath& extension_dir() const { return extension_dir_; }
+
+ LoadErrorReporter* error_reporter() {
+ return LoadErrorReporter::GetInstance();
+ }
+
+ private:
+ // Derived classes must override this to persist the extension to disk.
+ virtual void WriteExtensionData() = 0;
+
+ base::FilePath extension_dir_;
+ std::unique_ptr<ChromeTestExtensionLoader> loader_;
+ scoped_refptr<const Extension> extension_;
+};
+
+// Fixture testing that declarative rules corresponding to the Declarative Net
+// Request API are correctly indexed, for both packed and unpacked extensions.
+// This only tests a single ruleset.
+class SingleRulesetIndexingTest : public RuleIndexingTestBase {
+ public:
+ SingleRulesetIndexingTest() = default;
+
+ protected:
+ void AddRule(const TestRule& rule) { rules_list_.push_back(rule); }
+
+ // This takes precedence over the AddRule method.
+ void SetRules(std::unique_ptr<base::Value> rules) {
+ rules_value_ = std::move(rules);
+ }
+
void set_persist_invalid_json_file() { persist_invalid_json_file_ = true; }
void set_persist_initial_indexed_ruleset() {
persist_initial_indexed_ruleset_ = true;
}
- ChromeTestExtensionLoader* extension_loader() { return loader_.get(); }
-
- const Extension* extension() const { return extension_.get(); }
- void set_extension(scoped_refptr<const Extension> extension) {
- extension_ = extension;
+ void LoadAndExpectError(const std::string& expected_error) {
+ RuleIndexingTestBase::LoadAndExpectError(expected_error,
+ kJSONRulesFilename);
}
private:
- void WriteExtensionData() {
- extension_dir_ =
- temp_dir().GetPath().Append(FILE_PATH_LITERAL("test_extension"));
+ // RuleIndexingTestBase override:
+ void WriteExtensionData() override {
+ if (!rules_value_)
+ rules_value_ = ToListValue(rules_list_);
- // Create extension directory.
- EXPECT_TRUE(base::CreateDirectory(extension_dir_));
-
- if (rules_value_) {
- WriteManifestAndRuleset(extension_dir_, kJSONRulesetFilepath,
- kJSONRulesFilename, *rules_value_,
- {} /* hosts */);
- } else {
- WriteManifestAndRuleset(extension_dir_, kJSONRulesetFilepath,
- kJSONRulesFilename, rules_list_, {} /* hosts */);
- }
+ TestRulesetInfo info = {kJSONRulesFilename, std::move(*rules_value_)};
+ WriteManifestAndRuleset(extension_dir(), info, {} /* hosts */);
// Overwrite the JSON rules file with some invalid json.
if (persist_invalid_json_file_) {
std::string data = "invalid json";
- base::WriteFile(extension_dir_.Append(kJSONRulesetFilepath), data.c_str(),
- data.size());
+ ASSERT_EQ(static_cast<int>(data.size()),
+ base::WriteFile(extension_dir().AppendASCII(kJSONRulesFilename),
+ data.c_str(), data.size()));
}
if (persist_initial_indexed_ruleset_) {
std::string data = "user ruleset";
- base::WriteFile(file_util::GetIndexedRulesetPath(extension_dir_),
- data.c_str(), data.size());
+ base::FilePath ruleset_path = extension_dir().Append(
+ file_util::GetIndexedRulesetRelativePath(kMinValidStaticRulesetID));
+ ASSERT_TRUE(base::CreateDirectory(ruleset_path.DirName()));
+ ASSERT_EQ(static_cast<int>(data.size()),
+ base::WriteFile(ruleset_path, data.c_str(), data.size()));
}
}
- LoadErrorReporter* error_reporter() {
- return LoadErrorReporter::GetInstance();
- }
-
std::vector<TestRule> rules_list_;
std::unique_ptr<base::Value> rules_value_;
- base::FilePath extension_dir_;
- std::unique_ptr<ChromeTestExtensionLoader> loader_;
- scoped_refptr<const Extension> extension_;
bool persist_invalid_json_file_ = false;
bool persist_initial_indexed_ruleset_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(RuleIndexingTest);
};
-TEST_P(RuleIndexingTest, DuplicateResourceTypes) {
+TEST_P(SingleRulesetIndexingTest, DuplicateResourceTypes) {
TestRule rule = CreateGenericRule();
rule.condition->resource_types =
std::vector<std::string>({"image", "stylesheet"});
rule.condition->excluded_resource_types = std::vector<std::string>({"image"});
AddRule(rule);
LoadAndExpectError(
- ParseInfo(ParseResult::ERROR_RESOURCE_TYPE_DUPLICATED, *rule.id)
- .GetErrorDescription());
+ GetParseError(ParseResult::ERROR_RESOURCE_TYPE_DUPLICATED, *rule.id));
}
-TEST_P(RuleIndexingTest, EmptyRedirectRulePriority) {
+TEST_P(SingleRulesetIndexingTest, EmptyRedirectRulePriority) {
TestRule rule = CreateGenericRule();
rule.action->type = std::string("redirect");
rule.action->redirect.emplace();
rule.action->redirect->url = std::string("https://google.com");
+ rule.priority.reset();
AddRule(rule);
LoadAndExpectError(
- ParseInfo(ParseResult::ERROR_EMPTY_REDIRECT_RULE_PRIORITY, *rule.id)
- .GetErrorDescription());
+ GetParseError(ParseResult::ERROR_EMPTY_RULE_PRIORITY, *rule.id));
}
-TEST_P(RuleIndexingTest, EmptyRedirectRuleUrl) {
+TEST_P(SingleRulesetIndexingTest, EmptyRedirectRuleUrl) {
TestRule rule = CreateGenericRule();
rule.id = kMinValidID;
AddRule(rule);
@@ -209,19 +252,19 @@ TEST_P(RuleIndexingTest, EmptyRedirectRuleUrl) {
rule.priority = kMinValidPriority;
AddRule(rule);
- LoadAndExpectError(ParseInfo(ParseResult::ERROR_INVALID_REDIRECT, *rule.id)
- .GetErrorDescription());
+ LoadAndExpectError(
+ GetParseError(ParseResult::ERROR_INVALID_REDIRECT, *rule.id));
}
-TEST_P(RuleIndexingTest, InvalidRuleID) {
+TEST_P(SingleRulesetIndexingTest, InvalidRuleID) {
TestRule rule = CreateGenericRule();
rule.id = kMinValidID - 1;
AddRule(rule);
- LoadAndExpectError(ParseInfo(ParseResult::ERROR_INVALID_RULE_ID, *rule.id)
- .GetErrorDescription());
+ LoadAndExpectError(
+ GetParseError(ParseResult::ERROR_INVALID_RULE_ID, *rule.id));
}
-TEST_P(RuleIndexingTest, InvalidRedirectRulePriority) {
+TEST_P(SingleRulesetIndexingTest, InvalidRedirectRulePriority) {
TestRule rule = CreateGenericRule();
rule.action->type = std::string("redirect");
rule.action->redirect.emplace();
@@ -229,11 +272,10 @@ TEST_P(RuleIndexingTest, InvalidRedirectRulePriority) {
rule.priority = kMinValidPriority - 1;
AddRule(rule);
LoadAndExpectError(
- ParseInfo(ParseResult::ERROR_INVALID_REDIRECT_RULE_PRIORITY, *rule.id)
- .GetErrorDescription());
+ GetParseError(ParseResult::ERROR_INVALID_RULE_PRIORITY, *rule.id));
}
-TEST_P(RuleIndexingTest, NoApplicableResourceTypes) {
+TEST_P(SingleRulesetIndexingTest, NoApplicableResourceTypes) {
TestRule rule = CreateGenericRule();
rule.condition->excluded_resource_types = std::vector<std::string>(
{"main_frame", "sub_frame", "stylesheet", "script", "image", "font",
@@ -241,36 +283,34 @@ TEST_P(RuleIndexingTest, NoApplicableResourceTypes) {
"other"});
AddRule(rule);
LoadAndExpectError(
- ParseInfo(ParseResult::ERROR_NO_APPLICABLE_RESOURCE_TYPES, *rule.id)
- .GetErrorDescription());
+ GetParseError(ParseResult::ERROR_NO_APPLICABLE_RESOURCE_TYPES, *rule.id));
}
-TEST_P(RuleIndexingTest, EmptyDomainsList) {
+TEST_P(SingleRulesetIndexingTest, EmptyDomainsList) {
TestRule rule = CreateGenericRule();
rule.condition->domains = std::vector<std::string>();
AddRule(rule);
- LoadAndExpectError(ParseInfo(ParseResult::ERROR_EMPTY_DOMAINS_LIST, *rule.id)
- .GetErrorDescription());
+ LoadAndExpectError(
+ GetParseError(ParseResult::ERROR_EMPTY_DOMAINS_LIST, *rule.id));
}
-TEST_P(RuleIndexingTest, EmptyResourceTypeList) {
+TEST_P(SingleRulesetIndexingTest, EmptyResourceTypeList) {
TestRule rule = CreateGenericRule();
rule.condition->resource_types = std::vector<std::string>();
AddRule(rule);
LoadAndExpectError(
- ParseInfo(ParseResult::ERROR_EMPTY_RESOURCE_TYPES_LIST, *rule.id)
- .GetErrorDescription());
+ GetParseError(ParseResult::ERROR_EMPTY_RESOURCE_TYPES_LIST, *rule.id));
}
-TEST_P(RuleIndexingTest, EmptyURLFilter) {
+TEST_P(SingleRulesetIndexingTest, EmptyURLFilter) {
TestRule rule = CreateGenericRule();
rule.condition->url_filter = std::string();
AddRule(rule);
- LoadAndExpectError(ParseInfo(ParseResult::ERROR_EMPTY_URL_FILTER, *rule.id)
- .GetErrorDescription());
+ LoadAndExpectError(
+ GetParseError(ParseResult::ERROR_EMPTY_URL_FILTER, *rule.id));
}
-TEST_P(RuleIndexingTest, InvalidRedirectURL) {
+TEST_P(SingleRulesetIndexingTest, InvalidRedirectURL) {
TestRule rule = CreateGenericRule();
rule.action->type = std::string("redirect");
rule.action->redirect.emplace();
@@ -278,25 +318,23 @@ TEST_P(RuleIndexingTest, InvalidRedirectURL) {
rule.priority = kMinValidPriority;
AddRule(rule);
LoadAndExpectError(
- ParseInfo(ParseResult::ERROR_INVALID_REDIRECT_URL, *rule.id)
- .GetErrorDescription());
+ GetParseError(ParseResult::ERROR_INVALID_REDIRECT_URL, *rule.id));
}
-TEST_P(RuleIndexingTest, ListNotPassed) {
+TEST_P(SingleRulesetIndexingTest, ListNotPassed) {
SetRules(std::make_unique<base::DictionaryValue>());
LoadAndExpectError(kErrorListNotPassed);
}
-TEST_P(RuleIndexingTest, DuplicateIDS) {
+TEST_P(SingleRulesetIndexingTest, DuplicateIDS) {
TestRule rule = CreateGenericRule();
AddRule(rule);
AddRule(rule);
- LoadAndExpectError(ParseInfo(ParseResult::ERROR_DUPLICATE_IDS, *rule.id)
- .GetErrorDescription());
+ LoadAndExpectError(GetParseError(ParseResult::ERROR_DUPLICATE_IDS, *rule.id));
}
// Ensure that we limit the number of parse failure warnings shown.
-TEST_P(RuleIndexingTest, TooManyParseFailures) {
+TEST_P(SingleRulesetIndexingTest, TooManyParseFailures) {
const size_t kNumInvalidRules = 10;
const size_t kNumValidRules = 6;
const size_t kMaxUnparsedRulesWarnings = 5;
@@ -339,7 +377,7 @@ TEST_P(RuleIndexingTest, TooManyParseFailures) {
}
warning.message = ErrorUtils::FormatErrorMessage(
- kTooManyParseFailuresWarning,
+ GetErrorWithFilename(kTooManyParseFailuresWarning),
std::to_string(kMaxUnparsedRulesWarnings));
EXPECT_EQ(warning, expected_warnings[kMaxUnparsedRulesWarnings]);
}
@@ -347,7 +385,7 @@ TEST_P(RuleIndexingTest, TooManyParseFailures) {
// Ensures that rules which can't be parsed are ignored and cause an install
// warning.
-TEST_P(RuleIndexingTest, InvalidJSONRules_StrongTypes) {
+TEST_P(SingleRulesetIndexingTest, InvalidJSONRules_StrongTypes) {
{
TestRule rule = CreateGenericRule();
rule.id = 1;
@@ -395,27 +433,31 @@ TEST_P(RuleIndexingTest, InvalidJSONRules_StrongTypes) {
// Ensures that rules which can't be parsed are ignored and cause an install
// warning.
-TEST_P(RuleIndexingTest, InvalidJSONRules_Parsed) {
+TEST_P(SingleRulesetIndexingTest, InvalidJSONRules_Parsed) {
const char* kRules = R"(
[
{
"id" : 1,
+ "priority": 1,
"condition" : [],
"action" : {"type" : "block" }
},
{
"id" : 2,
+ "priority": 1,
"condition" : {"urlFilter" : "abc"},
"action" : {"type" : "block" }
},
{
"id" : 3,
+ "priority": 1,
"invalidKey" : "invalidKeyValue",
"condition" : {"urlFilter" : "example"},
"action" : {"type" : "block" }
},
{
"id" : "6",
+ "priority": 1,
"condition" : {"urlFilter" : "google"},
"action" : {"type" : "block" }
}
@@ -434,18 +476,20 @@ TEST_P(RuleIndexingTest, InvalidJSONRules_Parsed) {
expected_warnings.emplace_back(
ErrorUtils::FormatErrorMessage(
- kRuleNotParsedWarning, "id 1",
+ GetErrorWithFilename(kRuleNotParsedWarning), "id 1",
"'condition': expected dictionary, got list"),
manifest_keys::kDeclarativeNetRequestKey,
manifest_keys::kDeclarativeRuleResourcesKey);
expected_warnings.emplace_back(
- ErrorUtils::FormatErrorMessage(kRuleNotParsedWarning, "id 3",
- "found unexpected key 'invalidKey'"),
+ ErrorUtils::FormatErrorMessage(
+ GetErrorWithFilename(kRuleNotParsedWarning), "id 3",
+ "found unexpected key 'invalidKey'"),
manifest_keys::kDeclarativeNetRequestKey,
manifest_keys::kDeclarativeRuleResourcesKey);
expected_warnings.emplace_back(
- ErrorUtils::FormatErrorMessage(kRuleNotParsedWarning, "index 4",
- "'id': expected id, got string"),
+ ErrorUtils::FormatErrorMessage(
+ GetErrorWithFilename(kRuleNotParsedWarning), "index 4",
+ "'id': expected id, got string"),
manifest_keys::kDeclarativeNetRequestKey,
manifest_keys::kDeclarativeRuleResourcesKey);
EXPECT_EQ(expected_warnings, extension()->install_warnings());
@@ -453,8 +497,7 @@ TEST_P(RuleIndexingTest, InvalidJSONRules_Parsed) {
}
// Ensure that we can add up to MAX_NUMBER_OF_RULES.
-TEST_P(RuleIndexingTest, RuleCountLimitMatched) {
- namespace dnr_api = extensions::api::declarative_net_request;
+TEST_P(SingleRulesetIndexingTest, RuleCountLimitMatched) {
TestRule rule = CreateGenericRule();
for (int i = 0; i < dnr_api::MAX_NUMBER_OF_RULES; ++i) {
rule.id = kMinValidID + i;
@@ -465,8 +508,7 @@ TEST_P(RuleIndexingTest, RuleCountLimitMatched) {
}
// Ensure that we get an install warning on exceeding the rule count limit.
-TEST_P(RuleIndexingTest, RuleCountLimitExceeded) {
- namespace dnr_api = extensions::api::declarative_net_request;
+TEST_P(SingleRulesetIndexingTest, RuleCountLimitExceeded) {
TestRule rule = CreateGenericRule();
for (int i = 1; i <= dnr_api::MAX_NUMBER_OF_RULES + 1; ++i) {
rule.id = kMinValidID + i;
@@ -481,30 +523,126 @@ TEST_P(RuleIndexingTest, RuleCountLimitExceeded) {
// which causes it to lose the install warning. This should be fixed.
if (GetParam() != ExtensionLoadType::PACKED) {
ASSERT_EQ(1u, extension()->install_warnings().size());
- EXPECT_EQ(InstallWarning(kRuleCountExceeded,
+ EXPECT_EQ(InstallWarning(GetErrorWithFilename(kRuleCountExceeded),
+ manifest_keys::kDeclarativeNetRequestKey,
+ manifest_keys::kDeclarativeRuleResourcesKey),
+ extension()->install_warnings()[0]);
+ }
+}
+
+// Ensure that regex rules which exceed the per rule memory limit are ignored
+// and raise an install warning.
+TEST_P(SingleRulesetIndexingTest, LargeRegexIgnored) {
+ TestRule rule = CreateGenericRule();
+ rule.condition->url_filter.reset();
+ int id = kMinValidID;
+
+ const int kNumSmallRegex = 5;
+ std::string small_regex = "http://(yahoo|google)\\.com";
+ for (int i = 0; i < kNumSmallRegex; i++, id++) {
+ rule.id = id;
+ rule.condition->regex_filter = small_regex;
+ AddRule(rule);
+ }
+
+ const int kNumLargeRegex = 2;
+ for (int i = 0; i < kNumLargeRegex; i++, id++) {
+ rule.id = id;
+ rule.condition->regex_filter = kLargeRegexFilter;
+ AddRule(rule);
+ }
+
+ base::HistogramTester tester;
+ extension_loader()->set_ignore_manifest_warnings(true);
+
+ LoadAndExpectSuccess(kNumSmallRegex);
+
+ tester.ExpectBucketCount(kIsLargeRegexHistogram, true, kNumLargeRegex);
+ tester.ExpectBucketCount(kIsLargeRegexHistogram, false, kNumSmallRegex);
+
+ // TODO(crbug.com/879355): CrxInstaller reloads the extension after moving it,
+ // which causes it to lose the install warning. This should be fixed.
+ if (GetParam() != ExtensionLoadType::PACKED) {
+ InstallWarning warning_1 = GetLargeRegexWarning(kMinValidID + 5);
+ InstallWarning warning_2 = GetLargeRegexWarning(kMinValidID + 6);
+ EXPECT_THAT(
+ extension()->install_warnings(),
+ ::testing::UnorderedElementsAre(::testing::Eq(std::cref(warning_1)),
+ ::testing::Eq(std::cref(warning_2))));
+ }
+}
+
+// Test an extension with both an error and an install warning.
+TEST_P(SingleRulesetIndexingTest, WarningAndError) {
+ // Add a large regex rule which will exceed the per rule memory limit and
+ // cause an install warning.
+ TestRule rule = CreateGenericRule();
+ rule.condition->url_filter.reset();
+ rule.id = kMinValidID;
+ rule.condition->regex_filter = kLargeRegexFilter;
+ AddRule(rule);
+
+ // Add a regex rule with a syntax error.
+ rule.condition->regex_filter = "abc(";
+ rule.id = kMinValidID + 1;
+ AddRule(rule);
+
+ extension_loader()->set_ignore_manifest_warnings(true);
+ LoadAndExpectError(
+ GetParseError(ParseResult::ERROR_INVALID_REGEX_FILTER, kMinValidID + 1));
+}
+
+// Ensure that we get an install warning on exceeding the regex rule count
+// limit.
+TEST_P(SingleRulesetIndexingTest, RegexRuleCountExceeded) {
+ TestRule regex_rule = CreateGenericRule();
+ regex_rule.condition->url_filter.reset();
+ int rule_id = kMinValidID;
+ for (int i = 1; i <= dnr_api::MAX_NUMBER_OF_REGEX_RULES + 5; ++i, ++rule_id) {
+ regex_rule.id = rule_id;
+ regex_rule.condition->regex_filter = std::to_string(i);
+ AddRule(regex_rule);
+ }
+
+ const int kCountNonRegexRules = 5;
+ TestRule rule = CreateGenericRule();
+ for (int i = 1; i <= kCountNonRegexRules; i++, ++rule_id) {
+ rule.id = rule_id;
+ rule.condition->url_filter = std::to_string(i);
+ AddRule(rule);
+ }
+
+ extension_loader()->set_ignore_manifest_warnings(true);
+ LoadAndExpectSuccess(dnr_api::MAX_NUMBER_OF_REGEX_RULES +
+ kCountNonRegexRules);
+ // TODO(crbug.com/879355): CrxInstaller reloads the extension after moving it,
+ // which causes it to lose the install warning. This should be fixed.
+ if (GetParam() != ExtensionLoadType::PACKED) {
+ ASSERT_EQ(1u, extension()->install_warnings().size());
+ EXPECT_EQ(InstallWarning(GetErrorWithFilename(kRegexRuleCountExceeded),
manifest_keys::kDeclarativeNetRequestKey,
manifest_keys::kDeclarativeRuleResourcesKey),
extension()->install_warnings()[0]);
}
}
-TEST_P(RuleIndexingTest, InvalidJSONFile) {
+TEST_P(SingleRulesetIndexingTest, InvalidJSONFile) {
set_persist_invalid_json_file();
// The error is returned by the JSON parser we use. Hence just test an error
// is raised.
LoadAndExpectError("");
}
-TEST_P(RuleIndexingTest, EmptyRuleset) {
+TEST_P(SingleRulesetIndexingTest, EmptyRuleset) {
LoadAndExpectSuccess(0 /* rules count */);
}
-TEST_P(RuleIndexingTest, AddSingleRule) {
+TEST_P(SingleRulesetIndexingTest, AddSingleRule) {
AddRule(CreateGenericRule());
LoadAndExpectSuccess(1 /* rules count */);
}
-TEST_P(RuleIndexingTest, AddTwoRules) {
+TEST_P(SingleRulesetIndexingTest, AddTwoRules) {
TestRule rule = CreateGenericRule();
AddRule(rule);
@@ -514,14 +652,206 @@ TEST_P(RuleIndexingTest, AddTwoRules) {
}
// Test that we do not use an extension provided indexed ruleset.
-TEST_P(RuleIndexingTest, ExtensionWithIndexedRuleset) {
+TEST_P(SingleRulesetIndexingTest, ExtensionWithIndexedRuleset) {
set_persist_initial_indexed_ruleset();
AddRule(CreateGenericRule());
LoadAndExpectSuccess(1 /* rules count */);
}
+// Tests that multiple static rulesets are correctly indexed.
+class MultipleRulesetsIndexingTest : public RuleIndexingTestBase {
+ public:
+ MultipleRulesetsIndexingTest() = default;
+
+ protected:
+ // RuleIndexingTestBase override:
+ void WriteExtensionData() override {
+ WriteManifestAndRulesets(extension_dir(), rulesets_, {} /* hosts */);
+ }
+
+ void AddRuleset(TestRulesetInfo info) {
+ rulesets_.push_back(std::move(info));
+ }
+
+ private:
+ std::vector<TestRulesetInfo> rulesets_;
+};
+
+// Tests an extension with multiple static rulesets.
+TEST_P(MultipleRulesetsIndexingTest, Success) {
+ size_t kNumRulesets = 7;
+ size_t kRulesPerRuleset = 10;
+
+ std::vector<TestRule> rules;
+ for (size_t i = 0; i < kRulesPerRuleset; ++i) {
+ TestRule rule = CreateGenericRule();
+ rule.id = kMinValidID + i;
+ rules.push_back(rule);
+ }
+ base::Value rules_value = std::move(*ToListValue(rules));
+
+ for (size_t i = 0; i < kNumRulesets; ++i) {
+ TestRulesetInfo info;
+ info.relative_file_path = std::to_string(i);
+ info.rules_value = rules_value.Clone();
+ AddRuleset(std::move(info));
+ }
+
+ LoadAndExpectSuccess(kNumRulesets *
+ kRulesPerRuleset /* expected_indexed_rules_count */);
+}
+
+// Tests an extension with multiple empty rulesets.
+TEST_P(MultipleRulesetsIndexingTest, EmptyRulesets) {
+ size_t kNumRulesets = 7;
+
+ for (size_t i = 0; i < kNumRulesets; ++i) {
+ TestRulesetInfo info;
+ info.relative_file_path = std::to_string(i);
+ info.rules_value = base::ListValue();
+ AddRuleset(std::move(info));
+ }
+
+ LoadAndExpectSuccess(0u /* expected_indexed_rules_count */);
+}
+
+// Tests an extension with multiple static rulesets, with one of rulesets
+// specifying an invalid rules file.
+TEST_P(MultipleRulesetsIndexingTest, ListNotPassed) {
+ {
+ std::vector<TestRule> rules({CreateGenericRule()});
+ TestRulesetInfo info1;
+ info1.relative_file_path = "1";
+ info1.rules_value = std::move(*ToListValue(rules));
+ AddRuleset(std::move(info1));
+ }
+
+ {
+ // Persist a ruleset with an invalid rules file.
+ TestRulesetInfo info2;
+ info2.relative_file_path = "2";
+ info2.rules_value = base::DictionaryValue();
+ AddRuleset(std::move(info2));
+ }
+
+ {
+ TestRulesetInfo info3;
+ info3.relative_file_path = "3";
+ info3.rules_value = base::ListValue();
+ AddRuleset(std::move(info3));
+ }
+
+ LoadAndExpectError(kErrorListNotPassed, "2" /* filename */);
+}
+
+// Tests an extension with multiple static rulesets with each ruleset generating
+// some install warnings.
+TEST_P(MultipleRulesetsIndexingTest, InstallWarnings) {
+ size_t expected_rule_count = 0;
+ std::vector<std::string> expected_warnings;
+ {
+ // Persist a ruleset with an install warning for a large regex.
+ std::vector<TestRule> rules;
+ TestRule rule = CreateGenericRule();
+ rule.id = kMinValidID;
+ rules.push_back(rule);
+
+ rule.id = kMinValidID + 1;
+ rule.condition->url_filter.reset();
+ rule.condition->regex_filter = kLargeRegexFilter;
+ rules.push_back(rule);
+
+ TestRulesetInfo info;
+ info.relative_file_path = "1.json";
+ info.rules_value = std::move(*ToListValue(rules));
+
+ expected_warnings.push_back(
+ GetLargeRegexWarning(*rule.id, info.relative_file_path).message);
+
+ AddRuleset(std::move(info));
+
+ expected_rule_count += rules.size();
+ }
+
+ {
+ // Persist a ruleset with an install warning for exceeding the rule count.
+ std::vector<TestRule> rules;
+ for (int i = 1; i <= dnr_api::MAX_NUMBER_OF_RULES + 1; ++i) {
+ TestRule rule = CreateGenericRule();
+ rule.id = kMinValidID + i;
+ rules.push_back(rule);
+ }
+
+ TestRulesetInfo info;
+ info.relative_file_path = "2.json";
+ info.rules_value = std::move(*ToListValue(rules));
+
+ expected_warnings.push_back(
+ GetErrorWithFilename(kRuleCountExceeded, info.relative_file_path));
+
+ AddRuleset(std::move(info));
+
+ expected_rule_count += dnr_api::MAX_NUMBER_OF_RULES;
+ }
+
+ {
+ // Persist a ruleset with an install warning for exceeding the regex rule
+ // count.
+ std::vector<TestRule> rules;
+ TestRule regex_rule = CreateGenericRule();
+ regex_rule.condition->url_filter.reset();
+ int rule_id = kMinValidID;
+ for (int i = 1; i <= dnr_api::MAX_NUMBER_OF_REGEX_RULES + 1;
+ ++i, ++rule_id) {
+ regex_rule.id = rule_id;
+ regex_rule.condition->regex_filter = std::to_string(i);
+ rules.push_back(regex_rule);
+ }
+
+ const int kCountNonRegexRules = 5;
+ TestRule rule = CreateGenericRule();
+ for (int i = 1; i <= kCountNonRegexRules; i++, ++rule_id) {
+ rule.id = rule_id;
+ rule.condition->url_filter = std::to_string(i);
+ rules.push_back(rule);
+ }
+
+ TestRulesetInfo info;
+ info.relative_file_path = "3.json";
+ info.rules_value = std::move(*ToListValue(rules));
+
+ expected_warnings.push_back(
+ GetErrorWithFilename(kRegexRuleCountExceeded, info.relative_file_path));
+
+ AddRuleset(std::move(info));
+
+ expected_rule_count +=
+ kCountNonRegexRules + dnr_api::MAX_NUMBER_OF_REGEX_RULES;
+ }
+
+ extension_loader()->set_ignore_manifest_warnings(true);
+ LoadAndExpectSuccess(expected_rule_count);
+
+ // TODO(crbug.com/879355): CrxInstaller reloads the extension after moving it,
+ // which causes it to lose the install warning. This should be fixed.
+ if (GetParam() != ExtensionLoadType::PACKED) {
+ const std::vector<InstallWarning>& warnings =
+ extension()->install_warnings();
+ std::vector<std::string> warning_strings;
+ for (const InstallWarning& warning : warnings)
+ warning_strings.push_back(warning.message);
+
+ EXPECT_THAT(warning_strings,
+ ::testing::UnorderedElementsAreArray(expected_warnings));
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(All,
+ SingleRulesetIndexingTest,
+ ::testing::Values(ExtensionLoadType::PACKED,
+ ExtensionLoadType::UNPACKED));
INSTANTIATE_TEST_SUITE_P(All,
- RuleIndexingTest,
+ MultipleRulesetsIndexingTest,
::testing::Values(ExtensionLoadType::PACKED,
ExtensionLoadType::UNPACKED));
diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
index c9c00eb2913..1a3e1fba0bf 100644
--- a/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
@@ -43,8 +43,6 @@ namespace dnr_api = api::declarative_net_request;
namespace {
constexpr char kJSONRulesFilename[] = "rules_file.json";
-const base::FilePath::CharType kJSONRulesetFilepath[] =
- FILE_PATH_LITERAL("rules_file.json");
class RulesetManagerTest : public DNRTestBase {
public:
@@ -70,9 +68,12 @@ class RulesetManagerTest : public DNRTestBase {
// Create extension directory.
ASSERT_TRUE(base::CreateDirectory(extension_dir));
- WriteManifestAndRuleset(extension_dir, kJSONRulesetFilepath,
- kJSONRulesFilename, rules, host_permissions,
- has_background_script);
+ ConfigFlag flags = has_background_script
+ ? ConfigFlag::kConfig_HasBackgroundScript
+ : ConfigFlag::kConfig_None;
+
+ TestRulesetInfo info = {kJSONRulesFilename, std::move(*ToListValue(rules))};
+ WriteManifestAndRuleset(extension_dir, info, host_permissions, flags);
last_loaded_extension_ =
CreateExtensionLoader()->LoadExtension(extension_dir);
@@ -81,19 +82,22 @@ class RulesetManagerTest : public DNRTestBase {
ExtensionRegistry::Get(browser_context())
->AddEnabled(last_loaded_extension_);
+ std::vector<RulesetSource> sources =
+ RulesetSource::CreateStatic(*last_loaded_extension_);
+ ASSERT_EQ(1u, sources.size());
+
int expected_checksum;
EXPECT_TRUE(ExtensionPrefs::Get(browser_context())
- ->GetDNRRulesetChecksum(last_loaded_extension_->id(),
- &expected_checksum));
+ ->GetDNRStaticRulesetChecksum(last_loaded_extension_->id(),
+ sources[0].id(),
+ &expected_checksum));
std::vector<std::unique_ptr<RulesetMatcher>> matchers(1);
EXPECT_EQ(RulesetMatcher::kLoadSuccess,
RulesetMatcher::CreateVerifiedMatcher(
- RulesetSource::CreateStatic(*last_loaded_extension_),
- expected_checksum, &matchers[0]));
+ std::move(sources[0]), expected_checksum, &matchers[0]));
- *matcher = std::make_unique<CompositeMatcher>(std::move(matchers),
- nullptr /* action_tracker */);
+ *matcher = std::make_unique<CompositeMatcher>(std::move(matchers));
}
void SetIncognitoEnabled(const Extension* extension, bool incognito_enabled) {
@@ -163,8 +167,9 @@ TEST_P(RulesetManagerTest, MultipleRulesets) {
manager()->EvaluateRequest(request, false /*is_incognito_context*/);
return !request.dnr_actions->empty() &&
((*request.dnr_actions)[0] ==
- RequestAction(RequestActionType::BLOCK, rule_id, kDefaultPriority,
- dnr_api::SOURCE_TYPE_MANIFEST, extension_id));
+ CreateRequestActionForTesting(
+ RequestActionType::BLOCK, rule_id, kDefaultPriority,
+ dnr_api::SOURCE_TYPE_MANIFEST, extension_id));
};
for (int mask = 0; mask < 4; mask++) {
@@ -182,8 +187,7 @@ TEST_P(RulesetManagerTest, MultipleRulesets) {
ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
{rule_one}, std::to_string(mask) + "_one", &matcher));
extension_id_one = last_loaded_extension()->id();
- manager()->AddRuleset(extension_id_one, std::move(matcher),
- URLPatternSet());
+ manager()->AddRuleset(extension_id_one, std::move(matcher));
}
if (mask & kEnableRulesetTwo) {
++expected_matcher_count;
@@ -191,8 +195,7 @@ TEST_P(RulesetManagerTest, MultipleRulesets) {
ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
{rule_two}, std::to_string(mask) + "_two", &matcher));
extension_id_two = last_loaded_extension()->id();
- manager()->AddRuleset(extension_id_two, std::move(matcher),
- URLPatternSet());
+ manager()->AddRuleset(extension_id_two, std::move(matcher));
}
ASSERT_EQ(expected_matcher_count, manager()->GetMatcherCountForTest());
@@ -228,8 +231,7 @@ TEST_P(RulesetManagerTest, IncognitoRequests) {
std::unique_ptr<CompositeMatcher> matcher;
ASSERT_NO_FATAL_FAILURE(
CreateMatcherForRules({rule_one}, "test_extension", &matcher));
- manager()->AddRuleset(last_loaded_extension()->id(), std::move(matcher),
- URLPatternSet());
+ manager()->AddRuleset(last_loaded_extension()->id(), std::move(matcher));
WebRequestInfo request_info(GetRequestParamsForURL("http://example.com"));
@@ -244,9 +246,9 @@ TEST_P(RulesetManagerTest, IncognitoRequests) {
manager()->EvaluateRequest(request_info, false /*is_incognito_context*/);
ASSERT_EQ(1u, request_info.dnr_actions->size());
- EXPECT_EQ(RequestAction(RequestActionType::BLOCK, *rule_one.id,
- kDefaultPriority, dnr_api::SOURCE_TYPE_MANIFEST,
- last_loaded_extension()->id()),
+ EXPECT_EQ(CreateRequestActionForTesting(
+ RequestActionType::BLOCK, *rule_one.id, kDefaultPriority,
+ dnr_api::SOURCE_TYPE_MANIFEST, last_loaded_extension()->id()),
(*request_info.dnr_actions)[0]);
request_info.dnr_actions.reset();
@@ -258,23 +260,23 @@ TEST_P(RulesetManagerTest, IncognitoRequests) {
manager()->EvaluateRequest(request_info, true /*is_incognito_context*/);
ASSERT_EQ(1u, request_info.dnr_actions->size());
- EXPECT_EQ(RequestAction(RequestActionType::BLOCK, *rule_one.id,
- kDefaultPriority, dnr_api::SOURCE_TYPE_MANIFEST,
- last_loaded_extension()->id()),
+ EXPECT_EQ(CreateRequestActionForTesting(
+ RequestActionType::BLOCK, *rule_one.id, kDefaultPriority,
+ dnr_api::SOURCE_TYPE_MANIFEST, last_loaded_extension()->id()),
(*request_info.dnr_actions)[0]);
request_info.dnr_actions.reset();
manager()->EvaluateRequest(request_info, false /*is_incognito_context*/);
ASSERT_EQ(1u, request_info.dnr_actions->size());
- EXPECT_EQ(RequestAction(RequestActionType::BLOCK, *rule_one.id,
- kDefaultPriority, dnr_api::SOURCE_TYPE_MANIFEST,
- last_loaded_extension()->id()),
+ EXPECT_EQ(CreateRequestActionForTesting(
+ RequestActionType::BLOCK, *rule_one.id, kDefaultPriority,
+ dnr_api::SOURCE_TYPE_MANIFEST, last_loaded_extension()->id()),
(*request_info.dnr_actions)[0]);
request_info.dnr_actions.reset();
}
// Tests that
-// Extensions.DeclarativeNetRequest.EvaluateRequestTime.AllExtensions2
+// Extensions.DeclarativeNetRequest.EvaluateRequestTime.AllExtensions3
// is only emitted when there are active rulesets.
TEST_P(RulesetManagerTest, TotalEvaluationTimeHistogram) {
WebRequestInfo example_com_request(
@@ -283,7 +285,7 @@ TEST_P(RulesetManagerTest, TotalEvaluationTimeHistogram) {
GetRequestParamsForURL("http://google.com"));
bool is_incognito_context = false;
const char* kHistogramName =
- "Extensions.DeclarativeNetRequest.EvaluateRequestTime.AllExtensions2";
+ "Extensions.DeclarativeNetRequest.EvaluateRequestTime.AllExtensions3";
{
base::HistogramTester tester;
@@ -304,17 +306,16 @@ TEST_P(RulesetManagerTest, TotalEvaluationTimeHistogram) {
std::unique_ptr<CompositeMatcher> matcher;
ASSERT_NO_FATAL_FAILURE(
CreateMatcherForRules({rule}, "test_extension", &matcher));
- manager()->AddRuleset(last_loaded_extension()->id(), std::move(matcher),
- URLPatternSet());
+ manager()->AddRuleset(last_loaded_extension()->id(), std::move(matcher));
{
base::HistogramTester tester;
manager()->EvaluateRequest(example_com_request, is_incognito_context);
ASSERT_EQ(1u, example_com_request.dnr_actions->size());
- EXPECT_EQ(RequestAction(RequestActionType::BLOCK, *rule.id,
- kDefaultPriority, dnr_api::SOURCE_TYPE_MANIFEST,
- last_loaded_extension()->id()),
+ EXPECT_EQ(CreateRequestActionForTesting(
+ RequestActionType::BLOCK, *rule.id, kDefaultPriority,
+ dnr_api::SOURCE_TYPE_MANIFEST, last_loaded_extension()->id()),
(*example_com_request.dnr_actions)[0]);
tester.ExpectTotalCount(kHistogramName, 1);
@@ -341,14 +342,13 @@ TEST_P(RulesetManagerTest, Redirect) {
ASSERT_NO_FATAL_FAILURE(
CreateMatcherForRules({rule}, "test_extension", &matcher,
{"*://example.com/*", "*://abc.com/*"}));
- manager()->AddRuleset(last_loaded_extension()->id(), std::move(matcher),
- URLPatternSet());
+ manager()->AddRuleset(last_loaded_extension()->id(), std::move(matcher));
// Create a request to "example.com" with an empty initiator. It should be
// redirected to "google.com".
const bool is_incognito_context = false;
const char* kExampleURL = "http://example.com";
- RequestAction expected_redirect_action(
+ RequestAction expected_redirect_action = CreateRequestActionForTesting(
RequestActionType::REDIRECT, *rule.id, *rule.priority,
dnr_api::SOURCE_TYPE_MANIFEST, last_loaded_extension()->id());
expected_redirect_action.redirect_url = GURL("http://google.com");
@@ -392,10 +392,9 @@ TEST_P(RulesetManagerTest, ExtensionScheme) {
ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
{rule}, "test extension", &matcher,
std::vector<std::string>({URLPattern::kAllUrlsPattern}),
- true /* has_background_script*/));
+ true /* has_background_script */));
extension_1 = last_loaded_extension();
- manager()->AddRuleset(extension_1->id(), std::move(matcher),
- URLPatternSet());
+ manager()->AddRuleset(extension_1->id(), std::move(matcher));
}
// Add another extension with a background page which redirects all requests
@@ -411,10 +410,9 @@ TEST_P(RulesetManagerTest, ExtensionScheme) {
ASSERT_NO_FATAL_FAILURE(CreateMatcherForRules(
{rule}, "test extension_2", &matcher,
std::vector<std::string>({URLPattern::kAllUrlsPattern}),
- true /* has_background_script*/));
+ true /* has_background_script */));
extension_2 = last_loaded_extension();
- manager()->AddRuleset(extension_2->id(), std::move(matcher),
- URLPatternSet());
+ manager()->AddRuleset(extension_2->id(), std::move(matcher));
}
EXPECT_EQ(2u, manager()->GetMatcherCountForTest());
@@ -424,10 +422,10 @@ TEST_P(RulesetManagerTest, ExtensionScheme) {
WebRequestInfo request_1(GetRequestParamsForURL("http://example.com"));
manager()->EvaluateRequest(request_1, false /*is_incognito_context*/);
ASSERT_EQ(1u, request_1.dnr_actions->size());
- EXPECT_EQ(
- RequestAction(RequestActionType::BLOCK, kMinValidID, kDefaultPriority,
- dnr_api::SOURCE_TYPE_MANIFEST, extension_1->id()),
- (*request_1.dnr_actions)[0]);
+ EXPECT_EQ(CreateRequestActionForTesting(
+ RequestActionType::BLOCK, kMinValidID, kDefaultPriority,
+ dnr_api::SOURCE_TYPE_MANIFEST, extension_1->id()),
+ (*request_1.dnr_actions)[0]);
// Ensure that the background page for |extension_1| won't be blocked or
// redirected.
@@ -473,8 +471,7 @@ TEST_P(RulesetManagerTest, RemoveHeaders) {
ASSERT_NO_FATAL_FAILURE(
CreateMatcherForRules({rule}, "test extension", &matcher));
extension_1 = last_loaded_extension();
- manager()->AddRuleset(extension_1->id(), std::move(matcher),
- URLPatternSet());
+ manager()->AddRuleset(extension_1->id(), std::move(matcher));
}
// Add another extension with a background page which removes the "cookie" and
@@ -490,8 +487,7 @@ TEST_P(RulesetManagerTest, RemoveHeaders) {
ASSERT_NO_FATAL_FAILURE(
CreateMatcherForRules({rule}, "test extension 2", &matcher));
extension_2 = last_loaded_extension();
- manager()->AddRuleset(extension_2->id(), std::move(matcher),
- URLPatternSet());
+ manager()->AddRuleset(extension_2->id(), std::move(matcher));
}
EXPECT_EQ(2u, manager()->GetMatcherCountForTest());
@@ -511,7 +507,7 @@ TEST_P(RulesetManagerTest, RemoveHeaders) {
// Removal of the cookie header should be attributed to |extension_2| because
// it was installed later than |extension_1| and thus has more priority.
- RequestAction expected_action_1(
+ RequestAction expected_action_1 = CreateRequestActionForTesting(
RequestActionType::REMOVE_HEADERS, kMinValidID, kDefaultPriority,
dnr_api::SOURCE_TYPE_MANIFEST, extension_2->id());
expected_action_1.request_headers_to_remove.push_back(
@@ -521,7 +517,7 @@ TEST_P(RulesetManagerTest, RemoveHeaders) {
expected_action_1.request_headers_to_remove.push_back(
net::HttpRequestHeaders::kReferer);
- RequestAction expected_action_2(
+ RequestAction expected_action_2 = CreateRequestActionForTesting(
RequestActionType::REMOVE_HEADERS, kMinValidID, kDefaultPriority,
dnr_api::SOURCE_TYPE_MANIFEST, extension_1->id());
expected_action_2.response_headers_to_remove.push_back("set-cookie");
@@ -530,175 +526,6 @@ TEST_P(RulesetManagerTest, RemoveHeaders) {
EXPECT_EQ(expected_action_2, actual_actions[1]);
}
-TEST_P(RulesetManagerTest, PageAllowingAPI) {
- // Add an extension which blocks all requests except for requests from
- // http://google.com/allow* which are allowed.
- {
- std::unique_ptr<CompositeMatcher> matcher;
-
- // This blocks all subresource requests. By default the main-frame resource
- // type is excluded.
- TestRule rule1 = CreateGenericRule();
- rule1.id = kMinValidID;
- rule1.condition->url_filter = std::string("*");
-
- // Also block main frame requests.
- TestRule rule2 = CreateGenericRule();
- rule2.id = kMinValidID + 1;
- rule2.condition->url_filter = std::string("*");
- rule2.condition->resource_types = std::vector<std::string>({"main_frame"});
-
- ASSERT_NO_FATAL_FAILURE(
- CreateMatcherForRules({rule1, rule2}, "test extension", &matcher, {},
- true /* background_script */));
-
- URLPatternSet pattern_set(
- {URLPattern(URLPattern::SCHEME_ALL, "http://google.com/allow*")});
- manager()->AddRuleset(last_loaded_extension()->id(), std::move(matcher),
- std::move(pattern_set));
- }
-
- int rule_1_id = kMinValidID;
- int rule_2_id = kMinValidID + 1;
-
- constexpr int kDummyFrameRoutingId = 2;
- constexpr int kDummyFrameId = 3;
- constexpr int kDummyParentFrameId = 1;
- constexpr int kDummyTabId = 5;
- constexpr int kDummyWindowId = 7;
- constexpr char kAllowedPageURL[] = "http://google.com/allow123";
-
- struct FrameDataParams {
- int frame_id;
- int parent_frame_id;
- std::string last_committed_main_frame_url;
- base::Optional<GURL> pending_main_frame_url;
- };
- struct TestCase {
- std::string url;
- content::ResourceType type;
- base::Optional<std::string> initiator;
- int frame_routing_id;
- base::Optional<FrameDataParams> frame_data_params;
- bool expect_blocked_with_allowed_pages;
- base::Optional<int> matched_rule_id;
- } test_cases[] = {
- // Main frame requests. Allowed based on request url.
- {kAllowedPageURL, content::ResourceType::kMainFrame, base::nullopt,
- MSG_ROUTING_NONE,
- FrameDataParams({ExtensionApiFrameIdMap::kTopFrameId,
- ExtensionApiFrameIdMap::kInvalidFrameId,
- "http://google.com/xyz", base::nullopt}),
- false, base::nullopt},
- {"http://google.com/xyz", content::ResourceType::kMainFrame,
- base::nullopt, MSG_ROUTING_NONE,
- FrameDataParams({ExtensionApiFrameIdMap::kTopFrameId,
- ExtensionApiFrameIdMap::kInvalidFrameId,
- kAllowedPageURL, base::nullopt}),
- true, rule_2_id},
-
- // Non-navigation browser or service worker request. Not allowed,
- // since the request doesn't correspond to a frame.
- {"http://google.com/xyz", content::ResourceType::kScript, base::nullopt,
- MSG_ROUTING_NONE, base::nullopt, true, rule_1_id},
-
- // Renderer requests - with no |pending_main_frame_url|. Allowed based
- // on the |last_committed_main_frame_url|.
- {kAllowedPageURL, content::ResourceType::kScript, "http://google.com",
- kDummyFrameRoutingId,
- FrameDataParams({kDummyFrameId, kDummyParentFrameId,
- "http://google.com/xyz", base::nullopt}),
- true, rule_1_id},
- {"http://google.com/xyz", content::ResourceType::kScript,
- "http://google.com", kDummyFrameRoutingId,
- FrameDataParams({kDummyFrameId, kDummyParentFrameId, kAllowedPageURL,
- base::nullopt}),
- false, base::nullopt},
-
- // Renderer requests with |pending_main_frame_url|. This only happens for
- // main frame subresource requests.
-
- // Here we'll determine "http://example.com/xyz" to be the main frame url
- // due to the origin.
- {"http://example.com/script.js", content::ResourceType::kScript,
- "http://example.com", kDummyFrameRoutingId,
- FrameDataParams({ExtensionApiFrameIdMap::kTopFrameId,
- ExtensionApiFrameIdMap::kInvalidFrameId,
- kAllowedPageURL, GURL("http://example.com/xyz")}),
- true, rule_1_id},
-
- // Here we'll determine |kAllowedPageURL| to be the main
- // frame url due to the origin.
- {"http://example.com/script.js", content::ResourceType::kScript,
- "http://google.com", kDummyFrameRoutingId,
- FrameDataParams({ExtensionApiFrameIdMap::kTopFrameId,
- ExtensionApiFrameIdMap::kInvalidFrameId,
- kAllowedPageURL, GURL("http://yahoo.com/xyz")}),
- false, base::nullopt},
-
- // In these cases both |pending_main_frame_url| and
- // |last_committed_main_frame_url| will be tested since we won't be able
- // to determine the correct top level frame url using origin.
- {"http://example.com/script.js", content::ResourceType::kScript,
- "http://google.com", kDummyFrameRoutingId,
- FrameDataParams({ExtensionApiFrameIdMap::kTopFrameId,
- ExtensionApiFrameIdMap::kInvalidFrameId,
- "http://google.com/abc", GURL(kAllowedPageURL)}),
- false, base::nullopt},
- {"http://example.com/script.js", content::ResourceType::kScript,
- base::nullopt, kDummyFrameRoutingId,
- FrameDataParams({ExtensionApiFrameIdMap::kTopFrameId,
- ExtensionApiFrameIdMap::kInvalidFrameId,
- kAllowedPageURL, GURL("http://google.com/abc")}),
- false, base::nullopt},
- {"http://example.com/script.js", content::ResourceType::kScript,
- base::nullopt, kDummyFrameRoutingId,
- FrameDataParams({ExtensionApiFrameIdMap::kTopFrameId,
- ExtensionApiFrameIdMap::kInvalidFrameId,
- "http://yahoo.com/abc",
- GURL("http://yahoo.com/allow123")}),
- true, rule_1_id},
- };
-
- for (size_t i = 0; i < base::size(test_cases); ++i) {
- const TestCase test_case = test_cases[i];
- SCOPED_TRACE(base::StringPrintf("Testing case number %zu with url %s",
- i + 1, test_case.url.c_str()));
-
- WebRequestInfoInitParams params = GetRequestParamsForURL(test_case.url);
- ASSERT_TRUE(params.url.is_valid());
- params.type = test_case.type;
-
- if (test_case.initiator)
- params.initiator = url::Origin::Create(GURL(*test_case.initiator));
-
- params.frame_id = test_case.frame_routing_id;
-
- if (test_case.frame_data_params) {
- const FrameDataParams& frame_params = *test_case.frame_data_params;
- params.frame_data = ExtensionApiFrameIdMap::FrameData(
- frame_params.frame_id, frame_params.parent_frame_id, kDummyTabId,
- kDummyWindowId, GURL(frame_params.last_committed_main_frame_url),
- frame_params.pending_main_frame_url);
- }
-
- WebRequestInfo request_info(std::move(params));
- const std::vector<RequestAction>& actions = manager()->EvaluateRequest(
- request_info, false /*is_incognito_context*/);
-
- if (test_case.expect_blocked_with_allowed_pages) {
- ASSERT_EQ(1u, actions.size());
- EXPECT_EQ(
- RequestAction(RequestActionType::BLOCK, *test_case.matched_rule_id,
- kDefaultPriority, dnr_api::SOURCE_TYPE_MANIFEST,
- last_loaded_extension()->id()),
- actions[0]);
- } else {
- EXPECT_TRUE(actions.empty());
- }
- }
-}
-
TEST_P(RulesetManagerTest, HostPermissionForInitiator) {
// Add an extension which redirects all sub-resource and sub-frame requests
// made to example.com, to foo.com. By default, the "main_frame" type is
@@ -779,10 +606,9 @@ TEST_P(RulesetManagerTest, HostPermissionForInitiator) {
// Test redirect extension.
{
SCOPED_TRACE("Testing redirect extension");
- manager()->AddRuleset(redirect_extension_id, std::move(redirect_matcher),
- URLPatternSet());
+ manager()->AddRuleset(redirect_extension_id, std::move(redirect_matcher));
for (const auto& test : cases) {
- RequestAction redirect_action(
+ RequestAction redirect_action = CreateRequestActionForTesting(
RequestActionType::REDIRECT, kMinValidID, kMinValidPriority,
dnr_api::SOURCE_TYPE_MANIFEST, redirect_extension_id);
redirect_action.redirect_url = GURL("https://foo.com/");
@@ -797,10 +623,9 @@ TEST_P(RulesetManagerTest, HostPermissionForInitiator) {
// Test blocking extension.
{
SCOPED_TRACE("Testing blocking extension");
- manager()->AddRuleset(blocking_extension_id, std::move(blocking_matcher),
- URLPatternSet());
+ manager()->AddRuleset(blocking_extension_id, std::move(blocking_matcher));
for (const auto& test : cases) {
- RequestAction block_action(
+ RequestAction block_action = CreateRequestActionForTesting(
RequestActionType::BLOCK, kMinValidID, kDefaultPriority,
dnr_api::SOURCE_TYPE_MANIFEST, blocking_extension_id);
diff --git a/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
index 897c6601bb7..fc786dded3c 100644
--- a/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
@@ -58,7 +58,7 @@ WebRequestInfoInitParams CreateRequestParams(const GURL& url) {
WebRequestInfoInitParams info;
info.url = url;
info.is_navigation_request = true;
- info.type = content::ResourceType::kMainFrame;
+ info.type = blink::mojom::ResourceType::kMainFrame;
info.web_request_type = WebRequestResourceType::MAIN_FRAME;
return info;
}
@@ -611,16 +611,14 @@ TEST_F(WebRequestRulesRegistryTest, GetMatchesCheckFulfilled) {
EXPECT_EQ(expected_pair, (*matches.begin())->id());
}
-// Test that the url and firstPartyForCookiesUrl attributes are evaluated
-// against corresponding URLs. Tested on requests where these URLs actually
-// differ.
+// Test different URL patterns.
TEST_F(WebRequestRulesRegistryTest, GetMatchesDifferentUrls) {
scoped_refptr<TestWebRequestRulesRegistry> registry(
new TestWebRequestRulesRegistry(&profile_));
const std::string kUrlAttribute(
"\"url\": { \"hostContains\": \"url\" }, \n");
- const std::string kFirstPartyUrlAttribute(
- "\"firstPartyForCookiesUrl\": { \"hostContains\": \"fpfc\" }, \n");
+ const std::string kUrlAttribute2(
+ "\"url\": { \"hostContains\": \"www\" }, \n");
{
std::string error;
@@ -631,9 +629,9 @@ TEST_F(WebRequestRulesRegistryTest, GetMatchesDifferentUrls) {
attributes.push_back(&kUrlAttribute);
rules.push_back(CreateCancellingRule(kRuleId1, attributes));
- // Rule 2 has one condition, with a firstPartyForCookiesUrl attribute
+ // Rule 2 has one condition, also with a url attribute
attributes.clear();
- attributes.push_back(&kFirstPartyUrlAttribute);
+ attributes.push_back(&kUrlAttribute2);
rules.push_back(CreateCancellingRule(kRuleId2, attributes));
error = registry->AddRules(kExtensionId, std::move(rules));
@@ -647,15 +645,8 @@ TEST_F(WebRequestRulesRegistryTest, GetMatchesDifferentUrls) {
GURL("http://url.example.com"), // matching
GURL("http://www.example.com") // non-matching
};
- const GURL firstPartyUrls[] = {
- GURL("http://www.example.com"), // non-matching
- GURL("http://fpfc.example.com") // matching
- };
// Which rules should match in subsequent test iterations.
const char* const matchingRuleIds[] = { kRuleId1, kRuleId2 };
- static_assert(base::size(urls) == base::size(firstPartyUrls),
- "urls and firstPartyUrls must have the same number "
- "of elements");
static_assert(base::size(urls) == base::size(matchingRuleIds),
"urls and matchingRuleIds must have the same number "
"of elements");
@@ -663,7 +654,6 @@ TEST_F(WebRequestRulesRegistryTest, GetMatchesDifferentUrls) {
for (size_t i = 0; i < base::size(matchingRuleIds); ++i) {
// Construct the inputs.
WebRequestInfoInitParams params = CreateRequestParams(urls[i]);
- params.site_for_cookies = firstPartyUrls[i];
WebRequestInfo http_request_info(std::move(params));
WebRequestData request_data(&http_request_info, ON_BEFORE_REQUEST);
// Now run both rules on the input.
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc
index 9b97e1bbd96..911c4fdc978 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
@@ -37,7 +38,8 @@ DesktopCaptureChooseDesktopMediaFunction::
~DesktopCaptureChooseDesktopMediaFunction() {
}
-bool DesktopCaptureChooseDesktopMediaFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+DesktopCaptureChooseDesktopMediaFunction::Run() {
EXTENSION_FUNCTION_VALIDATE(args_->GetSize() > 0);
EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id_));
@@ -57,35 +59,32 @@ bool DesktopCaptureChooseDesktopMediaFunction::RunAsync() {
GURL origin;
if (params->target_tab) {
if (!params->target_tab->url) {
- error_ = kDesktopCaptureApiNoUrlError;
- return false;
+ return RespondNow(Error(kDesktopCaptureApiNoUrlError));
}
origin = GURL(*(params->target_tab->url)).GetOrigin();
if (!origin.is_valid()) {
- error_ = kDesktopCaptureApiInvalidOriginError;
- return false;
+ return RespondNow(Error(kDesktopCaptureApiInvalidOriginError));
}
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kAllowHttpScreenCapture) &&
!content::IsOriginSecure(origin)) {
- error_ = kDesktopCaptureApiTabUrlNotSecure;
- return false;
+ return RespondNow(Error(kDesktopCaptureApiTabUrlNotSecure));
}
target_name = base::UTF8ToUTF16(content::IsOriginSecure(origin) ?
net::GetHostAndOptionalPort(origin) : origin.spec());
if (!params->target_tab->id ||
*params->target_tab->id == api::tabs::TAB_ID_NONE) {
- error_ = kDesktopCaptureApiNoTabIdError;
- return false;
+ return RespondNow(Error(kDesktopCaptureApiNoTabIdError));
}
- if (!ExtensionTabUtil::GetTabById(*(params->target_tab->id), GetProfile(),
- true, &web_contents)) {
- error_ = kDesktopCaptureApiInvalidTabIdError;
- return false;
+ ChromeExtensionFunctionDetails details(this);
+ if (!ExtensionTabUtil::GetTabById(*(params->target_tab->id),
+ details.GetProfile(), true,
+ &web_contents)) {
+ return RespondNow(Error(kDesktopCaptureApiInvalidTabIdError));
}
DCHECK(web_contents);
} else {
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h
index 82cc4fc3c59..590a06410e8 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h
@@ -21,7 +21,7 @@ class DesktopCaptureChooseDesktopMediaFunction
~DesktopCaptureChooseDesktopMediaFunction() override;
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
// Returns the target name to show in the picker when capture is requested for
// an extension. Currently this is the same as the application name.
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
index 106d9fbcbdb..8d08473ddd7 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
@@ -149,8 +149,8 @@ IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, DISABLED_Delegation) {
// Load extension.
base::FilePath extension_path =
test_data_dir_.AppendASCII("desktop_capture_delegate");
- const Extension* extension = LoadExtensionWithFlags(
- extension_path, ExtensionBrowserTest::kFlagNone);
+ const Extension* extension =
+ LoadExtensionWithFlags(extension_path, kFlagNone);
ASSERT_TRUE(extension);
ui_test_utils::NavigateToURL(
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
index c0eed2de936..fa790782b3e 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
@@ -68,11 +68,11 @@ void DesktopCaptureChooseDesktopMediaFunctionBase::Cancel() {
// If this picker dialog is open, this will close it.
picker_controller_.reset();
- SetResultList(Create(std::string(), Options()));
- SendResponse(true);
+ Respond(ArgumentList(Create(std::string(), Options())));
}
-bool DesktopCaptureChooseDesktopMediaFunctionBase::Execute(
+ExtensionFunction::ResponseAction
+DesktopCaptureChooseDesktopMediaFunctionBase::Execute(
const std::vector<api::desktop_capture::DesktopCaptureSourceType>& sources,
content::WebContents* web_contents,
const GURL& origin,
@@ -96,8 +96,7 @@ bool DesktopCaptureChooseDesktopMediaFunctionBase::Execute(
for (auto source_type : sources) {
switch (source_type) {
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_NONE: {
- error_ = kInvalidSourceNameError;
- return false;
+ return RespondNow(Error(kInvalidSourceNameError));
}
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_SCREEN: {
media_types.push_back(content::DesktopMediaID::TYPE_SCREEN);
@@ -135,7 +134,7 @@ bool DesktopCaptureChooseDesktopMediaFunctionBase::Execute(
std::make_unique<DesktopMediaPickerController>(g_picker_factory);
picker_controller_->Show(picker_params, std::move(media_types),
std::move(callback));
- return true;
+ return RespondLater();
}
std::string DesktopCaptureChooseDesktopMediaFunctionBase::GetCallerDisplayName()
@@ -156,15 +155,13 @@ void DesktopCaptureChooseDesktopMediaFunctionBase::OnPickerDialogResults(
picker_controller_.reset();
if (!err.empty()) {
- SetError(err);
- SendResponse(false);
+ Respond(Error(err));
return;
}
if (source.is_null()) {
DLOG(ERROR) << "Sending empty results.";
- SetResultList(Create(std::string(), Options()));
- SendResponse(true);
+ Respond(ArgumentList(Create(std::string(), Options())));
return;
}
@@ -184,8 +181,7 @@ void DesktopCaptureChooseDesktopMediaFunctionBase::OnPickerDialogResults(
Options options;
options.can_request_audio_track = source.audio_share;
- results_ = Create(result, options);
- SendResponse(true);
+ Respond(ArgumentList(Create(result, options)));
}
DesktopCaptureRequestsRegistry::RequestId::RequestId(int process_id,
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
index 80232e13338..a52f8fdec80 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
@@ -12,17 +12,16 @@
#include "base/macros.h"
#include "base/memory/singleton.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/media/webrtc/desktop_media_list.h"
#include "chrome/browser/media/webrtc/desktop_media_picker_controller.h"
#include "chrome/browser/media/webrtc/desktop_media_picker_factory.h"
#include "chrome/common/extensions/api/desktop_capture.h"
+#include "extensions/browser/extension_function.h"
#include "url/gurl.h"
namespace extensions {
-class DesktopCaptureChooseDesktopMediaFunctionBase
- : public ChromeAsyncExtensionFunction {
+class DesktopCaptureChooseDesktopMediaFunctionBase : public ExtensionFunction {
public:
// Used to set PickerFactory used to create mock DesktopMediaPicker instances
// for tests. Calling tests keep ownership of the factory. Can be called with
@@ -40,11 +39,12 @@ class DesktopCaptureChooseDesktopMediaFunctionBase
// also be used to determine where to show the picker's UI.
// |origin| is the origin for which the stream is created.
// |target_name| is the display name of the stream target.
- bool Execute(const std::vector<
- api::desktop_capture::DesktopCaptureSourceType>& sources,
- content::WebContents* web_contents,
- const GURL& origin,
- const base::string16 target_name);
+ ResponseAction Execute(
+ const std::vector<api::desktop_capture::DesktopCaptureSourceType>&
+ sources,
+ content::WebContents* web_contents,
+ const GURL& origin,
+ const base::string16 target_name);
// Returns the calling application name to show in the picker.
std::string GetCallerDisplayName() const;
diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 864ce983083..331cb00c50d 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -20,6 +20,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/apps/app_service/app_launch_params.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/extensions/api/developer_private/developer_private_mangle.h"
@@ -33,7 +34,6 @@
#include "chrome/browser/extensions/extension_commands_global_registry.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/install_verifier.h"
#include "chrome/browser/extensions/permissions_updater.h"
@@ -45,7 +45,6 @@
#include "chrome/browser/platform_util.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/apps/app_info_dialog.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/extensions/application_launch.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
@@ -81,6 +80,7 @@
#include "extensions/browser/notification_types.h"
#include "extensions/browser/path_util.h"
#include "extensions/browser/process_manager_factory.h"
+#include "extensions/browser/ui_util.h"
#include "extensions/browser/warning_service.h"
#include "extensions/browser/warning_service_factory.h"
#include "extensions/browser/zipfile_installer.h"
@@ -101,6 +101,7 @@
#include "storage/browser/file_system/isolated_context.h"
#include "third_party/re2/src/re2/re2.h"
#include "ui/base/l10n/l10n_util.h"
+#include "url/origin.h"
namespace extensions {
@@ -176,9 +177,8 @@ void GetManifestError(const std::string& error,
// This will read the manifest and call AddFailure with the read manifest
// contents.
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(&ReadFileToString,
extension_path.Append(kManifestFilename)),
base::BindOnce(std::move(callback), extension_path, error, line));
@@ -211,7 +211,7 @@ void PerformVerificationCheck(content::BrowserContext* context) {
ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
bool should_do_verification_check = false;
for (const scoped_refptr<const Extension>& extension : *extensions) {
- if (ui_util::ShouldDisplayInExtensionSettings(extension.get(), context) &&
+ if (ui_util::ShouldDisplayInExtensionSettings(*extension) &&
prefs->HasDisableReason(extension->id(),
disable_reason::DISABLE_NOT_VERIFIED)) {
should_do_verification_check = true;
@@ -324,7 +324,6 @@ std::unique_ptr<developer::ProfileInfo> DeveloperPrivateAPI::CreateProfileInfo(
info->in_developer_mode =
!info->is_supervised &&
prefs->GetBoolean(prefs::kExtensionsUIDeveloperMode);
- info->app_info_dialog_enabled = CanPlatformShowAppInfoDialog();
info->can_load_unpacked =
ExtensionManagementFactory::GetForBrowserContext(profile)
->HasWhitelistedExtension();
@@ -932,6 +931,8 @@ DeveloperPrivateUpdateExtensionConfigurationFunction::Run() {
modifier.RemoveAllGrantedHostPermissions();
break;
case developer::HOST_ACCESS_ON_SPECIFIC_SITES:
+ if (modifier.HasBroadGrantedHostPermissions())
+ modifier.RemoveBroadGrantedHostPermissions();
modifier.SetWithholdHostPermissions(true);
break;
case developer::HOST_ACCESS_ON_ALL_SITES:
@@ -1176,8 +1177,8 @@ void DeveloperPrivateLoadUnpackedFunction::OnLoadComplete(
GetManifestError(
error, file_path,
- base::Bind(&DeveloperPrivateLoadUnpackedFunction::OnGotManifestError,
- this));
+ base::BindOnce(&DeveloperPrivateLoadUnpackedFunction::OnGotManifestError,
+ this));
}
void DeveloperPrivateLoadUnpackedFunction::OnGotManifestError(
@@ -1378,7 +1379,7 @@ DeveloperPrivatePackDirectoryFunction::
DeveloperPrivateLoadUnpackedFunction::~DeveloperPrivateLoadUnpackedFunction() {}
-bool DeveloperPrivateLoadDirectoryFunction::RunAsync() {
+ExtensionFunction::ResponseAction DeveloperPrivateLoadDirectoryFunction::Run() {
// TODO(grv) : add unittests.
std::string directory_url_str;
std::string filesystem_name;
@@ -1398,48 +1399,47 @@ bool DeveloperPrivateLoadDirectoryFunction::RunAsync() {
context_->CrackURL(GURL(directory_url_str));
if (!directory_url.is_valid() ||
directory_url.type() != storage::kFileSystemTypeSyncable) {
- SetError("DirectoryEntry of unsupported filesystem.");
- return false;
+ return RespondNow(Error("DirectoryEntry of unsupported filesystem."));
}
return LoadByFileSystemAPI(directory_url);
- } else {
- // Check if the DirectoryEntry is the instance of chrome filesystem.
- if (!app_file_handler_util::ValidateFileEntryAndGetPath(
- filesystem_name, filesystem_path, source_process_id(),
- &project_base_path_, &error_)) {
- SetError("DirectoryEntry of unsupported filesystem.");
- return false;
- }
+ }
- // Try to load using the FileSystem API backend, in case the filesystem
- // points to a non-native local directory.
- std::string filesystem_id;
- bool cracked =
- storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id);
- CHECK(cracked);
- base::FilePath virtual_path =
- storage::IsolatedContext::GetInstance()
- ->CreateVirtualRootPath(filesystem_id)
- .Append(base::FilePath::FromUTF8Unsafe(filesystem_path));
- storage::FileSystemURL directory_url = context_->CreateCrackedFileSystemURL(
- extensions::Extension::GetBaseURLFromExtensionId(extension_id()),
- storage::kFileSystemTypeIsolated,
- virtual_path);
-
- if (directory_url.is_valid() &&
- directory_url.type() != storage::kFileSystemTypeNativeLocal &&
- directory_url.type() != storage::kFileSystemTypeRestrictedNativeLocal &&
- directory_url.type() != storage::kFileSystemTypeDragged) {
- return LoadByFileSystemAPI(directory_url);
- }
+ std::string unused_error;
+ // Check if the DirectoryEntry is the instance of chrome filesystem.
+ if (!app_file_handler_util::ValidateFileEntryAndGetPath(
+ filesystem_name, filesystem_path, source_process_id(),
+ &project_base_path_, &unused_error)) {
+ return RespondNow(Error("DirectoryEntry of unsupported filesystem."));
+ }
- Load();
+ // Try to load using the FileSystem API backend, in case the filesystem
+ // points to a non-native local directory.
+ std::string filesystem_id;
+ bool cracked =
+ storage::CrackIsolatedFileSystemName(filesystem_name, &filesystem_id);
+ CHECK(cracked);
+ base::FilePath virtual_path =
+ storage::IsolatedContext::GetInstance()
+ ->CreateVirtualRootPath(filesystem_id)
+ .Append(base::FilePath::FromUTF8Unsafe(filesystem_path));
+ storage::FileSystemURL directory_url = context_->CreateCrackedFileSystemURL(
+ url::Origin::Create(
+ extensions::Extension::GetBaseURLFromExtensionId(extension_id())),
+ storage::kFileSystemTypeIsolated, virtual_path);
+
+ if (directory_url.is_valid() &&
+ directory_url.type() != storage::kFileSystemTypeNativeLocal &&
+ directory_url.type() != storage::kFileSystemTypeRestrictedNativeLocal &&
+ directory_url.type() != storage::kFileSystemTypeDragged) {
+ return LoadByFileSystemAPI(directory_url);
}
- return true;
+ Load();
+ return AlreadyResponded();
}
-bool DeveloperPrivateLoadDirectoryFunction::LoadByFileSystemAPI(
+ExtensionFunction::ResponseAction
+DeveloperPrivateLoadDirectoryFunction::LoadByFileSystemAPI(
const storage::FileSystemURL& directory_url) {
std::string directory_url_str = directory_url.ToGURL().spec();
@@ -1447,8 +1447,7 @@ bool DeveloperPrivateLoadDirectoryFunction::LoadByFileSystemAPI(
// Parse the project directory name from the project url. The project url is
// expected to have project name as the suffix.
if ((pos = directory_url_str.rfind("/")) == std::string::npos) {
- SetError("Invalid Directory entry.");
- return false;
+ return RespondNow(Error("Invalid Directory entry."));
}
std::string project_name;
@@ -1462,14 +1461,13 @@ bool DeveloperPrivateLoadDirectoryFunction::LoadByFileSystemAPI(
project_base_path_ = project_path;
- base::PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(
&DeveloperPrivateLoadDirectoryFunction::ClearExistingDirectoryContent,
this, project_base_path_));
- return true;
+ return RespondLater();
}
void DeveloperPrivateLoadDirectoryFunction::Load() {
@@ -1478,8 +1476,7 @@ void DeveloperPrivateLoadDirectoryFunction::Load() {
// TODO(grv) : The unpacked installer should fire an event when complete
// and return the extension_id.
- SetResult(std::make_unique<base::Value>("-1"));
- SendResponse(true);
+ Respond(OneArgument(std::make_unique<base::Value>("-1")));
}
void DeveloperPrivateLoadDirectoryFunction::ClearExistingDirectoryContent(
@@ -1524,7 +1521,7 @@ void DeveloperPrivateLoadDirectoryFunction::ReadDirectoryByFileSystemAPICb(
// are added for copying. We do that to ensure that pendingCopyOperationsCount
// does not become zero before all copy operations are finished.
// In case the directory happens to be executing the last copy operation it
- // will call SendResponse to send the response to the API. The pending copy
+ // will call Respond to send the response to the API. The pending copy
// operations of files are released by the CopyFile function.
pending_copy_operations_count_ += file_list.size();
@@ -1543,10 +1540,9 @@ void DeveloperPrivateLoadDirectoryFunction::ReadDirectoryByFileSystemAPICb(
target_path = target_path.Append(file_list[i].name);
context_->operation_runner()->CreateSnapshotFile(
- url,
- base::Bind(&DeveloperPrivateLoadDirectoryFunction::SnapshotFileCallback,
- this,
- target_path));
+ url, base::BindOnce(
+ &DeveloperPrivateLoadDirectoryFunction::SnapshotFileCallback,
+ this, target_path));
}
if (!has_more) {
@@ -1554,10 +1550,15 @@ void DeveloperPrivateLoadDirectoryFunction::ReadDirectoryByFileSystemAPICb(
pending_copy_operations_count_--;
if (!pending_copy_operations_count_) {
+ ExtensionFunction::ResponseValue response;
+ if (success_)
+ response = NoArguments();
+ else
+ response = Error(error_);
base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&DeveloperPrivateLoadDirectoryFunction::SendResponse,
- this, success_));
+ base::BindOnce(&DeveloperPrivateLoadDirectoryFunction::Respond, this,
+ std::move(response)));
}
}
}
@@ -1569,15 +1570,14 @@ void DeveloperPrivateLoadDirectoryFunction::SnapshotFileCallback(
const base::FilePath& src_path,
scoped_refptr<storage::ShareableFileReference> file_ref) {
if (result != base::File::FILE_OK) {
- SetError("Error in copying files from sync filesystem.");
+ error_ = "Error in copying files from sync filesystem.";
success_ = false;
return;
}
- base::PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&DeveloperPrivateLoadDirectoryFunction::CopyFile, this,
src_path, target_path));
}
@@ -1586,7 +1586,7 @@ void DeveloperPrivateLoadDirectoryFunction::CopyFile(
const base::FilePath& src_path,
const base::FilePath& target_path) {
if (!base::CreateDirectory(target_path.DirName())) {
- SetError("Error in copying files from sync filesystem.");
+ error_ = "Error in copying files from sync filesystem.";
success_ = false;
}
@@ -1702,11 +1702,10 @@ DeveloperPrivateRequestFileSourceFunction::Run() {
if (properties.path_suffix == kManifestFile && !properties.manifest_key)
return RespondNow(Error(kManifestKeyIsRequiredError));
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
- base::Bind(&ReadFileToString, extension->path().Append(path_suffix)),
- base::Bind(&DeveloperPrivateRequestFileSourceFunction::Finish, this));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(&ReadFileToString, extension->path().Append(path_suffix)),
+ base::BindOnce(&DeveloperPrivateRequestFileSourceFunction::Finish, this));
return RespondLater();
}
diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h
index 40b059db45b..3d4c533652e 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h
+++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -14,7 +14,6 @@
#include "base/scoped_observer.h"
#include "chrome/browser/extensions/api/commands/command_service.h"
#include "chrome/browser/extensions/api/developer_private/entry_picker.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/extensions/error_console/error_console.h"
#include "chrome/browser/extensions/extension_management.h"
#include "chrome/browser/extensions/extension_uninstall_dialog.h"
@@ -37,6 +36,7 @@
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_manager_observer.h"
#include "extensions/browser/warning_service.h"
+#include "extensions/common/extension_id.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_operation.h"
#include "ui/shell_dialogs/select_file_dialog.h"
@@ -624,8 +624,7 @@ class DeveloperPrivateIsProfileManagedFunction : public ExtensionFunction {
ResponseAction Run() override;
};
-class DeveloperPrivateLoadDirectoryFunction
- : public ChromeAsyncExtensionFunction {
+class DeveloperPrivateLoadDirectoryFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("developerPrivate.loadDirectory",
DEVELOPERPRIVATE_LOADUNPACKEDCROS)
@@ -636,9 +635,10 @@ class DeveloperPrivateLoadDirectoryFunction
~DeveloperPrivateLoadDirectoryFunction() override;
// ExtensionFunction:
- bool RunAsync() override;
+ ResponseAction Run() override;
- bool LoadByFileSystemAPI(const ::storage::FileSystemURL& directory_url);
+ ResponseAction LoadByFileSystemAPI(
+ const ::storage::FileSystemURL& directory_url);
void ClearExistingDirectoryContent(const base::FilePath& project_path);
@@ -678,6 +678,9 @@ class DeveloperPrivateLoadDirectoryFunction
// This is set to false if any of the copyFile operations fail on
// call of the API. It is returned as a response of the API call.
bool success_;
+
+ // Error string if |success_| is false.
+ std::string error_;
};
class DeveloperPrivateRequestFileSourceFunction
diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index 7dc5b23f894..d6f2776bc42 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -50,6 +50,7 @@
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
+#include "extensions/common/extension_id.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/permissions/permission_set.h"
@@ -1054,8 +1055,6 @@ TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateGetExtensionsInfo) {
// Test developerPrivate.deleteExtensionErrors.
TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateDeleteExtensionErrors) {
- FeatureSwitch::ScopedOverride error_console_override(
- FeatureSwitch::error_console(), true);
profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, true);
const Extension* extension = LoadSimpleExtension();
@@ -1565,6 +1564,45 @@ TEST_F(DeveloperPrivateApiUnitTest,
}
TEST_F(DeveloperPrivateApiUnitTest,
+ UpdateHostAccess_BroadPermissionsRemovedOnTransitionToSpecificSites) {
+ scoped_refptr<const Extension> extension =
+ ExtensionBuilder("test").AddPermission("<all_urls>").Build();
+ service()->AddExtension(extension.get());
+ ScriptingPermissionsModifier modifier(profile(), extension.get());
+ modifier.SetWithholdHostPermissions(true);
+
+ const GURL kGoogleCom("https://google.com/");
+ const GURL kChromiumCom("https://chromium.com");
+
+ // Request <all_urls> and google.com so they are both in the runtime granted
+ // list. We use the util function to specifically add the <all_urls> pattern
+ // here, similar to if it was requested through the chrome.permissions.request
+ // API.
+ URLPattern all_url_pattern(Extension::kValidHostPermissionSchemes,
+ "<all_urls>");
+ permissions_test_util::GrantRuntimePermissionsAndWaitForCompletion(
+ profile(), *extension,
+ PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
+ URLPatternSet({all_url_pattern}),
+ URLPatternSet({all_url_pattern})));
+ modifier.GrantHostPermission(kGoogleCom);
+
+ // Even though <all_urls> has been granted, it was granted as a runtime host
+ // pattern, so the extension is still is considered to have withheld host
+ // permissions.
+ EXPECT_TRUE(modifier.HasWithheldHostPermissions());
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kGoogleCom));
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kChromiumCom));
+
+ // Changing to specific sites should now remove the broad pattern, leaving
+ // only the google match pattern.
+ RunUpdateHostAccess(*extension, "ON_SPECIFIC_SITES");
+ EXPECT_TRUE(modifier.HasWithheldHostPermissions());
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kGoogleCom));
+ EXPECT_FALSE(modifier.HasGrantedHostPermission(kChromiumCom));
+}
+
+TEST_F(DeveloperPrivateApiUnitTest,
UpdateHostAccess_GrantScopeGreaterThanRequestedScope) {
scoped_refptr<const Extension> extension =
ExtensionBuilder("test").AddPermission("http://*/*").Build();
diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc b/chromium/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
index f4cb2836829..0c2d6d323aa 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc
@@ -27,8 +27,8 @@ IN_PROC_BROWSER_TEST_F(DeveloperPrivateApiTest, Basics) {
base_dir.AppendASCII("packaged_app"), 1, Manifest::INTERNAL));
LoadExtension(base_dir.AppendASCII("simple_extension"));
- ASSERT_TRUE(RunPlatformAppTestWithFlags(
- "developer/test", kFlagLoadAsComponent));
+ ASSERT_TRUE(RunPlatformAppTestWithFlags("developer/test", kFlagNone,
+ kFlagLoadAsComponent));
}
// Tests opening the developer tools for an app window.
diff --git a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
index 69ddefc32a4..59866f90ad8 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -22,7 +22,6 @@
#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
#include "chrome/browser/extensions/error_console/error_console.h"
#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/scripting_permissions_modifier.h"
#include "chrome/browser/extensions/shared_module_service.h"
@@ -34,12 +33,14 @@
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/render_frame_host.h"
#include "extensions/browser/extension_error.h"
+#include "extensions/browser/extension_icon_placeholder.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/image_loader.h"
#include "extensions/browser/path_util.h"
+#include "extensions/browser/ui_util.h"
#include "extensions/browser/warning_service.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/install_warning.h"
@@ -368,10 +369,15 @@ void AddPermissionsInfo(content::BrowserContext* browser_context,
} else {
granted_permissions =
extension_prefs->GetRuntimeGrantedPermissions(extension.id());
- runtime_host_permissions->host_access =
- granted_permissions->effective_hosts().is_empty()
- ? developer::HOST_ACCESS_ON_CLICK
- : developer::HOST_ACCESS_ON_SPECIFIC_SITES;
+ if (granted_permissions->effective_hosts().is_empty()) {
+ runtime_host_permissions->host_access = developer::HOST_ACCESS_ON_CLICK;
+ } else if (granted_permissions->ShouldWarnAllHosts(false)) {
+ runtime_host_permissions->host_access =
+ developer::HOST_ACCESS_ON_ALL_SITES;
+ } else {
+ runtime_host_permissions->host_access =
+ developer::HOST_ACCESS_ON_SPECIFIC_SITES;
+ }
}
runtime_host_permissions->hosts = GetSpecificSiteControls(
@@ -419,7 +425,7 @@ void ExtensionInfoGenerator::CreateExtensionInfo(
else if ((ext = registry->terminated_extensions().GetByID(id)) != nullptr)
state = developer::EXTENSION_STATE_TERMINATED;
- if (ext && ui_util::ShouldDisplayInExtensionSettings(ext, browser_context_))
+ if (ext && ui_util::ShouldDisplayInExtensionSettings(*ext))
CreateExtensionInfoHelper(*ext, state);
if (pending_image_loads_ == 0) {
@@ -439,8 +445,7 @@ void ExtensionInfoGenerator::CreateExtensionsInfo(
auto add_to_list = [this](const ExtensionSet& extensions,
developer::ExtensionState state) {
for (const scoped_refptr<const Extension>& extension : extensions) {
- if (ui_util::ShouldDisplayInExtensionSettings(extension.get(),
- browser_context_)) {
+ if (ui_util::ShouldDisplayInExtensionSettings(*extension)) {
CreateExtensionInfoHelper(*extension, state);
}
}
@@ -549,6 +554,11 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper(
info->disable_reasons.update_required =
(disable_reasons & disable_reason::DISABLE_UPDATE_REQUIRED_BY_POLICY) !=
0;
+ info->disable_reasons.blocked_by_policy =
+ (disable_reasons & disable_reason::DISABLE_BLOCKED_BY_POLICY) != 0;
+ info->disable_reasons.custodian_approval_required =
+ (disable_reasons & disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED) !=
+ 0;
// Error collection.
bool error_console_enabled =
@@ -706,7 +716,7 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper(
extension_misc::EXTENSION_ICON_MEDIUM,
ExtensionIconSet::MATCH_BIGGER);
if (icon.empty()) {
- info->icon_url = GetDefaultIconUrl(extension.is_app(), !is_enabled);
+ info->icon_url = GetDefaultIconUrl(extension.name());
list_.push_back(std::move(*info));
} else {
++pending_image_loads_;
@@ -721,25 +731,9 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper(
}
}
-const std::string& ExtensionInfoGenerator::GetDefaultIconUrl(
- bool is_app,
- bool is_greyscale) {
- std::string* str;
- if (is_app) {
- str = is_greyscale ? &default_disabled_app_icon_url_ :
- &default_app_icon_url_;
- } else {
- str = is_greyscale ? &default_disabled_extension_icon_url_ :
- &default_extension_icon_url_;
- }
-
- if (str->empty()) {
- *str = GetIconUrlFromImage(
- ui::ResourceBundle::GetSharedInstance().GetImageNamed(
- is_app ? IDR_APP_DEFAULT_ICON : IDR_EXTENSION_DEFAULT_ICON));
- }
-
- return *str;
+std::string ExtensionInfoGenerator::GetDefaultIconUrl(const std::string& name) {
+ return GetIconUrlFromImage(ExtensionIconPlaceholder::CreateImage(
+ extension_misc::EXTENSION_ICON_MEDIUM, name));
}
std::string ExtensionInfoGenerator::GetIconUrlFromImage(
@@ -759,12 +753,7 @@ void ExtensionInfoGenerator::OnImageLoaded(
if (!icon.IsEmpty()) {
info->icon_url = GetIconUrlFromImage(icon);
} else {
- bool is_app =
- info->type == developer::EXTENSION_TYPE_HOSTED_APP ||
- info->type == developer::EXTENSION_TYPE_LEGACY_PACKAGED_APP ||
- info->type == developer::EXTENSION_TYPE_PLATFORM_APP;
- info->icon_url = GetDefaultIconUrl(
- is_app, info->state != developer::EXTENSION_STATE_ENABLED);
+ info->icon_url = GetDefaultIconUrl(info->name);
}
list_.push_back(std::move(*info));
diff --git a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.h b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.h
index 43f14e8a704..83e71070fbf 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.h
+++ b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.h
@@ -67,7 +67,7 @@ class ExtensionInfoGenerator {
const gfx::Image& image);
// Returns the icon url for the default icon to use.
- const std::string& GetDefaultIconUrl(bool is_app, bool is_disabled);
+ std::string GetDefaultIconUrl(const std::string& name);
// Returns an icon url from the given image.
std::string GetIconUrlFromImage(const gfx::Image& image);
@@ -85,12 +85,6 @@ class ExtensionInfoGenerator {
// The number of pending image loads.
size_t pending_image_loads_;
- // Default icons, cached and lazily initialized.
- std::string default_app_icon_url_;
- std::string default_extension_icon_url_;
- std::string default_disabled_app_icon_url_;
- std::string default_disabled_extension_icon_url_;
-
// The list of extension infos that have been generated.
ExtensionInfoList list_;
diff --git a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
index 62b206bf7ab..c80a16f7e47 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -35,7 +35,6 @@
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
-#include "extensions/common/feature_switch.h"
#include "extensions/common/permissions/permission_message.h"
#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/permissions/permissions_data.h"
@@ -77,7 +76,6 @@ const developer::ExtensionInfo* GetInfoFromList(
std::string SiteControlsToString(
const std::vector<developer::SiteControl>& controls) {
base::Value list(base::Value::Type::LIST);
- list.GetList().reserve(controls.size());
for (const auto& control : controls) {
std::unique_ptr<base::Value> control_value = control.ToValue();
list.Append(std::move(*control_value));
@@ -231,9 +229,6 @@ class ExtensionInfoGeneratorUnitTest : public ExtensionServiceTestBase {
// Test some of the basic fields.
TEST_F(ExtensionInfoGeneratorUnitTest, BasicInfoTest) {
- // Enable error console for testing.
- FeatureSwitch::ScopedOverride error_console_override(
- FeatureSwitch::error_console(), true);
profile()->GetPrefs()->SetBoolean(prefs::kExtensionsUIDeveloperMode, true);
const char kName[] = "extension name";
@@ -299,6 +294,8 @@ TEST_F(ExtensionInfoGeneratorUnitTest, BasicInfoTest) {
EXPECT_FALSE(info->file_access.is_active);
EXPECT_TRUE(info->incognito_access.is_enabled);
EXPECT_FALSE(info->incognito_access.is_active);
+ EXPECT_TRUE(
+ base::StringPiece(info->icon_url).starts_with("data:image/png;base64,"));
// Strip out the kHostReadWrite permission created by the extension requesting
// host permissions above; runtime host permissions mean these are always
@@ -571,6 +568,43 @@ TEST_F(ExtensionInfoGeneratorUnitTest, RuntimeHostPermissionsSpecificHosts) {
EXPECT_FALSE(runtime_hosts->has_all_hosts);
}
+// Tests that requesting all_url style permissions as a runtime granted pattern
+// correctly is treated as having access to all sites.
+TEST_F(ExtensionInfoGeneratorUnitTest, RuntimeHostPermissionsAllURLs) {
+ scoped_refptr<const Extension> all_urls_extension = CreateExtension(
+ "all_urls", ListBuilder().Append(kAllHostsPermission).Build(),
+ Manifest::INTERNAL);
+
+ // Withholding host permissions should result in the extension being set to
+ // run on click.
+ ScriptingPermissionsModifier permissions_modifier(profile(),
+ all_urls_extension);
+ permissions_modifier.SetWithholdHostPermissions(true);
+ std::unique_ptr<developer::ExtensionInfo> info =
+ GenerateExtensionInfo(all_urls_extension->id());
+ const developer::RuntimeHostPermissions* runtime_hosts =
+ info->permissions.runtime_host_permissions.get();
+ EXPECT_EQ(developer::HOST_ACCESS_ON_CLICK, runtime_hosts->host_access);
+ EXPECT_EQ(R"([{"granted":false,"host":"*://*/*"}])",
+ SiteControlsToString(runtime_hosts->hosts));
+
+ // Grant the requested pattern ("*://*/*").
+ URLPattern all_url(Extension::kValidHostPermissionSchemes,
+ kAllHostsPermission);
+ PermissionSet all_url_set(APIPermissionSet(), ManifestPermissionSet(),
+ URLPatternSet({all_url}), URLPatternSet({all_url}));
+ PermissionsUpdater(profile()).GrantRuntimePermissions(
+ *all_urls_extension, all_url_set, base::DoNothing::Once());
+
+ // Now the extension should look like it has access to all hosts, while still
+ // also counting as having permission withholding enabled.
+ info = GenerateExtensionInfo(all_urls_extension->id());
+ runtime_hosts = info->permissions.runtime_host_permissions.get();
+ EXPECT_EQ(developer::HOST_ACCESS_ON_ALL_SITES, runtime_hosts->host_access);
+ EXPECT_EQ(R"([{"granted":true,"host":"*://*/*"}])",
+ SiteControlsToString(runtime_hosts->hosts));
+}
+
// Tests the population of withheld runtime hosts when they overlap with granted
// patterns.
TEST_F(ExtensionInfoGeneratorUnitTest, WithheldUrlsOverlapping) {
diff --git a/chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc b/chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
index b5f3d56bcb8..a2cfc5f9620 100644
--- a/chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/device_permissions_manager_unittest.cc
@@ -69,20 +69,19 @@ class DevicePermissionsManagerTest : public testing::Test {
device3_ = fake_usb_manager_.CreateAndAddDevice(0, 0, "Test Manufacturer",
"Test Product", "");
- mojo::PendingRemote<device::mojom::HidManager> hid_manager;
- fake_hid_manager_.Bind(hid_manager.InitWithNewPipeAndPassReceiver());
- HidDeviceManager::Get(env_->profile())
- ->SetFakeHidManagerForTesting(std::move(hid_manager));
+ HidDeviceManager::OverrideHidManagerBinderForTesting(base::BindRepeating(
+ &device::FakeHidManager::Bind, base::Unretained(&fake_hid_manager_)));
+ HidDeviceManager::Get(env_->profile())->LazyInitialize();
base::RunLoop().RunUntilIdle();
device4_ = fake_hid_manager_.CreateAndAddDevice(
- 0, 0, "Test HID Device", "abcde", HidBusType::kHIDBusTypeUSB);
- device5_ = fake_hid_manager_.CreateAndAddDevice(0, 0, "Test HID Device", "",
- HidBusType::kHIDBusTypeUSB);
+ "4", 0, 0, "Test HID Device", "abcde", HidBusType::kHIDBusTypeUSB);
+ device5_ = fake_hid_manager_.CreateAndAddDevice(
+ "5", 0, 0, "Test HID Device", "", HidBusType::kHIDBusTypeUSB);
device6_ = fake_hid_manager_.CreateAndAddDevice(
- 0, 0, "Test HID Device", "67890", HidBusType::kHIDBusTypeUSB);
- device7_ = fake_hid_manager_.CreateAndAddDevice(0, 0, "Test HID Device", "",
- HidBusType::kHIDBusTypeUSB);
+ "6", 0, 0, "Test HID Device", "67890", HidBusType::kHIDBusTypeUSB);
+ device7_ = fake_hid_manager_.CreateAndAddDevice(
+ "7", 0, 0, "Test HID Device", "", HidBusType::kHIDBusTypeUSB);
}
void TearDown() override { env_.reset(nullptr); }
diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc b/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
index 51009e7a503..49f2bad96fa 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -150,8 +150,10 @@ const char kDangerPasswordProtected[] = "passwordProtected";
const char kDangerTooLarge[] = "blockedTooLarge";
const char kDangerSensitiveContentWarning[] = "sensitiveContentWarning";
const char kDangerSensitiveContentBlock[] = "sensitiveContentBlock";
+const char kDangerUnsupportedFileType[] = "unsupportedFileType";
const char kDangerDeepScannedSafe[] = "deepScannedSafe";
const char kDangerDeepScannedOpenedDangerous[] = "deepScannedOpenedDangerous";
+const char kDangerPromptForScanning[] = "promptForScanning";
const char kDangerUrl[] = "url";
const char kEndTimeKey[] = "endTime";
const char kEndedAfterKey[] = "endedAfter";
@@ -201,7 +203,9 @@ const char* const kDangerStrings[] = {kDangerSafe,
kDangerSensitiveContentWarning,
kDangerSensitiveContentBlock,
kDangerDeepScannedSafe,
- kDangerDeepScannedOpenedDangerous};
+ kDangerDeepScannedOpenedDangerous,
+ kDangerPromptForScanning,
+ kDangerUnsupportedFileType};
static_assert(base::size(kDangerStrings) == download::DOWNLOAD_DANGER_TYPE_MAX,
"kDangerStrings should have DOWNLOAD_DANGER_TYPE_MAX elements");
@@ -1007,15 +1011,16 @@ DownloadsDownloadFunction::DownloadsDownloadFunction() {}
DownloadsDownloadFunction::~DownloadsDownloadFunction() {}
-bool DownloadsDownloadFunction::RunAsync() {
+ExtensionFunction::ResponseAction DownloadsDownloadFunction::Run() {
std::unique_ptr<downloads::Download::Params> params(
downloads::Download::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
const downloads::DownloadOptions& options = params->options;
GURL download_url(options.url);
+ std::string error;
if (Fault(!download_url.is_valid(), download_extension_errors::kInvalidURL,
- &error_))
- return false;
+ &error))
+ return RespondNow(Error(error));
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("downloads_api_run_async", R"(
@@ -1050,8 +1055,7 @@ bool DownloadsDownloadFunction::RunAsync() {
new download::DownloadUrlParameters(
download_url, source_process_id(),
render_frame_host()->GetRenderViewHost()->GetRoutingID(),
- render_frame_host()->GetRoutingID(), traffic_annotation,
- render_frame_host()->GetNetworkIsolationKey()));
+ render_frame_host()->GetRoutingID(), traffic_annotation));
base::FilePath creator_suggested_filename;
if (options.filename.get()) {
@@ -1068,8 +1072,7 @@ bool DownloadsDownloadFunction::RunAsync() {
creator_suggested_filename = base::FilePath(*options.filename);
#endif
if (!net::IsSafePortableRelativePath(creator_suggested_filename)) {
- error_ = download_extension_errors::kInvalidFilename;
- return false;
+ return RespondNow(Error(download_extension_errors::kInvalidFilename));
}
}
@@ -1079,16 +1082,15 @@ bool DownloadsDownloadFunction::RunAsync() {
if (options.headers.get()) {
for (const downloads::HeaderNameValuePair& name_value : *options.headers) {
if (!net::HttpUtil::IsValidHeaderName(name_value.name)) {
- error_ = download_extension_errors::kInvalidHeaderName;
- return false;
+ return RespondNow(Error(download_extension_errors::kInvalidHeaderName));
}
if (!net::HttpUtil::IsSafeHeader(name_value.name)) {
- error_ = download_extension_errors::kInvalidHeaderUnsafe;
- return false;
+ return RespondNow(
+ Error(download_extension_errors::kInvalidHeaderUnsafe));
}
if (!net::HttpUtil::IsValidHeaderValue(name_value.value)) {
- error_ = download_extension_errors::kInvalidHeaderValue;
- return false;
+ return RespondNow(
+ Error(download_extension_errors::kInvalidHeaderValue));
}
download_params->add_request_header(name_value.name, name_value.value);
}
@@ -1104,18 +1106,19 @@ bool DownloadsDownloadFunction::RunAsync() {
options.body->size()));
}
- download_params->set_callback(base::Bind(
- &DownloadsDownloadFunction::OnStarted, this,
- creator_suggested_filename, options.conflict_action));
+ download_params->set_callback(
+ base::BindOnce(&DownloadsDownloadFunction::OnStarted, this,
+ creator_suggested_filename, options.conflict_action));
// Prevent login prompts for 401/407 responses.
download_params->set_do_not_prompt_for_login(true);
download_params->set_download_source(download::DownloadSource::EXTENSION_API);
- DownloadManager* manager = BrowserContext::GetDownloadManager(GetProfile());
+ DownloadManager* manager =
+ BrowserContext::GetDownloadManager(browser_context());
manager->DownloadUrl(std::move(download_params));
RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD);
- return true;
+ return RespondLater();
}
void DownloadsDownloadFunction::OnStarted(
@@ -1127,7 +1130,8 @@ void DownloadsDownloadFunction::OnStarted(
VLOG(1) << __func__ << " " << item << " " << interrupt_reason;
if (item) {
DCHECK_EQ(download::DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
- SetResult(std::make_unique<base::Value>(static_cast<int>(item->GetId())));
+ Respond(OneArgument(
+ std::make_unique<base::Value>(static_cast<int>(item->GetId()))));
if (!creator_suggested_filename.empty() ||
(creator_conflict_action !=
downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY)) {
@@ -1145,9 +1149,8 @@ void DownloadsDownloadFunction::OnStarted(
item->UpdateObservers();
} else {
DCHECK_NE(download::DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
- error_ = download::DownloadInterruptReasonToString(interrupt_reason);
+ Respond(Error(download::DownloadInterruptReasonToString(interrupt_reason)));
}
- SendResponse(error_.empty());
}
DownloadsSearchFunction::DownloadsSearchFunction() {}
@@ -1295,30 +1298,32 @@ DownloadsRemoveFileFunction::DownloadsRemoveFileFunction() {
DownloadsRemoveFileFunction::~DownloadsRemoveFileFunction() {
}
-bool DownloadsRemoveFileFunction::RunAsync() {
+ExtensionFunction::ResponseAction DownloadsRemoveFileFunction::Run() {
std::unique_ptr<downloads::RemoveFile::Params> params(
downloads::RemoveFile::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
DownloadItem* download_item = GetDownload(
browser_context(), include_incognito_information(), params->download_id);
- if (InvalidId(download_item, &error_) ||
+ std::string error;
+ if (InvalidId(download_item, &error) ||
Fault((download_item->GetState() != DownloadItem::COMPLETE),
- download_extension_errors::kNotComplete, &error_) ||
+ download_extension_errors::kNotComplete, &error) ||
Fault(download_item->GetFileExternallyRemoved(),
- download_extension_errors::kFileAlreadyDeleted, &error_))
- return false;
+ download_extension_errors::kFileAlreadyDeleted, &error))
+ return RespondNow(Error(error));
RecordApiFunctions(DOWNLOADS_FUNCTION_REMOVE_FILE);
download_item->DeleteFile(
- base::Bind(&DownloadsRemoveFileFunction::Done, this));
- return true;
+ base::BindOnce(&DownloadsRemoveFileFunction::Done, this));
+ return RespondLater();
}
void DownloadsRemoveFileFunction::Done(bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!success) {
- error_ = download_extension_errors::kFileNotRemoved;
+ Respond(Error(download_extension_errors::kFileNotRemoved));
+ } else {
+ Respond(NoArguments());
}
- SendResponse(error_.empty());
}
DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {}
@@ -1328,26 +1333,27 @@ DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {}
DownloadsAcceptDangerFunction::OnPromptCreatedCallback*
DownloadsAcceptDangerFunction::on_prompt_created_ = NULL;
-bool DownloadsAcceptDangerFunction::RunAsync() {
+ExtensionFunction::ResponseAction DownloadsAcceptDangerFunction::Run() {
std::unique_ptr<downloads::AcceptDanger::Params> params(
downloads::AcceptDanger::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
PromptOrWait(params->download_id, 10);
- return true;
+ return RespondLater();
}
void DownloadsAcceptDangerFunction::PromptOrWait(int download_id, int retries) {
DownloadItem* download_item = GetDownload(
browser_context(), include_incognito_information(), download_id);
content::WebContents* web_contents = dispatcher()->GetVisibleWebContents();
- if (InvalidId(download_item, &error_) ||
+ std::string error;
+ if (InvalidId(download_item, &error) ||
Fault(download_item->GetState() != DownloadItem::IN_PROGRESS,
- download_extension_errors::kNotInProgress, &error_) ||
+ download_extension_errors::kNotInProgress, &error) ||
Fault(!download_item->IsDangerous(),
- download_extension_errors::kNotDangerous, &error_) ||
+ download_extension_errors::kNotDangerous, &error) ||
Fault(!web_contents, download_extension_errors::kInvisibleContext,
- &error_)) {
- SendResponse(error_.empty());
+ &error)) {
+ Respond(Error(error));
return;
}
bool visible = platform_util::IsVisible(web_contents->GetNativeView());
@@ -1360,8 +1366,7 @@ void DownloadsAcceptDangerFunction::PromptOrWait(int download_id, int retries) {
base::TimeDelta::FromMilliseconds(100));
return;
}
- error_ = download_extension_errors::kInvisibleContext;
- SendResponse(false);
+ Respond(Error(download_extension_errors::kInvisibleContext));
return;
}
RecordApiFunctions(DOWNLOADS_FUNCTION_ACCEPT_DANGER);
@@ -1384,10 +1389,13 @@ void DownloadsAcceptDangerFunction::DangerPromptCallback(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DownloadItem* download_item = GetDownload(
browser_context(), include_incognito_information(), download_id);
- if (InvalidId(download_item, &error_) ||
+ std::string error;
+ if (InvalidId(download_item, &error) ||
Fault(download_item->GetState() != DownloadItem::IN_PROGRESS,
- download_extension_errors::kNotInProgress, &error_))
+ download_extension_errors::kNotInProgress, &error)) {
+ Respond(Error(error));
return;
+ }
switch (action) {
case DownloadDangerPrompt::ACCEPT:
download_item->ValidateDangerousDownload();
@@ -1398,7 +1406,7 @@ void DownloadsAcceptDangerFunction::DangerPromptCallback(
case DownloadDangerPrompt::DISMISS:
break;
}
- SendResponse(error_.empty());
+ Respond(NoArguments());
}
DownloadsShowFunction::DownloadsShowFunction() {}
@@ -1578,7 +1586,7 @@ void DownloadsGetFileIconFunction::SetIconExtractorForTesting(
icon_extractor_.reset(extractor);
}
-bool DownloadsGetFileIconFunction::RunAsync() {
+ExtensionFunction::ResponseAction DownloadsGetFileIconFunction::Run() {
std::unique_ptr<downloads::GetFileIcon::Params> params(
downloads::GetFileIcon::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
@@ -1589,10 +1597,11 @@ bool DownloadsGetFileIconFunction::RunAsync() {
icon_size = *options->size;
DownloadItem* download_item = GetDownload(
browser_context(), include_incognito_information(), params->download_id);
- if (InvalidId(download_item, &error_) ||
+ std::string error;
+ if (InvalidId(download_item, &error) ||
Fault(download_item->GetTargetFilePath().empty(),
- download_extension_errors::kEmptyFile, &error_))
- return false;
+ download_extension_errors::kEmptyFile, &error))
+ return RespondNow(Error(error));
// In-progress downloads return the intermediate filename for GetFullPath()
// which doesn't have the final extension. Therefore a good file icon can't be
// found, so use GetTargetFilePath() instead.
@@ -1608,18 +1617,18 @@ bool DownloadsGetFileIconFunction::RunAsync() {
scale,
IconLoaderSizeFromPixelSize(icon_size),
base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this)));
- return true;
+ return RespondLater();
}
void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (Fault(url.empty(), download_extension_errors::kIconNotFound, &error_)) {
- SendResponse(false);
+ std::string error;
+ if (Fault(url.empty(), download_extension_errors::kIconNotFound, &error)) {
+ Respond(Error(error));
return;
}
RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON);
- SetResult(std::make_unique<base::Value>(url));
- SendResponse(true);
+ Respond(OneArgument(std::make_unique<base::Value>(url)));
}
ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter(
diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api.h b/chromium/chrome/browser/extensions/api/downloads/downloads_api.h
index d0b6f832269..8188d91a7f9 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api.h
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api.h
@@ -14,18 +14,19 @@
#include "base/scoped_observer.h"
#include "base/time/time.h"
#include "chrome/browser/download/download_danger_prompt.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/common/extensions/api/downloads.h"
#include "components/download/content/public/all_download_item_notifier.h"
#include "components/download/public/common/download_path_reservation_tracker.h"
#include "content/public/browser/download_manager.h"
#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/warning_set.h"
class DownloadFileIconExtractor;
class DownloadOpenPrompt;
+class Profile;
// Functions in the chrome.downloads namespace facilitate
// controlling downloads from extensions. See the full API doc at
@@ -85,11 +86,11 @@ class DownloadedByExtension : public base::SupportsUserData::Data {
DISALLOW_COPY_AND_ASSIGN(DownloadedByExtension);
};
-class DownloadsDownloadFunction : public ChromeAsyncExtensionFunction {
+class DownloadsDownloadFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("downloads.download", DOWNLOADS_DOWNLOAD)
DownloadsDownloadFunction();
- bool RunAsync() override;
+ ResponseAction Run() override;
protected:
~DownloadsDownloadFunction() override;
@@ -169,11 +170,11 @@ class DownloadsEraseFunction : public ExtensionFunction {
DISALLOW_COPY_AND_ASSIGN(DownloadsEraseFunction);
};
-class DownloadsRemoveFileFunction : public ChromeAsyncExtensionFunction {
+class DownloadsRemoveFileFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("downloads.removeFile", DOWNLOADS_REMOVEFILE)
DownloadsRemoveFileFunction();
- bool RunAsync() override;
+ ResponseAction Run() override;
protected:
~DownloadsRemoveFileFunction() override;
@@ -184,7 +185,7 @@ class DownloadsRemoveFileFunction : public ChromeAsyncExtensionFunction {
DISALLOW_COPY_AND_ASSIGN(DownloadsRemoveFileFunction);
};
-class DownloadsAcceptDangerFunction : public ChromeAsyncExtensionFunction {
+class DownloadsAcceptDangerFunction : public ExtensionFunction {
public:
typedef base::Callback<void(DownloadDangerPrompt*)> OnPromptCreatedCallback;
static void OnPromptCreatedForTesting(
@@ -194,7 +195,7 @@ class DownloadsAcceptDangerFunction : public ChromeAsyncExtensionFunction {
DECLARE_EXTENSION_FUNCTION("downloads.acceptDanger", DOWNLOADS_ACCEPTDANGER)
DownloadsAcceptDangerFunction();
- bool RunAsync() override;
+ ResponseAction Run() override;
protected:
~DownloadsAcceptDangerFunction() override;
@@ -272,11 +273,11 @@ class DownloadsSetShelfEnabledFunction : public ExtensionFunction {
DISALLOW_COPY_AND_ASSIGN(DownloadsSetShelfEnabledFunction);
};
-class DownloadsGetFileIconFunction : public ChromeAsyncExtensionFunction {
+class DownloadsGetFileIconFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("downloads.getFileIcon", DOWNLOADS_GETFILEICON)
DownloadsGetFileIconFunction();
- bool RunAsync() override;
+ ResponseAction Run() override;
void SetIconExtractorForTesting(DownloadFileIconExtractor* extractor);
protected:
diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index f2141ee57ce..4ec5445dd38 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -20,6 +20,7 @@
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -37,7 +38,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
-#include "chrome/browser/ui/extensions/browser_action_test_util.h"
+#include "chrome/browser/ui/extensions/extension_action_test_helper.h"
#include "chrome/common/extensions/api/downloads.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
@@ -820,7 +821,8 @@ class HTML5FileWriter {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
context->operation_runner()->CopyInForeignFile(
temp_file, path,
- base::Bind(&CopyInCompletion, base::Unretained(result), quit_closure));
+ base::BindOnce(&CopyInCompletion, base::Unretained(result),
+ quit_closure));
}
};
@@ -2049,8 +2051,20 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
DownloadExtensionTest_Download_InvalidURLs
#endif
+class DownloadExtensionTestWithFtp : public DownloadExtensionTest {
+ public:
+ DownloadExtensionTestWithFtp() {
+ // DownloadExtensionTest_Download_InvalidURLs requires FTP support.
+ // TODO(https://crbug.com/333943): Remove FTP tests and FTP feature flags.
+ scoped_feature_list_.InitAndEnableFeature(features::kFtpProtocol);
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
// Test that downloading invalid URLs immediately returns kInvalidURLError.
-IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
+IN_PROC_BROWSER_TEST_F(DownloadExtensionTestWithFtp,
MAYBE_DownloadExtensionTest_Download_InvalidURLs) {
LoadExtension("downloads_split");
GoOnTheRecord();
@@ -4280,7 +4294,7 @@ IN_PROC_BROWSER_TEST_F(
current_browser(),
GURL(net::URLRequestSlowDownloadJob::kErrorDownloadUrl),
WindowOpenDisposition::NEW_BACKGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Errors caught before filename determination are delayed until after
// filename determination.
@@ -4418,7 +4432,7 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
base::Bind(&OnDangerPromptCreated);
DownloadsAcceptDangerFunction::OnPromptCreatedForTesting(
&callback);
- BrowserActionTestUtil::Create(current_browser())->Press(0);
+ ExtensionActionTestHelper::Create(current_browser())->Press(0);
observer->WaitForFinished();
}
@@ -4458,7 +4472,7 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
R"( "current": "complete"}}])",
result_id)));
- item->DeleteFile(base::BindRepeating(OnFileDeleted));
+ item->DeleteFile(base::BindOnce(OnFileDeleted));
ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName,
base::StringPrintf(R"([{"id": %d,)"
diff --git a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS
index eca977606f0..10a65a818e5 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS
+++ b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/OWNERS
@@ -1,2 +1,4 @@
emaxx@chromium.org
pbond@chromium.org
+
+# COMPONENT: Enterprise
diff --git a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.cc b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.cc
index 60af1cbb3f6..d94b303a10b 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/policy/hostname_handler.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/enterprise_device_attributes.h"
@@ -20,6 +21,9 @@ namespace extensions {
namespace {
+// TODO(http://crbug.com/1056550): Return an error if the user is not permitted
+// to get device attributes instead of an empty string.
+
// Checks for the current browser context if the user is affiliated or belongs
// to the sign-in profile.
bool IsPermittedToGetDeviceAttributes(content::BrowserContext* context) {
@@ -110,4 +114,24 @@ EnterpriseDeviceAttributesGetDeviceAnnotatedLocationFunction::Run() {
Create(annotated_location)));
}
+EnterpriseDeviceAttributesGetDeviceHostnameFunction::
+ EnterpriseDeviceAttributesGetDeviceHostnameFunction() = default;
+
+EnterpriseDeviceAttributesGetDeviceHostnameFunction::
+ ~EnterpriseDeviceAttributesGetDeviceHostnameFunction() = default;
+
+ExtensionFunction::ResponseAction
+EnterpriseDeviceAttributesGetDeviceHostnameFunction::Run() {
+ std::string hostname;
+ if (IsPermittedToGetDeviceAttributes(browser_context())) {
+ hostname = g_browser_process->platform_part()
+ ->browser_policy_connector_chromeos()
+ ->GetHostnameHandler()
+ ->GetDeviceHostname();
+ }
+ return RespondNow(ArgumentList(
+ api::enterprise_device_attributes::GetDeviceHostname::Results::Create(
+ hostname)));
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h
index 5c6a57cf641..0974be24255 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h
+++ b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_api.h
@@ -71,5 +71,20 @@ class EnterpriseDeviceAttributesGetDeviceAnnotatedLocationFunction
ENTERPRISE_DEVICEATTRIBUTES_GETDEVICEANNOTATEDLOCATION)
};
+class EnterpriseDeviceAttributesGetDeviceHostnameFunction
+ : public ExtensionFunction {
+ public:
+ EnterpriseDeviceAttributesGetDeviceHostnameFunction();
+
+ protected:
+ ~EnterpriseDeviceAttributesGetDeviceHostnameFunction() override;
+
+ ResponseAction Run() override;
+
+ private:
+ DECLARE_EXTENSION_FUNCTION("enterprise.deviceAttributes.getDeviceHostname",
+ ENTERPRISE_DEVICEATTRIBUTES_GETDEVICEHOSTNAME)
+};
+
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_DEVICE_ATTRIBUTES_ENTERPRISE_DEVICE_ATTRIBUTES_API_H_
diff --git a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
index b4f0086533c..26d849096a4 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
@@ -40,6 +40,7 @@ constexpr char kDeviceId[] = "device_id";
constexpr char kSerialNumber[] = "serial_number";
constexpr char kAssetId[] = "asset_id";
constexpr char kAnnotatedLocation[] = "annotated_location";
+constexpr char kHostname[] = "hostname";
constexpr char kUpdateManifestPath[] =
"/extensions/api_test/enterprise_device_attributes/update_manifest.xml";
@@ -68,7 +69,8 @@ std::string PrintParam(testing::TestParamInfo<Params> param_info) {
base::Value BuildCustomArg(const std::string& expected_directory_device_id,
const std::string& expected_serial_number,
const std::string& expected_asset_id,
- const std::string& expected_annotated_location) {
+ const std::string& expected_annotated_location,
+ const std::string& expected_hostname) {
base::Value custom_arg(base::Value::Type::DICTIONARY);
custom_arg.SetKey("expectedDirectoryDeviceId",
base::Value(expected_directory_device_id));
@@ -77,6 +79,7 @@ base::Value BuildCustomArg(const std::string& expected_directory_device_id,
custom_arg.SetKey("expectedAssetId", base::Value(expected_asset_id));
custom_arg.SetKey("expectedAnnotatedLocation",
base::Value(expected_annotated_location));
+ custom_arg.SetKey("expectedHostname", base::Value(expected_hostname));
return custom_arg;
}
@@ -134,6 +137,9 @@ class EnterpriseDeviceAttributesTest
device_policy->policy_data().set_directory_api_id(kDeviceId);
device_policy->policy_data().set_annotated_asset_id(kAssetId);
device_policy->policy_data().set_annotated_location(kAnnotatedLocation);
+ enterprise_management::NetworkHostnameProto* proto =
+ device_policy->payload().mutable_network_hostname();
+ proto->set_device_hostname_template(kHostname);
device_policy->Build();
chromeos::FakeSessionManagerClient::Get()->set_device_policy(
@@ -226,13 +232,15 @@ IN_PROC_BROWSER_TEST_P(EnterpriseDeviceAttributesTest, Success) {
std::string expected_asset_id = GetParam().affiliated ? kAssetId : "";
std::string expected_annotated_location =
GetParam().affiliated ? kAnnotatedLocation : "";
+ std::string expected_hostname = GetParam().affiliated ? kHostname : "";
// Pass the expected value (device_id) to test.
ASSERT_TRUE(TestExtension(
CreateBrowser(profile()),
base::StringPrintf("chrome-extension://%s/basic.html", kTestExtensionID),
BuildCustomArg(expected_directory_device_id, expected_serial_number,
- expected_asset_id, expected_annotated_location)))
+ expected_asset_id, expected_annotated_location,
+ expected_hostname)))
<< message_;
}
@@ -245,7 +253,7 @@ IN_PROC_BROWSER_TEST_F(
EnterpriseDeviceAttributesIsRestrictedToPolicyExtension) {
ASSERT_TRUE(RunExtensionSubtest("enterprise_device_attributes",
"api_not_available.html",
- kFlagIgnoreManifestWarnings));
+ kFlagIgnoreManifestWarnings, kFlagNone));
base::FilePath extension_path =
test_data_dir_.AppendASCII("enterprise_device_attributes");
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/OWNERS b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/OWNERS
index 56eef3e7f82..f3044fe628a 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/OWNERS
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/OWNERS
@@ -1,2 +1,4 @@
emaxx@chromium.org
drcrash@chromium.org
+
+# COMPONENT: Enterprise
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
index cf6c55d7a3b..f3a5cfa7d60 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
@@ -9,7 +9,8 @@
#include "base/bind.h"
#include "base/task/post_task.h"
#include "base/values.h"
-#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
+#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h"
+#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service_factory.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h"
#include "chrome/browser/extensions/api/platform_keys/platform_keys_api.h"
@@ -51,22 +52,39 @@ ExtensionFunction::ResponseAction
EnterprisePlatformKeysInternalGenerateKeyFunction::Run() {
std::unique_ptr<api_epki::GenerateKey::Params> params(
api_epki::GenerateKey::Params::Create(*args_));
- // TODO(pneubeck): Add support for unsigned integers to IDL.
- EXTENSION_FUNCTION_VALIDATE(params && params->modulus_length >= 0);
+
+ EXTENSION_FUNCTION_VALIDATE(params);
std::string platform_keys_token_id;
if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id))
return RespondNow(Error(platform_keys::kErrorInvalidToken));
- chromeos::PlatformKeysService* service =
- chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
+ chromeos::ExtensionPlatformKeysService* service =
+ chromeos::ExtensionPlatformKeysServiceFactory::GetForBrowserContext(
browser_context());
DCHECK(service);
- service->GenerateRSAKey(
- platform_keys_token_id, params->modulus_length, extension_id(),
- base::Bind(
- &EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey,
- this));
+ if (params->algorithm.name == "RSASSA-PKCS1-v1_5") {
+ // TODO(pneubeck): Add support for unsigned integers to IDL.
+ EXTENSION_FUNCTION_VALIDATE(params->algorithm.modulus_length &&
+ *(params->algorithm.modulus_length) >= 0);
+ service->GenerateRSAKey(
+ platform_keys_token_id, *(params->algorithm.modulus_length),
+ extension_id(),
+ base::Bind(
+ &EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey,
+ this));
+ } else if (params->algorithm.name == "ECDSA") {
+ EXTENSION_FUNCTION_VALIDATE(params->algorithm.named_curve);
+ service->GenerateECKey(
+ platform_keys_token_id, *(params->algorithm.named_curve),
+ extension_id(),
+ base::Bind(
+ &EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey,
+ this));
+ } else {
+ NOTREACHED();
+ EXTENSION_FUNCTION_VALIDATE(false);
+ }
return RespondLater();
}
@@ -94,12 +112,14 @@ EnterprisePlatformKeysGetCertificatesFunction::Run() {
if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id))
return RespondNow(Error(platform_keys::kErrorInvalidToken));
- chromeos::platform_keys::GetCertificates(
+ chromeos::platform_keys::PlatformKeysService* platform_keys_service =
+ chromeos::platform_keys::PlatformKeysServiceFactory::GetForBrowserContext(
+ browser_context());
+ platform_keys_service->GetCertificates(
platform_keys_token_id,
base::Bind(
&EnterprisePlatformKeysGetCertificatesFunction::OnGotCertificates,
- this),
- browser_context());
+ this));
return RespondLater();
}
@@ -150,12 +170,16 @@ EnterprisePlatformKeysImportCertificateFunction::Run() {
if (!cert_x509.get())
return RespondNow(Error(kEnterprisePlatformErrorInvalidX509Cert));
- chromeos::platform_keys::ImportCertificate(
+ chromeos::platform_keys::PlatformKeysService* platform_keys_service =
+ chromeos::platform_keys::PlatformKeysServiceFactory::GetForBrowserContext(
+ browser_context());
+ CHECK(platform_keys_service);
+
+ platform_keys_service->ImportCertificate(
platform_keys_token_id, cert_x509,
base::Bind(&EnterprisePlatformKeysImportCertificateFunction::
OnImportedCertificate,
- this),
- browser_context());
+ this));
return RespondLater();
}
@@ -192,12 +216,16 @@ EnterprisePlatformKeysRemoveCertificateFunction::Run() {
if (!cert_x509.get())
return RespondNow(Error(kEnterprisePlatformErrorInvalidX509Cert));
- chromeos::platform_keys::RemoveCertificate(
+ chromeos::platform_keys::PlatformKeysService* platform_keys_service =
+ chromeos::platform_keys::PlatformKeysServiceFactory::GetForBrowserContext(
+ browser_context());
+ CHECK(platform_keys_service);
+
+ platform_keys_service->RemoveCertificate(
platform_keys_token_id, cert_x509,
base::Bind(&EnterprisePlatformKeysRemoveCertificateFunction::
OnRemovedCertificate,
- this),
- browser_context());
+ this));
return RespondLater();
}
@@ -217,10 +245,13 @@ ExtensionFunction::ResponseAction
EnterprisePlatformKeysInternalGetTokensFunction::Run() {
EXTENSION_FUNCTION_VALIDATE(args_->empty());
- chromeos::platform_keys::GetTokens(
- base::Bind(&EnterprisePlatformKeysInternalGetTokensFunction::OnGotTokens,
- this),
- browser_context());
+ chromeos::platform_keys::PlatformKeysService* platform_keys_service =
+ chromeos::platform_keys::PlatformKeysServiceFactory::GetForBrowserContext(
+ browser_context());
+ CHECK(platform_keys_service);
+
+ platform_keys_service->GetTokens(base::Bind(
+ &EnterprisePlatformKeysInternalGetTokensFunction::OnGotTokens, this));
return RespondLater();
}
@@ -277,7 +308,7 @@ void EnterprisePlatformKeysChallengeMachineKeyFunction::OnChallengedKey(
const chromeos::attestation::TpmChallengeKeyResult& result) {
if (result.IsSuccess()) {
Respond(ArgumentList(api_epk::ChallengeMachineKey::Results::Create(
- VectorFromString(result.data))));
+ VectorFromString(result.challenge_response))));
} else {
Respond(Error(result.GetErrorMessage()));
}
@@ -294,7 +325,7 @@ EnterprisePlatformKeysChallengeUserKeyFunction::Run() {
std::unique_ptr<api_epk::ChallengeUserKey::Params> params(
api_epk::ChallengeUserKey::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- chromeos::attestation::TpmChallengeKeyCallback callback = base::Bind(
+ chromeos::attestation::TpmChallengeKeyCallback callback = base::BindOnce(
&EnterprisePlatformKeysChallengeUserKeyFunction::OnChallengedKey, this);
// base::Unretained is safe on impl_ since its life-cycle matches |this| and
// |callback| holds a reference to |this|.
@@ -311,7 +342,7 @@ void EnterprisePlatformKeysChallengeUserKeyFunction::OnChallengedKey(
const chromeos::attestation::TpmChallengeKeyResult& result) {
if (result.IsSuccess()) {
Respond(ArgumentList(api_epk::ChallengeUserKey::Results::Create(
- VectorFromString(result.data))));
+ VectorFromString(result.challenge_response))));
} else {
Respond(Error(result.GetErrorMessage()));
}
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
index c10b5503855..f52957e87d6 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chrome/browser/chromeos/attestation/mock_tpm_challenge_key.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
@@ -40,7 +41,8 @@ void FakeRunCheckNotRegister(
const std::string& key_name_for_spkac) {
EXPECT_FALSE(register_key);
std::move(callback).Run(
- chromeos::attestation::TpmChallengeKeyResult::MakeResult("response"));
+ chromeos::attestation::TpmChallengeKeyResult::MakeChallengeResponse(
+ "response"));
}
class EPKChallengeKeyTestBase : public BrowserWithTestWindowTest {
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
index 36988ba6dac..f270a692328 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc
@@ -6,8 +6,12 @@
#include <stddef.h>
#include <memory>
+#include <string>
#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
@@ -23,6 +27,7 @@
#include "crypto/scoped_test_system_nss_key_slot.h"
#include "extensions/browser/extension_registry.h"
#include "net/cert/nss_cert_database.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -102,9 +107,6 @@ const unsigned char privateKeyPkcs8System[] = {
0xb5, 0x6f, 0xe9, 0x1b, 0x32, 0x91, 0x34, 0x38
};
-const char kUpdateManifestPath[] =
- "/extensions/api_test/enterprise_platform_keys/update_manifest.xml";
-
void ImportPrivateKeyPKCS8ToSlot(const unsigned char* pkcs8_der,
size_t pkcs8_der_size,
PK11SlotInfo* slot) {
@@ -131,6 +133,13 @@ void ImportPrivateKeyPKCS8ToSlot(const unsigned char* pkcs8_der,
// its extension ID is well-known and the policy system can push policies for
// the extension.
const char kTestExtensionID[] = "aecpbnckhoppanpmefllkdkohionpmig";
+const char kTestExtensionUpdateManifest[] =
+ R"(<?xml version='1.0' encoding='UTF-8'?>
+ <gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
+ <app appid='$1'>
+ <updatecheck codebase='$2' version='0.1' />
+ </app>
+ </gupdate>)";
struct Params {
Params(PlatformKeysTestBase::SystemTokenStatus system_token_status,
@@ -163,7 +172,23 @@ class EnterprisePlatformKeysTest
}
void SetUpOnMainThread() override {
- policy_test_utils::SetUpEmbeddedTestServer(embedded_test_server());
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ embedded_test_server()->ServeFilesFromDirectory(temp_dir_.GetPath());
+
+ crx_path_ = temp_dir_.GetPath().Append(kCrxFileName);
+ update_manifest_path_ = temp_dir_.GetPath().Append(kUpdateManifestFileName);
+
+ extension_path_ = test_data_dir_.Append(kExtensionDirName);
+ pem_path_ = test_data_dir_.Append(kPemFileName);
+
+ base::FilePath created_crx_path =
+ PackExtensionWithOptions(extension_path_, crx_path_, pem_path_,
+ /*pem_out_path=*/base::FilePath());
+ ASSERT_EQ(created_crx_path, crx_path_);
+
+ GenerateUpdateManifestFile();
+
PlatformKeysTestBase::SetUpOnMainThread();
}
@@ -177,6 +202,10 @@ class EnterprisePlatformKeysTest
done_callback.Run();
}
+ protected:
+ const std::string kUpdateManifestFileName =
+ "enterprise_platform_keys_update_manifest.xml";
+
private:
void PrepareTestSystemSlotOnIO(
crypto::ScopedTestSystemNSSKeySlot* system_slot) override {
@@ -187,6 +216,29 @@ class EnterprisePlatformKeysTest
system_slot->slot());
}
+ void GenerateUpdateManifestFile() {
+ const std::string kContent = base::ReplaceStringPlaceholders(
+ kTestExtensionUpdateManifest,
+ {kTestExtensionID,
+ embedded_test_server()->GetURL("/" + kCrxFileName).spec().c_str()},
+ /*offsets=*/nullptr);
+
+ int written_bytes = base::WriteFile(update_manifest_path_, kContent.data(),
+ kContent.size());
+ ASSERT_EQ(written_bytes, static_cast<int>(kContent.length()));
+ }
+
+ const std::string kCrxFileName = "enterprise_platform_keys.crx";
+ const std::string kExtensionDirName = "enterprise_platform_keys";
+ const std::string kPemFileName = "enterprise_platform_keys.pem";
+
+ base::FilePath crx_path_;
+ base::FilePath extension_path_;
+ base::FilePath pem_path_;
+ base::FilePath update_manifest_path_;
+
+ base::ScopedTempDir temp_dir_;
+
DISALLOW_COPY_AND_ASSIGN(EnterprisePlatformKeysTest);
};
@@ -207,8 +259,9 @@ IN_PROC_BROWSER_TEST_P(EnterprisePlatformKeysTest, Basic) {
loop.Run();
}
policy_test_utils::SetExtensionInstallForcelistPolicy(
- kTestExtensionID, embedded_test_server()->GetURL(kUpdateManifestPath),
- profile(), mock_policy_provider());
+ kTestExtensionID,
+ embedded_test_server()->GetURL("/" + kUpdateManifestFileName), profile(),
+ mock_policy_provider());
// By default, the system token is disabled.
std::string system_token_availability = "";
@@ -253,7 +306,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest,
EnterprisePlatformKeysIsRestrictedToPolicyExtension) {
ASSERT_TRUE(RunExtensionSubtest("enterprise_platform_keys",
"api_not_available.html",
- kFlagIgnoreManifestWarnings));
+ kFlagIgnoreManifestWarnings, kFlagNone));
base::FilePath extension_path =
test_data_dir_.AppendASCII("enterprise_platform_keys");
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/OWNERS b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/OWNERS
index 19c00429c36..3163d94a4e8 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/OWNERS
@@ -3,3 +3,5 @@ drcrash@chromium.org
bartfab@chromium.org
mnissler@chromium.org
dkrahn@chromium.org
+
+# COMPONENT: Enterprise
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
index d0bec814aa9..275d148f325 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
@@ -97,9 +97,9 @@ EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::Run() {
api_epkp::ChallengeMachineKey::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
chromeos::attestation::TpmChallengeKeyCallback callback =
- base::Bind(&EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::
- OnChallengedKey,
- this);
+ base::BindOnce(&EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::
+ OnChallengedKey,
+ this);
std::string challenge;
if (!base::Base64Decode(params->challenge, &challenge)) {
@@ -124,7 +124,7 @@ void EnterprisePlatformKeysPrivateChallengeMachineKeyFunction::OnChallengedKey(
const chromeos::attestation::TpmChallengeKeyResult& result) {
if (result.IsSuccess()) {
std::string encoded_response;
- base::Base64Encode(result.data, &encoded_response);
+ base::Base64Encode(result.challenge_response, &encoded_response);
Respond(ArgumentList(
api_epkp::ChallengeMachineKey::Results::Create(encoded_response)));
} else {
@@ -143,7 +143,7 @@ EnterprisePlatformKeysPrivateChallengeUserKeyFunction::Run() {
std::unique_ptr<api_epkp::ChallengeUserKey::Params> params(
api_epkp::ChallengeUserKey::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- chromeos::attestation::TpmChallengeKeyCallback callback = base::Bind(
+ chromeos::attestation::TpmChallengeKeyCallback callback = base::BindOnce(
&EnterprisePlatformKeysPrivateChallengeUserKeyFunction::OnChallengedKey,
this);
@@ -169,7 +169,7 @@ void EnterprisePlatformKeysPrivateChallengeUserKeyFunction::OnChallengedKey(
const chromeos::attestation::TpmChallengeKeyResult& result) {
if (result.IsSuccess()) {
std::string encoded_response;
- base::Base64Encode(result.data, &encoded_response);
+ base::Base64Encode(result.challenge_response, &encoded_response);
Respond(ArgumentList(
api_epkp::ChallengeUserKey::Results::Create(encoded_response)));
} else {
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
index 590e72b12df..af225296c4b 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/values.h"
#include "chrome/browser/chromeos/attestation/mock_tpm_challenge_key.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
index f1bf1cfcfd8..36d3139b284 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
@@ -13,6 +13,7 @@
#include "base/base_paths.h"
#include "base/files/file_util.h"
#include "base/json/json_writer.h"
+#include "base/lazy_instance.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -22,10 +23,11 @@
#include "chrome/browser/extensions/api/enterprise_reporting_private/prefs.h"
#include "chrome/browser/policy/browser_dm_token_storage.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
-#include "chrome/browser/policy/policy_conversions.h"
+#include "chrome/browser/policy/chrome_policy_conversions_client.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/pref_names.h"
+#include "components/policy/core/browser/policy_conversions.h"
#include "components/policy/core/common/cloud/cloud_policy_client.h"
#include "components/policy/core/common/cloud/cloud_policy_util.h"
#include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h"
@@ -38,6 +40,11 @@
#include "base/win/registry.h"
#endif
+#if defined(OS_LINUX)
+#include "base/environment.h"
+#include "base/nix/xdg_util.h"
+#endif
+
#if defined(OS_MACOSX)
#include "crypto/apple_keychain.h"
#endif
@@ -124,10 +131,11 @@ void AppendAdditionalBrowserInformation(em::ChromeDesktopReportRequest* request,
if (prefs->GetBoolean(enterprise_reporting::kReportPolicyData)) {
// Set policy data of the first profile. Extension will report this data in
// the future.
+ auto client =
+ std::make_unique<policy::ChromePolicyConversionsClient>(profile);
request->mutable_browser_report()
->mutable_chrome_user_profile_reports(0)
- ->set_policy_data(policy::DictionaryPolicyConversions()
- .WithBrowserContext(profile)
+ ->set_policy_data(policy::DictionaryPolicyConversions(std::move(client))
.EnablePrettyPrint(false)
.ToJSON());
@@ -364,20 +372,34 @@ std::string ReadEncryptedSecret() {
#endif // defined(OS_MACOSX)
+base::FilePath* GetEndpointVerificationDirOverride() {
+ static base::NoDestructor<base::FilePath> dir_override;
+ return dir_override.get();
+}
+
// Returns "AppData\Local\Google\Endpoint Verification".
base::FilePath GetEndpointVerificationDir() {
base::FilePath path;
+ if (!GetEndpointVerificationDirOverride()->empty())
+ return *GetEndpointVerificationDirOverride();
#if defined(OS_WIN)
if (!base::PathService::Get(base::DIR_LOCAL_APP_DATA, &path))
#elif defined(OS_LINUX)
- if (!base::PathService::Get(base::DIR_CACHE, &path))
+ std::unique_ptr<base::Environment> env(base::Environment::Create());
+ path = base::nix::GetXDGDirectory(env.get(), base::nix::kXdgConfigHomeEnvVar,
+ base::nix::kDotConfigDir);
+ if (path.empty())
#elif defined(OS_MACOSX)
if (!base::PathService::Get(base::DIR_APP_DATA, &path))
#else
if (true)
#endif
return path;
+#if defined(OS_LINUX)
+ path = path.AppendASCII("google");
+#else
path = path.AppendASCII("Google");
+#endif
path = path.AppendASCII("Endpoint Verification");
return path;
}
@@ -418,8 +440,13 @@ GenerateChromeDesktopReportRequest(const base::DictionaryValue& report,
return request;
}
+// Sets the path used to store Endpoint Verification data for tests.
+void OverrideEndpointVerificationDirForTesting(const base::FilePath& path) {
+ *GetEndpointVerificationDirOverride() = path;
+}
+
void StoreDeviceData(const std::string& id,
- const std::vector<uint8_t>& data,
+ const std::unique_ptr<std::vector<uint8_t>> data,
base::OnceCallback<void(bool)> callback) {
base::FilePath data_file = GetEndpointVerificationDir();
if (data_file.empty()) {
@@ -431,28 +458,36 @@ void StoreDeviceData(const std::string& id,
// subdir+file of the EV folder.
data_file = data_file.AppendASCII(id);
- // Ensure the directory exists.
- bool success = base::CreateDirectory(data_file.DirName());
- if (!success) {
- LOG(ERROR) << "Could not create directory: "
- << data_file.DirName().LossyDisplayName();
- std::move(callback).Run(false);
- return;
- }
+ bool success = false;
+ if (data) {
+ // Ensure the directory exists.
+ success = base::CreateDirectory(data_file.DirName());
+ if (!success) {
+ LOG(ERROR) << "Could not create directory: "
+ << data_file.DirName().LossyDisplayName();
+ std::move(callback).Run(false);
+ return;
+ }
- base::FilePath tmp_path;
- success = base::CreateTemporaryFileInDir(data_file.DirName(), &tmp_path);
- if (!success) {
- LOG(ERROR) << "Could not open file for writing: "
- << tmp_path.LossyDisplayName();
- std::move(callback).Run(false);
- return;
- }
+ base::FilePath tmp_path;
+ success = base::CreateTemporaryFileInDir(data_file.DirName(), &tmp_path);
+ if (!success) {
+ LOG(ERROR) << "Could not open file for writing: "
+ << tmp_path.LossyDisplayName();
+ std::move(callback).Run(false);
+ return;
+ }
- base::WriteFile(tmp_path, reinterpret_cast<const char*>(data.data()),
- data.size());
+ base::WriteFile(tmp_path, reinterpret_cast<const char*>(data->data()),
+ data->size());
+ success = base::Move(tmp_path, data_file);
+ } else {
+ // Not passing a second parameter means clear the data sored under |id|.
+ success = base::DeleteFile(data_file, false);
+ if (base::IsDirectoryEmpty(data_file.DirName()))
+ base::DeleteFile(data_file.DirName(), false);
+ }
- success = base::Move(tmp_path, data_file);
std::move(callback).Run(success);
}
@@ -465,9 +500,16 @@ void RetrieveDeviceData(
return;
}
data_file = data_file.AppendASCII(id);
- // TODO(pastarmovj): Make sure the resulting path is still a direct file or
- // subdir+file of the EV folder.
+ // If the file does not exist don't treat this as an error rather return an
+ // empty string.
+ if (!base::PathExists(data_file)) {
+ std::move(callback).Run("", true);
+ return;
+ }
std::string data;
+ // ReadFileToString does not permit traversal with .. so this is guaranteed to
+ // be a descendant of the data directory up to links created outside of
+ // Chrome.
bool result = base::ReadFileToString(data_file, &data);
std::move(callback).Run(data, result);
@@ -489,8 +531,10 @@ void RetrieveDeviceSecret(
}
#elif defined(OS_MACOSX)
secret = ReadEncryptedSecret();
- if (secret.empty())
+ if (secret.empty()) {
std::move(callback).Run(secret, false);
+ return;
+ }
#endif
std::move(callback).Run(secret, true);
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h
index 8fc45f04a00..fd6d229ea24 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/files/file_path.h"
#include "components/policy/proto/device_management_backend.pb.h"
class Profile;
@@ -26,10 +27,13 @@ std::unique_ptr<enterprise_management::ChromeDesktopReportRequest>
GenerateChromeDesktopReportRequest(const base::DictionaryValue& report,
Profile* profile);
+// Override the path where Endpoint Verification data is stored for tests.
+void OverrideEndpointVerificationDirForTesting(const base::FilePath& path);
+
// Store the |data| associated with the identifier |id|. Calls |callback| on
// completion with true on success.
void StoreDeviceData(const std::string& id,
- const std::vector<uint8_t>& data,
+ const std::unique_ptr<std::vector<uint8_t>> data,
base::OnceCallback<void(bool)> callback);
// Retrieves the data associated with the identifier |id|. Calls |callback| on
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher.cc
index 36f40909392..97c7c3689df 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher.cc
@@ -11,6 +11,8 @@
#include "chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_mac.h"
#elif defined(OS_WIN)
#include "chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_win.h"
+#elif defined(OS_LINUX)
+#include "chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.h"
#endif
namespace extensions {
@@ -56,6 +58,8 @@ std::unique_ptr<DeviceInfoFetcher> DeviceInfoFetcher::CreateInstance() {
return std::make_unique<DeviceInfoFetcherMac>();
#elif defined(OS_WIN)
return std::make_unique<DeviceInfoFetcherWin>();
+#elif defined(OS_LINUX)
+ return std::make_unique<DeviceInfoFetcherLinux>();
#else
return std::make_unique<StubDeviceFetcher>();
#endif
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.cc
new file mode 100644
index 00000000000..ccf6a8092b9
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.cc
@@ -0,0 +1,135 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.h"
+
+#if defined(USE_GIO)
+#include <gio/gio.h>
+#endif // defined(USE_GIO)
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+
+#include <string>
+
+#include "base/environment.h"
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/nix/xdg_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/system/sys_info.h"
+#include "net/base/network_interfaces.h"
+
+namespace enterprise_reporting_private =
+ ::extensions::api::enterprise_reporting_private;
+
+namespace extensions {
+namespace enterprise_reporting {
+
+namespace {
+
+std::string GetDeviceModel() {
+ return base::SysInfo::HardwareModelName();
+}
+
+std::string GetOsVersion() {
+ return base::SysInfo::OperatingSystemVersion();
+}
+
+std::string GetDeviceHostName() {
+ return net::GetHostName();
+}
+
+std::string GetSerialNumber() {
+ return std::string();
+}
+
+// Implements the logic from the native client setup script. It reads the
+// setting value straight from gsettings but picks the schema relevant to the
+// currently active desktop environment.
+// The current implementation support Gnone and Cinnamon only.
+enterprise_reporting_private::SettingValue GetScreenlockSecured() {
+#if defined(USE_GIO)
+ constexpr char kLockScreenKey[] = "lock-enabled";
+
+ std::unique_ptr<base::Environment> env(base::Environment::Create());
+ const base::nix::DesktopEnvironment desktop_env =
+ base::nix::GetDesktopEnvironment(env.get());
+ if (desktop_env != base::nix::DESKTOP_ENVIRONMENT_CINNAMON &&
+ desktop_env != base::nix::DESKTOP_ENVIRONMENT_GNOME) {
+ return enterprise_reporting_private::SETTING_VALUE_UNKNOWN;
+ }
+
+ const std::string settings_schema = base::StringPrintf(
+ "org.%s.desktop.screensaver",
+ desktop_env == base::nix::DESKTOP_ENVIRONMENT_CINNAMON ? "cinnamon"
+ : "gnome");
+
+ GSettingsSchema* screensaver_schema = g_settings_schema_source_lookup(
+ g_settings_schema_source_get_default(), settings_schema.c_str(), FALSE);
+ GSettings* screensaver_settings = nullptr;
+ if (!screensaver_schema ||
+ !g_settings_schema_has_key(screensaver_schema, kLockScreenKey)) {
+ return enterprise_reporting_private::SETTING_VALUE_UNKNOWN;
+ }
+ screensaver_settings = g_settings_new(settings_schema.c_str());
+ if (!screensaver_settings)
+ return enterprise_reporting_private::SETTING_VALUE_UNKNOWN;
+ gboolean lock_screen_enabled =
+ g_settings_get_boolean(screensaver_settings, kLockScreenKey);
+ g_object_unref(screensaver_settings);
+
+ return lock_screen_enabled
+ ? enterprise_reporting_private::SETTING_VALUE_ENABLED
+ : enterprise_reporting_private::SETTING_VALUE_DISABLED;
+#else
+ return enterprise_reporting_private::SETTING_VALUE_UNKNOWN;
+#endif // defined(USE_GIO)
+}
+
+// Implements the logic from the native host installation script. First find the
+// root device identifier, then locate its parent and get its type.
+enterprise_reporting_private::SettingValue GetDiskEncrypted() {
+ struct stat info;
+ // First figure out the device identifier.
+ stat("/", &info);
+ int dev_major = major(info.st_dev);
+ // The parent identifier will have the same major and minor 0. If and only if
+ // it is a dm device can it also be an encrypted device (as evident from the
+ // source code of the lsblk command).
+ base::FilePath dev_uuid(
+ base::StringPrintf("/sys/dev/block/%d:0/dm/uuid", dev_major));
+ std::string uuid;
+ if (base::PathExists(dev_uuid) &&
+ base::ReadFileToStringWithMaxSize(dev_uuid, &uuid, 1024)) {
+ // The device uuid starts with the driver type responsible for it. If it is
+ // the "crypt" driver then it is an encrypted device.
+ bool is_encrypted =
+ base::StartsWith(uuid, "crypt-", base::CompareCase::INSENSITIVE_ASCII);
+ return is_encrypted ? enterprise_reporting_private::SETTING_VALUE_ENABLED
+ : enterprise_reporting_private::SETTING_VALUE_DISABLED;
+ }
+ return enterprise_reporting_private::SETTING_VALUE_UNKNOWN;
+}
+
+} // namespace
+
+DeviceInfoFetcherLinux::DeviceInfoFetcherLinux() = default;
+
+DeviceInfoFetcherLinux::~DeviceInfoFetcherLinux() = default;
+
+DeviceInfo DeviceInfoFetcherLinux::Fetch() {
+ DeviceInfo device_info;
+ device_info.os_name = "linux";
+ device_info.os_version = GetOsVersion();
+ device_info.device_host_name = GetDeviceHostName();
+ device_info.device_model = GetDeviceModel();
+ device_info.serial_number = GetSerialNumber();
+ device_info.screen_lock_secured = GetScreenlockSecured();
+ device_info.disk_encrypted = GetDiskEncrypted();
+ return device_info;
+}
+
+} // namespace enterprise_reporting
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.h b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.h
new file mode 100644
index 00000000000..67a4781a9c4
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_linux.h
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_DEVICE_INFO_FETCHER_LINUX_H_
+#define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_DEVICE_INFO_FETCHER_LINUX_H_
+
+#include "chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher.h"
+
+namespace extensions {
+namespace enterprise_reporting {
+
+using DeviceInfo = ::extensions::api::enterprise_reporting_private::DeviceInfo;
+
+// Linux implementation of DeviceInfoFetcher.
+class DeviceInfoFetcherLinux : public DeviceInfoFetcher {
+ public:
+ DeviceInfoFetcherLinux();
+ DeviceInfoFetcherLinux(const DeviceInfoFetcherLinux&) = delete;
+ DeviceInfoFetcherLinux& operator=(const DeviceInfoFetcherLinux&) = delete;
+ ~DeviceInfoFetcherLinux() override;
+
+ // Overrides DeviceInfoFetcher:
+ DeviceInfo Fetch() override;
+};
+
+} // namespace enterprise_reporting
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_DEVICE_INFO_FETCHER_LINUX_H_
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_mac.mm b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_mac.mm
index d74e49d706b..bd5ed9364f5 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_mac.mm
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_mac.mm
@@ -5,12 +5,14 @@
#include "chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_mac.h"
#import <Foundation/Foundation.h>
-#import <IOKit/IOKitLib.h>
-#import <sys/sysctl.h>
+
+#include <IOKit/IOKitLib.h>
+#include <sys/sysctl.h>
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/mac/foundation_util.h"
+#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_ioobject.h"
#include "base/process/launch.h"
@@ -38,26 +40,8 @@ std::string GetDeviceHostName() {
return net::GetHostName();
}
-// This approach was described here:
-// https://developer.apple.com/library/content/technotes/tn1103/_index.html
std::string GetSerialNumber() {
- std::string serial_number;
- base::mac::ScopedIOObject<io_service_t> platform_expert(
- IOServiceGetMatchingService(kIOMasterPortDefault,
- IOServiceMatching("IOPlatformExpertDevice")));
-
- if (platform_expert) {
- base::ScopedCFTypeRef<CFTypeRef> serial_number_cf_string(
- IORegistryEntryCreateCFProperty(platform_expert,
- CFSTR(kIOPlatformSerialNumberKey),
- kCFAllocatorDefault, 0));
- if (serial_number_cf_string) {
- serial_number = base::SysCFStringRefToUTF8(
- base::mac::CFCastStrict<CFStringRef>(serial_number_cf_string));
- }
- }
-
- return serial_number;
+ return base::mac::GetPlatformSerialNumber();
}
enterprise_reporting_private::SettingValue GetScreenlockSecured() {
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_win.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_win.cc
index f381fecbb6b..0a8935a022e 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_win.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/device_info_fetcher_win.cc
@@ -71,9 +71,6 @@ base::Optional<bool> GetConsoleLockStatus() {
if (!::GetSystemPowerStatus(&sps))
return status;
- auto const power_read_current_value =
- sps.ACLineStatus != 0U ? &PowerReadACValue : &PowerReadDCValue;
-
LPGUID p_active_policy = nullptr;
// https://docs.microsoft.com/en-us/windows/desktop/api/powersetting/nf-powersetting-powergetactivescheme
// Retrieves the active power scheme and returns a GUID that identifies the
@@ -87,6 +84,8 @@ base::Optional<bool> GetConsoleLockStatus() {
const GUID active_policy = *p_active_policy;
::LocalFree(p_active_policy);
+ auto const power_read_current_value_func =
+ sps.ACLineStatus != 0U ? &PowerReadACValue : &PowerReadDCValue;
ULONG type;
DWORD value;
DWORD value_size = sizeof(value);
@@ -96,7 +95,7 @@ base::Optional<bool> GetConsoleLockStatus() {
// LPBYTE case is safe and is needed as the function expects generic byte
// array buffer regardless of the exact value read as it is a generic
// interface.
- if (power_read_current_value(
+ if (power_read_current_value_func(
nullptr, &active_policy, &NO_SUBGROUP_GUID, &kConsoleLock, &type,
reinterpret_cast<LPBYTE>(&value), &value_size) == ERROR_SUCCESS) {
status = value != 0U;
@@ -124,8 +123,7 @@ enterprise_reporting_private::SettingValue GetScreenlockSecured() {
return enterprise_reporting_private::SETTING_VALUE_UNKNOWN;
}
-// Writes the volume where the Windows OS is installed in |out_volume|. Returns
-// false if there was an error retrieving the volume.
+// Returns the volume where the Windows OS is installed.
base::Optional<std::wstring> GetOsVolume() {
base::Optional<std::wstring> volume;
base::FilePath windows_dir;
@@ -180,7 +178,7 @@ bool GetPropVariantAsInt64(PROPVARIANT variant, int64_t* out_value) {
// The values given in the BitLockerStatus enum contain the relevant values
// for the shell property. I also directly validated them.
enterprise_reporting_private::SettingValue GetDiskEncrypted() {
- // It has to be a |wstring| because |SHCreateItemFromParsingName| only
+ // |volume| has to be a |wstring| because SHCreateItemFromParsingName() only
// accepts |PCWSTR| which is |wchar_t*|.
base::Optional<std::wstring> volume = GetOsVolume();
if (!volume.has_value())
@@ -192,9 +190,6 @@ enterprise_reporting_private::SettingValue GetDiskEncrypted() {
if (FAILED(property_key_result))
return enterprise_reporting_private::SETTING_VALUE_UNKNOWN;
- // This class inherits from IUnknown, which is essentially a pointer to
- // a reference counted object. The reference should be released explicitly
- // calling item->Release().
Microsoft::WRL::ComPtr<IShellItem2> item;
const HRESULT create_item_result = SHCreateItemFromParsingName(
volume.value().c_str(), nullptr, IID_IShellItem2, &item);
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
index d270a2b6d42..af9cb307756 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
@@ -12,6 +12,7 @@
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
@@ -120,7 +121,7 @@ EnterpriseReportingPrivateUploadChromeDesktopReportFunction::Run() {
cloud_policy_client_->UploadChromeDesktopReport(
std::move(request),
- base::BindRepeating(
+ base::BindOnce(
&EnterpriseReportingPrivateUploadChromeDesktopReportFunction::
OnReportUploaded,
this));
@@ -182,10 +183,9 @@ EnterpriseReportingPrivateGetPersistentSecretFunction::
ExtensionFunction::ResponseAction
EnterpriseReportingPrivateGetPersistentSecretFunction::Run() {
// TODO(pastarmovj): Consider keying the secret retrieval by extension id.
- base::PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(
&RetrieveDeviceSecret,
base::BindOnce(
@@ -222,10 +222,9 @@ EnterpriseReportingPrivateGetDeviceDataFunction::Run() {
params(api::enterprise_reporting_private::GetDeviceData::Params::Create(
*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
- base::PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(
&RetrieveDeviceData, params->id,
base::BindOnce(
@@ -261,12 +260,11 @@ EnterpriseReportingPrivateSetDeviceDataFunction::Run() {
params(api::enterprise_reporting_private::SetDeviceData::Params::Create(
*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
- base::PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(
- &StoreDeviceData, params->id, params->data,
+ &StoreDeviceData, params->id, std::move(params->data),
base::BindOnce(
&EnterpriseReportingPrivateSetDeviceDataFunction::OnDataStored,
this)));
@@ -295,7 +293,7 @@ ExtensionFunction::ResponseAction
EnterpriseReportingPrivateGetDeviceInfoFunction::Run() {
#if defined(OS_WIN)
base::PostTaskAndReplyWithResult(
- base::CreateCOMSTATaskRunner({base::ThreadPool()}).get(), FROM_HERE,
+ base::ThreadPool::CreateCOMSTATaskRunner({}).get(), FROM_HERE,
base::BindOnce(&enterprise_reporting::DeviceInfoFetcher::Fetch,
enterprise_reporting::DeviceInfoFetcher::CreateInstance()),
base::BindOnce(&EnterpriseReportingPrivateGetDeviceInfoFunction::
@@ -303,8 +301,7 @@ EnterpriseReportingPrivateGetDeviceInfoFunction::Run() {
this));
#else
base::PostTaskAndReplyWithResult(
- base::CreateTaskRunner({base::ThreadPool(), base::MayBlock()}).get(),
- FROM_HERE,
+ base::ThreadPool::CreateTaskRunner({base::MayBlock()}).get(), FROM_HERE,
base::BindOnce(&enterprise_reporting::DeviceInfoFetcher::Fetch,
enterprise_reporting::DeviceInfoFetcher::CreateInstance()),
base::BindOnce(&EnterpriseReportingPrivateGetDeviceInfoFunction::
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
index 9cda730cd68..325ef19e167 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
@@ -10,6 +10,7 @@
#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
+#include "chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h"
#include "chrome/browser/extensions/extension_api_unittest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/policy/fake_browser_dm_token_storage.h"
@@ -170,15 +171,7 @@ class EnterpriseReportingPrivateDeviceDataFunctionsTest
void SetUp() override {
ExtensionApiUnittest::SetUp();
ASSERT_TRUE(fake_appdata_dir_.CreateUniqueTempDir());
-#if defined(OS_WIN)
- base::PathService::Override(base::DIR_LOCAL_APP_DATA,
- fake_appdata_dir_.GetPath());
-#elif defined(OS_LINUX)
- base::PathService::Override(base::DIR_CACHE, fake_appdata_dir_.GetPath());
-#elif defined(OS_MACOSX)
- base::PathService::Override(base::DIR_APP_DATA,
- fake_appdata_dir_.GetPath());
-#endif
+ OverrideEndpointVerificationDirForTesting(fake_appdata_dir_.GetPath());
}
private:
@@ -211,6 +204,32 @@ TEST_F(EnterpriseReportingPrivateDeviceDataFunctionsTest, DeviceDataMissing) {
browser(),
extensions::api_test_utils::NONE);
ASSERT_TRUE(function->GetResultList());
+ EXPECT_EQ(1u, function->GetResultList()->GetSize());
+ EXPECT_TRUE(function->GetError().empty());
+}
+
+TEST_F(EnterpriseReportingPrivateDeviceDataFunctionsTest, DeviceBadId) {
+ auto set_function =
+ base::MakeRefCounted<EnterpriseReportingPrivateSetDeviceDataFunction>();
+ std::unique_ptr<base::ListValue> set_values =
+ std::make_unique<base::ListValue>();
+ set_values->AppendString("a/b");
+ set_values->Append(
+ std::make_unique<base::Value>(base::Value::BlobStorage({1, 2, 3})));
+ extension_function_test_utils::RunFunction(set_function.get(),
+ std::move(set_values), browser(),
+ extensions::api_test_utils::NONE);
+ ASSERT_TRUE(set_function->GetError().empty());
+
+ // Try to read the directory as a file and should fail.
+ auto function =
+ base::MakeRefCounted<EnterpriseReportingPrivateGetDeviceDataFunction>();
+ std::unique_ptr<base::ListValue> values = std::make_unique<base::ListValue>();
+ values->AppendString("a");
+ extension_function_test_utils::RunFunction(function.get(), std::move(values),
+ browser(),
+ extensions::api_test_utils::NONE);
+ ASSERT_TRUE(function->GetResultList());
EXPECT_EQ(0u, function->GetResultList()->GetSize());
EXPECT_FALSE(function->GetError().empty());
}
@@ -242,6 +261,32 @@ TEST_F(EnterpriseReportingPrivateDeviceDataFunctionsTest, RetrieveDeviceData) {
ASSERT_TRUE(single_result);
ASSERT_TRUE(single_result->is_blob());
EXPECT_EQ(base::Value::BlobStorage({1, 2, 3}), single_result->GetBlob());
+
+ // Clear the data and check that it is gone.
+ auto set_function2 =
+ base::MakeRefCounted<EnterpriseReportingPrivateSetDeviceDataFunction>();
+ std::unique_ptr<base::ListValue> reset_values =
+ std::make_unique<base::ListValue>();
+ reset_values->AppendString("c");
+ extension_function_test_utils::RunFunction(set_function2.get(),
+ std::move(reset_values), browser(),
+ extensions::api_test_utils::NONE);
+ ASSERT_TRUE(set_function2->GetError().empty());
+
+ auto get_function2 =
+ base::MakeRefCounted<EnterpriseReportingPrivateGetDeviceDataFunction>();
+ std::unique_ptr<base::ListValue> values2 =
+ std::make_unique<base::ListValue>();
+ values2->AppendString("c");
+ extension_function_test_utils::RunFunction(get_function2.get(),
+ std::move(values2), browser(),
+ extensions::api_test_utils::NONE);
+ ASSERT_TRUE(get_function2->GetResultList());
+ EXPECT_TRUE(get_function2->GetResultList()->Get(0, &single_result));
+ EXPECT_TRUE(get_function2->GetError().empty());
+ ASSERT_TRUE(single_result);
+ ASSERT_TRUE(single_result->is_blob());
+ EXPECT_EQ(base::Value::BlobStorage(), single_result->GetBlob());
}
// TODO(pastarmovj): Remove once implementation for the other platform exists.
@@ -308,6 +353,10 @@ TEST_F(EnterpriseReportingPrivateGetDeviceInfoTest, GetDeviceInfo) {
EXPECT_EQ("macOS", info.os_name);
#elif defined(OS_WIN)
EXPECT_EQ("windows", info.os_name);
+#elif defined(OS_LINUX)
+ std::unique_ptr<base::Environment> env(base::Environment::Create());
+ env->SetVar("XDG_CURRENT_DESKTOP", "XFCE");
+ EXPECT_EQ("linux", info.os_name);
#else
// Verify a stub implementation.
EXPECT_EQ("stubOS", info.os_name);
diff --git a/chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
index def1cb767b5..ea817b1bb3f 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -9,6 +9,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/scoped_observer.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
@@ -30,8 +31,9 @@
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/extensions/browser_action_test_util.h"
+#include "chrome/browser/ui/extensions/extension_action_test_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/ui_features.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
@@ -47,15 +49,16 @@
#include "content/public/test/download_test_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
+#include "extensions/browser/extension_host.h"
+#include "extensions/browser/extension_host_observer.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
-#include "extensions/browser/notification_types.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/common/feature_switch.h"
+#include "extensions/common/scoped_worker_based_extensions_channel.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
-#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/base/resource/resource_bundle.h"
@@ -103,35 +106,20 @@ class BrowserActionApiTest : public ExtensionApiTest {
BrowserActionApiTest() {}
~BrowserActionApiTest() override {}
- void SetUpOnMainThread() override {
- ExtensionApiTest::SetUpOnMainThread();
- host_resolver()->AddRule("*", "127.0.0.1");
+ void TearDownOnMainThread() override {
+ // Clean up the test util first, so that any created UI properly removes
+ // itself before profile destruction.
+ browser_action_test_util_.reset();
+ ExtensionApiTest::TearDownOnMainThread();
}
protected:
- BrowserActionTestUtil* GetBrowserActionsBar() {
+ ExtensionActionTestHelper* GetBrowserActionsBar() {
if (!browser_action_test_util_)
- browser_action_test_util_ = BrowserActionTestUtil::Create(browser());
+ browser_action_test_util_ = ExtensionActionTestHelper::Create(browser());
return browser_action_test_util_.get();
}
- WebContents* OpenPopup(int index) {
- ResultCatcher catcher;
- content::WindowedNotificationObserver popup_observer(
- content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
- content::NotificationService::AllSources());
- GetBrowserActionsBar()->Press(index);
- popup_observer.Wait();
- EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
-
- if (!GetBrowserActionsBar()->HasPopup())
- return nullptr;
-
- const auto& source = static_cast<const content::Source<WebContents>&>(
- popup_observer.source());
- return source.ptr();
- }
-
ExtensionAction* GetBrowserAction(Browser* browser,
const Extension& extension) {
ExtensionAction* extension_action =
@@ -143,7 +131,7 @@ class BrowserActionApiTest : public ExtensionApiTest {
}
private:
- std::unique_ptr<BrowserActionTestUtil> browser_action_test_util_;
+ std::unique_ptr<ExtensionActionTestHelper> browser_action_test_util_;
DISALLOW_COPY_AND_ASSIGN(BrowserActionApiTest);
};
@@ -158,33 +146,50 @@ class BrowserActionApiCanvasTest : public BrowserActionApiTest {
}
};
-// Watches a frame is swapped with a new frame by e.g., navigation.
-class RenderFrameChangedWatcher : public content::WebContentsObserver {
+enum TestFlags {
+ kNone = 0,
+ kUseServiceWorker = 1,
+ kUseExtensionsMenuUi = 1 << 1,
+};
+
+class BrowserActionApiLazyTest : public BrowserActionApiTest,
+ public testing::WithParamInterface<int> {
public:
- explicit RenderFrameChangedWatcher(WebContents* web_contents)
- : WebContentsObserver(web_contents) {}
+ void SetUp() override {
+ BrowserActionApiTest::SetUp();
+ // Service Workers are currently only available on certain channels, so set
+ // the channel for those tests.
+ if ((GetParam() & kUseServiceWorker) != 0) {
+ current_channel_ =
+ std::make_unique<extensions::ScopedWorkerBasedExtensionsChannel>();
+ }
- void RenderFrameHostChanged(content::RenderFrameHost* old_host,
- content::RenderFrameHost* new_host) override {
- created_frame_ = new_host;
- run_loop_.Quit();
+ if ((GetParam() & kUseExtensionsMenuUi) != 0) {
+ feature_list_.InitAndEnableFeature(features::kExtensionsToolbarMenu);
+ } else {
+ feature_list_.InitAndDisableFeature(features::kExtensionsToolbarMenu);
+ }
}
- content::RenderFrameHost* WaitAndReturnNewFrame() {
- run_loop_.Run();
- return created_frame_;
+ const extensions::Extension* LoadExtensionWithParamFlags(
+ const base::FilePath& path) {
+ int flags = kFlagEnableFileAccess;
+ if ((GetParam() & kUseServiceWorker) != 0)
+ flags |= ExtensionBrowserTest::kFlagRunAsServiceWorkerBasedExtension;
+ return LoadExtensionWithFlags(path, flags);
}
private:
- base::RunLoop run_loop_;
- content::RenderFrameHost* created_frame_;
+ base::test::ScopedFeatureList feature_list_;
+ std::unique_ptr<extensions::ScopedWorkerBasedExtensionsChannel>
+ current_channel_;
};
-IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, Basic) {
+IN_PROC_BROWSER_TEST_P(BrowserActionApiLazyTest, Basic) {
ExtensionTestMessageListener ready_listener("ready", false);
ASSERT_TRUE(embedded_test_server()->Start());
- const Extension* extension =
- LoadExtension(test_data_dir_.AppendASCII("browser_action/basics"));
+ const Extension* extension = LoadExtensionWithParamFlags(
+ test_data_dir_.AppendASCII("browser_action/basics"));
ASSERT_TRUE(extension) << message_;
// Test that there is a browser action in the toolbar.
@@ -204,11 +209,12 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, Basic) {
EXPECT_TRUE(catcher.GetNextResult());
}
-IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, Update) {
+using BrowserActionApiUpdateLazyTest = BrowserActionApiLazyTest;
+IN_PROC_BROWSER_TEST_P(BrowserActionApiUpdateLazyTest, Update) {
ExtensionTestMessageListener ready_listener("ready", true);
ASSERT_TRUE(embedded_test_server()->Start());
- const Extension* extension =
- LoadExtension(test_data_dir_.AppendASCII("browser_action/update"));
+ const Extension* extension = LoadExtensionWithParamFlags(
+ test_data_dir_.AppendASCII("browser_action/update"));
ASSERT_TRUE(extension) << message_;
// Test that there is a browser action in the toolbar.
ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions());
@@ -236,6 +242,36 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, Update) {
action->GetBadgeBackgroundColor(ExtensionAction::kDefaultTabId));
}
+INSTANTIATE_TEST_SUITE_P(EventPageAndLegacyToolbar,
+ BrowserActionApiLazyTest,
+ ::testing::Values(kNone));
+INSTANTIATE_TEST_SUITE_P(EventPageAndExtensionsMenu,
+ BrowserActionApiLazyTest,
+ ::testing::Values(kUseExtensionsMenuUi));
+INSTANTIATE_TEST_SUITE_P(ServiceWorkerAndLegacyToolbar,
+ BrowserActionApiLazyTest,
+ ::testing::Values(kUseServiceWorker));
+INSTANTIATE_TEST_SUITE_P(ServiceWorkerAndExtensionsMenu,
+ BrowserActionApiLazyTest,
+ ::testing::Values(kUseServiceWorker |
+ kUseExtensionsMenuUi));
+
+INSTANTIATE_TEST_SUITE_P(EventPageAndLegacyToolbar,
+ BrowserActionApiUpdateLazyTest,
+ ::testing::Values(kNone));
+INSTANTIATE_TEST_SUITE_P(EventPageAndExtensionsMenu,
+ BrowserActionApiUpdateLazyTest,
+ ::testing::Values(kUseExtensionsMenuUi));
+// TODO(crbug.com/1015136): Enable these once setIcon works in Service worker
+// extensions. Also, combine this suite with BrowserActionApiLazyTest.
+// INSTANTIATE_TEST_SUITE_P(ServiceWorkerAndLegacyToolbar,
+// BrowserActionApiUpdateLazyTest,
+// ::testing::Values(kUseServiceWorker));
+// INSTANTIATE_TEST_SUITE_P(ServiceWorkerAndExtensionsMenu,
+// BrowserActionApiUpdateLazyTest,
+// ::testing::Values(kUseServiceWorker |
+// kUseExtensionsMenuUi));
+
IN_PROC_BROWSER_TEST_F(BrowserActionApiCanvasTest, DynamicBrowserAction) {
ASSERT_TRUE(RunExtensionTest("browser_action/no_icon")) << message_;
const Extension* extension = GetSingleLoadedExtension();
@@ -418,14 +454,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiCanvasTest, DynamicBrowserAction) {
EXPECT_EQ(kEmptyPathError, catcher.message());
}
-// https://crbug.com/1019669; flaky on ChromeOS.
-#if defined(OS_CHROMEOS)
-#define MAYBE_InvisibleIconBrowserAction DISABLED_InvisibleIconBrowserAction
-#else
-#define MAYBE_InvisibleIconBrowserAction InvisibleIconBrowserAction
-#endif
-IN_PROC_BROWSER_TEST_F(BrowserActionApiCanvasTest,
- MAYBE_InvisibleIconBrowserAction) {
+IN_PROC_BROWSER_TEST_F(BrowserActionApiCanvasTest, InvisibleIconBrowserAction) {
// Turn this on so errors are reported.
ExtensionActionSetIconFunction::SetReportErrorForInvisibleIconForTesting(
true);
@@ -515,41 +544,6 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, TabSpecificBrowserActionState) {
EXPECT_EQ("hi!", GetBrowserActionsBar()->GetTooltip(0));
}
-// http://code.google.com/p/chromium/issues/detail?id=70829
-// Mac used to be ok, but then mac 10.5 started failing too. =(
-IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, DISABLED_BrowserActionPopup) {
- ASSERT_TRUE(
- LoadExtension(test_data_dir_.AppendASCII("browser_action/popup")));
- BrowserActionTestUtil* actions_bar = GetBrowserActionsBar();
- const Extension* extension = GetSingleLoadedExtension();
- ASSERT_TRUE(extension) << message_;
-
- // The extension's popup's size grows by |growFactor| each click.
- const int growFactor = 500;
- gfx::Size minSize = actions_bar->GetMinPopupSize();
- gfx::Size middleSize = gfx::Size(growFactor, growFactor);
- gfx::Size maxSize = actions_bar->GetMaxPopupSize();
-
- // Ensure that two clicks will exceed the maximum allowed size.
- ASSERT_GT(minSize.height() + growFactor * 2, maxSize.height());
- ASSERT_GT(minSize.width() + growFactor * 2, maxSize.width());
-
- // Simulate a click on the browser action and verify the size of the resulting
- // popup. The first one tries to be 0x0, so it should be the min values.
- ASSERT_TRUE(OpenPopup(0));
- EXPECT_EQ(minSize, actions_bar->GetPopupSize());
- EXPECT_TRUE(actions_bar->HidePopup());
-
- ASSERT_TRUE(OpenPopup(0));
- EXPECT_EQ(middleSize, actions_bar->GetPopupSize());
- EXPECT_TRUE(actions_bar->HidePopup());
-
- // One more time, but this time it should be constrained by the max values.
- ASSERT_TRUE(OpenPopup(0));
- EXPECT_EQ(maxSize, actions_bar->GetPopupSize());
- EXPECT_TRUE(actions_bar->HidePopup());
-}
-
// Test that calling chrome.browserAction.setPopup() can enable and change
// a popup.
IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionAddPopup) {
@@ -641,11 +635,11 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionRemovePopup) {
<< "a specific tab id.";
}
-IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoBasic) {
+IN_PROC_BROWSER_TEST_P(BrowserActionApiLazyTest, IncognitoBasic) {
ExtensionTestMessageListener ready_listener("ready", false);
ASSERT_TRUE(embedded_test_server()->Start());
- const Extension* extension =
- LoadExtension(test_data_dir_.AppendASCII("browser_action/basics"));
+ const Extension* extension = LoadExtensionWithParamFlags(
+ test_data_dir_.AppendASCII("browser_action/basics"));
ASSERT_TRUE(extension) << message_;
// Test that there is a browser action in the toolbar.
@@ -655,7 +649,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoBasic) {
// default.
Browser* incognito_browser = CreateIncognitoBrowser(browser()->profile());
- ASSERT_EQ(0, BrowserActionTestUtil::Create(incognito_browser)
+ ASSERT_EQ(0, ExtensionActionTestHelper::Create(incognito_browser)
->NumberOfBrowserActions());
ASSERT_TRUE(ready_listener.WaitUntilSatisfied());
@@ -671,7 +665,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoBasic) {
extension->id(), browser()->profile(), true);
extension = registry_observer.WaitForExtensionLoaded();
- ASSERT_EQ(1, BrowserActionTestUtil::Create(incognito_browser)
+ ASSERT_EQ(1, ExtensionActionTestHelper::Create(incognito_browser)
->NumberOfBrowserActions());
ASSERT_TRUE(incognito_ready_listener.WaitUntilSatisfied());
@@ -689,10 +683,14 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoBasic) {
EXPECT_TRUE(catcher.GetNextResult());
}
-IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoUpdate) {
+IN_PROC_BROWSER_TEST_P(BrowserActionApiLazyTest, IncognitoUpdate) {
+ // TODO(crbug.com/1015136): Investigate flakiness WRT Service Workers and
+ // incognito mode.
+ if ((GetParam() & kUseServiceWorker) != 0)
+ return;
ASSERT_TRUE(embedded_test_server()->Start());
- const Extension* extension =
- LoadExtension(test_data_dir_.AppendASCII("browser_action/update"));
+ const Extension* extension = LoadExtensionWithParamFlags(
+ test_data_dir_.AppendASCII("browser_action/update"));
ASSERT_TRUE(extension) << message_;
// Test that there is a browser action in the toolbar.
ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions());
@@ -701,7 +699,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoUpdate) {
// default.
Browser* incognito_browser = CreateIncognitoBrowser(browser()->profile());
- ASSERT_EQ(0, BrowserActionTestUtil::Create(incognito_browser)
+ ASSERT_EQ(0, ExtensionActionTestHelper::Create(incognito_browser)
->NumberOfBrowserActions());
// Set up a listener so we can reply for the extension to do the update.
@@ -716,7 +714,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoUpdate) {
extensions::util::SetIsIncognitoEnabled(extension->id(), browser()->profile(),
true);
extension = registry_observer.WaitForExtensionLoaded();
- ASSERT_EQ(1, BrowserActionTestUtil::Create(incognito_browser)
+ ASSERT_EQ(1, ExtensionActionTestHelper::Create(incognito_browser)
->NumberOfBrowserActions());
ASSERT_TRUE(incognito_ready_listener.WaitUntilSatisfied());
@@ -752,7 +750,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoSplit) {
// Open an incognito browser.
Browser* incognito_browser = CreateIncognitoBrowser(browser()->profile());
- ASSERT_EQ(1, BrowserActionTestUtil::Create(incognito_browser)
+ ASSERT_EQ(1, ExtensionActionTestHelper::Create(incognito_browser)
->NumberOfBrowserActions());
// A click in the regular profile should open a tab in the regular profile.
@@ -766,31 +764,64 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, IncognitoSplit) {
}
IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, CloseBackgroundPage) {
+ ExtensionTestMessageListener listener("ready", /*will_reply=*/false);
ASSERT_TRUE(LoadExtension(
test_data_dir_.AppendASCII("browser_action/close_background")));
const Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(listener.WaitUntilSatisfied());
// There is a background page and a browser action with no badge text.
extensions::ProcessManager* manager =
extensions::ProcessManager::Get(browser()->profile());
- ASSERT_TRUE(manager->GetBackgroundHostForExtension(extension->id()));
+
+ ExtensionHost* extension_host =
+ manager->GetBackgroundHostForExtension(extension->id());
+ ASSERT_TRUE(extension_host);
+
ExtensionAction* action = GetBrowserAction(browser(), *extension);
ASSERT_EQ("",
action->GetExplicitlySetBadgeText(ExtensionAction::kDefaultTabId));
- content::WindowedNotificationObserver host_destroyed_observer(
- extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
- content::NotificationService::AllSources());
+ // A helper class to wait for the ExtensionHost to shut down.
+ // TODO(devlin): Hoist this somewhere more common and track down other similar
+ // usages.
+ class ExtensionHostDestructionObserver : public ExtensionHostObserver {
+ public:
+ explicit ExtensionHostDestructionObserver(ExtensionHost* host) {
+ host_observer_.Add(host);
+ }
+ ExtensionHostDestructionObserver(
+ const ExtensionHostDestructionObserver& other) = delete;
+ ExtensionHostDestructionObserver& operator=(
+ const ExtensionHostDestructionObserver& other) = delete;
+ ~ExtensionHostDestructionObserver() override = default;
+
+ void OnExtensionHostDestroyed(const ExtensionHost* host) override {
+ // TODO(devlin): It would be nice to
+ // ASSERT_TRUE(host_observer_.IsObserving(host));
+ // host_observer_.Remove(host);
+ // But we can't, because |host| is const. Work around it by just
+ // RemoveAll()ing.
+ host_observer_.RemoveAll();
+ run_loop_.QuitWhenIdle();
+ }
+
+ void Wait() { run_loop_.Run(); }
+
+ private:
+ base::RunLoop run_loop_;
+ ScopedObserver<ExtensionHost, ExtensionHostObserver> host_observer_{this};
+ };
+
+ ExtensionHostDestructionObserver host_destroyed_observer(extension_host);
// Click the browser action.
ExecuteExtensionAction(browser(), extension);
- // It can take a moment for the background page to actually get destroyed
- // so we wait for the notification before checking that it's really gone
- // and the badge text has been set.
host_destroyed_observer.Wait();
- ASSERT_FALSE(manager->GetBackgroundHostForExtension(extension->id()));
- ASSERT_EQ("X",
+
+ EXPECT_FALSE(manager->GetBackgroundHostForExtension(extension->id()));
+ EXPECT_EQ("X",
action->GetExplicitlySetBadgeText(ExtensionAction::kDefaultTabId));
}
@@ -900,58 +931,6 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, TestTriggerBrowserAction) {
EXPECT_EQ(result, "red");
}
-// Test that a browser action popup with a web iframe works correctly. The
-// iframe is expected to run in a separate process.
-// See https://crbug.com/546267.
-IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionPopupWithIframe) {
- ASSERT_TRUE(embedded_test_server()->Start());
-
- ASSERT_TRUE(LoadExtension(
- test_data_dir_.AppendASCII("browser_action/popup_with_iframe")));
- BrowserActionTestUtil* actions_bar = GetBrowserActionsBar();
- const Extension* extension = GetSingleLoadedExtension();
- ASSERT_TRUE(extension) << message_;
-
- // Simulate a click on the browser action to open the popup.
- ASSERT_TRUE(OpenPopup(0));
-
- // Find the RenderFrameHost associated with the iframe in the popup.
- content::RenderFrameHost* frame_host = nullptr;
- extensions::ProcessManager* manager =
- extensions::ProcessManager::Get(browser()->profile());
- std::set<content::RenderFrameHost*> frame_hosts =
- manager->GetRenderFrameHostsForExtension(extension->id());
- for (auto* host : frame_hosts) {
- if (host->GetFrameName() == "child_frame") {
- frame_host = host;
- break;
- }
- }
-
- ASSERT_TRUE(frame_host);
- EXPECT_EQ(extension->GetResourceURL("frame.html"),
- frame_host->GetLastCommittedURL());
- EXPECT_TRUE(frame_host->GetParent());
-
- // Navigate the popup's iframe to a (cross-site) web page, and wait for that
- // page to send a message, which will ensure that the page has loaded.
- RenderFrameChangedWatcher watcher(
- WebContents::FromRenderFrameHost(frame_host));
- GURL foo_url(embedded_test_server()->GetURL("foo.com", "/popup_iframe.html"));
- std::string script = "location.href = '" + foo_url.spec() + "'";
- EXPECT_TRUE(ExecuteScript(frame_host, script));
-
- frame_host = watcher.WaitAndReturnNewFrame();
-
- // Confirm that the new page (popup_iframe.html) is actually loaded.
- content::DOMMessageQueue dom_message_queue(frame_host);
- std::string json;
- EXPECT_TRUE(dom_message_queue.WaitForMessage(&json));
- EXPECT_EQ("\"DONE\"", json);
-
- EXPECT_TRUE(actions_bar->HidePopup());
-}
-
IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionWithRectangularIcon) {
ExtensionTestMessageListener ready_listener("ready", true);
@@ -1015,254 +994,6 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, BrowserActionOpenPopupOnPopup) {
EXPECT_TRUE(catcher.GetNextResult()) << message_;
}
-// Test that a browser action popup can download data URLs. See
-// https://crbug.com/821219
-// Fails consistently on Win7. https://crbug.com/827160
-#if defined(OS_WIN)
-#define MAYBE_BrowserActionPopupDownload DISABLED_BrowserActionPopupDownload
-#else
-#define MAYBE_BrowserActionPopupDownload BrowserActionPopupDownload
-#endif
-IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, MAYBE_BrowserActionPopupDownload) {
- ASSERT_TRUE(embedded_test_server()->Start());
-
- ASSERT_TRUE(LoadExtension(
- test_data_dir_.AppendASCII("browser_action/popup_download")));
- const Extension* extension = GetSingleLoadedExtension();
- ASSERT_TRUE(extension) << message_;
-
- content::DownloadTestObserverTerminal downloads_observer(
- content::BrowserContext::GetDownloadManager(browser()->profile()), 1,
- content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
-
- // Simulate a click on the browser action to open the popup.
- content::WebContents* popup = OpenPopup(0);
- ASSERT_TRUE(popup);
- content::ExecuteScriptAsync(popup, "run_tests()");
-
- // Wait for the download that this should have triggered to finish.
- downloads_observer.WaitForFinished();
-
- EXPECT_EQ(1u, downloads_observer.NumDownloadsSeenInState(
- download::DownloadItem::COMPLETE));
- EXPECT_TRUE(GetBrowserActionsBar()->HidePopup());
-}
-
-class NavigatingExtensionPopupBrowserTest : public BrowserActionApiTest {
- public:
- const Extension& popup_extension() { return *popup_extension_; }
- const Extension& other_extension() { return *other_extension_; }
-
- void SetUpOnMainThread() override {
- BrowserActionApiTest::SetUpOnMainThread();
-
- ASSERT_TRUE(embedded_test_server()->Start());
-
- // Load an extension with a pop-up.
- ASSERT_TRUE(popup_extension_ = LoadExtension(test_data_dir_.AppendASCII(
- "browser_action/popup_with_form")));
-
- // Load another extension (that we can try navigating to).
- ASSERT_TRUE(other_extension_ = LoadExtension(test_data_dir_.AppendASCII(
- "browser_action/popup_with_iframe")));
- }
-
- enum ExpectedNavigationStatus {
- EXPECTING_NAVIGATION_SUCCESS,
- EXPECTING_NAVIGATION_FAILURE,
- EXPECTING_NO_NAVIGATION,
- };
-
- void TestPopupNavigationViaGet(
- const GURL& target_url,
- ExpectedNavigationStatus expected_navigation_status) {
- std::string navigation_starting_script =
- "window.location = '" + target_url.spec() + "';\n";
- TestPopupNavigation(target_url, expected_navigation_status,
- navigation_starting_script);
- }
-
- void TestPopupNavigationViaPost(
- const GURL& target_url,
- ExpectedNavigationStatus expected_navigation_status) {
- std::string navigation_starting_script =
- "var form = document.getElementById('form');\n"
- "form.action = '" + target_url.spec() + "';\n"
- "form.submit();\n";
- TestPopupNavigation(target_url, expected_navigation_status,
- navigation_starting_script);
- }
-
- private:
- void TestPopupNavigation(const GURL& target_url,
- ExpectedNavigationStatus expected_navigation_status,
- std::string navigation_starting_script) {
- // Were there any failures so far (e.g. in SetUpOnMainThread)?
- ASSERT_FALSE(HasFailure());
-
- // Simulate a click on the browser action to open the popup.
- WebContents* popup = OpenPopup(0);
- ASSERT_TRUE(popup);
- GURL popup_url = popup_extension().GetResourceURL("popup.html");
- EXPECT_EQ(popup_url, popup->GetLastCommittedURL());
-
- // Note that the |setTimeout| call below is needed to make sure
- // ExecuteScriptAndExtractBool returns *after* a scheduled navigation has
- // already started.
- std::string script_to_execute =
- navigation_starting_script +
- "setTimeout(\n"
- " function() { window.domAutomationController.send(true); },\n"
- " 0);\n";
-
- // Try to navigate the pop-up.
- bool ignored_script_result = false;
- content::WebContentsDestroyedWatcher popup_destruction_watcher(popup);
- content::TestNavigationObserver popup_navigation_observer(popup);
- EXPECT_TRUE(ExecuteScriptAndExtractBool(popup, script_to_execute,
- &ignored_script_result));
- popup = popup_destruction_watcher.web_contents();
-
- // Verify if the popup navigation succeeded or failed as expected.
- if (!popup) {
- // If navigation ends up in a tab, then the tab will be focused and
- // therefore the popup will be closed, destroying associated WebContents -
- // don't do any verification in this case.
- ADD_FAILURE() << "Navigation should not close extension pop-up";
- } else {
- // If the extension popup is still opened, then wait until there is no
- // load in progress, and verify whether the navigation succeeded or not.
- if (expected_navigation_status != EXPECTING_NO_NAVIGATION) {
- popup_navigation_observer.Wait();
- } else {
- EXPECT_FALSE(popup->IsLoading());
- }
- // The popup should still be alive.
- ASSERT_TRUE(popup_destruction_watcher.web_contents());
-
- if (expected_navigation_status == EXPECTING_NAVIGATION_SUCCESS) {
- EXPECT_EQ(target_url, popup->GetLastCommittedURL())
- << "Navigation to " << target_url
- << " should succeed in an extension pop-up";
- } else {
- EXPECT_NE(target_url, popup->GetLastCommittedURL())
- << "Navigation to " << target_url
- << " should fail in an extension pop-up";
- EXPECT_THAT(
- popup->GetLastCommittedURL(),
- ::testing::AnyOf(::testing::Eq(popup_url),
- ::testing::Eq(GURL("chrome-extension://invalid")),
- ::testing::Eq(GURL("about:blank"))));
- }
-
- // Close the pop-up.
- EXPECT_TRUE(GetBrowserActionsBar()->HidePopup());
- popup_destruction_watcher.Wait();
- }
-
- // Make sure that the web navigation did not succeed somewhere outside of
- // the extension popup (as it might if ExtensionViewHost::OpenURLFromTab
- // forwards the navigation to Browser::OpenURL [which doesn't specify a
- // source WebContents]).
- TabStripModel* tabs = browser()->tab_strip_model();
- for (int i = 0; i < tabs->count(); i++) {
- WebContents* tab_contents = tabs->GetWebContentsAt(i);
- WaitForLoadStop(tab_contents);
- EXPECT_NE(target_url, tab_contents->GetLastCommittedURL())
- << "Navigating an extension pop-up should not affect tabs.";
- }
- }
-
- const Extension* popup_extension_;
- const Extension* other_extension_;
-};
-
-// Flaky - crbug.com/1021172
-#if defined(OS_LINUX)
-#define MAYBE_Webpage DISABLED_Webpage
-#else
-#define MAYBE_Webpage Webpage
-#endif
-// Tests that an extension pop-up cannot be navigated to a web page.
-IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupBrowserTest, MAYBE_Webpage) {
- GURL web_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
-
- // The GET request will be blocked in ExtensionViewHost::OpenURLFromTab
- // (which silently drops navigations with CURRENT_TAB disposition).
- TestPopupNavigationViaGet(web_url, EXPECTING_NO_NAVIGATION);
-
- // POST requests don't go through ExtensionViewHost::OpenURLFromTab.
- TestPopupNavigationViaPost(web_url, EXPECTING_NAVIGATION_FAILURE);
-}
-
-// Tests that an extension pop-up can be navigated to another page
-// in the same extension.
-// Times out on all platforms: https://crbug.com/882200
-IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupBrowserTest,
- DISABLED_PageInSameExtension) {
- GURL other_page_in_same_extension =
- popup_extension().GetResourceURL("other_page.html");
- TestPopupNavigationViaGet(other_page_in_same_extension,
- EXPECTING_NAVIGATION_SUCCESS);
- TestPopupNavigationViaPost(other_page_in_same_extension,
- EXPECTING_NAVIGATION_SUCCESS);
-}
-
-// Tests that an extension pop-up cannot be navigated to a page
-// in another extension.
-IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupBrowserTest,
- PageInOtherExtension) {
- GURL other_extension_url = other_extension().GetResourceURL("other.html");
- TestPopupNavigationViaGet(other_extension_url, EXPECTING_NO_NAVIGATION);
- TestPopupNavigationViaPost(other_extension_url, EXPECTING_NAVIGATION_FAILURE);
-}
-
-// Tests that navigating an extension pop-up to a http URI that returns
-// Content-Disposition: attachment; filename=...
-// works: No navigation, but download shelf visible + download goes through.
-//
-// Note - there is no "...ViaGet" flavour of this test, because we don't care
-// (yet) if GET succeeds with the download or not (it probably should succeed
-// for consistency with POST, but it always failed in M54 and before). After
-// abandoing ShouldFork/OpenURL for all methods (not just for POST) [see comment
-// about https://crbug.com/646261 in ChromeContentRendererClient::ShouldFork]
-// GET should automagically start working for downloads.
-// TODO(lukasza): https://crbug.com/650694: Add a "Get" flavour of the test once
-// the download works both for GET and POST requests.
-IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupBrowserTest, DownloadViaPost) {
- // Setup monitoring of the downloads.
- content::DownloadTestObserverTerminal downloads_observer(
- content::BrowserContext::GetDownloadManager(browser()->profile()),
- 1, // == wait_count (only waiting for "download-test3.gif").
- content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
-
- // Navigate to a URL that replies with
- // Content-Disposition: attachment; filename=...
- // header.
- GURL download_url(
- embedded_test_server()->GetURL("foo.com", "/download-test3.gif"));
- TestPopupNavigationViaPost(download_url, EXPECTING_NAVIGATION_FAILURE);
-
- // Verify that "download-test3.gif got downloaded.
- downloads_observer.WaitForFinished();
- EXPECT_EQ(0u, downloads_observer.NumDangerousDownloadsSeen());
- EXPECT_EQ(1u, downloads_observer.NumDownloadsSeenInState(
- download::DownloadItem::COMPLETE));
-
- base::ScopedAllowBlockingForTesting allow_blocking;
- base::FilePath downloads_directory =
- DownloadPrefs(browser()->profile()).DownloadPath();
- EXPECT_TRUE(base::PathExists(
- downloads_directory.AppendASCII("download-test3-attachment.gif")));
-
- // The test verification below is applicable only to scenarios where the
- // download shelf is supported - on ChromeOS, instead of the download shelf,
- // there is a download notification in the right-bottom corner of the screen.
-#if !defined(OS_CHROMEOS)
- EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
-#endif
-}
-
// Verify video can enter and exit Picture-in_Picture when browser action icon
// is clicked.
IN_PROC_BROWSER_TEST_F(BrowserActionApiTest,
diff --git a/chromium/chrome/browser/extensions/api/extension_action/browser_action_browsertest.cc b/chromium/chrome/browser/extensions/api/extension_action/browser_action_browsertest.cc
index 5027f9ac3e0..1bce61079f1 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/browser_action_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/browser_action_browsertest.cc
@@ -38,7 +38,7 @@ void WaitForStateStore(Profile* profile, const std::string& extension_id) {
new content::MessageLoopRunner;
ExtensionSystem::Get(profile)->state_store()->GetExtensionValue(
extension_id, kBrowserActionStorageKey,
- base::Bind(&QuitMessageLoop, base::RetainedRef(runner)));
+ base::BindOnce(&QuitMessageLoop, base::RetainedRef(runner)));
runner->Run();
}
diff --git a/chromium/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc b/chromium/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
index 5d765101e1b..219390ecbe9 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/browser_action_interactive_test.cc
@@ -7,25 +7,29 @@
#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
+#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/extensions/browser_action_test_util.h"
+#include "chrome/browser/ui/extensions/extension_action_test_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "components/zoom/test/zoom_test_utils.h"
#include "components/zoom/zoom_controller.h"
#include "content/public/browser/host_zoom_map.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/download_test_observer.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/notification_types.h"
#include "extensions/common/extension.h"
@@ -33,8 +37,12 @@
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
+#include "net/dns/mock_host_resolver.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/page/page_zoom.h"
#include "ui/base/buildflags.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/views/widget/widget.h"
#if defined(OS_WIN)
#include "ui/views/win/hwnd_util.h"
@@ -101,6 +109,7 @@ class BrowserActionInteractiveTest : public ExtensionApiTest {
void SetUpOnMainThread() override {
host_watcher_ = std::make_unique<ExtensionHostWatcher>();
ExtensionApiTest::SetUpOnMainThread();
+ host_resolver()->AddRule("*", "127.0.0.1");
EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
}
@@ -129,7 +138,7 @@ class BrowserActionInteractiveTest : public ExtensionApiTest {
}
void EnsurePopupActive() {
- auto test_util = BrowserActionTestUtil::Create(browser());
+ auto test_util = ExtensionActionTestHelper::Create(browser());
EXPECT_TRUE(test_util->HasPopup());
EXPECT_TRUE(test_util->WaitForPopup());
EXPECT_TRUE(test_util->HasPopup());
@@ -158,21 +167,27 @@ class BrowserActionInteractiveTest : public ExtensionApiTest {
}
// Open an extension popup by clicking the browser action button.
- void OpenPopupViaToolbar() {
- content::WindowedNotificationObserver frame_observer(
+ content::WebContents* OpenPopupViaToolbar() {
+ content::WindowedNotificationObserver popup_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
- BrowserActionTestUtil::Create(browser())->Press(0);
- frame_observer.Wait();
+ ExtensionActionTestHelper::Create(browser())->Press(0);
+ popup_observer.Wait();
EnsurePopupActive();
+ const auto& source =
+ static_cast<const content::Source<content::WebContents>&>(
+ popup_observer.source());
+ return source.ptr();
}
// Close the popup window directly.
- void ClosePopup() { BrowserActionTestUtil::Create(browser())->HidePopup(); }
+ bool ClosePopup() {
+ return ExtensionActionTestHelper::Create(browser())->HidePopup();
+ }
// Trigger a focus loss to close the popup.
void ClosePopupViaFocusLoss() {
- EXPECT_TRUE(BrowserActionTestUtil::Create(browser())->HasPopup());
+ EXPECT_TRUE(ExtensionActionTestHelper::Create(browser())->HasPopup());
content::WindowedNotificationObserver observer(
extensions::NOTIFICATION_EXTENSION_HOST_DESTROYED,
content::NotificationService::AllSources());
@@ -191,7 +206,7 @@ class BrowserActionInteractiveTest : public ExtensionApiTest {
#endif
// The window disappears immediately.
- EXPECT_FALSE(BrowserActionTestUtil::Create(browser())->HasPopup());
+ EXPECT_FALSE(ExtensionActionTestHelper::Create(browser())->HasPopup());
// Wait for the notification to achieve a consistent state and verify that
// the popup was properly torn down.
@@ -212,7 +227,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TestOpenPopup) {
if (!ShouldRunPopupTest())
return;
- auto browserActionBar = BrowserActionTestUtil::Create(browser());
+ auto browserActionBar = ExtensionActionTestHelper::Create(browser());
// Setup extension message listener to wait for javascript to finish running.
ExtensionTestMessageListener listener("ready", true);
{
@@ -248,10 +263,10 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TestOpenPopup) {
// Show second popup in new window.
listener.Reply("show another");
frame_observer.Wait();
- EXPECT_TRUE(BrowserActionTestUtil::Create(new_browser)->HasPopup());
+ EXPECT_TRUE(ExtensionActionTestHelper::Create(new_browser)->HasPopup());
}
ASSERT_TRUE(catcher.GetNextResult()) << message_;
- BrowserActionTestUtil::Create(new_browser)->HidePopup();
+ ExtensionActionTestHelper::Create(new_browser)->HidePopup();
}
// Tests opening a popup in an incognito window.
@@ -264,17 +279,17 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TestOpenPopupIncognito) {
content::NotificationService::AllSources());
ASSERT_TRUE(RunExtensionSubtest("browser_action/open_popup",
"open_popup_succeeds.html",
- kFlagEnableIncognito | kFlagUseIncognito))
+ kFlagEnableIncognito, kFlagUseIncognito))
<< message_;
frame_observer.Wait();
// Non-Aura Linux uses a singleton for the popup, so it looks like all windows
// have popups if there is any popup open.
#if !(defined(OS_LINUX) && !defined(USE_AURA))
// Starting window does not have a popup.
- EXPECT_FALSE(BrowserActionTestUtil::Create(browser())->HasPopup());
+ EXPECT_FALSE(ExtensionActionTestHelper::Create(browser())->HasPopup());
#endif
// Incognito window should have a popup.
- auto test_util = BrowserActionTestUtil::Create(
+ auto test_util = ExtensionActionTestHelper::Create(
BrowserList::GetInstance()->GetLastActive());
EXPECT_TRUE(test_util->HasPopup());
test_util->HidePopup();
@@ -299,7 +314,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
OpenURLOffTheRecord(profile(), GURL("chrome://newtab/"));
EXPECT_TRUE(listener.WaitUntilSatisfied());
EXPECT_EQ(std::string("opened"), listener.message());
- auto test_util = BrowserActionTestUtil::Create(incognito_browser);
+ auto test_util = ExtensionActionTestHelper::Create(incognito_browser);
EXPECT_TRUE(test_util->HasPopup());
test_util->HidePopup();
}
@@ -328,7 +343,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
// Return control to javascript to validate that opening a popup fails now.
listener.Reply("show another");
ASSERT_TRUE(catcher.GetNextResult()) << message_;
- ClosePopup();
+ EXPECT_TRUE(ClosePopup());
}
// Test that openPopup does not grant tab permissions like for browser action
@@ -345,11 +360,11 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
ExtensionRegistry::ENABLED)
->permissions_data()
->HasAPIPermissionForTab(
- SessionTabHelper::IdForTab(
+ sessions::SessionTabHelper::IdForTab(
browser()->tab_strip_model()->GetActiveWebContents())
.id(),
APIPermission::kTab));
- ClosePopup();
+ EXPECT_TRUE(ClosePopup());
}
// Test that the extension popup is closed when the browser window is focused.
@@ -394,7 +409,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, TabSwitchClosesPopup) {
0, {TabStripModel::GestureType::kOther});
observer.Wait();
- EXPECT_FALSE(BrowserActionTestUtil::Create(browser())->HasPopup());
+ EXPECT_FALSE(ExtensionActionTestHelper::Create(browser())->HasPopup());
}
IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
@@ -404,7 +419,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
// First, we open a popup.
OpenPopupViaAPI(false);
- auto browser_action_test_util = BrowserActionTestUtil::Create(browser());
+ auto browser_action_test_util = ExtensionActionTestHelper::Create(browser());
EXPECT_TRUE(browser_action_test_util->HasPopup());
// Then, find the extension that created it.
@@ -490,7 +505,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, PopupZoomsIndependently) {
EXPECT_TRUE(blink::PageZoomValuesEqual(popup_zoom_level, default_zoom_level))
<< popup_zoom_level << " vs " << default_zoom_level;
- ClosePopup();
+ EXPECT_TRUE(ClosePopup());
}
class BrowserActionInteractiveViewsTest : public BrowserActionInteractiveTest {
@@ -518,9 +533,9 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveViewsTest,
content::WindowedNotificationObserver frame_observer(
content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
content::NotificationService::AllSources());
- BrowserActionTestUtil::Create(browser())->InspectPopup(0);
+ ExtensionActionTestHelper::Create(browser())->InspectPopup(0);
frame_observer.Wait();
- EXPECT_TRUE(BrowserActionTestUtil::Create(browser())->HasPopup());
+ EXPECT_TRUE(ExtensionActionTestHelper::Create(browser())->HasPopup());
// Close the browser window, this should not cause a crash.
chrome::CloseWindow(browser());
@@ -533,7 +548,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, DestroyHWNDDoesNotCrash) {
return;
OpenPopupViaAPI(false);
- auto test_util = BrowserActionTestUtil::Create(browser());
+ auto test_util = ExtensionActionTestHelper::Create(browser());
const gfx::NativeView popup_view = test_util->GetPopupNativeView();
EXPECT_NE(static_cast<gfx::NativeView>(nullptr), popup_view);
const HWND popup_hwnd = views::HWNDForNativeView(popup_view);
@@ -555,5 +570,434 @@ IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, DestroyHWNDDoesNotCrash) {
}
#endif // OS_WIN
+class MainFrameSizeWaiter : public content::WebContentsObserver {
+ public:
+ MainFrameSizeWaiter(content::WebContents* web_contents,
+ const gfx::Size& size_to_wait_for)
+ : content::WebContentsObserver(web_contents),
+ size_to_wait_for_(size_to_wait_for) {}
+
+ void Wait() {
+ if (current_size() != size_to_wait_for_)
+ run_loop_.Run();
+ }
+
+ private:
+ gfx::Size current_size() {
+ return web_contents()->GetContainerBounds().size();
+ }
+
+ void MainFrameWasResized(bool width_changed) override {
+ if (current_size() == size_to_wait_for_)
+ run_loop_.Quit();
+ }
+
+ gfx::Size size_to_wait_for_;
+ base::RunLoop run_loop_;
+};
+
+IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest, BrowserActionPopup) {
+ if (!ShouldRunPopupTest())
+ return;
+
+ ASSERT_TRUE(
+ LoadExtension(test_data_dir_.AppendASCII("browser_action/popup")));
+ const Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension) << message_;
+
+ // The extension's popup's size grows by |kGrowFactor| each click.
+ const int kGrowFactor = 500;
+ std::unique_ptr<ExtensionActionTestHelper> actions_bar =
+ ExtensionActionTestHelper::Create(browser());
+ gfx::Size minSize = actions_bar->GetMinPopupSize();
+ gfx::Size middleSize = gfx::Size(kGrowFactor, kGrowFactor);
+ gfx::Size maxSize = actions_bar->GetMaxPopupSize();
+
+ // Ensure that two clicks will exceed the maximum allowed size.
+ ASSERT_GT(minSize.height() + kGrowFactor * 2, maxSize.height());
+ ASSERT_GT(minSize.width() + kGrowFactor * 2, maxSize.width());
+
+ // Simulate a click on the browser action and verify the size of the resulting
+ // popup.
+ const gfx::Size kExpectedSizes[] = {minSize, middleSize, maxSize};
+ for (size_t i = 0; i < base::size(kExpectedSizes); i++) {
+ const gfx::Size& kExpectedSize = kExpectedSizes[i];
+ SCOPED_TRACE(testing::Message()
+ << "Test #" << i << ": size = " << kExpectedSize.ToString());
+
+ content::WebContentsAddedObserver popup_observer;
+ actions_bar->Press(0);
+ content::WebContents* popup = popup_observer.GetWebContents();
+ MainFrameSizeWaiter(popup, kExpectedSize).Wait();
+ EXPECT_EQ(kExpectedSize, popup->GetContainerBounds().size());
+ ASSERT_TRUE(actions_bar->HidePopup());
+ }
+}
+
+// Test that a browser action popup can download data URLs. See
+// https://crbug.com/821219
+IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
+ BrowserActionPopupDownload) {
+ if (!ShouldRunPopupTest())
+ return;
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ ASSERT_TRUE(LoadExtension(
+ test_data_dir_.AppendASCII("browser_action/popup_download")));
+ const Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension) << message_;
+
+ content::DownloadTestObserverTerminal downloads_observer(
+ content::BrowserContext::GetDownloadManager(browser()->profile()), 1,
+ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+
+ // Simulate a click on the browser action to open the popup.
+ content::WebContents* popup = OpenPopupViaToolbar();
+ ASSERT_TRUE(popup);
+ content::ExecuteScriptAsync(popup, "run_tests()");
+
+ // Wait for the download that this should have triggered to finish.
+ downloads_observer.WaitForFinished();
+
+ EXPECT_EQ(1u, downloads_observer.NumDownloadsSeenInState(
+ download::DownloadItem::COMPLETE));
+ EXPECT_TRUE(ClosePopup());
+}
+
+// Watches a frame is swapped with a new frame by e.g., navigation.
+class RenderFrameChangedWatcher : public content::WebContentsObserver {
+ public:
+ explicit RenderFrameChangedWatcher(content::WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+ void RenderFrameHostChanged(content::RenderFrameHost* old_host,
+ content::RenderFrameHost* new_host) override {
+ created_frame_ = new_host;
+ run_loop_.Quit();
+ }
+
+ content::RenderFrameHost* WaitAndReturnNewFrame() {
+ run_loop_.Run();
+ return created_frame_;
+ }
+
+ private:
+ base::RunLoop run_loop_;
+ content::RenderFrameHost* created_frame_;
+};
+
+// Test that a browser action popup with a web iframe works correctly. The
+// iframe is expected to run in a separate process.
+// See https://crbug.com/546267.
+IN_PROC_BROWSER_TEST_F(BrowserActionInteractiveTest,
+ BrowserActionPopupWithIframe) {
+ if (!ShouldRunPopupTest())
+ return;
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ ASSERT_TRUE(LoadExtension(
+ test_data_dir_.AppendASCII("browser_action/popup_with_iframe")));
+ const Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension) << message_;
+
+ // Simulate a click on the browser action to open the popup.
+ ASSERT_TRUE(OpenPopupViaToolbar());
+
+ // Find the RenderFrameHost associated with the iframe in the popup.
+ content::RenderFrameHost* frame_host = nullptr;
+ extensions::ProcessManager* manager =
+ extensions::ProcessManager::Get(browser()->profile());
+ std::set<content::RenderFrameHost*> frame_hosts =
+ manager->GetRenderFrameHostsForExtension(extension->id());
+ for (auto* host : frame_hosts) {
+ if (host->GetFrameName() == "child_frame") {
+ frame_host = host;
+ break;
+ }
+ }
+
+ ASSERT_TRUE(frame_host);
+ EXPECT_EQ(extension->GetResourceURL("frame.html"),
+ frame_host->GetLastCommittedURL());
+ EXPECT_TRUE(frame_host->GetParent());
+
+ // Navigate the popup's iframe to a (cross-site) web page, and wait for that
+ // page to send a message, which will ensure that the page has loaded.
+ RenderFrameChangedWatcher watcher(
+ content::WebContents::FromRenderFrameHost(frame_host));
+ GURL foo_url(embedded_test_server()->GetURL("foo.com", "/popup_iframe.html"));
+ std::string script = "location.href = '" + foo_url.spec() + "'";
+ EXPECT_TRUE(ExecuteScript(frame_host, script));
+
+ frame_host = watcher.WaitAndReturnNewFrame();
+
+ // Confirm that the new page (popup_iframe.html) is actually loaded.
+ content::DOMMessageQueue dom_message_queue(frame_host);
+ std::string json;
+ EXPECT_TRUE(dom_message_queue.WaitForMessage(&json));
+ EXPECT_EQ("\"DONE\"", json);
+
+ EXPECT_TRUE(ClosePopup());
+}
+
+class NavigatingExtensionPopupInteractiveTest
+ : public BrowserActionInteractiveTest {
+ public:
+ const Extension& popup_extension() { return *popup_extension_; }
+ const Extension& other_extension() { return *other_extension_; }
+
+ void SetUpOnMainThread() override {
+ BrowserActionInteractiveTest::SetUpOnMainThread();
+
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // Load an extension with a pop-up.
+ ASSERT_TRUE(popup_extension_ = LoadExtension(test_data_dir_.AppendASCII(
+ "browser_action/popup_with_form")));
+
+ // Load another extension (that we can try navigating to).
+ ASSERT_TRUE(other_extension_ = LoadExtension(test_data_dir_.AppendASCII(
+ "browser_action/popup_with_iframe")));
+ }
+
+ enum ExpectedNavigationStatus {
+ EXPECTING_NAVIGATION_SUCCESS,
+ EXPECTING_NAVIGATION_FAILURE,
+ };
+
+ void TestPopupNavigationViaGet(
+ const GURL& target_url,
+ ExpectedNavigationStatus expected_navigation_status) {
+ std::string navigation_starting_script =
+ content::JsReplace("window.location = $1;\n", target_url);
+ TestPopupNavigation(target_url, expected_navigation_status,
+ navigation_starting_script);
+ }
+
+ void TestPopupNavigationViaPost(
+ const GURL& target_url,
+ ExpectedNavigationStatus expected_navigation_status) {
+ const char kNavigationStartingScriptTemplate[] = R"(
+ var form = document.getElementById('form');
+ form.action = $1;
+ form.submit();
+ )";
+ std::string navigation_starting_script =
+ content::JsReplace(kNavigationStartingScriptTemplate, target_url);
+ TestPopupNavigation(target_url, expected_navigation_status,
+ navigation_starting_script);
+ }
+
+ private:
+ void TestPopupNavigation(const GURL& target_url,
+ ExpectedNavigationStatus expected_navigation_status,
+ std::string navigation_starting_script) {
+ if (!ShouldRunPopupTest())
+ return;
+
+ // Were there any failures so far (e.g. in SetUpOnMainThread)?
+ ASSERT_FALSE(HasFailure());
+
+ // Verify that the right action bar buttons are present.
+ {
+ std::unique_ptr<ExtensionActionTestHelper> action_bar_helper =
+ ExtensionActionTestHelper::Create(browser());
+ ASSERT_EQ(2, action_bar_helper->NumberOfBrowserActions());
+ ASSERT_EQ(popup_extension().id(), action_bar_helper->GetExtensionId(0));
+ ASSERT_EQ(other_extension().id(), action_bar_helper->GetExtensionId(1));
+ }
+
+ // Simulate a click on the browser action to open the popup.
+ content::WebContents* popup = OpenPopupViaToolbar();
+ ASSERT_TRUE(popup);
+ GURL popup_url = popup_extension().GetResourceURL("popup.html");
+ EXPECT_EQ(popup_url, popup->GetLastCommittedURL());
+
+ // Note that the |setTimeout| call below is needed to make sure
+ // ExecuteScriptAndExtractBool returns *after* a scheduled navigation has
+ // already started.
+ std::string script_to_execute =
+ navigation_starting_script +
+ "setTimeout(\n"
+ " function() { window.domAutomationController.send(true); },\n"
+ " 0);\n";
+
+ // Try to navigate the pop-up.
+ bool ignored_script_result = false;
+ content::WebContentsDestroyedWatcher popup_destruction_watcher(popup);
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(popup, script_to_execute,
+ &ignored_script_result));
+ popup = popup_destruction_watcher.web_contents();
+
+ // Verify if the popup navigation succeeded or failed as expected.
+ if (!popup) {
+ // If navigation ends up in a tab, then the tab will be focused and
+ // therefore the popup will be closed, destroying associated WebContents -
+ // don't do any verification in this case.
+ ADD_FAILURE() << "Navigation should not close extension pop-up";
+ } else {
+ // If the extension popup is still opened, then wait until there is no
+ // load in progress, and verify whether the navigation succeeded or not.
+ content::WaitForLoadStop(popup);
+
+ // The popup should still be alive.
+ ASSERT_TRUE(popup_destruction_watcher.web_contents());
+
+ if (expected_navigation_status == EXPECTING_NAVIGATION_SUCCESS) {
+ EXPECT_EQ(target_url, popup->GetLastCommittedURL())
+ << "Navigation to " << target_url
+ << " should succeed in an extension pop-up";
+ } else {
+ EXPECT_NE(target_url, popup->GetLastCommittedURL())
+ << "Navigation to " << target_url
+ << " should fail in an extension pop-up";
+ EXPECT_THAT(
+ popup->GetLastCommittedURL(),
+ ::testing::AnyOf(::testing::Eq(popup_url),
+ ::testing::Eq(GURL("chrome-extension://invalid")),
+ ::testing::Eq(GURL("about:blank"))));
+ }
+
+ EXPECT_TRUE(ClosePopup());
+ }
+
+ // Make sure that the web navigation did not succeed somewhere outside of
+ // the extension popup (as it might if ExtensionViewHost::OpenURLFromTab
+ // forwards the navigation to Browser::OpenURL [which doesn't specify a
+ // source WebContents]).
+ TabStripModel* tabs = browser()->tab_strip_model();
+ for (int i = 0; i < tabs->count(); i++) {
+ content::WebContents* tab_contents = tabs->GetWebContentsAt(i);
+ WaitForLoadStop(tab_contents);
+ EXPECT_NE(target_url, tab_contents->GetLastCommittedURL())
+ << "Navigating an extension pop-up should not affect tabs.";
+ }
+ }
+
+ const Extension* popup_extension_;
+ const Extension* other_extension_;
+};
+
+// Tests that an extension pop-up cannot be navigated to a web page.
+IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupInteractiveTest, Webpage_Get) {
+ GURL web_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ TestPopupNavigationViaGet(web_url, EXPECTING_NAVIGATION_FAILURE);
+}
+IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupInteractiveTest, Webpage_Post) {
+ GURL web_url(embedded_test_server()->GetURL("foo.com", "/title1.html"));
+ TestPopupNavigationViaPost(web_url, EXPECTING_NAVIGATION_FAILURE);
+}
+
+// Tests that an extension pop-up can be navigated to another page
+// in the same extension.
+IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupInteractiveTest,
+ PageInSameExtension_Get) {
+ GURL other_page_in_same_extension =
+ popup_extension().GetResourceURL("other_page.html");
+ TestPopupNavigationViaGet(other_page_in_same_extension,
+ EXPECTING_NAVIGATION_SUCCESS);
+}
+IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupInteractiveTest,
+ PageInSameExtension_Post) {
+ GURL other_page_in_same_extension =
+ popup_extension().GetResourceURL("other_page.html");
+ TestPopupNavigationViaPost(other_page_in_same_extension,
+ EXPECTING_NAVIGATION_SUCCESS);
+}
+
+// Tests that an extension pop-up cannot be navigated to a page
+// in another extension.
+IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupInteractiveTest,
+ PageInOtherExtension_Get) {
+ GURL other_extension_url = other_extension().GetResourceURL("other.html");
+ TestPopupNavigationViaGet(other_extension_url, EXPECTING_NAVIGATION_FAILURE);
+}
+IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupInteractiveTest,
+ PageInOtherExtension_Post) {
+ GURL other_extension_url = other_extension().GetResourceURL("other.html");
+ TestPopupNavigationViaPost(other_extension_url, EXPECTING_NAVIGATION_FAILURE);
+}
+
+// Tests that navigating an extension pop-up to a http URI that returns
+// Content-Disposition: attachment; filename=...
+// works: No navigation, but download shelf visible + download goes through.
+IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupInteractiveTest,
+ DownloadViaPost) {
+ if (!ShouldRunPopupTest())
+ return;
+
+ // Setup monitoring of the downloads.
+ content::DownloadTestObserverTerminal downloads_observer(
+ content::BrowserContext::GetDownloadManager(browser()->profile()),
+ 1, // == wait_count (only waiting for "download-test3.gif").
+ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+
+ // Navigate to a URL that replies with
+ // Content-Disposition: attachment; filename=...
+ // header.
+ GURL download_url(
+ embedded_test_server()->GetURL("foo.com", "/download-test3.gif"));
+ TestPopupNavigationViaPost(download_url, EXPECTING_NAVIGATION_FAILURE);
+
+ // Verify that "download-test3.gif got downloaded.
+ downloads_observer.WaitForFinished();
+ EXPECT_EQ(0u, downloads_observer.NumDangerousDownloadsSeen());
+ EXPECT_EQ(1u, downloads_observer.NumDownloadsSeenInState(
+ download::DownloadItem::COMPLETE));
+
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath downloads_directory =
+ DownloadPrefs(browser()->profile()).DownloadPath();
+ EXPECT_TRUE(base::PathExists(
+ downloads_directory.AppendASCII("download-test3-attachment.gif")));
+
+ // The test verification below is applicable only to scenarios where the
+ // download shelf is supported - on ChromeOS, instead of the download shelf,
+ // there is a download notification in the right-bottom corner of the screen.
+#if !defined(OS_CHROMEOS)
+ EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+#endif
+}
+
+IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupInteractiveTest,
+ DownloadViaGet) {
+ if (!ShouldRunPopupTest())
+ return;
+
+ // Setup monitoring of the downloads.
+ content::DownloadTestObserverTerminal downloads_observer(
+ content::BrowserContext::GetDownloadManager(browser()->profile()),
+ 1, // == wait_count (only waiting for "download-test3.gif").
+ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+
+ // Navigate to a URL that replies with
+ // Content-Disposition: attachment; filename=...
+ // header.
+ GURL download_url(
+ embedded_test_server()->GetURL("foo.com", "/download-test3.gif"));
+ TestPopupNavigationViaGet(download_url, EXPECTING_NAVIGATION_FAILURE);
+
+ // Verify that "download-test3.gif got downloaded.
+ downloads_observer.WaitForFinished();
+ EXPECT_EQ(0u, downloads_observer.NumDangerousDownloadsSeen());
+ EXPECT_EQ(1u, downloads_observer.NumDownloadsSeenInState(
+ download::DownloadItem::COMPLETE));
+
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ base::FilePath downloads_directory =
+ DownloadPrefs(browser()->profile()).DownloadPath();
+ EXPECT_TRUE(base::PathExists(
+ downloads_directory.AppendASCII("download-test3-attachment.gif")));
+
+ // The test verification below is applicable only to scenarios where the
+ // download shelf is supported - on ChromeOS, instead of the download shelf,
+ // there is a download notification in the right-bottom corner of the screen.
+#if !defined(OS_CHROMEOS)
+ EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
+#endif
+}
+
} // namespace
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc
index bb0799b4cc9..10385b38529 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc
@@ -23,13 +23,13 @@
#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/extensions/extensions_container.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/extensions/api/extension_action/action_info.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/notification_service.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
#include "extensions/browser/event_router.h"
@@ -188,7 +188,7 @@ void ExtensionActionAPI::DispatchExtensionActionClicked(
void ExtensionActionAPI::ClearAllValuesForTab(
content::WebContents* web_contents) {
DCHECK(web_contents);
- const SessionID tab_id = SessionTabHelper::IdForTab(web_contents);
+ const SessionID tab_id = sessions::SessionTabHelper::IdForTab(web_contents);
content::BrowserContext* browser_context = web_contents->GetBrowserContext();
const ExtensionSet& enabled_extensions =
ExtensionRegistry::Get(browser_context_)->enabled_extensions();
@@ -426,9 +426,13 @@ ExtensionActionSetPopupFunction::RunExtensionAction() {
ExtensionFunction::ResponseAction
ExtensionActionSetBadgeTextFunction::RunExtensionAction() {
EXTENSION_FUNCTION_VALIDATE(details_);
+
std::string badge_text;
- EXTENSION_FUNCTION_VALIDATE(details_->GetString("text", &badge_text));
- extension_action_->SetBadgeText(tab_id_, badge_text);
+ if (details_->GetString("text", &badge_text))
+ extension_action_->SetBadgeText(tab_id_, badge_text);
+ else
+ extension_action_->ClearBadgeText(tab_id_);
+
NotifyChange();
return RespondNow(NoArguments());
}
diff --git a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api_unittest.cc b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api_unittest.cc
index 2b73a6dd59b..cbd0be151ab 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api_unittest.cc
@@ -2,35 +2,38 @@
// 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/file_util.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_with_install.h"
#include "chrome/common/extensions/api/extension_action/action_info.h"
+#include "chrome/common/extensions/extension_test_util.h"
+#include "extensions/common/features/feature_channel.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/test/test_extension_dir.h"
namespace extensions {
namespace {
-enum class TestActionType {
- kBrowser,
- kPage,
-};
-
class ExtensionActionAPIUnitTest
: public ExtensionServiceTestWithInstall,
- public ::testing::WithParamInterface<TestActionType> {
+ public ::testing::WithParamInterface<ActionInfo::Type> {
public:
- ExtensionActionAPIUnitTest() {}
+ ExtensionActionAPIUnitTest()
+ : current_channel_(
+ extension_test_util::GetOverrideChannelForActionType(GetParam())) {}
~ExtensionActionAPIUnitTest() override {}
const char* GetManifestKey() {
switch (GetParam()) {
- case TestActionType::kBrowser:
+ case ActionInfo::TYPE_BROWSER:
return manifest_keys::kBrowserAction;
- case TestActionType::kPage:
+ case ActionInfo::TYPE_PAGE:
return manifest_keys::kPageAction;
+ case ActionInfo::TYPE_ACTION:
+ return manifest_keys::kAction;
}
NOTREACHED();
return nullptr;
@@ -38,16 +41,20 @@ class ExtensionActionAPIUnitTest
const ActionInfo* GetActionInfo(const Extension& extension) {
switch (GetParam()) {
- case TestActionType::kBrowser:
+ case ActionInfo::TYPE_BROWSER:
return ActionInfo::GetBrowserActionInfo(&extension);
- case TestActionType::kPage:
+ case ActionInfo::TYPE_PAGE:
return ActionInfo::GetPageActionInfo(&extension);
+ case ActionInfo::TYPE_ACTION:
+ return ActionInfo::GetExtensionActionInfo(&extension);
}
NOTREACHED();
return nullptr;
}
private:
+ std::unique_ptr<ScopedCurrentChannel> current_channel_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionActionAPIUnitTest);
};
@@ -103,8 +110,9 @@ TEST_P(ExtensionActionAPIUnitTest, MultiIcons) {
INSTANTIATE_TEST_SUITE_P(All,
ExtensionActionAPIUnitTest,
- testing::Values(TestActionType::kBrowser,
- TestActionType::kPage));
+ testing::Values(ActionInfo::TYPE_BROWSER,
+ ActionInfo::TYPE_PAGE,
+ ActionInfo::TYPE_ACTION));
} // namespace
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc b/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc
index dc6716b3ba6..70f89b7e154 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc
@@ -17,12 +17,12 @@
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/extensions/browser_action_test_util.h"
+#include "chrome/browser/ui/extensions/extension_action_test_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/extensions/extension_test_util.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "components/version_info/channel.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -254,7 +254,7 @@ class MultiActionAPITest
// Returns the id of the currently-active tab.
int GetActiveTabId() const {
content::WebContents* web_contents = GetActiveTab();
- return SessionTabHelper::IdForTab(web_contents).id();
+ return sessions::SessionTabHelper::IdForTab(web_contents).id();
}
content::WebContents* GetActiveTab() const {
@@ -312,7 +312,7 @@ IN_PROC_BROWSER_TEST_F(BrowserActionAPITest, TestNoUnnecessaryIO) {
domAutomationController.send('pass');)";
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
- SessionID tab_id = SessionTabHelper::IdForTab(web_contents);
+ SessionID tab_id = sessions::SessionTabHelper::IdForTab(web_contents);
constexpr char kBrowserActionKey[] = "browser_action";
TestStateStoreObserver test_state_store_observer(profile(), extension->id());
@@ -381,11 +381,11 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPITest,
GURL initial_url = embedded_test_server()->GetURL("/title1.html");
ui_test_utils::NavigateToURLWithDisposition(
browser(), initial_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
TabStripModel* tab_strip_model = browser()->tab_strip_model();
content::WebContents* web_contents = tab_strip_model->GetActiveWebContents();
- int tab_id = SessionTabHelper::IdForTab(web_contents).id();
+ int tab_id = sessions::SessionTabHelper::IdForTab(web_contents).id();
// There should be no explicit title to start, but should be one if we set
// one.
@@ -440,7 +440,7 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPITest, TitleLocalization) {
EXPECT_EQ(base::WideToUTF8(L"Hreggvi\u00F0ur is my name"), extension->name());
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
- int tab_id = SessionTabHelper::IdForTab(web_contents).id();
+ int tab_id = sessions::SessionTabHelper::IdForTab(web_contents).id();
EXPECT_EQ(base::WideToUTF8(L"Hreggvi\u00F0ur"), action->GetTitle(tab_id));
EXPECT_EQ(base::WideToUTF8(L"Hreggvi\u00F0ur"),
action->GetTitle(ExtensionAction::kDefaultTabId));
@@ -473,11 +473,11 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPITest, OnClickedDispatching) {
FILE_PATH_LITERAL("background.js"),
base::StringPrintf(kBackgroundJsTemplate, GetAPIName(GetParam())));
- // Though this says "BrowserActionTestUtil", it's actually used for all
+ // Though this says "ExtensionActionTestHelper", it's actually used for all
// toolbar actions.
// TODO(devlin): Rename it to ToolbarActionTestUtil.
- std::unique_ptr<BrowserActionTestUtil> toolbar_helper =
- BrowserActionTestUtil::Create(browser());
+ std::unique_ptr<ExtensionActionTestHelper> toolbar_helper =
+ ExtensionActionTestHelper::Create(browser());
EXPECT_EQ(0, toolbar_helper->NumberOfBrowserActions());
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
@@ -526,8 +526,8 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPITest, PopupCreation) {
const Extension* extension = LoadExtension(test_dir.UnpackedPath());
ASSERT_TRUE(extension);
- std::unique_ptr<BrowserActionTestUtil> toolbar_helper =
- BrowserActionTestUtil::Create(browser());
+ std::unique_ptr<ExtensionActionTestHelper> toolbar_helper =
+ ExtensionActionTestHelper::Create(browser());
ExtensionAction* action = GetExtensionAction(*extension);
ASSERT_TRUE(action);
@@ -615,8 +615,8 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPICanvasTest, DynamicSetIcon) {
EXPECT_TRUE(ActionHasDefaultState(*action, tab_id));
EnsureActionIsEnabledOnActiveTab(action);
- std::unique_ptr<BrowserActionTestUtil> toolbar_helper =
- BrowserActionTestUtil::Create(browser());
+ std::unique_ptr<ExtensionActionTestHelper> toolbar_helper =
+ ExtensionActionTestHelper::Create(browser());
ASSERT_EQ(1, toolbar_helper->NumberOfBrowserActions());
EXPECT_EQ(extension->id(), toolbar_helper->GetExtensionId(0));
@@ -637,7 +637,7 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPICanvasTest, DynamicSetIcon) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL("chrome://newtab"),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
const int new_tab_id = GetActiveTabId();
EXPECT_NE(new_tab_id, tab_id);
@@ -727,7 +727,7 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPITest, GettersAndSetters) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL("chrome://newtab"),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
int second_tab_id = GetActiveTabId();
// A simple structure to hold different representations of values (one JS,
@@ -911,7 +911,7 @@ IN_PROC_BROWSER_TEST_P(MultiActionAPITest, EnableAndDisable) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL("chrome://newtab"),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
const int tab_id2 = GetActiveTabId();
EnsureActionIsEnabledOnTab(action, tab_id2);
diff --git a/chromium/chrome/browser/extensions/api/extension_action/page_action_apitest.cc b/chromium/chrome/browser/extensions/api/extension_action/page_action_apitest.cc
index 117882e39ed..d30c5a9abdd 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/page_action_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/page_action_apitest.cc
@@ -12,12 +12,12 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/extension_system.h"
@@ -56,8 +56,10 @@ IN_PROC_BROWSER_TEST_F(PageActionApiTest, Basic) {
}
// Test that we received the changes.
- int tab_id = SessionTabHelper::FromWebContents(
- browser()->tab_strip_model()->GetActiveWebContents())->session_id().id();
+ int tab_id = sessions::SessionTabHelper::FromWebContents(
+ browser()->tab_strip_model()->GetActiveWebContents())
+ ->session_id()
+ .id();
ExtensionAction* action = GetPageAction(*extension);
ASSERT_TRUE(action);
EXPECT_EQ("Modified", action->GetTitle(tab_id));
@@ -84,8 +86,10 @@ IN_PROC_BROWSER_TEST_F(PageActionApiTest, Basic) {
ExtensionActionIconFactory icon_factory(profile(), extension, action, NULL);
// Test that we received the changes.
- tab_id = SessionTabHelper::FromWebContents(
- browser()->tab_strip_model()->GetActiveWebContents())->session_id().id();
+ tab_id = sessions::SessionTabHelper::FromWebContents(
+ browser()->tab_strip_model()->GetActiveWebContents())
+ ->session_id()
+ .id();
EXPECT_FALSE(icon_factory.GetIcon(tab_id).IsEmpty());
}
diff --git a/chromium/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc b/chromium/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
index 19d94452146..cb3b85fb7b6 100644
--- a/chromium/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
@@ -18,6 +18,7 @@
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/grit/generated_resources.h"
#include "components/feedback/system_logs/system_logs_fetcher.h"
+#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/browser_context.h"
@@ -33,10 +34,10 @@
#include "chrome/browser/chromeos/system_logs/single_log_file_log_source.h"
#include "chrome/browser/extensions/component_loader.h"
#include "chrome/browser/extensions/extension_service.h"
-#include "components/feedback/feedback_util.h"
#include "components/feedback/system_logs/system_logs_source.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/constants.h"
+#include "google_apis/gaia/gaia_auth_util.h"
#endif // defined(OS_CHROMEOS)
namespace extensions {
@@ -224,7 +225,7 @@ api::feedback_private::LandingPageType
ChromeFeedbackPrivateDelegate::GetLandingPageType(
const feedback::FeedbackData& feedback_data) const {
// Googlers using eve get a custom landing page.
- if (!feedback_util::IsGoogleEmail(feedback_data.user_email()))
+ if (!gaia::IsGoogleInternalAccountEmail(feedback_data.user_email()))
return api::feedback_private::LANDING_PAGE_TYPE_NORMAL;
const std::vector<std::string> board =
@@ -239,8 +240,12 @@ std::string ChromeFeedbackPrivateDelegate::GetSignedInUserEmail(
content::BrowserContext* context) const {
auto* identity_manager = IdentityManagerFactory::GetForProfile(
Profile::FromBrowserContext(context));
- return identity_manager ? identity_manager->GetPrimaryAccountInfo().email
- : std::string();
+ if (!identity_manager)
+ return std::string();
+ // Browser sync consent is not required to use feedback.
+ return identity_manager
+ ->GetPrimaryAccountInfo(signin::ConsentLevel::kNotRequired)
+ .email;
}
void ChromeFeedbackPrivateDelegate::NotifyFeedbackDelayed() const {
diff --git a/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc b/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc
index 76b2c7bb560..8c0d5dbdbd1 100644
--- a/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc
@@ -53,6 +53,8 @@
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/constants.h"
+#include "url/gurl.h"
+#include "url/origin.h"
#include "url/url_constants.h"
#endif
@@ -140,9 +142,8 @@ void OnConsentReceived(
return;
}
- const GURL site = util::GetSiteForExtensionId(extension_id, browser_context);
scoped_refptr<storage::FileSystemContext> file_system_context =
- content::BrowserContext::GetStoragePartitionForSite(browser_context, site)
+ util::GetStoragePartitionForExtensionId(extension_id, browser_context)
->GetFileSystemContext();
storage::ExternalFileSystemBackend* const backend =
file_system_context->external_backend();
@@ -160,8 +161,9 @@ void OnConsentReceived(
const storage::FileSystemURL original_url =
file_system_context->CreateCrackedFileSystemURL(
- GURL(std::string(kExtensionScheme) + url::kStandardSchemeSeparator +
- extension_id),
+ url::Origin::Create(GURL(std::string(kExtensionScheme) +
+ url::kStandardSchemeSeparator +
+ extension_id)),
storage::kFileSystemTypeExternal, virtual_path);
// Set a fixed register name, as the automatic one would leak the mount point
@@ -297,10 +299,11 @@ void ChromeFileSystemDelegate::ConfirmSensitiveDirectoryAccess(
bool has_write_permission,
const base::string16& app_name,
content::WebContents* web_contents,
- const base::Closure& on_accept,
- const base::Closure& on_cancel) {
+ base::OnceClosure on_accept,
+ base::OnceClosure on_cancel) {
CreateDirectoryAccessConfirmationDialog(has_write_permission, app_name,
- web_contents, on_accept, on_cancel);
+ web_contents, std::move(on_accept),
+ std::move(on_cancel));
}
int ChromeFileSystemDelegate::GetDescriptionIdForAcceptType(
@@ -365,10 +368,8 @@ void ChromeFileSystemDelegate::RequestFileSystem(
return;
}
- const GURL site =
- util::GetSiteForExtensionId(extension.id(), browser_context);
scoped_refptr<storage::FileSystemContext> file_system_context =
- content::BrowserContext::GetStoragePartitionForSite(browser_context, site)
+ util::GetStoragePartitionForExtensionId(extension.id(), browser_context)
->GetFileSystemContext();
storage::ExternalFileSystemBackend* const backend =
file_system_context->external_backend();
diff --git a/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h b/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h
index a1276399fa3..e30edac6834 100644
--- a/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h
+++ b/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.h
@@ -41,8 +41,8 @@ class ChromeFileSystemDelegate : public FileSystemDelegate {
void ConfirmSensitiveDirectoryAccess(bool has_write_permission,
const base::string16& app_name,
content::WebContents* web_contents,
- const base::Closure& on_accept,
- const base::Closure& on_cancel) override;
+ base::OnceClosure on_accept,
+ base::OnceClosure on_cancel) override;
int GetDescriptionIdForAcceptType(const std::string& accept_type) override;
#if defined(OS_CHROMEOS)
FileSystemDelegate::GrantVolumesMode GetGrantVolumesMode(
diff --git a/chromium/chrome/browser/extensions/api/file_system/file_system_apitest.cc b/chromium/chrome/browser/extensions/api/file_system/file_system_apitest.cc
index d624301ffc8..aed785c3276 100644
--- a/chromium/chrome/browser/extensions/api/file_system/file_system_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/file_system/file_system_apitest.cc
@@ -677,7 +677,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiRestoreDirectoryEntry) {
IN_PROC_BROWSER_TEST_F(FileSystemApiTest, RequestFileSystem_NotChromeOS) {
ASSERT_TRUE(RunPlatformAppTestWithFlags(
"api_test/file_system/request_file_system_not_chromeos",
- kFlagIgnoreManifestWarnings))
+ kFlagIgnoreManifestWarnings, kFlagNone))
<< message_;
}
#endif
diff --git a/chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc b/chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
index ad3332d9d32..40d49f8499e 100644
--- a/chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc
@@ -505,7 +505,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem,
ScopedSkipRequestFileSystemDialog dialog_skipper(ui::DIALOG_BUTTON_CANCEL);
ASSERT_TRUE(RunPlatformAppTestWithFlags(
"api_test/file_system/request_file_system_whitelisted_component",
- kFlagLoadAsComponent))
+ kFlagNone, kFlagLoadAsComponent))
<< message_;
}
@@ -514,7 +514,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem,
ScopedSkipRequestFileSystemDialog dialog_skipper(ui::DIALOG_BUTTON_OK);
ASSERT_TRUE(RunPlatformAppTestWithFlags(
"api_test/file_system/request_file_system_not_whitelisted_component",
- kFlagLoadAsComponent))
+ kFlagNone, kFlagLoadAsComponent))
<< message_;
}
@@ -549,7 +549,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTestForRequestFileSystem,
WhitelistedExtensionForDownloads) {
ScopedSkipRequestFileSystemDialog dialog_skipper(ui::DIALOG_BUTTON_CANCEL);
ASSERT_TRUE(RunPlatformAppTestWithFlags(
- "api_test/file_system/request_downloads_whitelisted_extension",
+ "api_test/file_system/request_downloads_whitelisted_extension", kFlagNone,
kFlagLaunchPlatformApp))
<< message_;
}
diff --git a/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc b/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc
index 95152d04cec..ea8a2e24dbb 100644
--- a/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc
+++ b/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.cc
@@ -285,38 +285,38 @@ ExtensionFunction::ResponseAction FontSettingsSetFontFunction::Run() {
return RespondNow(NoArguments());
}
-bool FontSettingsGetFontListFunction::RunAsync() {
+ExtensionFunction::ResponseAction FontSettingsGetFontListFunction::Run() {
content::GetFontListAsync(
BindOnce(&FontSettingsGetFontListFunction::FontListHasLoaded, this));
- return true;
+ return RespondLater();
}
void FontSettingsGetFontListFunction::FontListHasLoaded(
std::unique_ptr<base::ListValue> list) {
- bool success = CopyFontsToResult(list.get());
- SendResponse(success);
+ ExtensionFunction::ResponseValue response = CopyFontsToResult(list.get());
+ Respond(std::move(response));
}
-bool FontSettingsGetFontListFunction::CopyFontsToResult(
- base::ListValue* fonts) {
+ExtensionFunction::ResponseValue
+FontSettingsGetFontListFunction::CopyFontsToResult(base::ListValue* fonts) {
std::unique_ptr<base::ListValue> result(new base::ListValue());
for (auto it = fonts->begin(); it != fonts->end(); ++it) {
base::ListValue* font_list_value;
if (!it->GetAsList(&font_list_value)) {
NOTREACHED();
- return false;
+ return Error("");
}
std::string name;
if (!font_list_value->GetString(0, &name)) {
NOTREACHED();
- return false;
+ return Error("");
}
std::string localized_name;
if (!font_list_value->GetString(1, &localized_name)) {
NOTREACHED();
- return false;
+ return Error("");
}
std::unique_ptr<base::DictionaryValue> font_name(
@@ -327,8 +327,7 @@ bool FontSettingsGetFontListFunction::CopyFontsToResult(
result->Append(std::move(font_name));
}
- SetResult(std::move(result));
- return true;
+ return OneArgument(std::move(result));
}
ExtensionFunction::ResponseAction ClearFontPrefExtensionFunction::Run() {
diff --git a/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.h b/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.h
index 6b206d44778..c4d9224a14b 100644
--- a/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.h
+++ b/chromium/chrome/browser/extensions/api/font_settings/font_settings_api.h
@@ -12,13 +12,13 @@
#include <string>
#include "base/macros.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/font_pref_change_notifier.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_event_histogram_value.h"
+#include "extensions/browser/extension_function.h"
class Profile;
@@ -139,7 +139,7 @@ class FontSettingsSetFontFunction : public ExtensionFunction {
};
// fontSettings.getFontList API function.
-class FontSettingsGetFontListFunction : public ChromeAsyncExtensionFunction {
+class FontSettingsGetFontListFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("fontSettings.getFontList",
FONTSETTINGS_GETFONTLIST)
@@ -148,11 +148,11 @@ class FontSettingsGetFontListFunction : public ChromeAsyncExtensionFunction {
~FontSettingsGetFontListFunction() override {}
// ExtensionFunction:
- bool RunAsync() override;
+ ResponseAction Run() override;
private:
void FontListHasLoaded(std::unique_ptr<base::ListValue> list);
- bool CopyFontsToResult(base::ListValue* fonts);
+ ResponseValue CopyFontsToResult(base::ListValue* fonts);
};
// Base class for extension API functions that clear a browser font pref.
diff --git a/chromium/chrome/browser/extensions/api/font_settings/font_settings_apitest.cc b/chromium/chrome/browser/extensions/api/font_settings/font_settings_apitest.cc
index 603f84f1610..e6b4071b6a9 100644
--- a/chromium/chrome/browser/extensions/api/font_settings/font_settings_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/font_settings/font_settings_apitest.cc
@@ -32,11 +32,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, FontSettingsIncognito) {
prefs->SetString(prefs::kWebKitSansSerifFontFamily, "Arial");
prefs->SetInteger(prefs::kWebKitDefaultFontSize, 16);
- int flags = ExtensionApiTest::kFlagEnableIncognito |
- ExtensionApiTest::kFlagUseIncognito;
- EXPECT_TRUE(RunExtensionSubtest("font_settings/incognito",
- "launch.html",
- flags));
+ EXPECT_TRUE(RunExtensionSubtest("font_settings/incognito", "launch.html",
+ kFlagEnableIncognito, kFlagUseIncognito));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/gcm/gcm_api.cc b/chromium/chrome/browser/extensions/api/gcm/gcm_api.cc
index 3415d2fcaed..3045b247a36 100644
--- a/chromium/chrome/browser/extensions/api/gcm/gcm_api.cc
+++ b/chromium/chrome/browser/extensions/api/gcm/gcm_api.cc
@@ -96,7 +96,7 @@ bool GcmApiFunction::IsGcmApiEnabled(std::string* error) const {
return false;
}
- return gcm::GCMProfileService::IsGCMEnabled(profile->GetPrefs());
+ return true;
}
gcm::GCMDriver* GcmApiFunction::GetGCMDriver() const {
@@ -114,9 +114,8 @@ ExtensionFunction::ResponseAction GcmRegisterFunction::Run() {
EXTENSION_FUNCTION_VALIDATE(params.get());
GetGCMDriver()->Register(
- extension()->id(),
- params->sender_ids,
- base::Bind(&GcmRegisterFunction::CompleteFunctionWithResult, this));
+ extension()->id(), params->sender_ids,
+ base::BindOnce(&GcmRegisterFunction::CompleteFunctionWithResult, this));
// Register() might have returned synchronously.
return did_respond() ? AlreadyResponded() : RespondLater();
@@ -143,7 +142,7 @@ GcmUnregisterFunction::~GcmUnregisterFunction() {}
ExtensionFunction::ResponseAction GcmUnregisterFunction::Run() {
GetGCMDriver()->Unregister(
extension()->id(),
- base::Bind(&GcmUnregisterFunction::CompleteFunctionWithResult, this));
+ base::BindOnce(&GcmUnregisterFunction::CompleteFunctionWithResult, this));
// Unregister might have responded already (synchronously).
return did_respond() ? AlreadyResponded() : RespondLater();
@@ -173,10 +172,8 @@ ExtensionFunction::ResponseAction GcmSendFunction::Run() {
outgoing_message.time_to_live = *params->message.time_to_live;
GetGCMDriver()->Send(
- extension()->id(),
- params->message.destination_id,
- outgoing_message,
- base::Bind(&GcmSendFunction::CompleteFunctionWithResult, this));
+ extension()->id(), params->message.destination_id, outgoing_message,
+ base::BindOnce(&GcmSendFunction::CompleteFunctionWithResult, this));
// Send might have already responded synchronously.
return did_respond() ? AlreadyResponded() : RespondLater();
diff --git a/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc b/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
new file mode 100644
index 00000000000..1d786a2d056
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
@@ -0,0 +1,166 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h"
+
+#include "base/bind.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/extensions/api/identity/identity_api.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "components/signin/public/base/multilogin_parameters.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
+#include "content/public/browser/storage_partition.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "google_apis/gaia/gaia_auth_util.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "net/base/escape.h"
+#include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "url/gurl.h"
+#include "url/url_constants.h"
+
+namespace extensions {
+
+GaiaRemoteConsentFlow::Delegate::~Delegate() = default;
+
+GaiaRemoteConsentFlow::GaiaRemoteConsentFlow(
+ Delegate* delegate,
+ Profile* profile,
+ const ExtensionTokenKey& token_key,
+ const RemoteConsentResolutionData& resolution_data)
+ : delegate_(delegate),
+ profile_(profile),
+ account_id_(token_key.account_id),
+ resolution_data_(resolution_data) {}
+
+GaiaRemoteConsentFlow::~GaiaRemoteConsentFlow() {
+ if (web_flow_)
+ web_flow_.release()->DetachDelegateAndDelete();
+}
+
+void GaiaRemoteConsentFlow::Start() {
+ if (!web_flow_) {
+ web_flow_ = std::make_unique<WebAuthFlow>(
+ this, profile_, resolution_data_.url, WebAuthFlow::INTERACTIVE);
+ }
+
+ auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_);
+ std::vector<CoreAccountId> accounts;
+ auto chrome_accounts_with_refresh_tokens =
+ identity_manager->GetAccountsWithRefreshTokens();
+ for (const auto& chrome_account : chrome_accounts_with_refresh_tokens) {
+ // An account in persistent error state would make multilogin fail. Showing
+ // only a subset of accounts seems to be a better alternative than failing
+ // with an error.
+ if (identity_manager->HasAccountWithRefreshTokenInPersistentErrorState(
+ chrome_account.account_id)) {
+ continue;
+ }
+ accounts.push_back(chrome_account.account_id);
+ }
+
+ set_accounts_in_cookie_task_ =
+ identity_manager->GetAccountsCookieMutator()
+ ->SetAccountsInCookieForPartition(
+ this,
+ {gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER,
+ accounts},
+ base::BindOnce(&GaiaRemoteConsentFlow::OnSetAccountsComplete,
+ base::Unretained(this)));
+}
+
+void GaiaRemoteConsentFlow::OnSetAccountsComplete(
+ signin::SetAccountsInCookieResult result) {
+ if (result != signin::SetAccountsInCookieResult::kSuccess) {
+ delegate_->OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlow::Failure::SET_ACCOUNTS_IN_COOKIE_FAILED);
+ return;
+ }
+
+ network::mojom::CookieManager* cookie_manager =
+ GetCookieManagerForPartition();
+ net::CookieOptions options;
+ for (const auto& cookie : resolution_data_.cookies) {
+ cookie_manager->SetCanonicalCookie(
+ cookie, url::kHttpsScheme, options,
+ network::mojom::CookieManager::SetCanonicalCookieCallback());
+ }
+
+ identity_api_set_consent_result_subscription_ =
+ IdentityAPI::GetFactoryInstance()
+ ->Get(profile_)
+ ->RegisterOnSetConsentResultCallback(
+ base::Bind(&GaiaRemoteConsentFlow::OnConsentResultSet,
+ base::Unretained(this)));
+
+ set_accounts_in_cookie_task_.reset();
+ web_flow_->Start();
+}
+
+void GaiaRemoteConsentFlow::OnConsentResultSet(
+ const std::string& consent_result,
+ const std::string& window_id) {
+ if (!web_flow_ || window_id != web_flow_->GetAppWindowKey())
+ return;
+
+ identity_api_set_consent_result_subscription_.reset();
+
+ bool consent_approved = false;
+ std::string gaia_id;
+ if (!gaia::ParseOAuth2MintTokenConsentResult(consent_result,
+ &consent_approved, &gaia_id)) {
+ delegate_->OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT);
+ return;
+ }
+
+ if (!consent_approved) {
+ delegate_->OnGaiaRemoteConsentFlowFailed(GaiaRemoteConsentFlow::NO_GRANT);
+ return;
+ }
+
+ delegate_->OnGaiaRemoteConsentFlowApproved(consent_result, gaia_id);
+}
+
+void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
+ GaiaRemoteConsentFlow::Failure gaia_failure;
+
+ switch (failure) {
+ case WebAuthFlow::WINDOW_CLOSED:
+ gaia_failure = GaiaRemoteConsentFlow::WINDOW_CLOSED;
+ break;
+ case WebAuthFlow::LOAD_FAILED:
+ gaia_failure = GaiaRemoteConsentFlow::LOAD_FAILED;
+ break;
+ case WebAuthFlow::INTERACTION_REQUIRED:
+ NOTREACHED() << "Unexpected error from web auth flow: " << failure;
+ gaia_failure = GaiaRemoteConsentFlow::LOAD_FAILED;
+ break;
+ }
+
+ delegate_->OnGaiaRemoteConsentFlowFailed(gaia_failure);
+}
+
+std::unique_ptr<GaiaAuthFetcher>
+GaiaRemoteConsentFlow::CreateGaiaAuthFetcherForPartition(
+ GaiaAuthConsumer* consumer) {
+ return std::make_unique<GaiaAuthFetcher>(
+ consumer, gaia::GaiaSource::kChrome,
+ web_flow_->GetGuestPartition()->GetURLLoaderFactoryForBrowserProcess());
+}
+
+network::mojom::CookieManager*
+GaiaRemoteConsentFlow::GetCookieManagerForPartition() {
+ return web_flow_->GetGuestPartition()->GetCookieManagerForBrowserProcess();
+}
+
+void GaiaRemoteConsentFlow::SetWebAuthFlowForTesting(
+ std::unique_ptr<WebAuthFlow> web_auth_flow) {
+ if (web_flow_)
+ web_flow_.release()->DetachDelegateAndDelete();
+ web_flow_ = std::move(web_auth_flow);
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h b/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h
new file mode 100644
index 00000000000..9c5d4867dc3
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h
@@ -0,0 +1,88 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_REMOTE_CONSENT_FLOW_H_
+#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_REMOTE_CONSENT_FLOW_H_
+
+#include "base/callback_list.h"
+
+#include "base/macros.h"
+#include "chrome/browser/extensions/api/identity/extension_token_key.h"
+#include "chrome/browser/extensions/api/identity/web_auth_flow.h"
+#include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
+#include "google_apis/gaia/core_account_id.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_mint_token_flow.h"
+
+namespace extensions {
+
+class GaiaRemoteConsentFlow
+ : public WebAuthFlow::Delegate,
+ public signin::AccountsCookieMutator::PartitionDelegate {
+ public:
+ enum Failure {
+ WINDOW_CLOSED,
+ LOAD_FAILED,
+ SET_ACCOUNTS_IN_COOKIE_FAILED,
+ INVALID_CONSENT_RESULT,
+ NO_GRANT
+ };
+
+ class Delegate {
+ public:
+ virtual ~Delegate();
+ // Called when the flow ends without getting the user consent.
+ virtual void OnGaiaRemoteConsentFlowFailed(Failure failure) = 0;
+ // Called when the user gives the approval via the OAuth2 remote consent
+ // screen.
+ virtual void OnGaiaRemoteConsentFlowApproved(
+ const std::string& consent_result,
+ const std::string& gaia_id) = 0;
+ };
+
+ GaiaRemoteConsentFlow(Delegate* delegate,
+ Profile* profile,
+ const ExtensionTokenKey& token_key,
+ const RemoteConsentResolutionData& resolution_data);
+ ~GaiaRemoteConsentFlow() override;
+
+ GaiaRemoteConsentFlow(const GaiaRemoteConsentFlow& other) = delete;
+ GaiaRemoteConsentFlow& operator=(const GaiaRemoteConsentFlow& other) = delete;
+
+ // Starts the flow by setting accounts in cookie.
+ void Start();
+
+ // Set accounts in cookie completion callback.
+ void OnSetAccountsComplete(signin::SetAccountsInCookieResult result);
+
+ // setConsentResult() JavaScript callback.
+ void OnConsentResultSet(const std::string& consent_result,
+ const std::string& window_id);
+
+ // WebAuthFlow::Delegate implementation.
+ void OnAuthFlowFailure(WebAuthFlow::Failure failure) override;
+
+ // AccountsCookieMutator::PartitionDelegate:
+ std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcherForPartition(
+ GaiaAuthConsumer* consumer) override;
+ network::mojom::CookieManager* GetCookieManagerForPartition() override;
+
+ void SetWebAuthFlowForTesting(std::unique_ptr<WebAuthFlow> web_auth_flow);
+
+ private:
+ Delegate* delegate_;
+ Profile* profile_;
+ CoreAccountId account_id_;
+ RemoteConsentResolutionData resolution_data_;
+ std::unique_ptr<WebAuthFlow> web_flow_;
+ std::unique_ptr<signin::AccountsCookieMutator::SetAccountsInCookieTask>
+ set_accounts_in_cookie_task_;
+ std::unique_ptr<base::CallbackList<void(const std::string&,
+ const std::string&)>::Subscription>
+ identity_api_set_consent_result_subscription_;
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_REMOTE_CONSENT_FLOW_H_
diff --git a/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_unittest.cc b/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_unittest.cc
new file mode 100644
index 00000000000..95441a4941f
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_unittest.cc
@@ -0,0 +1,172 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h"
+
+#include <vector>
+
+#include "base/run_loop.h"
+#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/signin/public/identity_manager/set_accounts_in_cookie_result.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+const char kWindowKey[] = "window_key";
+const char kGaiaId[] = "fake_gaia_id";
+const char kConsentResult[] = "CAESCUVOQ1JZUFRFRBoMZmFrZV9nYWlhX2lk";
+
+class FakeWebAuthFlowWithWindowKey : public WebAuthFlow {
+ public:
+ explicit FakeWebAuthFlowWithWindowKey(WebAuthFlow::Delegate* delegate,
+ std::string window_key)
+ : WebAuthFlow(delegate, nullptr, GURL(), WebAuthFlow::INTERACTIVE),
+ fake_window_key_(window_key) {}
+
+ ~FakeWebAuthFlowWithWindowKey() override = default;
+
+ void Start() override {}
+
+ const std::string& GetAppWindowKey() const override {
+ return fake_window_key_;
+ }
+
+ private:
+ const std::string fake_window_key_;
+};
+
+class TestGaiaRemoteConsentFlow : public GaiaRemoteConsentFlow {
+ public:
+ TestGaiaRemoteConsentFlow(GaiaRemoteConsentFlow::Delegate* delegate,
+ const ExtensionTokenKey& token_key,
+ const RemoteConsentResolutionData& resolution_data,
+ const std::string& window_key)
+ : GaiaRemoteConsentFlow(delegate, nullptr, token_key, resolution_data),
+ window_key_(window_key) {
+ SetWebAuthFlowForTesting(
+ std::make_unique<FakeWebAuthFlowWithWindowKey>(this, window_key_));
+ }
+
+ private:
+ const std::string window_key_;
+};
+
+class MockGaiaRemoteConsentFlowDelegate
+ : public GaiaRemoteConsentFlow::Delegate {
+ public:
+ MOCK_METHOD1(OnGaiaRemoteConsentFlowFailed,
+ void(GaiaRemoteConsentFlow::Failure failure));
+ MOCK_METHOD2(OnGaiaRemoteConsentFlowApproved,
+ void(const std::string& consent_result,
+ const std::string& gaia_id));
+};
+
+class IdentityGaiaRemoteConsentFlowTest : public testing::Test {
+ public:
+ IdentityGaiaRemoteConsentFlowTest() = default;
+
+ void TearDown() override {
+ testing::Test::TearDown();
+ base::RunLoop()
+ .RunUntilIdle(); // Run tasks so all FakeWebAuthFlowWithWindowKey get
+ // deleted.
+ }
+
+ std::unique_ptr<TestGaiaRemoteConsentFlow> CreateTestFlow(
+ const std::string& window_key) {
+ return CreateTestFlow(window_key, &delegate_);
+ }
+
+ std::unique_ptr<TestGaiaRemoteConsentFlow> CreateTestFlow(
+ const std::string& window_key,
+ GaiaRemoteConsentFlow::Delegate* delegate) {
+ ExtensionTokenKey token_key("extension_id", CoreAccountId("account_id"),
+ std::set<std::string>());
+ RemoteConsentResolutionData resolution_data;
+ resolution_data.url = GURL("https://example.com/auth/");
+ return std::unique_ptr<TestGaiaRemoteConsentFlow>(
+ new TestGaiaRemoteConsentFlow(delegate, token_key, resolution_data,
+ window_key));
+ }
+
+ protected:
+ base::test::TaskEnvironment task_env_;
+ testing::StrictMock<MockGaiaRemoteConsentFlowDelegate> delegate_;
+};
+
+TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult) {
+ std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
+ EXPECT_CALL(delegate_,
+ OnGaiaRemoteConsentFlowApproved(kConsentResult, kGaiaId));
+ flow->OnConsentResultSet(kConsentResult, kWindowKey);
+}
+
+TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult_WrongWindowIgnored) {
+ std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
+ // No call is expected.
+ flow->OnConsentResultSet(kConsentResult, "another_window_key");
+}
+
+TEST_F(IdentityGaiaRemoteConsentFlowTest, ConsentResult_TwoWindows) {
+ std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
+ const char kWindowKey2[] = "window_key2";
+ testing::StrictMock<MockGaiaRemoteConsentFlowDelegate> delegate2;
+ std::unique_ptr<TestGaiaRemoteConsentFlow> flow2 =
+ CreateTestFlow(kWindowKey2, &delegate2);
+
+ const char kConsentResult2[] = "CAESCkVOQ1JZUFRFRDI";
+ EXPECT_CALL(delegate2, OnGaiaRemoteConsentFlowApproved(kConsentResult2, ""));
+ flow2->OnConsentResultSet(kConsentResult2, kWindowKey2);
+
+ EXPECT_CALL(delegate_,
+ OnGaiaRemoteConsentFlowApproved(kConsentResult, kGaiaId));
+ flow->OnConsentResultSet(kConsentResult, kWindowKey);
+}
+
+TEST_F(IdentityGaiaRemoteConsentFlowTest, InvalidConsentResult) {
+ const char kInvalidConsentResult[] = "abc";
+ std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
+ EXPECT_CALL(delegate_,
+ OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlow::Failure::INVALID_CONSENT_RESULT));
+ flow->OnConsentResultSet(kInvalidConsentResult, kWindowKey);
+}
+
+TEST_F(IdentityGaiaRemoteConsentFlowTest, NoGrant) {
+ const char kNoGrantConsentResult[] = "CAA";
+ std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
+ EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlow::Failure::NO_GRANT));
+ flow->OnConsentResultSet(kNoGrantConsentResult, kWindowKey);
+}
+
+TEST_F(IdentityGaiaRemoteConsentFlowTest, SetAccountsFailure) {
+ std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
+ EXPECT_CALL(
+ delegate_,
+ OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlow::Failure::SET_ACCOUNTS_IN_COOKIE_FAILED));
+ flow->OnSetAccountsComplete(
+ signin::SetAccountsInCookieResult::kPersistentError);
+}
+
+TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_WindowClosed) {
+ std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
+ EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlow::Failure::WINDOW_CLOSED));
+ flow->OnAuthFlowFailure(WebAuthFlow::Failure::WINDOW_CLOSED);
+}
+
+TEST_F(IdentityGaiaRemoteConsentFlowTest, WebAuthFlowFailure_LoadFailed) {
+ std::unique_ptr<TestGaiaRemoteConsentFlow> flow = CreateTestFlow(kWindowKey);
+ EXPECT_CALL(delegate_, OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlow::Failure::LOAD_FAILED));
+ flow->OnAuthFlowFailure(WebAuthFlow::Failure::LOAD_FAILED);
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
index df079cc13d2..4eafced9daa 100644
--- a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
@@ -16,9 +16,11 @@
#include "chrome/browser/signin/identity_manager_factory.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/ubertoken_fetcher.h"
+#include "content/public/browser/storage_partition.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
#include "google_apis/gaia/gaia_urls.h"
#include "net/base/escape.h"
+#include "services/network/public/mojom/cookie_manager.mojom.h"
namespace extensions {
@@ -30,9 +32,9 @@ GaiaWebAuthFlow::GaiaWebAuthFlow(Delegate* delegate,
: delegate_(delegate),
profile_(profile),
account_id_(token_key->account_id) {
- TRACE_EVENT_ASYNC_BEGIN2("identity", "GaiaWebAuthFlow", this, "extension_id",
- token_key->extension_id, "account_id",
- token_key->account_id.ToString());
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
+ "identity", "GaiaWebAuthFlow", this, "extension_id",
+ token_key->extension_id, "account_id", token_key->account_id.ToString());
const char kOAuth2RedirectPathFormat[] = "/%s";
const char kOAuth2AuthorizeFormat[] =
@@ -78,13 +80,14 @@ GaiaWebAuthFlow::GaiaWebAuthFlow(Delegate* delegate,
}
GaiaWebAuthFlow::~GaiaWebAuthFlow() {
- TRACE_EVENT_ASYNC_END0("identity", "GaiaWebAuthFlow", this);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("identity", "GaiaWebAuthFlow", this);
if (web_flow_)
web_flow_.release()->DetachDelegateAndDelete();
}
void GaiaWebAuthFlow::Start() {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("identity", "UbertokenFetch", this);
auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_);
ubertoken_fetcher_ = identity_manager->CreateUbertokenFetcherForAccount(
account_id_,
@@ -96,9 +99,8 @@ void GaiaWebAuthFlow::Start() {
void GaiaWebAuthFlow::OnUbertokenFetchComplete(GoogleServiceAuthError error,
const std::string& token) {
if (error != GoogleServiceAuthError::AuthErrorNone()) {
- TRACE_EVENT_ASYNC_STEP_PAST1("identity", "GaiaWebAuthFlow", this,
- "OnUbertokenFetchComplete", "error",
- error.ToString());
+ TRACE_EVENT_NESTABLE_ASYNC_END1("identity", "UbertokenFetch", this, "error",
+ error.ToString());
DVLOG(1) << "OnUbertokenFetchComplete failure: " << error.error_message();
delegate_->OnGaiaFlowFailure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error,
@@ -106,8 +108,7 @@ void GaiaWebAuthFlow::OnUbertokenFetchComplete(GoogleServiceAuthError error,
return;
}
- TRACE_EVENT_ASYNC_STEP_PAST0("identity", "GaiaWebAuthFlow", this,
- "OnUbertokenFetchComplete");
+ TRACE_EVENT_NESTABLE_ASYNC_END0("identity", "UbertokenFetch", this);
const char kMergeSessionQueryFormat[] = "?uberauth=%s&"
"continue=%s&"
@@ -121,6 +122,15 @@ void GaiaWebAuthFlow::OnUbertokenFetchComplete(GoogleServiceAuthError error,
GaiaUrls::GetInstance()->merge_session_url().Resolve(merge_query));
web_flow_ = CreateWebAuthFlow(merge_url);
+ network::mojom::CookieManager* cookie_manager =
+ web_flow_->GetGuestPartition()->GetCookieManagerForBrowserProcess();
+ cookie_manager->DeleteCookies(
+ network::mojom::CookieDeletionFilter::New(),
+ base::BindOnce(&GaiaWebAuthFlow::OnCookiesDeleted,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void GaiaWebAuthFlow::OnCookiesDeleted(uint32_t num_deleted) {
web_flow_->Start();
}
@@ -141,12 +151,8 @@ void GaiaWebAuthFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
break;
}
- TRACE_EVENT_ASYNC_STEP_PAST1("identity",
- "GaiaWebAuthFlow",
- this,
- "OnAuthFlowFailure",
- "error",
- gaia_failure);
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("identity", "OnAuthFlowFailure", this,
+ "error", gaia_failure);
delegate_->OnGaiaFlowFailure(
gaia_failure,
@@ -155,10 +161,7 @@ void GaiaWebAuthFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
}
void GaiaWebAuthFlow::OnAuthFlowURLChange(const GURL& url) {
- TRACE_EVENT_ASYNC_STEP_PAST0("identity",
- "GaiaWebAuthFlow",
- this,
- "OnAuthFlowURLChange");
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "OnAuthFlowURLChange", this);
const char kOAuth2RedirectAccessTokenKey[] = "access_token";
const char kOAuth2RedirectErrorKey[] = "error";
diff --git a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.h b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.h
index 037ac0cd0b8..37575c807f2 100644
--- a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.h
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_GAIA_WEB_AUTH_FLOW_H_
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "chrome/browser/extensions/api/identity/extension_token_key.h"
#include "chrome/browser/extensions/api/identity/web_auth_flow.h"
#include "extensions/common/manifest_handlers/oauth2_manifest_handler.h"
@@ -77,6 +78,9 @@ class GaiaWebAuthFlow : public WebAuthFlow::Delegate {
void OnUbertokenFetchComplete(GoogleServiceAuthError error,
const std::string& token);
+ // DeleteCookies completion callback.
+ void OnCookiesDeleted(uint32_t num_deleted);
+
// WebAuthFlow::Delegate implementation.
void OnAuthFlowFailure(WebAuthFlow::Failure failure) override;
void OnAuthFlowURLChange(const GURL& redirect_url) override;
@@ -96,6 +100,8 @@ class GaiaWebAuthFlow : public WebAuthFlow::Delegate {
std::unique_ptr<signin::UbertokenFetcher> ubertoken_fetcher_;
std::unique_ptr<WebAuthFlow> web_flow_;
+ base::WeakPtrFactory<GaiaWebAuthFlow> weak_ptr_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(GaiaWebAuthFlow);
};
diff --git a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc
index 68296a8a217..9738fe8944f 100644
--- a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc
@@ -7,21 +7,44 @@
#include <vector>
#include "base/run_loop.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_storage_partition.h"
+#include "services/network/test/test_cookie_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
+class DeleteCookiesTestCookieManager : public network::TestCookieManager {
+ public:
+ void DeleteCookies(network::mojom::CookieDeletionFilterPtr filter,
+ DeleteCookiesCallback callback) override {
+ cookies_deleted_ = true;
+ std::move(callback).Run(0U);
+ }
+ bool cookies_deleted() { return cookies_deleted_; }
+
+ private:
+ bool cookies_deleted_ = false;
+};
+
class FakeWebAuthFlow : public WebAuthFlow {
public:
explicit FakeWebAuthFlow(WebAuthFlow::Delegate* delegate)
- : WebAuthFlow(delegate,
- NULL,
- GURL(),
- WebAuthFlow::INTERACTIVE) {}
+ : WebAuthFlow(delegate, nullptr, GURL(), WebAuthFlow::INTERACTIVE) {
+ storage_partition.set_cookie_manager_for_browser_process(&cookie_manager);
+ }
+
+ void Start() override { EXPECT_TRUE(cookie_manager.cookies_deleted()); }
- void Start() override {}
+ content::StoragePartition* GetGuestPartition() override {
+ return &storage_partition;
+ }
+
+ private:
+ content::TestStoragePartition storage_partition;
+ DeleteCookiesTestCookieManager cookie_manager;
};
class TestGaiaWebAuthFlow : public GaiaWebAuthFlow {
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_api.cc b/chromium/chrome/browser/extensions/api/identity/identity_api.cc
index 5b492a1775e..7c83df99493 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_api.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <algorithm>
#include <memory>
#include <set>
#include <string>
@@ -31,6 +32,7 @@
#include "chrome/common/extensions/api/identity.h"
#include "chrome/common/url_constants.h"
#include "extensions/browser/extension_function_dispatcher.h"
+#include "extensions/browser/extension_prefs.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_l10n_util.h"
#include "extensions/common/manifest_handlers/oauth2_manifest_handler.h"
@@ -41,20 +43,59 @@
namespace extensions {
-IdentityTokenCacheValue::IdentityTokenCacheValue()
- : status_(CACHE_STATUS_NOTFOUND) {}
+namespace {
+const char kIdentityGaiaIdPref[] = "identity_gaia_id";
+}
+IdentityTokenCacheValue::IdentityTokenCacheValue() = default;
IdentityTokenCacheValue::IdentityTokenCacheValue(
- const IssueAdviceInfo& issue_advice)
- : status_(CACHE_STATUS_ADVICE), issue_advice_(issue_advice) {
- expiration_time_ =
+ const IdentityTokenCacheValue& other) = default;
+IdentityTokenCacheValue::~IdentityTokenCacheValue() = default;
+
+// static
+IdentityTokenCacheValue IdentityTokenCacheValue::CreateIssueAdvice(
+ const IssueAdviceInfo& issue_advice) {
+ IdentityTokenCacheValue cache_value;
+ cache_value.status_ = CACHE_STATUS_ADVICE;
+ cache_value.issue_advice_ = issue_advice;
+ cache_value.expiration_time_ =
base::Time::Now() + base::TimeDelta::FromSeconds(
identity_constants::kCachedIssueAdviceTTLSeconds);
+ return cache_value;
}
-IdentityTokenCacheValue::IdentityTokenCacheValue(const std::string& token,
- base::TimeDelta time_to_live)
- : status_(CACHE_STATUS_TOKEN), token_(token) {
+// static
+IdentityTokenCacheValue IdentityTokenCacheValue::CreateRemoteConsent(
+ const RemoteConsentResolutionData& resolution_data) {
+ IdentityTokenCacheValue cache_value;
+ cache_value.status_ = CACHE_STATUS_REMOTE_CONSENT;
+ cache_value.resolution_data_ = resolution_data;
+ cache_value.expiration_time_ =
+ base::Time::Now() + base::TimeDelta::FromSeconds(
+ identity_constants::kCachedIssueAdviceTTLSeconds);
+ return cache_value;
+}
+
+// static
+IdentityTokenCacheValue IdentityTokenCacheValue::CreateRemoteConsentApproved(
+ const std::string& consent_result) {
+ IdentityTokenCacheValue cache_value;
+ cache_value.status_ = CACHE_STATUS_REMOTE_CONSENT_APPROVED;
+ cache_value.consent_result_ = consent_result;
+ cache_value.expiration_time_ =
+ base::Time::Now() + base::TimeDelta::FromSeconds(
+ identity_constants::kCachedIssueAdviceTTLSeconds);
+ return cache_value;
+}
+
+// static
+IdentityTokenCacheValue IdentityTokenCacheValue::CreateToken(
+ const std::string& token,
+ base::TimeDelta time_to_live) {
+ IdentityTokenCacheValue cache_value;
+ cache_value.status_ = CACHE_STATUS_TOKEN;
+ cache_value.token_ = token;
+
// Remove 20 minutes from the ttl so cached tokens will have some time
// to live any time they are returned.
time_to_live -= base::TimeDelta::FromMinutes(20);
@@ -63,14 +104,10 @@ IdentityTokenCacheValue::IdentityTokenCacheValue(const std::string& token,
if (time_to_live < zero_delta)
time_to_live = zero_delta;
- expiration_time_ = base::Time::Now() + time_to_live;
+ cache_value.expiration_time_ = base::Time::Now() + time_to_live;
+ return cache_value;
}
-IdentityTokenCacheValue::IdentityTokenCacheValue(
- const IdentityTokenCacheValue& other) = default;
-
-IdentityTokenCacheValue::~IdentityTokenCacheValue() {}
-
IdentityTokenCacheValue::CacheValueStatus IdentityTokenCacheValue::status()
const {
if (is_expired())
@@ -83,6 +120,15 @@ const IssueAdviceInfo& IdentityTokenCacheValue::issue_advice() const {
return issue_advice_;
}
+const RemoteConsentResolutionData& IdentityTokenCacheValue::resolution_data()
+ const {
+ return resolution_data_;
+}
+
+const std::string& IdentityTokenCacheValue::consent_result() const {
+ return consent_result_;
+}
+
const std::string& IdentityTokenCacheValue::token() const { return token_; }
bool IdentityTokenCacheValue::is_expired() const {
@@ -95,9 +141,11 @@ const base::Time& IdentityTokenCacheValue::expiration_time() const {
}
IdentityAPI::IdentityAPI(content::BrowserContext* context)
- : profile_(Profile::FromBrowserContext(context)) {
- IdentityManagerFactory::GetForProfile(profile_)->AddObserver(this);
-}
+ : IdentityAPI(Profile::FromBrowserContext(context),
+ IdentityManagerFactory::GetForProfile(
+ Profile::FromBrowserContext(context)),
+ ExtensionPrefs::Get(context),
+ EventRouter::Get(context)) {}
IdentityAPI::~IdentityAPI() {}
@@ -136,9 +184,66 @@ const IdentityAPI::CachedTokens& IdentityAPI::GetAllCachedTokens() {
return token_cache_;
}
+void IdentityAPI::SetGaiaIdForExtension(const std::string& extension_id,
+ const std::string& gaia_id) {
+ DCHECK(!gaia_id.empty());
+ extension_prefs_->UpdateExtensionPref(extension_id, kIdentityGaiaIdPref,
+ std::make_unique<base::Value>(gaia_id));
+}
+
+base::Optional<std::string> IdentityAPI::GetGaiaIdForExtension(
+ const std::string& extension_id) {
+ std::string gaia_id;
+ if (!extension_prefs_->ReadPrefAsString(extension_id, kIdentityGaiaIdPref,
+ &gaia_id)) {
+ return base::nullopt;
+ }
+ return gaia_id;
+}
+
+void IdentityAPI::EraseGaiaIdForExtension(const std::string& extension_id) {
+ extension_prefs_->UpdateExtensionPref(extension_id, kIdentityGaiaIdPref,
+ nullptr);
+}
+
+void IdentityAPI::EraseStaleGaiaIdsForAllExtensions() {
+ // Refresh tokens haven't been loaded yet. Wait for OnRefreshTokensLoaded() to
+ // fire.
+ if (!identity_manager_->AreRefreshTokensLoaded())
+ return;
+ std::vector<CoreAccountInfo> accounts =
+ identity_manager_->GetAccountsWithRefreshTokens();
+ extensions::ExtensionIdList extensions;
+ extension_prefs_->GetExtensions(&extensions);
+ for (const ExtensionId& extension_id : extensions) {
+ base::Optional<std::string> gaia_id = GetGaiaIdForExtension(extension_id);
+ if (!gaia_id)
+ continue;
+ auto account_it = std::find_if(accounts.begin(), accounts.end(),
+ [&](const CoreAccountInfo& account) {
+ return account.gaia == *gaia_id;
+ });
+ if (account_it == accounts.end()) {
+ EraseGaiaIdForExtension(extension_id);
+ }
+ }
+}
+
+void IdentityAPI::SetConsentResult(const std::string& result,
+ const std::string& window_id) {
+ on_set_consent_result_callback_list_.Notify(result, window_id);
+}
+
+std::unique_ptr<
+ base::CallbackList<IdentityAPI::OnSetConsentResultSignature>::Subscription>
+IdentityAPI::RegisterOnSetConsentResultCallback(
+ const base::RepeatingCallback<OnSetConsentResultSignature>& callback) {
+ return on_set_consent_result_callback_list_.Add(callback);
+}
+
void IdentityAPI::Shutdown() {
on_shutdown_callback_list_.Notify();
- IdentityManagerFactory::GetForProfile(profile_)->RemoveObserver(this);
+ identity_manager_->RemoveObserver(this);
}
static base::LazyInstance<BrowserContextKeyedAPIFactory<IdentityAPI>>::
@@ -149,15 +254,36 @@ BrowserContextKeyedAPIFactory<IdentityAPI>* IdentityAPI::GetFactoryInstance() {
return g_identity_api_factory.Pointer();
}
+std::unique_ptr<base::CallbackList<void()>::Subscription>
+IdentityAPI::RegisterOnShutdownCallback(const base::Closure& cb) {
+ return on_shutdown_callback_list_.Add(cb);
+}
+
bool IdentityAPI::AreExtensionsRestrictedToPrimaryAccount() {
return !AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_);
}
+IdentityAPI::IdentityAPI(Profile* profile,
+ signin::IdentityManager* identity_manager,
+ ExtensionPrefs* extension_prefs,
+ EventRouter* event_router)
+ : profile_(profile),
+ identity_manager_(identity_manager),
+ extension_prefs_(extension_prefs),
+ event_router_(event_router) {
+ identity_manager_->AddObserver(this);
+ EraseStaleGaiaIdsForAllExtensions();
+}
+
+void IdentityAPI::OnRefreshTokensLoaded() {
+ EraseStaleGaiaIdsForAllExtensions();
+}
+
void IdentityAPI::OnRefreshTokenUpdatedForAccount(
const CoreAccountInfo& account_info) {
// Refresh tokens are sometimes made available in contexts where
- // AccountTrackerService is not tracking the account in question (one example
- // is SupervisedUserService::InitSync()). Bail out in these cases.
+ // AccountTrackerService is not tracking the account in question. Bail out in
+ // these cases.
if (account_info.gaia.empty())
return;
@@ -167,6 +293,7 @@ void IdentityAPI::OnRefreshTokenUpdatedForAccount(
void IdentityAPI::OnExtendedAccountInfoRemoved(
const AccountInfo& account_info) {
DCHECK(!account_info.gaia.empty());
+ EraseStaleGaiaIdsForAllExtensions();
FireOnAccountSignInChanged(account_info.gaia, false);
}
@@ -185,7 +312,7 @@ void IdentityAPI::FireOnAccountSignInChanged(const std::string& gaia_id,
if (on_signin_changed_callback_for_testing_)
on_signin_changed_callback_for_testing_.Run(event.get());
- EventRouter::Get(profile_)->BroadcastEvent(std::move(event));
+ event_router_->BroadcastEvent(std::move(event));
}
template <>
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_api.h b/chromium/chrome/browser/extensions/api/identity/identity_api.h
index 54970056211..e5e3eeda3ce 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_api.h
+++ b/chromium/chrome/browser/extensions/api/identity/identity_api.h
@@ -17,6 +17,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "base/optional.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "chrome/browser/extensions/api/identity/extension_token_key.h"
@@ -28,7 +29,6 @@
#include "chrome/browser/extensions/api/identity/identity_mint_queue.h"
#include "chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h"
#include "chrome/browser/extensions/api/identity/web_auth_flow.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "components/signin/public/base/signin_buildflags.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
@@ -45,30 +45,42 @@ namespace extensions {
class IdentityTokenCacheValue {
public:
IdentityTokenCacheValue();
- explicit IdentityTokenCacheValue(const IssueAdviceInfo& issue_advice);
- IdentityTokenCacheValue(const std::string& token,
- base::TimeDelta time_to_live);
IdentityTokenCacheValue(const IdentityTokenCacheValue& other);
~IdentityTokenCacheValue();
+ static IdentityTokenCacheValue CreateIssueAdvice(
+ const IssueAdviceInfo& issue_advice);
+ static IdentityTokenCacheValue CreateRemoteConsent(
+ const RemoteConsentResolutionData& resolution_data);
+ static IdentityTokenCacheValue CreateRemoteConsentApproved(
+ const std::string& consent_result);
+ static IdentityTokenCacheValue CreateToken(const std::string& token,
+ base::TimeDelta time_to_live);
+
// Order of these entries is used to determine whether or not new
- // entries supercede older ones in SetCachedToken.
+ // entries supersede older ones in SetCachedToken.
enum CacheValueStatus {
CACHE_STATUS_NOTFOUND,
CACHE_STATUS_ADVICE,
+ CACHE_STATUS_REMOTE_CONSENT,
+ CACHE_STATUS_REMOTE_CONSENT_APPROVED,
CACHE_STATUS_TOKEN
};
CacheValueStatus status() const;
const IssueAdviceInfo& issue_advice() const;
+ const RemoteConsentResolutionData& resolution_data() const;
+ const std::string& consent_result() const;
const std::string& token() const;
const base::Time& expiration_time() const;
private:
bool is_expired() const;
- CacheValueStatus status_;
+ CacheValueStatus status_ = CACHE_STATUS_NOTFOUND;
IssueAdviceInfo issue_advice_;
+ RemoteConsentResolutionData resolution_data_;
+ std::string consent_result_;
std::string token_;
base::Time expiration_time_;
};
@@ -76,7 +88,9 @@ class IdentityTokenCacheValue {
class IdentityAPI : public BrowserContextKeyedAPI,
public signin::IdentityManager::Observer {
public:
- typedef std::map<ExtensionTokenKey, IdentityTokenCacheValue> CachedTokens;
+ using CachedTokens = std::map<ExtensionTokenKey, IdentityTokenCacheValue>;
+ using OnSetConsentResultSignature = void(const std::string&,
+ const std::string&);
explicit IdentityAPI(content::BrowserContext* context);
~IdentityAPI() override;
@@ -84,24 +98,40 @@ class IdentityAPI : public BrowserContextKeyedAPI,
// Request serialization queue for getAuthToken.
IdentityMintRequestQueue* mint_queue();
- // Token cache
+ // Token cache.
void SetCachedToken(const ExtensionTokenKey& key,
const IdentityTokenCacheValue& token_data);
void EraseCachedToken(const std::string& extension_id,
const std::string& token);
void EraseAllCachedTokens();
const IdentityTokenCacheValue& GetCachedToken(const ExtensionTokenKey& key);
-
const CachedTokens& GetAllCachedTokens();
+ // GAIA id cache.
+ void SetGaiaIdForExtension(const std::string& extension_id,
+ const std::string& gaia_id);
+ // Returns |base::nullopt| if no GAIA id is saved for |extension_id|.
+ // Otherwise, returns GAIA id previously saved via SetGaiaIdForExtension().
+ base::Optional<std::string> GetGaiaIdForExtension(
+ const std::string& extension_id);
+ void EraseGaiaIdForExtension(const std::string& extension_id);
+ // If refresh tokens have been loaded, erases GAIA ids of accounts that are no
+ // longer signed in to Chrome for all extensions.
+ void EraseStaleGaiaIdsForAllExtensions();
+
+ // Consent result.
+ void SetConsentResult(const std::string& result,
+ const std::string& window_id);
+ std::unique_ptr<base::CallbackList<OnSetConsentResultSignature>::Subscription>
+ RegisterOnSetConsentResultCallback(
+ const base::RepeatingCallback<OnSetConsentResultSignature>& callback);
+
// BrowserContextKeyedAPI:
void Shutdown() override;
static BrowserContextKeyedAPIFactory<IdentityAPI>* GetFactoryInstance();
std::unique_ptr<base::CallbackList<void()>::Subscription>
- RegisterOnShutdownCallback(const base::Closure& cb) {
- return on_shutdown_callback_list_.Add(cb);
- }
+ RegisterOnShutdownCallback(const base::Closure& cb);
// Callback that is used in testing contexts to test the implementation of
// the chrome.identity.onSignInChanged event. Note that the passed-in Event is
@@ -118,12 +148,20 @@ class IdentityAPI : public BrowserContextKeyedAPI,
private:
friend class BrowserContextKeyedAPIFactory<IdentityAPI>;
+ friend class IdentityAPITest;
// BrowserContextKeyedAPI:
static const char* service_name() { return "IdentityAPI"; }
static const bool kServiceIsNULLWhileTesting = true;
+ // This constructor allows to mock keyed services in tests.
+ IdentityAPI(Profile* profile,
+ signin::IdentityManager* identity_manager,
+ ExtensionPrefs* extension_prefs,
+ EventRouter* event_router);
+
// signin::IdentityManager::Observer:
+ void OnRefreshTokensLoaded() override;
void OnRefreshTokenUpdatedForAccount(
const CoreAccountInfo& account_info) override;
// NOTE: This class must listen for this callback rather than
@@ -135,12 +173,18 @@ class IdentityAPI : public BrowserContextKeyedAPI,
void FireOnAccountSignInChanged(const std::string& gaia_id,
bool is_signed_in);
- Profile* profile_;
+ Profile* const profile_;
+ signin::IdentityManager* const identity_manager_;
+ ExtensionPrefs* const extension_prefs_;
+ EventRouter* const event_router_;
+
IdentityMintRequestQueue mint_queue_;
CachedTokens token_cache_;
OnSignInChangedCallback on_signin_changed_callback_for_testing_;
+ base::CallbackList<OnSetConsentResultSignature>
+ on_set_consent_result_callback_list_;
base::CallbackList<void()> on_shutdown_callback_list_;
};
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_api_unittest.cc b/chromium/chrome/browser/extensions/api/identity/identity_api_unittest.cc
index 682d4f77b3e..61fd982c158 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_api_unittest.cc
@@ -4,32 +4,149 @@
#include "chrome/browser/extensions/api/identity/identity_api.h"
+#include <memory>
+
+#include "base/optional.h"
#include "base/test/scoped_feature_list.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
+#include "chrome/browser/extensions/test_extension_prefs.h"
#include "chrome/test/base/testing_profile.h"
#include "components/signin/public/base/signin_buildflags.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "content/public/test/browser_task_environment.h"
+#include "google_apis/gaia/core_account_id.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
+class IdentityAPITest : public testing::Test {
+ public:
+ IdentityAPITest()
+ : prefs_(base::ThreadTaskRunnerHandle::Get()),
+ event_router_(prefs_.profile(), prefs_.prefs()),
+ api_(CreateIdentityAPI()) {
+ // IdentityAPITest requires the extended account info callbacks to be fired
+ // on account update/removal.
+ identity_env_.EnableRemovalOfExtendedAccountInfo();
+ }
+
+ ~IdentityAPITest() override { api_->Shutdown(); }
+
+ std::unique_ptr<IdentityAPI> CreateIdentityAPI() {
+ return base::WrapUnique(new IdentityAPI(prefs_.profile(),
+ identity_env_.identity_manager(),
+ prefs_.prefs(), &event_router_));
+ }
+
+ void ResetIdentityAPI(std::unique_ptr<IdentityAPI> new_api) {
+ api_ = std::move(new_api);
+ }
+
+ content::BrowserTaskEnvironment* task_env() { return &task_env_; }
+
+ signin::IdentityTestEnvironment* identity_env() { return &identity_env_; }
+
+ TestExtensionPrefs* prefs() { return &prefs_; }
+
+ IdentityAPI* api() { return api_.get(); }
+
+ private:
+ content::BrowserTaskEnvironment task_env_;
+ signin::IdentityTestEnvironment identity_env_;
+ TestExtensionPrefs prefs_;
+ EventRouter event_router_;
+ std::unique_ptr<IdentityAPI> api_;
+};
+
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
// Tests that all accounts in extensions is enabled when Dice is enabled.
-TEST(IdentityApiTest, DiceAllAccountsExtensions) {
- content::BrowserTaskEnvironment task_environment;
- TestingProfile profile;
- IdentityAPI api(&profile);
- EXPECT_FALSE(api.AreExtensionsRestrictedToPrimaryAccount());
- api.Shutdown();
+TEST_F(IdentityAPITest, DiceAllAccountsExtensions) {
+ EXPECT_FALSE(api()->AreExtensionsRestrictedToPrimaryAccount());
}
#else
-TEST(IdentityApiTest, AllAccountsExtensionDisabled) {
- content::BrowserTaskEnvironment task_environment;
- TestingProfile profile;
- IdentityAPI api(&profile);
- EXPECT_TRUE(api.AreExtensionsRestrictedToPrimaryAccount());
- api.Shutdown();
+TEST_F(IdentityAPITest, AllAccountsExtensionDisabled) {
+ EXPECT_TRUE(api()->AreExtensionsRestrictedToPrimaryAccount());
}
#endif
+TEST_F(IdentityAPITest, GetGaiaIdForExtension) {
+ std::string extension_id = prefs()->AddExtensionAndReturnId("extension");
+ std::string gaia_id =
+ identity_env()->MakeAccountAvailable("test@example.com").gaia;
+ api()->SetGaiaIdForExtension(extension_id, gaia_id);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension_id), gaia_id);
+
+ std::string another_extension_id =
+ prefs()->AddExtensionAndReturnId("another_extension");
+ EXPECT_EQ(api()->GetGaiaIdForExtension(another_extension_id), base::nullopt);
+}
+
+TEST_F(IdentityAPITest, GetGaiaIdForExtension_SurvivesShutdown) {
+ std::string extension_id = prefs()->AddExtensionAndReturnId("extension");
+ std::string gaia_id =
+ identity_env()->MakeAccountAvailable("test@example.com").gaia;
+ api()->SetGaiaIdForExtension(extension_id, gaia_id);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension_id), gaia_id);
+
+ api()->Shutdown();
+ ResetIdentityAPI(CreateIdentityAPI());
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension_id), gaia_id);
+}
+
+TEST_F(IdentityAPITest, EraseGaiaIdForExtension) {
+ std::string extension_id = prefs()->AddExtensionAndReturnId("extension");
+ CoreAccountInfo account =
+ identity_env()->MakeAccountAvailable("test@example.com");
+ api()->SetGaiaIdForExtension(extension_id, account.gaia);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension_id), account.gaia);
+
+ api()->EraseGaiaIdForExtension(extension_id);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension_id), base::nullopt);
+}
+
+TEST_F(IdentityAPITest, GaiaIdErasedAfterSignOut) {
+ std::string extension_id = prefs()->AddExtensionAndReturnId("extension");
+ CoreAccountInfo account =
+ identity_env()->MakeAccountAvailable("test@example.com");
+ api()->SetGaiaIdForExtension(extension_id, account.gaia);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension_id), account.gaia);
+
+ identity_env()->RemoveRefreshTokenForAccount(account.account_id);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension_id), base::nullopt);
+}
+
+TEST_F(IdentityAPITest, GaiaIdErasedAfterSignOut_TwoAccounts) {
+ std::string extension1_id = prefs()->AddExtensionAndReturnId("extension1");
+ CoreAccountInfo account1 =
+ identity_env()->MakeAccountAvailable("test1@example.com");
+ api()->SetGaiaIdForExtension(extension1_id, account1.gaia);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension1_id), account1.gaia);
+
+ std::string extension2_id = prefs()->AddExtensionAndReturnId("extension2");
+ CoreAccountInfo account2 =
+ identity_env()->MakeAccountAvailable("test2@example.com");
+ api()->SetGaiaIdForExtension(extension2_id, account2.gaia);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension2_id), account2.gaia);
+
+ identity_env()->RemoveRefreshTokenForAccount(account1.account_id);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension1_id), base::nullopt);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension2_id), account2.gaia);
+}
+
+TEST_F(IdentityAPITest, GaiaIdErasedAfterSignOut_AfterShutdown) {
+ std::string extension_id = prefs()->AddExtensionAndReturnId("extension");
+ CoreAccountInfo account =
+ identity_env()->MakeAccountAvailable("test@example.com");
+ api()->SetGaiaIdForExtension(extension_id, account.gaia);
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension_id), account.gaia);
+
+ api()->Shutdown();
+ ResetIdentityAPI(nullptr);
+
+ identity_env()->RemoveRefreshTokenForAccount(account.account_id);
+ ResetIdentityAPI(CreateIdentityAPI());
+ EXPECT_EQ(api()->GetGaiaIdForExtension(extension_id), base::nullopt);
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc b/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
index 03045aa8d09..41eef37347e 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -13,10 +13,13 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
+#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h"
+#include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h"
#include "chrome/browser/extensions/api/identity/identity_api.h"
#include "chrome/browser/extensions/api/identity/identity_constants.h"
#include "chrome/browser/extensions/api/identity/identity_get_accounts_function.h"
@@ -48,6 +51,7 @@
#include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/public/base/list_accounts_test_utils.h"
#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/signin_switches.h"
#include "components/signin/public/identity_manager/accounts_mutator.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
@@ -56,6 +60,7 @@
#include "content/public/test/test_utils.h"
#include "extensions/browser/api_test_utils.h"
#include "extensions/common/extension_builder.h"
+#include "google_apis/gaia/oauth2_mint_token_flow.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
@@ -172,6 +177,7 @@ class TestOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
public:
enum ResultType {
ISSUE_ADVICE_SUCCESS,
+ REMOTE_CONSENT_SUCCESS,
MINT_TOKEN_SUCCESS,
MINT_TOKEN_FAILURE,
MINT_TOKEN_BAD_CREDENTIALS,
@@ -192,6 +198,11 @@ class TestOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
delegate_->OnIssueAdviceSuccess(info);
break;
}
+ case REMOTE_CONSENT_SUCCESS: {
+ RemoteConsentResolutionData resolution_data;
+ delegate_->OnRemoteConsentSuccess(resolution_data);
+ break;
+ }
case MINT_TOKEN_SUCCESS: {
delegate_->OnMintTokenSuccess(kAccessToken, 3600);
break;
@@ -290,12 +301,12 @@ class FakeGetAuthTokenFunction : public IdentityGetAuthTokenFunction {
void set_login_ui_result(bool result) { login_ui_result_ = result; }
- void set_mint_token_flow(std::unique_ptr<OAuth2MintTokenFlow> flow) {
- flow_ = std::move(flow);
+ void push_mint_token_flow(std::unique_ptr<OAuth2MintTokenFlow> flow) {
+ flow_queue_.push(std::move(flow));
}
- void set_mint_token_result(TestOAuth2MintTokenFlow::ResultType result_type) {
- set_mint_token_flow(
+ void push_mint_token_result(TestOAuth2MintTokenFlow::ResultType result_type) {
+ push_mint_token_flow(
std::make_unique<TestOAuth2MintTokenFlow>(result_type, this));
}
@@ -316,11 +327,17 @@ class FakeGetAuthTokenFunction : public IdentityGetAuthTokenFunction {
scope_ui_oauth_error_ = oauth_error;
}
+ void set_remote_consent_gaia_id(const std::string& gaia_id) {
+ remote_consent_gaia_id_ = gaia_id;
+ }
+
bool login_ui_shown() const { return login_ui_shown_; }
bool scope_ui_shown() const { return scope_ui_shown_; }
- std::string login_access_token() const { return login_access_token_; }
+ std::vector<std::string> login_access_tokens() const {
+ return login_access_tokens_;
+ }
void StartTokenKeyAccountAccessTokenRequest() override {
if (auto_login_access_token_) {
@@ -410,16 +427,28 @@ class FakeGetAuthTokenFunction : public IdentityGetAuthTokenFunction {
}
}
+ void ShowRemoteConsentDialog(
+ const RemoteConsentResolutionData& resolution_data) override {
+ scope_ui_shown_ = true;
+ if (scope_ui_result_) {
+ OnGaiaRemoteConsentFlowApproved("fake_consent_result",
+ remote_consent_gaia_id_);
+ } else {
+ OnGaiaRemoteConsentFlowFailed(GaiaRemoteConsentFlow::WINDOW_CLOSED);
+ }
+ }
+
void StartGaiaRequest(const std::string& login_access_token) override {
- EXPECT_TRUE(login_access_token_.empty());
// Save the login token used in the mint token flow so tests can see
// what account was used.
- login_access_token_ = login_access_token;
+ login_access_tokens_.push_back(login_access_token);
IdentityGetAuthTokenFunction::StartGaiaRequest(login_access_token);
}
std::unique_ptr<OAuth2MintTokenFlow> CreateMintTokenFlow() override {
- return std::move(flow_);
+ auto flow = std::move(flow_queue_.front());
+ flow_queue_.pop();
+ return flow;
}
private:
@@ -434,9 +463,11 @@ class FakeGetAuthTokenFunction : public IdentityGetAuthTokenFunction {
bool login_ui_shown_;
bool scope_ui_shown_;
- std::unique_ptr<OAuth2MintTokenFlow> flow_;
+ std::queue<std::unique_ptr<OAuth2MintTokenFlow>> flow_queue_;
+
+ std::vector<std::string> login_access_tokens_;
- std::string login_access_token_;
+ std::string remote_consent_gaia_id_;
};
class MockQueuedMintRequest : public IdentityMintRequestQueue::Request {
@@ -684,7 +715,9 @@ class GetAuthTokenFunctionTest
: public IdentityTestWithSignin,
public signin::IdentityManager::DiagnosticsObserver {
public:
- GetAuthTokenFunctionTest() = default;
+ GetAuthTokenFunctionTest() {
+ scoped_feature_list_.InitAndEnableFeature(switches::kOAuthRemoteConsent);
+ }
std::string IssueLoginAccessTokenForAccount(const CoreAccountId& account_id) {
std::string access_token = "access_token-" + account_id.ToString();
@@ -753,6 +786,10 @@ class GetAuthTokenFunctionTest
id_api()->SetCachedToken(key, token_data);
}
+ void SetCachedGaiaId(const std::string& gaia_id) {
+ id_api()->SetGaiaIdForExtension(extension_id_, gaia_id);
+ }
+
const IdentityTokenCacheValue& GetCachedToken(
const CoreAccountId& account_id) {
ExtensionTokenKey key(
@@ -761,6 +798,10 @@ class GetAuthTokenFunctionTest
return id_api()->GetCachedToken(key);
}
+ base::Optional<std::string> GetCachedGaiaId() {
+ return id_api()->GetGaiaIdForExtension(extension_id_);
+ }
+
void QueueRequestStart(IdentityMintRequestQueue::MintType type,
IdentityMintRequestQueue::Request* request) {
ExtensionTokenKey key(extension_id_, GetPrimaryAccountId(), oauth_scopes_);
@@ -779,7 +820,7 @@ class GetAuthTokenFunctionTest
// signin::IdentityManager::DiagnosticsObserver:
void OnAccessTokenRequested(const CoreAccountId& account_id,
const std::string& consumer_id,
- const identity::ScopeSet& scopes) override {
+ const signin::ScopeSet& scopes) override {
if (on_access_token_requested_.is_null())
return;
std::move(on_access_token_requested_).Run();
@@ -787,6 +828,8 @@ class GetAuthTokenFunctionTest
std::string extension_id_;
std::set<std::string> oauth_scopes_;
+
+ base::test::ScopedFeatureList scoped_feature_list_;
};
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoClientId) {
@@ -860,7 +903,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveMintFailure) {
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
std::string error =
utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
EXPECT_TRUE(base::StartsWith(error, errors::kAuthFailure,
@@ -887,7 +930,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
std::string error =
utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
EXPECT_EQ(std::string(errors::kNoGrant), error);
@@ -903,7 +946,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(
+ func->push_mint_token_result(
TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS);
std::string error =
utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
@@ -918,7 +961,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(
+ func->push_mint_token_result(
TestOAuth2MintTokenFlow::MINT_TOKEN_SERVICE_ERROR);
std::string error =
utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
@@ -933,7 +976,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(
+ func->push_mint_token_result(
TestOAuth2MintTokenFlow::MINT_TOKEN_SERVICE_ERROR);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
@@ -953,7 +996,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_login_ui_result(true);
- func->set_mint_token_result(
+ func->push_mint_token_result(
TestOAuth2MintTokenFlow::MINT_TOKEN_SERVICE_ERROR);
// The function should complete with an error, showing the signin UI only
@@ -972,7 +1015,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoOptionsSuccess) {
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
std::unique_ptr<base::Value> value(
utils::RunFunctionAndReturnSingleResult(func.get(), "[]", browser()));
std::string access_token;
@@ -989,7 +1032,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveSuccess) {
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
std::unique_ptr<base::Value> value(
utils::RunFunctionAndReturnSingleResult(func.get(), "[{}]", browser()));
std::string access_token;
@@ -1021,7 +1064,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(
+ func->push_mint_token_result(
TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
@@ -1041,7 +1084,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_login_ui_result(true);
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
EXPECT_TRUE(base::StartsWith(error, errors::kAuthFailure,
@@ -1055,7 +1098,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_login_ui_result(true);
- func->set_mint_token_result(
+ func->push_mint_token_result(
TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
@@ -1086,7 +1129,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_login_ui_result(true);
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
std::unique_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
func.get(), "[{\"interactive\": true}]", browser()));
std::string access_token;
@@ -1101,7 +1144,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_login_ui_result(true);
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
@@ -1116,7 +1159,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(extension.get());
func->set_login_ui_result(true);
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
std::unique_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
func.get(), "[{\"interactive\": true}]", browser()));
@@ -1132,7 +1175,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveApprovalAborted) {
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
@@ -1146,7 +1189,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_failure(GaiaWebAuthFlow::LOAD_FAILED);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
@@ -1160,7 +1203,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_failure(GaiaWebAuthFlow::INVALID_REDIRECT);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
@@ -1174,7 +1217,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_service_error(
GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
std::string error = utils::RunFunctionAndReturnError(
@@ -1190,7 +1233,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_service_error(
GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR));
std::string error = utils::RunFunctionAndReturnError(
@@ -1210,7 +1253,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_login_ui_result(true);
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_service_error(
GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR));
@@ -1246,7 +1289,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
// Make sure we don't get a cached issue_advice result, which would cause
// flow to be leaked.
id_api()->EraseAllCachedTokens();
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_oauth_error(it->first);
std::string error = utils::RunFunctionAndReturnError(
func.get(), "[{\"interactive\": true}]", browser());
@@ -1261,7 +1304,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveApprovalSuccess) {
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
std::unique_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
func.get(), "[{\"interactive\": true}]", browser()));
@@ -1286,7 +1329,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
SignIn("primary@example.com");
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_service_error(
GoogleServiceAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
func->set_login_ui_result(false);
@@ -1331,7 +1374,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveQueue) {
testing::Mock::VerifyAndClearExpectations(func.get());
// The flow will be created after the first queued request clears.
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
QueueRequestComplete(type, &queued_request);
@@ -1359,7 +1402,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueue) {
// The real request will start processing, but wait in the queue behind
// the blocker.
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
// Verify that we have fetched the login token and run the first flow.
testing::Mock::VerifyAndClearExpectations(func.get());
@@ -1393,7 +1436,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueueShutdown) {
// The real request will start processing, but wait in the queue behind
// the blocker.
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
// Verify that we have fetched the login token and run the first flow.
testing::Mock::VerifyAndClearExpectations(func.get());
@@ -1414,7 +1457,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveShutdown) {
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(extension.get());
- func->set_mint_token_flow(std::make_unique<TestHangOAuth2MintTokenFlow>());
+ func->push_mint_token_flow(std::make_unique<TestHangOAuth2MintTokenFlow>());
RunFunctionAsync(func.get(), "[{\"interactive\": false}]");
// After the request is canceled, the function will complete.
@@ -1455,8 +1498,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveCacheHit) {
func->set_extension(extension.get());
// pre-populate the cache with a token
- IdentityTokenCacheValue token(kAccessToken,
- base::TimeDelta::FromSeconds(3600));
+ IdentityTokenCacheValue token = IdentityTokenCacheValue::CreateToken(
+ kAccessToken, base::TimeDelta::FromSeconds(3600));
SetCachedToken(token);
// Get a token. Should not require a GAIA request.
@@ -1491,8 +1534,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
func->set_extension(extension.get());
// pre-populate the cache with a token
- IdentityTokenCacheValue token(kAccessToken,
- base::TimeDelta::FromSeconds(3600));
+ IdentityTokenCacheValue token = IdentityTokenCacheValue::CreateToken(
+ kAccessToken, base::TimeDelta::FromSeconds(3600));
SetCachedTokenForAccount(account_info.account_id, token);
if (id_api()->AreExtensionsRestrictedToPrimaryAccount()) {
@@ -1522,7 +1565,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
// pre-populate the cache with advice
IssueAdviceInfo info;
- IdentityTokenCacheValue token(info);
+ IdentityTokenCacheValue token =
+ IdentityTokenCacheValue::CreateIssueAdvice(info);
SetCachedToken(token);
// Should return an error without a GAIA request.
@@ -1549,12 +1593,12 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveCacheHit) {
// The real request will start processing, but wait in the queue behind
// the blocker.
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
// Populate the cache with a token while the request is blocked.
- IdentityTokenCacheValue token(kAccessToken,
- base::TimeDelta::FromSeconds(3600));
+ IdentityTokenCacheValue token = IdentityTokenCacheValue::CreateToken(
+ kAccessToken, base::TimeDelta::FromSeconds(3600));
SetCachedToken(token);
// When we wake up the request, it returns the cached token without
@@ -1579,14 +1623,14 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, LoginInvalidatesTokenCache) {
func->set_extension(extension.get());
// pre-populate the cache with a token
- IdentityTokenCacheValue token(kAccessToken,
- base::TimeDelta::FromSeconds(3600));
+ IdentityTokenCacheValue token = IdentityTokenCacheValue::CreateToken(
+ kAccessToken, base::TimeDelta::FromSeconds(3600));
SetCachedToken(token);
// Because the user is not signed in, the token will be removed,
// and we'll hit GAIA for new tokens.
func->set_login_ui_result(true);
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
std::unique_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
func.get(), "[{\"interactive\": true}]", browser()));
@@ -1598,6 +1642,60 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, LoginInvalidatesTokenCache) {
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
GetCachedToken(CoreAccountId()).status());
}
+
+// ChromeOS supports primary accounts only. So the test isn't applicable on that
+// platform.
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+ IssueAdviceInvalidatesGaiaIdCache) {
+ SignIn("primary@example.com");
+ AccountInfo secondary_account_info =
+ identity_test_env()->MakeAccountAvailable("secondary@example.com");
+
+ scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
+ scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+ func->set_extension(extension.get());
+
+ // Pre-populate the gaia id cache.
+ SetCachedGaiaId(secondary_account_info.gaia);
+
+ // The user revoked their token and must give a consent again. Gaia disabled
+ // the new flow for the secondary account.
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+
+ std::unique_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
+ func.get(), "[{\"interactive\": true}]", browser()));
+ ASSERT_TRUE(value->is_string());
+ EXPECT_EQ(kAccessToken, value->GetString());
+ EXPECT_TRUE(func->scope_ui_shown());
+ EXPECT_FALSE(GetCachedGaiaId().has_value());
+}
+
+// ChromeOS supports primary accounts only. So the test isn't applicable on that
+// platform.
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+ IssueAdviceFailureInvalidatesGaiaIdCache) {
+ SignIn("primary@example.com");
+ AccountInfo secondary_account_info =
+ identity_test_env()->MakeAccountAvailable("secondary@example.com");
+
+ scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
+ scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
+ func->set_extension(extension.get());
+
+ // Pre-populate the gaia id cache.
+ SetCachedGaiaId(secondary_account_info.gaia);
+
+ // The user revoked their token and must give a consent again. Gaia disabled
+ // the new flow for the secondary account.
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
+
+ std::string error = utils::RunFunctionAndReturnError(
+ func.get(), "[{\"interactive\": true}]", browser());
+ EXPECT_EQ(std::string(errors::kUserRejected), error);
+ EXPECT_TRUE(func->scope_ui_shown());
+ EXPECT_FALSE(GetCachedGaiaId().has_value());
+}
#endif
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithChromeClientId) {
@@ -1627,7 +1725,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, IdentityAPIShutdown) {
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
// Have GetAuthTokenFunction actually make the request for the access token to
// ensure that the function doesn't immediately succeed.
@@ -1648,14 +1746,14 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<const Extension> extension1(
CreateExtension(CLIENT_ID | SCOPES));
func1->set_extension(extension1.get());
- func1->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func1->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
func1->set_auto_login_access_token(false);
scoped_refptr<FakeGetAuthTokenFunction> func2(new FakeGetAuthTokenFunction());
scoped_refptr<const Extension> extension2(
CreateExtension(CLIENT_ID | SCOPES));
func2->set_extension(extension2.get());
- func2->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func2->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
func2->set_auto_login_access_token(false);
// Run both functions. Note that it's necessary to use AsyncFunctionRunner
@@ -1683,7 +1781,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueToken) {
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
// Have GetAuthTokenFunction actually make the request for the access token.
func->set_auto_login_access_token(false);
@@ -1702,7 +1800,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueToken) {
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken(CoreAccountId()).status());
- EXPECT_EQ(primary_account_access_token, func->login_access_token());
+ EXPECT_THAT(func->login_access_tokens(),
+ testing::ElementsAre(primary_account_access_token));
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueTokenFailure) {
@@ -1711,7 +1810,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueTokenFailure) {
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
// Have GetAuthTokenFunction actually make the request for the access token.
func->set_auto_login_access_token(false);
@@ -1741,7 +1840,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
func->set_auto_login_access_token(false);
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
base::RunLoop run_loop;
on_access_token_requested_ = run_loop.QuitClosure();
@@ -1757,7 +1856,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken(CoreAccountId()).status());
- EXPECT_EQ(primary_account_access_token, func->login_access_token());
+ EXPECT_THAT(func->login_access_tokens(),
+ testing::ElementsAre(primary_account_access_token));
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1769,7 +1869,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
func->set_auto_login_access_token(false);
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
base::RunLoop run_loop;
on_access_token_requested_ = run_loop.QuitClosure();
@@ -1787,7 +1887,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken(CoreAccountId()).status());
- EXPECT_EQ(primary_account_access_token, func->login_access_token());
+ EXPECT_THAT(func->login_access_tokens(),
+ testing::ElementsAre(primary_account_access_token));
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1806,7 +1907,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
func->set_auto_login_access_token(false);
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
base::RunLoop run_loop;
on_access_token_requested_ = run_loop.QuitClosure();
@@ -1824,7 +1925,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_EQ(std::string(kAccessToken), access_token);
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken(secondary_account_id).status());
- EXPECT_EQ(secondary_account_access_token, func->login_access_token());
+ EXPECT_THAT(func->login_access_tokens(),
+ testing::ElementsAre(secondary_account_access_token));
}
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1854,7 +1956,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
std::string error = utils::RunFunctionAndReturnError(
func.get(),
"[{\"account\": { \"id\": \"gaia_id_for_secondary_example.com\" } }]",
@@ -1896,7 +1998,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
std::string error = utils::RunFunctionAndReturnError(
func.get(),
@@ -1908,6 +2010,72 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_TRUE(func->scope_ui_shown());
}
+// Tests that Chrome remembers user's choice of an account at the end of the
+// remote consent flow. Chrome should reuse this account in the next
+// getAuthToken() call for the same extension.
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+ MultiSecondaryInteractiveRemoteConsent) {
+ // This test is only relevant if extensions see all accounts.
+ if (id_api()->AreExtensionsRestrictedToPrimaryAccount())
+ return;
+
+ CoreAccountId primary_account_id = SignIn("primary@example.com");
+ AccountInfo secondary_account =
+ identity_test_env()->MakeAccountAvailable("secondary@example.com");
+ const extensions::Extension* extension = CreateExtension(CLIENT_ID | SCOPES);
+
+ {
+ scoped_refptr<FakeGetAuthTokenFunction> func(
+ new FakeGetAuthTokenFunction());
+ func->set_extension(extension);
+ func->push_mint_token_result(
+ TestOAuth2MintTokenFlow::REMOTE_CONSENT_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->set_remote_consent_gaia_id(secondary_account.gaia);
+ // Have GetAuthTokenFunction actually make the request for the access token.
+ func->set_auto_login_access_token(false);
+
+ base::RunLoop run_loop;
+ on_access_token_requested_ = run_loop.QuitClosure();
+ RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
+ run_loop.Run();
+
+ // The first request will be for the primary account and the second one for
+ // the account that has been returned in result of the remote consent.
+ std::string primary_account_access_token =
+ IssueLoginAccessTokenForAccount(primary_account_id);
+ std::string secondary_account_access_token =
+ IssueLoginAccessTokenForAccount(secondary_account.account_id);
+
+ std::unique_ptr<base::Value> value(WaitForSingleResult(func.get()));
+ EXPECT_TRUE(value->is_string());
+ std::string access_token = value->GetString();
+ EXPECT_EQ(kAccessToken, access_token);
+ EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
+ GetCachedToken(secondary_account.account_id).status());
+ EXPECT_EQ(secondary_account.gaia,
+ id_api()->GetGaiaIdForExtension(extension->id()));
+ EXPECT_THAT(func->login_access_tokens(),
+ testing::ElementsAre(primary_account_access_token,
+ secondary_account_access_token));
+ }
+
+ {
+ // Check that the next function call returns a token for the same account
+ // from the cache.
+ scoped_refptr<FakeGetAuthTokenFunction> func(
+ new FakeGetAuthTokenFunction());
+ func->set_extension(extension);
+ std::unique_ptr<base::Value> value(
+ utils::RunFunctionAndReturnSingleResult(func.get(), "[{}]", browser()));
+ EXPECT_TRUE(value->is_string());
+ std::string access_token = value->GetString();
+ EXPECT_EQ(std::string(kAccessToken), access_token);
+ EXPECT_FALSE(func->login_ui_shown());
+ EXPECT_FALSE(func->scope_ui_shown());
+ }
+}
+
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
MultiSecondaryInteractiveInvalidToken) {
// Setup a secondary account with no valid refresh token, and try to get a
@@ -1922,7 +2090,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(extension.get());
func->set_login_ui_result(true);
- func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
const char kFunctionParams[] =
"[{\"account\": { \"id\": \"gaia_id_for_secondary@example.com\" }, "
@@ -1953,7 +2121,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesDefault) {
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
std::unique_ptr<base::Value> value(
utils::RunFunctionAndReturnSingleResult(func.get(), "[{}]", browser()));
std::string access_token;
@@ -1982,7 +2150,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmail) {
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
std::unique_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
func.get(), "[{\"scopes\": [\"email\"]}]", browser()));
std::string access_token;
@@ -1999,7 +2167,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmailFooBar) {
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
func->set_extension(extension.get());
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
std::unique_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
func.get(), "[{\"scopes\": [\"email\", \"foo\", \"bar\"]}]", browser()));
std::string access_token;
@@ -2076,7 +2244,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionPublicSessionTest,
base::WrapUnique(user_manager_));
scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
func->set_extension(CreateTestExtension("ljacajndfccfgnfohlgkdphmbnpkjflk"));
- func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
+ func->push_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
std::unique_ptr<base::Value> value(
utils::RunFunctionAndReturnSingleResult(func.get(), "[{}]", browser()));
std::string access_token;
@@ -2123,7 +2291,8 @@ IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NotFound) {
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, Advice) {
IssueAdviceInfo info;
- IdentityTokenCacheValue advice(info);
+ IdentityTokenCacheValue advice =
+ IdentityTokenCacheValue::CreateIssueAdvice(info);
SetCachedToken(advice);
EXPECT_TRUE(InvalidateDefaultToken());
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
@@ -2131,8 +2300,8 @@ IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, Advice) {
}
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NonMatchingToken) {
- IdentityTokenCacheValue token("non_matching_token",
- base::TimeDelta::FromSeconds(3600));
+ IdentityTokenCacheValue token = IdentityTokenCacheValue::CreateToken(
+ "non_matching_token", base::TimeDelta::FromSeconds(3600));
SetCachedToken(token);
EXPECT_TRUE(InvalidateDefaultToken());
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
@@ -2141,8 +2310,8 @@ IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NonMatchingToken) {
}
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, MatchingToken) {
- IdentityTokenCacheValue token(kAccessToken,
- base::TimeDelta::FromSeconds(3600));
+ IdentityTokenCacheValue token = IdentityTokenCacheValue::CreateToken(
+ kAccessToken, base::TimeDelta::FromSeconds(3600));
SetCachedToken(token);
EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
GetCachedToken().status());
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_constants.cc b/chromium/chrome/browser/extensions/api/identity/identity_constants.cc
index fefac477308..657911b1d57 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_constants.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_constants.cc
@@ -18,6 +18,8 @@ const char kInteractionRequired[] = "User interaction required.";
const char kInvalidRedirect[] = "Did not redirect to the right URL.";
const char kOffTheRecord[] = "Identity API is disabled in incognito windows.";
const char kPageLoadFailure[] = "Authorization page could not be loaded.";
+const char kSetAccountsInCookieFailure[] = "Account cookies could not be set.";
+const char kInvalidConsentResult[] = "Returned an invalid consent result.";
const char kCanceled[] = "canceled";
const int kCachedIssueAdviceTTLSeconds = 1;
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_constants.h b/chromium/chrome/browser/extensions/api/identity/identity_constants.h
index e849ccd2222..67079d6de49 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_constants.h
+++ b/chromium/chrome/browser/extensions/api/identity/identity_constants.h
@@ -19,6 +19,8 @@ extern const char kInteractionRequired[];
extern const char kInvalidRedirect[];
extern const char kOffTheRecord[];
extern const char kPageLoadFailure[];
+extern const char kSetAccountsInCookieFailure[];
+extern const char kInvalidConsentResult[];
extern const char kCanceled[];
extern const int kCachedIssueAdviceTTLSeconds;
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
index 676b41285ce..0079eee80eb 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/location.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -22,24 +23,27 @@
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
+#include "chrome/common/channel_info.h"
#include "chrome/common/extensions/api/identity.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/base/signin_pref_names.h"
+#include "components/signin/public/base/signin_switches.h"
#include "components/signin/public/identity_manager/access_token_info.h"
#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
+#include "components/signin/public/identity_manager/scope_set.h"
+#include "components/version_info/version_info.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/extension_l10n_util.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_urls.h"
-#include "services/identity/public/cpp/scope_set.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/app_mode/app_mode_utils.h"
#include "chrome/browser/chromeos/login/session/user_session_manager.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
-#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
-#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
+#include "chrome/browser/device_identity/device_oauth2_token_service.h"
+#include "chrome/browser/device_identity/device_oauth2_token_service_factory.h"
#include "components/user_manager/user_manager.h"
#include "google_apis/gaia/gaia_constants.h"
#endif
@@ -65,6 +69,14 @@ bool IsBrowserSigninAllowed(Profile* profile) {
return profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed);
}
+std::string GetOAuth2MintTokenFlowVersion() {
+ return version_info::GetVersionNumber();
+}
+
+std::string GetOAuth2MintTokenFlowChannel() {
+ return version_info::GetChannelString(chrome::GetChannel());
+}
+
} // namespace
IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
@@ -83,27 +95,23 @@ IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
}
IdentityGetAuthTokenFunction::~IdentityGetAuthTokenFunction() {
- TRACE_EVENT_ASYNC_END0("identity", "IdentityGetAuthTokenFunction", this);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("identity", "IdentityGetAuthTokenFunction",
+ this);
}
-bool IdentityGetAuthTokenFunction::RunAsync() {
- TRACE_EVENT_ASYNC_BEGIN1("identity",
- "IdentityGetAuthTokenFunction",
- this,
- "extension",
- extension()->id());
+ExtensionFunction::ResponseAction IdentityGetAuthTokenFunction::Run() {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("identity", "IdentityGetAuthTokenFunction",
+ this, "extension", extension()->id());
if (GetProfile()->IsOffTheRecord()) {
- error_ = identity_constants::kOffTheRecord;
- return false;
+ return RespondNow(Error(identity_constants::kOffTheRecord));
}
std::unique_ptr<api::identity::GetAuthToken::Params> params(
api::identity::GetAuthToken::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
- interactive_ = params->details.get() &&
- params->details->interactive.get() &&
- *params->details->interactive;
+ interactive_ = params->details.get() && params->details->interactive.get() &&
+ *params->details->interactive;
should_prompt_for_scopes_ = interactive_;
should_prompt_for_signin_ =
@@ -114,8 +122,7 @@ bool IdentityGetAuthTokenFunction::RunAsync() {
// Check that the necessary information is present in the manifest.
oauth2_client_id_ = GetOAuth2ClientId();
if (oauth2_client_id_.empty()) {
- error_ = identity_constants::kInvalidClientId;
- return false;
+ return RespondNow(Error(identity_constants::kInvalidClientId));
}
std::set<std::string> scopes(oauth2_info.scopes.begin(),
@@ -133,13 +140,19 @@ bool IdentityGetAuthTokenFunction::RunAsync() {
}
if (scopes.empty()) {
- error_ = identity_constants::kInvalidScopes;
- return false;
+ return RespondNow(Error(identity_constants::kInvalidScopes));
}
token_key_.scopes = scopes;
token_key_.extension_id = extension()->id();
+ if (gaia_id.empty()) {
+ gaia_id = IdentityAPI::GetFactoryInstance()
+ ->Get(GetProfile())
+ ->GetGaiaIdForExtension(token_key_.extension_id)
+ .value_or("");
+ }
+
// From here on out, results must be returned asynchronously.
StartAsyncRun();
@@ -159,7 +172,7 @@ bool IdentityGetAuthTokenFunction::RunAsync() {
weak_ptr_factory_.GetWeakPtr(), gaia_id));
}
- return true;
+ return RespondLater();
}
void IdentityGetAuthTokenFunction::GetAuthTokenForPrimaryAccount(
@@ -282,29 +295,23 @@ void IdentityGetAuthTokenFunction::StartAsyncRun() {
&IdentityGetAuthTokenFunction::OnIdentityAPIShutdown, this));
}
-void IdentityGetAuthTokenFunction::CompleteAsyncRun(bool success) {
+void IdentityGetAuthTokenFunction::CompleteAsyncRun(ResponseValue response) {
identity_api_shutdown_subscription_.reset();
- SendResponse(success);
+ Respond(std::move(response));
Release(); // Balanced in StartAsyncRun
}
void IdentityGetAuthTokenFunction::CompleteFunctionWithResult(
const std::string& access_token) {
- SetResult(std::make_unique<base::Value>(access_token));
- CompleteAsyncRun(true);
+ CompleteAsyncRun(OneArgument(std::make_unique<base::Value>(access_token)));
}
void IdentityGetAuthTokenFunction::CompleteFunctionWithError(
const std::string& error) {
- TRACE_EVENT_ASYNC_STEP_PAST1("identity",
- "IdentityGetAuthTokenFunction",
- this,
- "CompleteFunctionWithError",
- "error",
- error);
- error_ = error;
- CompleteAsyncRun(false);
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("identity", "CompleteFunctionWithError",
+ this, "error", error);
+ CompleteAsyncRun(Error(error));
}
bool IdentityGetAuthTokenFunction::ShouldStartSigninFlow() {
@@ -335,9 +342,7 @@ void IdentityGetAuthTokenFunction::StartSigninFlow() {
// re-establish credentials. Let the global error popup handle everything.
// In kiosk mode, interactive sign-in is not supported.
SigninFailed();
- return;
-#endif
-
+#else
if (g_browser_process->IsShuttingDown()) {
// The login prompt cannot be displayed when the browser process is shutting
// down.
@@ -364,6 +369,7 @@ void IdentityGetAuthTokenFunction::StartSigninFlow() {
scoped_identity_manager_observer_.Add(identity_manager);
ShowExtensionLoginPrompt();
+#endif
}
void IdentityGetAuthTokenFunction::StartMintTokenFlow(
@@ -374,6 +380,8 @@ void IdentityGetAuthTokenFunction::StartMintTokenFlow(
DCHECK(IdentityManagerFactory::GetForProfile(GetProfile())
->HasAccountWithRefreshToken(token_key_.account_id));
#endif
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("identity", "MintTokenFlow", this, "type",
+ type);
mint_token_flow_type_ = type;
@@ -390,6 +398,8 @@ void IdentityGetAuthTokenFunction::StartMintTokenFlow(
CompleteFunctionWithError(identity_constants::kNoGrant);
return;
}
+ // TODO(https://crbug.com/1026237): figure out whether this can be ignored
+ // when running the remote consent approval.
if (!id_api->mint_queue()->empty(
IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE, token_key_)) {
// Another call is going through a consent UI.
@@ -397,10 +407,13 @@ void IdentityGetAuthTokenFunction::StartMintTokenFlow(
return;
}
}
+
id_api->mint_queue()->RequestStart(type, token_key_, this);
}
void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() {
+ TRACE_EVENT_NESTABLE_ASYNC_END0("identity", "MintTokenFlow", this);
+
IdentityMintRequestQueue::MintType type = mint_token_flow_type_;
extensions::IdentityAPI::GetFactoryInstance()
@@ -411,18 +424,13 @@ void IdentityGetAuthTokenFunction::CompleteMintTokenFlow() {
void IdentityGetAuthTokenFunction::StartMintToken(
IdentityMintRequestQueue::MintType type) {
- TRACE_EVENT_ASYNC_STEP_PAST1("identity",
- "IdentityGetAuthTokenFunction",
- this,
- "StartMintToken",
- "type",
- type);
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("identity", "StartMintToken", this,
+ "type", type);
const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension());
IdentityAPI* id_api = IdentityAPI::GetFactoryInstance()->Get(GetProfile());
IdentityTokenCacheValue cache_entry = id_api->GetCachedToken(token_key_);
- IdentityTokenCacheValue::CacheValueStatus cache_status =
- cache_entry.status();
+ IdentityTokenCacheValue::CacheValueStatus cache_status = cache_entry.status();
if (type == IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE) {
switch (cache_status) {
@@ -471,28 +479,55 @@ void IdentityGetAuthTokenFunction::StartMintToken(
issue_advice_ = cache_entry.issue_advice();
StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
break;
+
+ case IdentityTokenCacheValue::CACHE_STATUS_REMOTE_CONSENT:
+ CompleteMintTokenFlow();
+ should_prompt_for_signin_ = false;
+ resolution_data_ = cache_entry.resolution_data();
+ StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
+ break;
+
+ case IdentityTokenCacheValue::CACHE_STATUS_REMOTE_CONSENT_APPROVED:
+ consent_result_ = cache_entry.consent_result();
+ should_prompt_for_scopes_ = false;
+ should_prompt_for_signin_ = false;
+ gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE;
+ StartTokenKeyAccountAccessTokenRequest();
+ break;
}
} else {
DCHECK(type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
- if (cache_status == IdentityTokenCacheValue::CACHE_STATUS_TOKEN) {
- CompleteMintTokenFlow();
- CompleteFunctionWithResult(cache_entry.token());
- } else {
- ShowOAuthApprovalDialog(issue_advice_);
+ switch (cache_status) {
+ case IdentityTokenCacheValue::CACHE_STATUS_TOKEN:
+ CompleteMintTokenFlow();
+ CompleteFunctionWithResult(cache_entry.token());
+ break;
+ case IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
+ case IdentityTokenCacheValue::CACHE_STATUS_ADVICE:
+ ShowOAuthApprovalDialog(issue_advice_);
+ break;
+ case IdentityTokenCacheValue::CACHE_STATUS_REMOTE_CONSENT:
+ ShowRemoteConsentDialog(resolution_data_);
+ break;
+ case IdentityTokenCacheValue::CACHE_STATUS_REMOTE_CONSENT_APPROVED:
+ consent_result_ = cache_entry.consent_result();
+ should_prompt_for_scopes_ = false;
+ should_prompt_for_signin_ = false;
+ gaia_mint_token_mode_ = OAuth2MintTokenFlow::MODE_MINT_TOKEN_NO_FORCE;
+ StartTokenKeyAccountAccessTokenRequest();
+ break;
}
}
}
void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
- const std::string& access_token, int time_to_live) {
- TRACE_EVENT_ASYNC_STEP_PAST0("identity",
- "IdentityGetAuthTokenFunction",
- this,
- "OnMintTokenSuccess");
-
- IdentityTokenCacheValue token(access_token,
- base::TimeDelta::FromSeconds(time_to_live));
+ const std::string& access_token,
+ int time_to_live) {
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "OnMintTokenSuccess", this);
+
+ IdentityTokenCacheValue token = IdentityTokenCacheValue::CreateToken(
+ access_token, base::TimeDelta::FromSeconds(time_to_live));
IdentityAPI::GetFactoryInstance()
->Get(GetProfile())
->SetCachedToken(token_key_, token);
@@ -503,12 +538,8 @@ void IdentityGetAuthTokenFunction::OnMintTokenSuccess(
void IdentityGetAuthTokenFunction::OnMintTokenFailure(
const GoogleServiceAuthError& error) {
- TRACE_EVENT_ASYNC_STEP_PAST1("identity",
- "IdentityGetAuthTokenFunction",
- this,
- "OnMintTokenFailure",
- "error",
- error.ToString());
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("identity", "OnMintTokenFailure", this,
+ "error", error.ToString());
CompleteMintTokenFlow();
switch (error.state()) {
case GoogleServiceAuthError::SERVICE_ERROR:
@@ -529,20 +560,22 @@ void IdentityGetAuthTokenFunction::OnMintTokenFailure(
break;
}
- CompleteFunctionWithError(
- std::string(identity_constants::kAuthFailure) + error.ToString());
+ CompleteFunctionWithError(std::string(identity_constants::kAuthFailure) +
+ error.ToString());
}
void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
const IssueAdviceInfo& issue_advice) {
- TRACE_EVENT_ASYNC_STEP_PAST0("identity",
- "IdentityGetAuthTokenFunction",
- this,
- "OnIssueAdviceSuccess");
-
- IdentityAPI::GetFactoryInstance()
- ->Get(GetProfile())
- ->SetCachedToken(token_key_, IdentityTokenCacheValue(issue_advice));
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "OnIssueAdviceSuccess", this);
+
+ IdentityAPI* identity_api =
+ IdentityAPI::GetFactoryInstance()->Get(GetProfile());
+ identity_api->SetCachedToken(
+ token_key_, IdentityTokenCacheValue::CreateIssueAdvice(issue_advice));
+ // IssueAdvice doesn't communicate back to Chrome which account has been
+ // chosen by the user. Cached gaia id may contain incorrect information so
+ // it's better to remove it.
+ identity_api->EraseGaiaIdForExtension(token_key_.extension_id);
CompleteMintTokenFlow();
should_prompt_for_signin_ = false;
@@ -552,6 +585,21 @@ void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
}
+void IdentityGetAuthTokenFunction::OnRemoteConsentSuccess(
+ const RemoteConsentResolutionData& resolution_data) {
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "OnRemoteConsentSuccess",
+ this);
+
+ IdentityAPI::GetFactoryInstance()
+ ->Get(GetProfile())
+ ->SetCachedToken(token_key_, IdentityTokenCacheValue::CreateRemoteConsent(
+ resolution_data));
+ should_prompt_for_signin_ = false;
+ resolution_data_ = resolution_data;
+ CompleteMintTokenFlow();
+ StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE);
+}
+
void IdentityGetAuthTokenFunction::OnRefreshTokenUpdatedForAccount(
const CoreAccountInfo& account_info) {
if (account_listening_mode_ != AccountListeningMode::kListeningTokens)
@@ -575,8 +623,7 @@ void IdentityGetAuthTokenFunction::OnPrimaryAccountSet(
if (account_listening_mode_ != AccountListeningMode::kListeningPrimaryAccount)
return;
- TRACE_EVENT_ASYNC_STEP_PAST0("identity", "IdentityGetAuthTokenFunction", this,
- "OnPrimaryAccountSet");
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "OnPrimaryAccountSet", this);
DCHECK(token_key_.account_id.empty());
token_key_.account_id = primary_account_info.account_id;
@@ -591,10 +638,7 @@ void IdentityGetAuthTokenFunction::OnPrimaryAccountSet(
}
void IdentityGetAuthTokenFunction::SigninFailed() {
- TRACE_EVENT_ASYNC_STEP_PAST0("identity",
- "IdentityGetAuthTokenFunction",
- this,
- "SigninFailed");
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "SigninFailed", this);
CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
}
@@ -626,7 +670,7 @@ void IdentityGetAuthTokenFunction::OnGaiaFlowFailure(
}
}
error = std::string(identity_constants::kAuthFailure) +
- service_error.ToString();
+ service_error.ToString();
break;
case GaiaWebAuthFlow::OAUTH_ERROR:
@@ -649,13 +693,10 @@ void IdentityGetAuthTokenFunction::OnGaiaFlowFailure(
void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted(
const std::string& access_token,
const std::string& expiration) {
- TRACE_EVENT_ASYNC_STEP_PAST0("identity",
- "IdentityGetAuthTokenFunction",
- this,
- "OnGaiaFlowCompleted");
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "OnGaiaFlowCompleted", this);
int time_to_live;
if (!expiration.empty() && base::StringToInt(expiration, &time_to_live)) {
- IdentityTokenCacheValue token_value(
+ IdentityTokenCacheValue token_value = IdentityTokenCacheValue::CreateToken(
access_token, base::TimeDelta::FromSeconds(time_to_live));
IdentityAPI::GetFactoryInstance()
->Get(GetProfile())
@@ -666,6 +707,65 @@ void IdentityGetAuthTokenFunction::OnGaiaFlowCompleted(
CompleteFunctionWithResult(access_token);
}
+void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlow::Failure failure) {
+ CompleteMintTokenFlow();
+ std::string error;
+
+ switch (failure) {
+ case GaiaRemoteConsentFlow::WINDOW_CLOSED:
+ error = identity_constants::kUserRejected;
+ break;
+
+ case GaiaRemoteConsentFlow::SET_ACCOUNTS_IN_COOKIE_FAILED:
+ error = identity_constants::kSetAccountsInCookieFailure;
+ break;
+
+ case GaiaRemoteConsentFlow::LOAD_FAILED:
+ error = identity_constants::kPageLoadFailure;
+ break;
+
+ case GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT:
+ error = identity_constants::kInvalidConsentResult;
+ break;
+
+ case GaiaRemoteConsentFlow::NO_GRANT:
+ error = identity_constants::kNoGrant;
+ break;
+ }
+
+ CompleteFunctionWithError(error);
+}
+
+void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowApproved(
+ const std::string& consent_result,
+ const std::string& gaia_id) {
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(
+ "identity", "OnGaiaRemoteConsentFlowApproved", this, "gaia_id", gaia_id);
+ DCHECK(!consent_result.empty());
+
+ CompleteMintTokenFlow();
+ base::Optional<AccountInfo> account =
+ IdentityManagerFactory::GetForProfile(GetProfile())
+ ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(gaia_id);
+ if (!account) {
+ CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+ return;
+ }
+
+ IdentityAPI* id_api = IdentityAPI::GetFactoryInstance()->Get(GetProfile());
+ id_api->SetGaiaIdForExtension(token_key_.extension_id, gaia_id);
+
+ token_key_.account_id = account->account_id;
+ consent_result_ = consent_result;
+ should_prompt_for_scopes_ = false;
+ should_prompt_for_signin_ = false;
+ id_api->SetCachedToken(
+ token_key_,
+ IdentityTokenCacheValue::CreateRemoteConsentApproved(consent_result));
+ StartMintTokenFlow(IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE);
+}
+
void IdentityGetAuthTokenFunction::OnGetAccessTokenComplete(
const base::Optional<std::string>& access_token,
base::Time expiration_time,
@@ -675,15 +775,14 @@ void IdentityGetAuthTokenFunction::OnGetAccessTokenComplete(
DCHECK(!device_access_token_request_);
DCHECK(!token_key_account_access_token_fetcher_);
if (access_token) {
- TRACE_EVENT_ASYNC_STEP_PAST1("identity", "IdentityGetAuthTokenFunction",
- this, "OnGetAccessTokenComplete", "account",
- token_key_.account_id.ToString());
+ TRACE_EVENT_NESTABLE_ASYNC_END1("identity", "GetAccessToken", this,
+ "account",
+ token_key_.account_id.ToString());
StartGaiaRequest(access_token.value());
} else {
- TRACE_EVENT_ASYNC_STEP_PAST1("identity", "IdentityGetAuthTokenFunction",
- this, "OnGetAccessTokenComplete", "error",
- error.ToString());
+ TRACE_EVENT_NESTABLE_ASYNC_END1("identity", "GetAccessToken", this, "error",
+ error.ToString());
OnGaiaFlowFailure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error,
std::string());
@@ -735,15 +834,17 @@ void IdentityGetAuthTokenFunction::OnIdentityAPIShutdown() {
}
#if defined(OS_CHROMEOS)
+// Even though the DeviceOAuth2TokenService may be available on non-ChromeOS
+// platforms, its robot account is not made available because it should only be
+// used for very specific policy-related things. In fact, the device account on
+// desktop isn't scoped for anything other than policy invalidations.
void IdentityGetAuthTokenFunction::StartDeviceAccessTokenRequest() {
- chromeos::DeviceOAuth2TokenService* service =
- chromeos::DeviceOAuth2TokenServiceFactory::Get();
+ DeviceOAuth2TokenService* service = DeviceOAuth2TokenServiceFactory::Get();
// Since robot account refresh tokens are scoped down to [any-api] only,
// request access token for [any-api] instead of login.
OAuth2AccessTokenManager::ScopeSet scopes;
scopes.insert(GaiaConstants::kAnyApiOAuth2Scope);
- device_access_token_request_ = service->StartAccessTokenRequest(
- service->GetRobotAccountId(), scopes, this);
+ device_access_token_request_ = service->StartAccessTokenRequest(scopes, this);
}
bool IdentityGetAuthTokenFunction::IsOriginWhitelistedInPublicSession() {
@@ -761,18 +862,20 @@ bool IdentityGetAuthTokenFunction::IsOriginWhitelistedInPublicSession() {
#endif
void IdentityGetAuthTokenFunction::StartTokenKeyAccountAccessTokenRequest() {
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("identity", "GetAccessToken", this);
+
auto* identity_manager = IdentityManagerFactory::GetForProfile(GetProfile());
#if defined(OS_CHROMEOS)
if (chrome::IsRunningInForcedAppMode()) {
std::string app_client_id;
std::string app_client_secret;
- if (chromeos::UserSessionManager::GetInstance()->
- GetAppModeChromeClientOAuthInfo(&app_client_id,
- &app_client_secret)) {
+ if (chromeos::UserSessionManager::GetInstance()
+ ->GetAppModeChromeClientOAuthInfo(&app_client_id,
+ &app_client_secret)) {
token_key_account_access_token_fetcher_ =
identity_manager->CreateAccessTokenFetcherForClient(
token_key_.account_id, app_client_id, app_client_secret,
- kExtensionsIdentityAPIOAuthConsumerName, ::identity::ScopeSet(),
+ kExtensionsIdentityAPIOAuthConsumerName, signin::ScopeSet(),
base::BindOnce(
&IdentityGetAuthTokenFunction::OnAccessTokenFetchCompleted,
base::Unretained(this)),
@@ -785,7 +888,7 @@ void IdentityGetAuthTokenFunction::StartTokenKeyAccountAccessTokenRequest() {
token_key_account_access_token_fetcher_ =
identity_manager->CreateAccessTokenFetcherForAccount(
token_key_.account_id, kExtensionsIdentityAPIOAuthConsumerName,
- ::identity::ScopeSet(),
+ signin::ScopeSet(),
base::BindOnce(
&IdentityGetAuthTokenFunction::OnAccessTokenFetchCompleted,
base::Unretained(this)),
@@ -823,6 +926,13 @@ void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog(
gaia_web_auth_flow_->Start();
}
+void IdentityGetAuthTokenFunction::ShowRemoteConsentDialog(
+ const RemoteConsentResolutionData& resolution_data) {
+ gaia_remote_consent_flow_ = std::make_unique<GaiaRemoteConsentFlow>(
+ this, GetProfile(), token_key_, resolution_data);
+ gaia_remote_consent_flow_->Start();
+}
+
std::unique_ptr<OAuth2MintTokenFlow>
IdentityGetAuthTokenFunction::CreateMintTokenFlow() {
std::string signin_scoped_device_id =
@@ -832,7 +942,9 @@ IdentityGetAuthTokenFunction::CreateMintTokenFlow() {
extension()->id(), oauth2_client_id_,
std::vector<std::string>(token_key_.scopes.begin(),
token_key_.scopes.end()),
- signin_scoped_device_id, gaia_mint_token_mode_));
+ signin_scoped_device_id, consent_result_,
+ GetOAuth2MintTokenFlowVersion(),
+ GetOAuth2MintTokenFlowChannel(), gaia_mint_token_mode_));
return mint_token_flow;
}
@@ -873,4 +985,8 @@ bool IdentityGetAuthTokenFunction::IsPrimaryAccountOnly() const {
->AreExtensionsRestrictedToPrimaryAccount();
}
+Profile* IdentityGetAuthTokenFunction::GetProfile() const {
+ return Profile::FromBrowserContext(browser_context());
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
index 1b3b46143d4..77dae78c32d 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
+++ b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
@@ -12,10 +12,11 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/scoped_observer.h"
+#include "chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h"
#include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h"
#include "chrome/browser/extensions/api/identity/identity_mint_queue.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "components/signin/public/identity_manager/identity_manager.h"
+#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_function_histogram_value.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_manager.h"
@@ -45,8 +46,9 @@ namespace extensions {
// profile will be signed in already, but if it turns out we need a
// new login token, there is a sign-in flow. If that flow completes
// successfully, getAuthToken proceeds to the non-interactive flow.
-class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
+class IdentityGetAuthTokenFunction : public ExtensionFunction,
public GaiaWebAuthFlow::Delegate,
+ public GaiaRemoteConsentFlow::Delegate,
public IdentityMintRequestQueue::Request,
public signin::IdentityManager::Observer,
#if defined(OS_CHROMEOS)
@@ -75,6 +77,12 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
void OnGaiaFlowCompleted(const std::string& access_token,
const std::string& expiration) override;
+ // GaiaRemoteConsentFlow::Delegate implementation:
+ void OnGaiaRemoteConsentFlowFailed(
+ GaiaRemoteConsentFlow::Failure failure) override;
+ void OnGaiaRemoteConsentFlowApproved(const std::string& consent_result,
+ const std::string& gaia_id) override;
+
// Starts a login access token request.
virtual void StartTokenKeyAccountAccessTokenRequest();
@@ -106,6 +114,8 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
// Exposed for testing.
virtual std::unique_ptr<OAuth2MintTokenFlow> CreateMintTokenFlow();
+ Profile* GetProfile() const;
+
// Pending request for an access token from the device account (via
// DeviceOAuth2TokenService).
std::unique_ptr<OAuth2AccessTokenManager::Request>
@@ -146,11 +156,11 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
const CoreAccountInfo& primary_account_info) override;
// ExtensionFunction:
- bool RunAsync() override;
+ ResponseAction Run() override;
// Helpers to report async function results to the caller.
void StartAsyncRun();
- void CompleteAsyncRun(bool success);
+ void CompleteAsyncRun(ResponseValue response);
void CompleteFunctionWithResult(const std::string& access_token);
void CompleteFunctionWithError(const std::string& error);
@@ -170,6 +180,8 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
int time_to_live) override;
void OnMintTokenFailure(const GoogleServiceAuthError& error) override;
void OnIssueAdviceSuccess(const IssueAdviceInfo& issue_advice) override;
+ void OnRemoteConsentSuccess(
+ const RemoteConsentResolutionData& resolution_data) override;
#if defined(OS_CHROMEOS)
// Starts a login access token request for device robot account. This method
@@ -184,6 +196,8 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
// Methods for invoking UI. Overridable for testing.
virtual void ShowExtensionLoginPrompt();
virtual void ShowOAuthApprovalDialog(const IssueAdviceInfo& issue_advice);
+ virtual void ShowRemoteConsentDialog(
+ const RemoteConsentResolutionData& resolution_data);
// Checks if there is a master login token to mint tokens for the extension.
bool HasRefreshTokenForTokenKeyAccount() const;
@@ -213,6 +227,10 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
// a permissions prompt will be popped up to the user.
IssueAdviceInfo issue_advice_;
std::unique_ptr<GaiaWebAuthFlow> gaia_web_auth_flow_;
+ // The browser resolution consent flow.
+ RemoteConsentResolutionData resolution_data_;
+ std::unique_ptr<GaiaRemoteConsentFlow> gaia_remote_consent_flow_;
+ std::string consent_result_;
// Invoked when IdentityAPI is shut down.
std::unique_ptr<base::CallbackList<void()>::Subscription>
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc b/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc
index 32853d9c4d5..a2898874ad4 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.cc
@@ -27,10 +27,10 @@ IdentityLaunchWebAuthFlowFunction::~IdentityLaunchWebAuthFlowFunction() {
auth_flow_.release()->DetachDelegateAndDelete();
}
-bool IdentityLaunchWebAuthFlowFunction::RunAsync() {
- if (GetProfile()->IsOffTheRecord()) {
- error_ = identity_constants::kOffTheRecord;
- return false;
+ExtensionFunction::ResponseAction IdentityLaunchWebAuthFlowFunction::Run() {
+ Profile* profile = Profile::FromBrowserContext(browser_context());
+ if (profile->IsOffTheRecord()) {
+ return RespondNow(Error(identity_constants::kOffTheRecord));
}
std::unique_ptr<api::identity::LaunchWebAuthFlow::Params> params(
@@ -48,9 +48,9 @@ bool IdentityLaunchWebAuthFlowFunction::RunAsync() {
AddRef(); // Balanced in OnAuthFlowSuccess/Failure.
- auth_flow_.reset(new WebAuthFlow(this, GetProfile(), auth_url, mode));
+ auth_flow_.reset(new WebAuthFlow(this, profile, auth_url, mode));
auth_flow_->Start();
- return true;
+ return RespondLater();
}
void IdentityLaunchWebAuthFlowFunction::InitFinalRedirectURLPrefixForTest(
@@ -68,32 +68,32 @@ void IdentityLaunchWebAuthFlowFunction::InitFinalRedirectURLPrefix(
void IdentityLaunchWebAuthFlowFunction::OnAuthFlowFailure(
WebAuthFlow::Failure failure) {
+ std::string error;
switch (failure) {
case WebAuthFlow::WINDOW_CLOSED:
- error_ = identity_constants::kUserRejected;
+ error = identity_constants::kUserRejected;
break;
case WebAuthFlow::INTERACTION_REQUIRED:
- error_ = identity_constants::kInteractionRequired;
+ error = identity_constants::kInteractionRequired;
break;
case WebAuthFlow::LOAD_FAILED:
- error_ = identity_constants::kPageLoadFailure;
+ error = identity_constants::kPageLoadFailure;
break;
default:
NOTREACHED() << "Unexpected error from web auth flow: " << failure;
- error_ = identity_constants::kInvalidRedirect;
+ error = identity_constants::kInvalidRedirect;
break;
}
- SendResponse(false);
+ Respond(Error(error));
if (auth_flow_)
auth_flow_.release()->DetachDelegateAndDelete();
- Release(); // Balanced in RunAsync.
+ Release(); // Balanced in Run.
}
void IdentityLaunchWebAuthFlowFunction::OnAuthFlowURLChange(
const GURL& redirect_url) {
if (redirect_url.GetWithEmptyPath() == final_url_prefix_) {
- SetResult(std::make_unique<base::Value>(redirect_url.spec()));
- SendResponse(true);
+ Respond(OneArgument(std::make_unique<base::Value>(redirect_url.spec())));
if (auth_flow_)
auth_flow_.release()->DetachDelegateAndDelete();
Release(); // Balanced in RunAsync.
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.h b/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.h
index e40e5b12674..f15067ea579 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.h
+++ b/chromium/chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.h
@@ -8,12 +8,12 @@
#include <string>
#include "chrome/browser/extensions/api/identity/web_auth_flow.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
+#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_function_histogram_value.h"
namespace extensions {
-class IdentityLaunchWebAuthFlowFunction : public ChromeAsyncExtensionFunction,
+class IdentityLaunchWebAuthFlowFunction : public ExtensionFunction,
public WebAuthFlow::Delegate {
public:
DECLARE_EXTENSION_FUNCTION("identity.launchWebAuthFlow",
@@ -26,7 +26,7 @@ class IdentityLaunchWebAuthFlowFunction : public ChromeAsyncExtensionFunction,
private:
~IdentityLaunchWebAuthFlowFunction() override;
- bool RunAsync() override;
+ ResponseAction Run() override;
// WebAuthFlow::Delegate implementation.
void OnAuthFlowFailure(WebAuthFlow::Failure failure) override;
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_mint_queue.cc b/chromium/chrome/browser/extensions/api/identity/identity_mint_queue.cc
index ea6dc52f2e7..6ac11af851d 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_mint_queue.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_mint_queue.cc
@@ -32,8 +32,8 @@ void IdentityMintRequestQueue::RequestStart(
IdentityMintRequestQueue::MintType type,
const ExtensionTokenKey& key,
IdentityMintRequestQueue::Request* request) {
- TRACE_EVENT_ASYNC_BEGIN1(
- "identity", "IdentityMintRequestQueue", request, "type", type);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("identity", "IdentityMintRequestQueue",
+ request, "type", type);
RequestQueue& request_queue = GetRequestQueueMap(type)[key];
request_queue.push_back(request);
// If this is the first request, start it now. RequestComplete will start
@@ -46,11 +46,8 @@ void IdentityMintRequestQueue::RequestComplete(
IdentityMintRequestQueue::MintType type,
const ExtensionTokenKey& key,
IdentityMintRequestQueue::Request* request) {
- TRACE_EVENT_ASYNC_END1("identity",
- "IdentityMintRequestQueue",
- request,
- "completed",
- "RequestComplete");
+ TRACE_EVENT_NESTABLE_ASYNC_END1("identity", "IdentityMintRequestQueue",
+ request, "completed", "RequestComplete");
RequestQueue& request_queue = GetRequestQueueMap(type)[key];
CHECK_EQ(request_queue.front(), request);
request_queue.pop_front();
@@ -61,11 +58,8 @@ void IdentityMintRequestQueue::RequestComplete(
void IdentityMintRequestQueue::RequestCancel(
const ExtensionTokenKey& key,
IdentityMintRequestQueue::Request* request) {
- TRACE_EVENT_ASYNC_END1("identity",
- "IdentityMintRequestQueue",
- request,
- "completed",
- "RequestCancel");
+ TRACE_EVENT_NESTABLE_ASYNC_END1("identity", "IdentityMintRequestQueue",
+ request, "completed", "RequestCancel");
GetRequestQueueMap(MINT_TYPE_INTERACTIVE)[key].remove(request);
GetRequestQueueMap(MINT_TYPE_NONINTERACTIVE)[key].remove(request);
}
@@ -87,8 +81,8 @@ IdentityMintRequestQueue::GetRequestQueueMap(
void IdentityMintRequestQueue::RunRequest(
IdentityMintRequestQueue::MintType type,
RequestQueue& request_queue) {
- TRACE_EVENT_ASYNC_STEP_INTO0(
- "identity", "IdentityMintRequestQueue", request_queue.front(), "RUNNING");
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "RunRequest",
+ request_queue.front());
request_queue.front()->StartMintToken(type);
}
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_private_api.cc b/chromium/chrome/browser/extensions/api/identity/identity_private_api.cc
new file mode 100644
index 00000000000..a0342d733df
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/identity/identity_private_api.cc
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/identity/identity_private_api.h"
+
+#include "chrome/browser/extensions/api/identity/identity_api.h"
+
+namespace extensions {
+
+IdentityPrivateSetConsentResultFunction::
+ IdentityPrivateSetConsentResultFunction() = default;
+IdentityPrivateSetConsentResultFunction::
+ ~IdentityPrivateSetConsentResultFunction() = default;
+
+ExtensionFunction::ResponseAction
+IdentityPrivateSetConsentResultFunction::Run() {
+ std::unique_ptr<Params> params = Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params);
+
+ IdentityAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->SetConsentResult(params->result, params->window_id);
+
+ return RespondNow(NoArguments());
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_private_api.h b/chromium/chrome/browser/extensions/api/identity/identity_private_api.h
new file mode 100644
index 00000000000..4df809d1ada
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/identity/identity_private_api.h
@@ -0,0 +1,29 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_PRIVATE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_PRIVATE_API_H_
+
+#include "chrome/common/extensions/api/identity_private.h"
+#include "extensions/browser/extension_function.h"
+
+namespace extensions {
+
+class IdentityPrivateSetConsentResultFunction : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("identityPrivate.setConsentResult",
+ IDENTITYPRIVATE_SETCONSENTRESULT)
+
+ IdentityPrivateSetConsentResultFunction();
+
+ private:
+ using Params = api::identity_private::SetConsentResult::Params;
+ ~IdentityPrivateSetConsentResultFunction() override;
+
+ ExtensionFunction::ResponseAction Run() override;
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_PRIVATE_API_H_
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_private_apitest.cc b/chromium/chrome/browser/extensions/api/identity/identity_private_apitest.cc
new file mode 100644
index 00000000000..ea6d0d36919
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/identity/identity_private_apitest.cc
@@ -0,0 +1,70 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/identity/identity_private_api.h"
+
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "chrome/browser/extensions/api/identity/identity_api.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "extensions/browser/api_test_utils.h"
+
+namespace extensions {
+
+struct SetConsentResultParams {
+ std::string consent_result;
+ std::string window_id;
+};
+
+class IdentityPrivateApiTest : public ExtensionBrowserTest {
+ protected:
+ void SetUpOnMainThread() override {
+ ExtensionBrowserTest::SetUpOnMainThread();
+ callback_loop_ = std::make_unique<base::RunLoop>();
+ // base::Unretained(this) is safe because the callback will be unregistered
+ // on |callback_subscription_| destruction.
+ callback_subscription_ = identity_api()->RegisterOnSetConsentResultCallback(
+ base::BindRepeating(&IdentityPrivateApiTest::OnSetConsentResult,
+ base::Unretained(this)));
+ }
+
+ IdentityAPI* identity_api() {
+ return IdentityAPI::GetFactoryInstance()->Get(profile());
+ }
+
+ SetConsentResultParams WaitForConsentResult() {
+ callback_loop_->Run();
+ return {consent_result_, window_id_};
+ }
+
+ private:
+ void OnSetConsentResult(const std::string& consent_result,
+ const std::string& window_id) {
+ consent_result_ = consent_result;
+ window_id_ = window_id;
+ callback_loop_->Quit();
+ }
+
+ std::string consent_result_;
+ std::string window_id_;
+ std::unique_ptr<base::RunLoop> callback_loop_;
+ std::unique_ptr<base::CallbackList<
+ IdentityAPI::OnSetConsentResultSignature>::Subscription>
+ callback_subscription_;
+};
+
+IN_PROC_BROWSER_TEST_F(IdentityPrivateApiTest, SetConsentResult) {
+ scoped_refptr<ExtensionFunction> func =
+ base::MakeRefCounted<IdentityPrivateSetConsentResultFunction>();
+ bool success = api_test_utils::RunFunction(
+ func.get(),
+ std::string("[\"consent_result_value\", \"window_id_value\"]"),
+ profile());
+ ASSERT_TRUE(success);
+ SetConsentResultParams params = WaitForConsentResult();
+ EXPECT_EQ(params.consent_result, "consent_result_value");
+ EXPECT_EQ(params.window_id, "window_id_value");
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h b/chromium/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h
index e99b46414ab..0ada4378ad3 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h
+++ b/chromium/chrome/browser/extensions/api/identity/identity_remove_cached_auth_token_function.h
@@ -5,7 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_REMOVE_CACHED_AUTH_TOKEN_FUNCTION_H_
#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_REMOVE_CACHED_AUTH_TOKEN_FUNCTION_H_
-#include "chrome/browser/extensions/chrome_extension_function.h"
+#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_function_histogram_value.h"
namespace extensions {
diff --git a/chromium/chrome/browser/extensions/api/identity/web_auth_flow.cc b/chromium/chrome/browser/extensions/api/identity/web_auth_flow.cc
index d26238cd2d6..6e12abb52f2 100644
--- a/chromium/chrome/browser/extensions/api/identity/web_auth_flow.cc
+++ b/chromium/chrome/browser/extensions/api/identity/web_auth_flow.cc
@@ -21,6 +21,7 @@
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/grit/browser_resources.h"
#include "components/guest_view/browser/guest_view_base.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
@@ -34,6 +35,7 @@
#include "extensions/browser/app_window/app_window.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_system.h"
+#include "extensions/browser/guest_view/web_view/web_view_guest.h"
#include "net/http/http_response_headers.h"
#include "url/gurl.h"
#include "url/url_constants.h"
@@ -57,7 +59,7 @@ WebAuthFlow::WebAuthFlow(
provider_url_(provider_url),
mode_(mode),
embedded_window_created_(false) {
- TRACE_EVENT_ASYNC_BEGIN0("identity", "WebAuthFlow", this);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("identity", "WebAuthFlow", this);
}
WebAuthFlow::~WebAuthFlow() {
@@ -74,7 +76,7 @@ WebAuthFlow::~WebAuthFlow() {
if (app_window_ && app_window_->web_contents())
app_window_->web_contents()->Close();
}
- TRACE_EVENT_ASYNC_END0("identity", "WebAuthFlow", this);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("identity", "WebAuthFlow", this);
}
void WebAuthFlow::Start() {
@@ -118,6 +120,22 @@ void WebAuthFlow::DetachDelegateAndDelete() {
base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
+content::StoragePartition* WebAuthFlow::GetGuestPartition() {
+ return content::BrowserContext::GetStoragePartitionForSite(
+ profile_, GetWebViewSiteURL());
+}
+
+const std::string& WebAuthFlow::GetAppWindowKey() const {
+ return app_window_key_;
+}
+
+// static
+GURL WebAuthFlow::GetWebViewSiteURL() {
+ return extensions::WebViewGuest::GetSiteForGuestPartitionConfig(
+ extension_misc::kIdentityApiUiAppId, /*partition_name=*/std::string(),
+ /*in_memory=*/true);
+}
+
void WebAuthFlow::OnAppWindowAdded(AppWindow* app_window) {
if (app_window->window_key() == app_window_key_ &&
app_window->extension_id() == extension_misc::kIdentityApiUiAppId) {
@@ -203,8 +221,13 @@ void WebAuthFlow::DidRedirectNavigation(
void WebAuthFlow::DidFinishNavigation(
content::NavigationHandle* navigation_handle) {
- bool failed = false;
+ // Websites may create and remove <iframe> during the auth flow. In
+ // particular, to integrate CAPTCHA tests. Chrome shouldn't abort the auth
+ // flow if a navigation failed in a sub-frame. https://crbug.com/1049565.
+ if (!navigation_handle->IsInMainFrame())
+ return;
+ bool failed = false;
if (navigation_handle->GetNetErrorCode() != net::OK) {
if (navigation_handle->GetURL().spec() == url::kAboutBlankURL) {
// As part of the OAUth 2.0 protocol with GAIA, at the end of the web
@@ -226,17 +249,15 @@ void WebAuthFlow::DidFinishNavigation(
navigation_handle->GetNetErrorCode());
} else {
failed = true;
- TRACE_EVENT_ASYNC_STEP_PAST1("identity", "WebAuthFlow", this,
- "DidFinishNavigationFailure", "error_code",
- navigation_handle->GetNetErrorCode());
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(
+ "identity", "DidFinishNavigationFailure", this, "error_code",
+ navigation_handle->GetNetErrorCode());
}
- } else if (navigation_handle->IsInMainFrame() &&
- navigation_handle->GetResponseHeaders() &&
+ } else if (navigation_handle->GetResponseHeaders() &&
navigation_handle->GetResponseHeaders()->response_code() >= 400) {
failed = true;
- TRACE_EVENT_ASYNC_STEP_PAST1(
- "identity", "WebAuthFlow", this, "DidFinishNavigationFailure",
- "response_code",
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT1(
+ "identity", "DidFinishNavigationFailure", this, "response_code",
navigation_handle->GetResponseHeaders()->response_code());
}
diff --git a/chromium/chrome/browser/extensions/api/identity/web_auth_flow.h b/chromium/chrome/browser/extensions/api/identity/web_auth_flow.h
index 2252a9f768f..b86e3dc908d 100644
--- a/chromium/chrome/browser/extensions/api/identity/web_auth_flow.h
+++ b/chromium/chrome/browser/extensions/api/identity/web_auth_flow.h
@@ -21,6 +21,7 @@ class WebAuthFlowTest;
namespace content {
class NotificationDetails;
class NotificationSource;
+class StoragePartition;
}
namespace extensions {
@@ -64,9 +65,9 @@ class WebAuthFlow : public content::NotificationObserver,
virtual void OnAuthFlowFailure(Failure failure) = 0;
// Called on redirects and other navigations to see if the URL should stop
// the flow.
- virtual void OnAuthFlowURLChange(const GURL& redirect_url) = 0;
+ virtual void OnAuthFlowURLChange(const GURL& redirect_url) {}
// Called when the title of the current page changes.
- virtual void OnAuthFlowTitleChange(const std::string& title) = 0;
+ virtual void OnAuthFlowTitleChange(const std::string& title) {}
protected:
virtual ~Delegate() {}
@@ -87,6 +88,17 @@ class WebAuthFlow : public content::NotificationObserver,
// Prevents further calls to the delegate and deletes the flow.
void DetachDelegateAndDelete();
+ // Returns a StoragePartition of the guest webview. Used to inject cookies
+ // into Gaia page. Can override for testing.
+ virtual content::StoragePartition* GetGuestPartition();
+
+ // Returns an ID string attached to the window. Can override for testing.
+ virtual const std::string& GetAppWindowKey() const;
+
+ // Returns the URL used by the SiteInstance associated with the WebViewGuest
+ // used in the WebAuthFlow.
+ static GURL GetWebViewSiteURL();
+
private:
friend class ::WebAuthFlowTest;
diff --git a/chromium/chrome/browser/extensions/api/idltest/idltest_api.cc b/chromium/chrome/browser/extensions/api/idltest/idltest_api.cc
index 8e9ed22303b..ac6205e8ea2 100644
--- a/chromium/chrome/browser/extensions/api/idltest/idltest_api.cc
+++ b/chromium/chrome/browser/extensions/api/idltest/idltest_api.cc
@@ -15,12 +15,11 @@ namespace {
std::unique_ptr<base::Value> CopyBinaryValueToIntegerList(
const base::Value::BlobStorage& input) {
- base::Value output(base::Value::Type::LIST);
- auto& list = output.GetList();
+ base::Value::ListStorage list;
list.reserve(input.size());
for (int c : input)
list.emplace_back(c);
- return base::Value::ToUniquePtrValue(std::move(output));
+ return base::Value::ToUniquePtrValue(base::Value(std::move(list)));
}
} // namespace
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
index 952862996d3..8e48068c9e2 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.cc
@@ -24,9 +24,10 @@ ImageWriterPrivateBaseFunction::~ImageWriterPrivateBaseFunction() {}
void ImageWriterPrivateBaseFunction::OnComplete(bool success,
const std::string& error) {
- if (!success)
- error_ = error;
- SendResponse(success);
+ if (success)
+ Respond(NoArguments());
+ else
+ Respond(Error(error));
}
ImageWriterPrivateWriteFromUrlFunction::
@@ -37,12 +38,13 @@ ImageWriterPrivateWriteFromUrlFunction::
~ImageWriterPrivateWriteFromUrlFunction() {
}
-bool ImageWriterPrivateWriteFromUrlFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+ImageWriterPrivateWriteFromUrlFunction::Run() {
#if defined(OS_CHROMEOS)
- if (GetProfile()->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled) ||
- GetProfile()->GetPrefs()->GetBoolean(prefs::kExternalStorageReadOnly)) {
- error_ = image_writer::error::kDeviceWriteError;
- return false;
+ Profile* profile = Profile::FromBrowserContext(browser_context());
+ if (profile->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled) ||
+ profile->GetPrefs()->GetBoolean(prefs::kExternalStorageReadOnly)) {
+ return RespondNow(Error(image_writer::error::kDeviceWriteError));
}
#endif
std::unique_ptr<image_writer_api::WriteFromUrl::Params> params(
@@ -50,22 +52,20 @@ bool ImageWriterPrivateWriteFromUrlFunction::RunAsync() {
EXTENSION_FUNCTION_VALIDATE(params.get());
GURL url(params->image_url);
- if (!url.is_valid()) {
- error_ = image_writer::error::kUrlInvalid;
- return false;
- }
+ if (!url.is_valid())
+ return RespondNow(Error(image_writer::error::kUrlInvalid));
std::string hash;
if (params->options.get() && params->options->image_hash.get()) {
hash = *params->options->image_hash;
}
- image_writer::OperationManager::Get(GetProfile())
+ image_writer::OperationManager::Get(browser_context())
->StartWriteFromUrl(
extension_id(), url, hash, params->storage_unit_id,
base::BindOnce(&ImageWriterPrivateWriteFromUrlFunction::OnComplete,
this));
- return true;
+ return RespondLater();
}
ImageWriterPrivateWriteFromFileFunction::
@@ -76,12 +76,13 @@ ImageWriterPrivateWriteFromFileFunction::
~ImageWriterPrivateWriteFromFileFunction() {
}
-bool ImageWriterPrivateWriteFromFileFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+ImageWriterPrivateWriteFromFileFunction::Run() {
#if defined(OS_CHROMEOS)
- if (GetProfile()->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled) ||
- GetProfile()->GetPrefs()->GetBoolean(prefs::kExternalStorageReadOnly)) {
- error_ = image_writer::error::kDeviceWriteError;
- return false;
+ Profile* profile = Profile::FromBrowserContext(browser_context());
+ if (profile->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled) ||
+ profile->GetPrefs()->GetBoolean(prefs::kExternalStorageReadOnly)) {
+ return RespondNow(Error(image_writer::error::kDeviceWriteError));
}
#endif
std::string filesystem_name;
@@ -94,17 +95,19 @@ bool ImageWriterPrivateWriteFromFileFunction::RunAsync() {
base::FilePath path;
+ std::string error;
if (!extensions::app_file_handler_util::ValidateFileEntryAndGetPath(
filesystem_name, filesystem_path, source_process_id(), &path,
- &error_))
- return false;
+ &error)) {
+ return RespondNow(Error(error));
+ }
- image_writer::OperationManager::Get(GetProfile())
+ image_writer::OperationManager::Get(browser_context())
->StartWriteFromFile(
extension_id(), path, storage_unit_id,
base::BindOnce(&ImageWriterPrivateWriteFromFileFunction::OnComplete,
this));
- return true;
+ return RespondLater();
}
ImageWriterPrivateCancelWriteFunction::ImageWriterPrivateCancelWriteFunction() {
@@ -114,13 +117,13 @@ ImageWriterPrivateCancelWriteFunction::
~ImageWriterPrivateCancelWriteFunction() {
}
-bool ImageWriterPrivateCancelWriteFunction::RunAsync() {
- image_writer::OperationManager::Get(GetProfile())
+ExtensionFunction::ResponseAction ImageWriterPrivateCancelWriteFunction::Run() {
+ image_writer::OperationManager::Get(browser_context())
->CancelWrite(
extension_id(),
base::BindOnce(&ImageWriterPrivateCancelWriteFunction::OnComplete,
this));
- return true;
+ return RespondLater();
}
ImageWriterPrivateDestroyPartitionsFunction::
@@ -131,12 +134,13 @@ ImageWriterPrivateDestroyPartitionsFunction::
~ImageWriterPrivateDestroyPartitionsFunction() {
}
-bool ImageWriterPrivateDestroyPartitionsFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+ImageWriterPrivateDestroyPartitionsFunction::Run() {
#if defined(OS_CHROMEOS)
- if (GetProfile()->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled) ||
- GetProfile()->GetPrefs()->GetBoolean(prefs::kExternalStorageReadOnly)) {
- error_ = image_writer::error::kDeviceWriteError;
- return false;
+ Profile* profile = Profile::FromBrowserContext(browser_context());
+ if (profile->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled) ||
+ profile->GetPrefs()->GetBoolean(prefs::kExternalStorageReadOnly)) {
+ return RespondNow(Error(image_writer::error::kDeviceWriteError));
}
#endif
@@ -144,12 +148,12 @@ bool ImageWriterPrivateDestroyPartitionsFunction::RunAsync() {
image_writer_api::DestroyPartitions::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
- image_writer::OperationManager::Get(GetProfile())
+ image_writer::OperationManager::Get(browser_context())
->DestroyPartitions(
extension_id(), params->storage_unit_id,
base::BindOnce(
&ImageWriterPrivateDestroyPartitionsFunction::OnComplete, this));
- return true;
+ return RespondLater();
}
ImageWriterPrivateListRemovableStorageDevicesFunction::
@@ -160,30 +164,31 @@ ImageWriterPrivateListRemovableStorageDevicesFunction::
~ImageWriterPrivateListRemovableStorageDevicesFunction() {
}
-bool ImageWriterPrivateListRemovableStorageDevicesFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+ImageWriterPrivateListRemovableStorageDevicesFunction::Run() {
#if defined(OS_CHROMEOS)
- if (GetProfile()->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled)) {
+ Profile* profile = Profile::FromBrowserContext(browser_context());
+ if (profile->GetPrefs()->GetBoolean(prefs::kExternalStorageDisabled)) {
// Return an empty device list.
OnDeviceListReady(base::MakeRefCounted<StorageDeviceList>());
- return true;
+ return AlreadyResponded();
}
#endif
RemovableStorageProvider::GetAllDevices(base::BindOnce(
&ImageWriterPrivateListRemovableStorageDevicesFunction::OnDeviceListReady,
this));
- return true;
+ return RespondLater();
}
void ImageWriterPrivateListRemovableStorageDevicesFunction::OnDeviceListReady(
scoped_refptr<StorageDeviceList> device_list) {
const bool success = device_list.get() != nullptr;
if (success) {
- results_ = image_writer_api::ListRemovableStorageDevices::Results::Create(
- device_list->data);
- SendResponse(true);
+ Respond(ArgumentList(
+ image_writer_api::ListRemovableStorageDevices::Results::Create(
+ device_list->data)));
} else {
- error_ = image_writer::error::kDeviceListError;
- SendResponse(false);
+ Respond(Error(image_writer::error::kDeviceListError));
}
}
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.h b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.h
index 883bc2943ae..58c4d50655e 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.h
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_api.h
@@ -5,12 +5,12 @@
#define CHROME_BROWSER_EXTENSIONS_API_IMAGE_WRITER_PRIVATE_IMAGE_WRITER_PRIVATE_API_H_
#include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/common/extensions/api/image_writer_private.h"
+#include "extensions/browser/extension_function.h"
namespace extensions {
-class ImageWriterPrivateBaseFunction : public ChromeAsyncExtensionFunction {
+class ImageWriterPrivateBaseFunction : public ExtensionFunction {
public:
ImageWriterPrivateBaseFunction();
@@ -32,7 +32,7 @@ class ImageWriterPrivateWriteFromUrlFunction
private:
~ImageWriterPrivateWriteFromUrlFunction() override;
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class ImageWriterPrivateWriteFromFileFunction
@@ -44,7 +44,7 @@ class ImageWriterPrivateWriteFromFileFunction
private:
~ImageWriterPrivateWriteFromFileFunction() override;
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class ImageWriterPrivateCancelWriteFunction
@@ -56,7 +56,7 @@ class ImageWriterPrivateCancelWriteFunction
private:
~ImageWriterPrivateCancelWriteFunction() override;
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class ImageWriterPrivateDestroyPartitionsFunction
@@ -68,20 +68,20 @@ class ImageWriterPrivateDestroyPartitionsFunction
private:
~ImageWriterPrivateDestroyPartitionsFunction() override;
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class ImageWriterPrivateListRemovableStorageDevicesFunction
- : public ChromeAsyncExtensionFunction {
- public:
- DECLARE_EXTENSION_FUNCTION("imageWriterPrivate.listRemovableStorageDevices",
- IMAGEWRITER_LISTREMOVABLESTORAGEDEVICES)
- ImageWriterPrivateListRemovableStorageDevicesFunction();
-
- private:
- ~ImageWriterPrivateListRemovableStorageDevicesFunction() override;
- bool RunAsync() override;
- void OnDeviceListReady(scoped_refptr<StorageDeviceList> device_list);
+ : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("imageWriterPrivate.listRemovableStorageDevices",
+ IMAGEWRITER_LISTREMOVABLESTORAGEDEVICES)
+ ImageWriterPrivateListRemovableStorageDevicesFunction();
+
+ private:
+ ~ImageWriterPrivateListRemovableStorageDevicesFunction() override;
+ ResponseAction Run() override;
+ void OnDeviceListReady(scoped_refptr<StorageDeviceList> device_list);
};
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
index 657ecfd62f8..10c31bf444f 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
@@ -160,9 +160,9 @@ void ImageWriterUtilityClient::BindServiceIfNeeded() {
#if defined(OS_WIN)
constexpr auto kSandboxType =
- service_manager::SANDBOX_TYPE_NO_SANDBOX_AND_ELEVATED_PRIVILEGES;
+ service_manager::SandboxType::kNoSandboxAndElevatedPrivileges;
#else
- constexpr auto kSandboxType = service_manager::SANDBOX_TYPE_NO_SANDBOX;
+ constexpr auto kSandboxType = service_manager::SandboxType::kNoSandbox;
#endif
content::ServiceProcessHost::Launch(
removable_storage_writer_.BindNewPipeAndPassReceiver(),
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
index 797239e9342..49704aebbb7 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
@@ -13,6 +13,7 @@
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/image_writer_private/operation.h"
#include "chrome/services/removable_storage_writer/public/mojom/removable_storage_writer.mojom.h"
@@ -41,8 +42,8 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &image_));
base::RunLoop run_loop;
- base::PostTaskAndReply(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::MayBlock()},
base::BindOnce(&ImageWriterUtilityClientTest::FillFile, image_,
pattern),
run_loop.QuitClosure());
@@ -54,8 +55,8 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
device_ = image_.ReplaceExtension(FILE_PATH_LITERAL("out"));
base::RunLoop run_loop;
- base::PostTaskAndReply(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::MayBlock()},
base::BindOnce(&ImageWriterUtilityClientTest::FillFile, device_,
pattern),
run_loop.QuitClosure());
@@ -218,8 +219,8 @@ class ImageWriterUtilityClientTest : public InProcessBrowserTest {
base::SequencedTaskRunner* CreateTaskRunner() {
DCHECK(!task_runner_.get());
- task_runner_ =
- base::CreateSequencedTaskRunner(Operation::blocking_task_traits());
+ task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
+ Operation::blocking_task_traits());
return task_runner_.get();
}
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc b/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
index 330d582ae81..608842bfe5d 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
#include "chrome/browser/extensions/api/image_writer_private/operation_manager.h"
@@ -42,7 +43,8 @@ Operation::Operation(base::WeakPtr<OperationManager> manager,
stage_(image_writer_api::STAGE_UNKNOWN),
progress_(0),
download_folder_(download_folder),
- task_runner_(base::CreateSequencedTaskRunner(blocking_task_traits())) {
+ task_runner_(
+ base::ThreadPool::CreateSequencedTaskRunner(blocking_task_traits())) {
}
Operation::~Operation() {
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation.h b/chromium/chrome/browser/extensions/api/image_writer_private/operation.h
index 7444da741d7..575d2c38c8e 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation.h
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation.h
@@ -229,7 +229,6 @@ class Operation : public base::RefCountedThreadSafe<Operation> {
static constexpr base::TaskTraits blocking_task_traits() {
return {
- base::ThreadPool(),
// Requires I/O.
base::MayBlock(),
// Apps (e.g. Chromebook Recovery Utility) present UI feedback based on
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc b/chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
index 9144e4d6cfd..5140db323c9 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
@@ -43,7 +43,7 @@ void Operation::Write(const base::Closure& continuation) {
SetStage(image_writer_api::STAGE_WRITE);
// Note this has to be run on the FILE thread to avoid concurrent access.
- AddCleanUpFunction(base::Bind(&ClearImageBurner));
+ AddCleanUpFunction(base::BindOnce(&ClearImageBurner));
base::PostTask(
FROM_HERE, {BrowserThread::UI},
@@ -61,7 +61,7 @@ void Operation::UnmountVolumes(const base::Closure& continuation) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DiskMountManager::GetInstance()->UnmountDeviceRecursively(
device_path_.value(),
- base::Bind(&Operation::UnmountVolumesCallback, this, continuation));
+ base::BindOnce(&Operation::UnmountVolumesCallback, this, continuation));
}
void Operation::UnmountVolumesCallback(const base::Closure& continuation,
@@ -70,7 +70,8 @@ void Operation::UnmountVolumesCallback(const base::Closure& continuation,
if (error_code != chromeos::MOUNT_ERROR_NONE) {
LOG(ERROR) << "Volume unmounting failed with error code " << error_code;
- PostTask(base::Bind(&Operation::Error, this, error::kUnmountVolumesError));
+ PostTask(
+ base::BindOnce(&Operation::Error, this, error::kUnmountVolumesError));
return;
}
@@ -81,7 +82,8 @@ void Operation::UnmountVolumesCallback(const base::Closure& continuation,
if (iter == disks.end()) {
LOG(ERROR) << "Disk not found in disk list after unmounting volumes.";
- PostTask(base::Bind(&Operation::Error, this, error::kUnmountVolumesError));
+ PostTask(
+ base::BindOnce(&Operation::Error, this, error::kUnmountVolumesError));
return;
}
@@ -100,9 +102,8 @@ void Operation::StartWriteOnUIThread(const std::string& target_path,
base::Bind(&Operation::OnBurnFinished, this, continuation),
base::Bind(&Operation::OnBurnProgress, this));
- burner->BurnImage(image_path_.value(),
- target_path,
- base::Bind(&Operation::OnBurnError, this));
+ burner->BurnImage(image_path_.value(), target_path,
+ base::BindOnce(&Operation::OnBurnError, this));
}
void Operation::OnBurnFinished(const base::Closure& continuation,
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc
index ec433f683f3..2b7c60d42d7 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_thread.h"
@@ -28,9 +29,9 @@ void RemovableStorageProvider::GetAllDevices(DeviceListReadyCallback callback) {
return;
}
// We need to do some file i/o to get the device block size
- base::PostTaskAndReplyWithResult(
+ base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&RemovableStorageProvider::PopulateDeviceList),
std::move(callback));
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc
index af1d4c4852b..764aa1d9ed3 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc
@@ -119,8 +119,8 @@ TEST_F(RemovableStorageProviderChromeOsUnitTest, GetAllDevices) {
CreateDisk("/dev/OnBootDevice", chromeos::DEVICE_TYPE_USB, true, true, true);
RemovableStorageProvider::GetAllDevices(
- base::Bind(&RemovableStorageProviderChromeOsUnitTest::DevicesCallback,
- base::Unretained(this)));
+ base::BindOnce(&RemovableStorageProviderChromeOsUnitTest::DevicesCallback,
+ base::Unretained(this)));
task_environment_.RunUntilIdle();
@@ -140,8 +140,8 @@ TEST_F(RemovableStorageProviderChromeOsUnitTest, EmptyProductAndModel) {
kDevicePathSD, "", "", chromeos::DEVICE_TYPE_SD, true, true, false);
RemovableStorageProvider::GetAllDevices(
- base::Bind(&RemovableStorageProviderChromeOsUnitTest::DevicesCallback,
- base::Unretained(this)));
+ base::BindOnce(&RemovableStorageProviderChromeOsUnitTest::DevicesCallback,
+ base::Unretained(this)));
task_environment_.RunUntilIdle();
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc b/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc
index 6a2237729c0..fc78d4819c7 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc
@@ -11,6 +11,7 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
@@ -91,9 +92,8 @@ SimulateProgressInfo::SimulateProgressInfo(const SimulateProgressInfo&) =
default;
FakeImageWriterClient::FakeImageWriterClient()
- : ImageWriterUtilityClient(base::CreateSequencedTaskRunner(
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE,
+ : ImageWriterUtilityClient(base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})) {}
FakeImageWriterClient::~FakeImageWriterClient() {}
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc b/chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc
index 4ae7b054f1b..54e7d2d0f1c 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc
@@ -10,6 +10,7 @@
#include "base/files/file_util.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
#include "third_party/zlib/google/zip_reader.h"
@@ -34,8 +35,8 @@ UnzipHelper::~UnzipHelper() {}
void UnzipHelper::Unzip(const base::FilePath& image_path,
const base::FilePath& temp_dir_path) {
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- base::CreateSingleThreadTaskRunner({base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE});
+ base::ThreadPool::CreateSingleThreadTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
task_runner->PostTask(FROM_HERE, base::BindOnce(&UnzipHelper::UnzipImpl, this,
image_path, temp_dir_path));
}
@@ -67,8 +68,8 @@ void UnzipHelper::UnzipImpl(const base::FilePath& image_path,
OnOpenSuccess(out_image_path);
zip_reader_->ExtractCurrentEntryToFilePathAsync(
- out_image_path, base::Bind(&UnzipHelper::OnComplete, this),
- base::Bind(&UnzipHelper::OnError, this, error::kUnzipGenericError),
+ out_image_path, base::BindOnce(&UnzipHelper::OnComplete, this),
+ base::BindOnce(&UnzipHelper::OnError, this, error::kUnzipGenericError),
base::Bind(&UnzipHelper::OnProgress, this, entry_info->original_size()));
}
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
index ac0689ea80a..53e015b9f4c 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
@@ -12,6 +12,7 @@
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
namespace extensions {
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
index 9652923b642..02fbee63263 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
@@ -9,7 +9,7 @@
#include "chrome/browser/extensions/api/image_writer_private/operation.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "url/gurl.h"
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc
index 3f790e96da7..c7ed15c5204 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/lazy_instance.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "extensions/browser/extension_registry.h"
#include "ui/base/ime/ime_bridge.h"
@@ -27,7 +28,7 @@ InputMethodEngineBase* GetEngineIfActive(Profile* profile,
std::string* error) {
extensions::InputImeEventRouter* event_router =
extensions::GetInputImeEventRouter(profile);
- CHECK(event_router) << kErrorRouterNotAvailable;
+ DCHECK(event_router) << kErrorRouterNotAvailable;
InputMethodEngineBase* engine =
event_router->GetEngineIfActive(extension_id, error);
return engine;
@@ -164,7 +165,7 @@ void ImeObserver::OnCompositionBoundsChanged(
const std::vector<gfx::Rect>& bounds) {}
void ImeObserver::OnSurroundingTextChanged(const std::string& component_id,
- const std::string& text,
+ const base::string16& text,
int cursor_pos,
int anchor_pos,
int offset_pos) {
@@ -173,7 +174,10 @@ void ImeObserver::OnSurroundingTextChanged(const std::string& component_id,
return;
input_ime::OnSurroundingTextChanged::SurroundingInfo info;
- info.text = text;
+ // |info.text| is encoded in UTF8 here so |info.focus| etc may not match the
+ // index in |info.text|, the javascript code on the extension side should
+ // handle it.
+ info.text = base::UTF16ToUTF8(text);
info.focus = cursor_pos;
info.anchor = anchor_pos;
info.offset = offset_pos;
@@ -419,9 +423,11 @@ ExtensionFunction::ResponseAction InputImeSendKeyEventsFunction::Run() {
event.shift_key = key_event.shift_key ? *(key_event.shift_key) : false;
event.caps_lock = key_event.caps_lock ? *(key_event.caps_lock) : false;
}
- if (!engine->SendKeyEvents(params.context_id, key_data_out))
- return RespondNow(
- Error(InformativeError(kErrorSetKeyEventsFail, function_name())));
+
+ if (!engine->SendKeyEvents(params.context_id, key_data_out, &error))
+ return RespondNow(Error(InformativeError(
+ base::StringPrintf("%s %s", kErrorSetKeyEventsFail, error.c_str()),
+ function_name())));
return RespondNow(NoArguments());
}
@@ -461,7 +467,7 @@ InputImeEventRouter* GetInputImeEventRouter(Profile* profile) {
std::string InformativeError(const std::string& error,
const char* function_name) {
- return base::StringPrintf("%s\nThrown by %s", error.c_str(), function_name);
+ return base::StringPrintf("[%s]: %s", function_name, error.c_str());
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h
index 7386a065d49..0c4eaac6687 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h
@@ -59,7 +59,7 @@ class ImeObserver : public input_method::InputMethodEngineBase::Observer {
void OnCompositionBoundsChanged(
const std::vector<gfx::Rect>& bounds) override;
void OnSurroundingTextChanged(const std::string& component_id,
- const std::string& text,
+ const base::string16& text,
int cursor_pos,
int anchor_pos,
int offset_pos) override;
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index 09aa4b1bd10..73dd19caa87 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -12,6 +12,7 @@
#include "ash/public/cpp/keyboard/keyboard_config.h"
#include "base/feature_list.h"
#include "base/macros.h"
+#include "base/strings/stringprintf.h"
#include "chrome/browser/chromeos/input_method/input_method_engine.h"
#include "chrome/browser/chromeos/input_method/native_input_method_engine.h"
#include "chrome/browser/chromeos/login/lock/screen_locker.h"
@@ -21,6 +22,7 @@
#include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
#include "chrome/common/extensions/api/input_ime.h"
#include "chrome/common/extensions/api/input_method_private.h"
+#include "chromeos/constants/chromeos_features.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/process_manager.h"
#include "extensions/common/manifest_handlers/background_info.h"
@@ -231,6 +233,8 @@ class ImeObserverChromeOS : public ui::ImeObserver {
input_context.context_id = context.id;
input_context.type = input_method_private::ParseInputContextType(
ConvertInputContextType(context));
+ input_context.mode = input_method_private::ParseInputModeType(
+ ConvertInputContextMode(context));
input_context.auto_correct = ConvertInputContextAutoCorrect(context);
input_context.auto_complete = ConvertInputContextAutoComplete(context);
input_context.auto_capitalize =
@@ -376,6 +380,41 @@ class ImeObserverChromeOS : public ui::ImeObserver {
return input_context.flags & ui::TEXT_INPUT_FLAG_HAS_BEEN_PASSWORD;
}
+ std::string ConvertInputContextMode(
+ ui::IMEEngineHandlerInterface::InputContext input_context) {
+ std::string input_mode_type = "none"; // default to nothing
+ switch (input_context.mode) {
+ case ui::TEXT_INPUT_MODE_SEARCH:
+ input_mode_type = "search";
+ break;
+ case ui::TEXT_INPUT_MODE_TEL:
+ input_mode_type = "tel";
+ break;
+ case ui::TEXT_INPUT_MODE_URL:
+ input_mode_type = "url";
+ break;
+ case ui::TEXT_INPUT_MODE_EMAIL:
+ input_mode_type = "email";
+ break;
+ case ui::TEXT_INPUT_MODE_NUMERIC:
+ input_mode_type = "numeric";
+ break;
+ case ui::TEXT_INPUT_MODE_DECIMAL:
+ input_mode_type = "decimal";
+ break;
+ case ui::TEXT_INPUT_MODE_NONE:
+ input_mode_type = "noKeyboard";
+ break;
+ case ui::TEXT_INPUT_MODE_TEXT:
+ input_mode_type = "text";
+ break;
+ default:
+ input_mode_type = "";
+ break;
+ }
+ return input_mode_type;
+ }
+
DISALLOW_COPY_AND_ASSIGN(ImeObserverChromeOS);
};
@@ -387,7 +426,7 @@ InputMethodEngine* GetEngineIfActive(Profile* profile,
const std::string& extension_id,
std::string* error) {
InputImeEventRouter* event_router = GetInputImeEventRouter(profile);
- CHECK(event_router) << kErrorRouterNotAvailable;
+ DCHECK(event_router) << kErrorRouterNotAvailable;
InputMethodEngine* engine = static_cast<InputMethodEngine*>(
event_router->GetEngineIfActive(extension_id, error));
return engine;
@@ -398,7 +437,7 @@ InputMethodEngine* GetEngine(content::BrowserContext* browser_context,
std::string* error) {
Profile* profile = Profile::FromBrowserContext(browser_context);
InputImeEventRouter* event_router = GetInputImeEventRouter(profile);
- CHECK(event_router) << kErrorRouterNotAvailable;
+ DCHECK(event_router) << kErrorRouterNotAvailable;
InputMethodEngine* engine =
static_cast<InputMethodEngine*>(event_router->GetEngine(extension_id));
DCHECK(engine) << kErrorEngineNotAvailable;
@@ -461,9 +500,11 @@ bool InputImeEventRouter::RegisterImeExtension(
}
auto observer = std::make_unique<ImeObserverChromeOS>(extension_id, profile);
- auto engine = (extension_id == "jkghodnilhceideoidjikpgommlajknk")
- ? std::make_unique<chromeos::NativeInputMethodEngine>()
- : std::make_unique<chromeos::InputMethodEngine>();
+ auto engine =
+ (extension_id == "jkghodnilhceideoidjikpgommlajknk" &&
+ base::FeatureList::IsEnabled(chromeos::features::kNativeRuleBasedTyping))
+ ? std::make_unique<chromeos::NativeInputMethodEngine>()
+ : std::make_unique<chromeos::InputMethodEngine>();
engine->Initialize(std::move(observer), extension_id.c_str(), profile);
engine_map_[extension_id] = std::move(engine);
@@ -699,9 +740,11 @@ ExtensionFunction::ResponseAction InputImeSetMenuItemsFunction::Run() {
SetMenuItemToMenu(item_in, &items_out.back());
}
- if (!engine->SetMenuItems(items_out))
- return RespondNow(
- Error(InformativeError(kErrorSetMenuItemsFail, function_name())));
+ if (!engine->SetMenuItems(items_out, &error)) {
+ return RespondNow(Error(InformativeError(
+ base::StringPrintf("%s %s", kErrorSetMenuItemsFail, error.c_str()),
+ function_name())));
+ }
return RespondNow(NoArguments());
}
@@ -724,9 +767,11 @@ ExtensionFunction::ResponseAction InputImeUpdateMenuItemsFunction::Run() {
SetMenuItemToMenu(item_in, &items_out.back());
}
- if (!engine->UpdateMenuItems(items_out))
- return RespondNow(
- Error(InformativeError(kErrorUpdateMenuItemsFail, function_name())));
+ if (!engine->UpdateMenuItems(items_out, &error)) {
+ return RespondNow(Error(InformativeError(
+ base::StringPrintf("%s %s", kErrorUpdateMenuItemsFail, error.c_str()),
+ function_name())));
+ }
return RespondNow(NoArguments());
}
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
index 32086846ff6..64c0f13ffe2 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_nonchromeos.cc
@@ -128,7 +128,7 @@ InputMethodEngine* GetEngineIfActive(content::BrowserContext* browser_context,
std::string* error) {
Profile* profile = Profile::FromBrowserContext(browser_context);
InputImeEventRouter* event_router = GetInputImeEventRouter(profile);
- CHECK(event_router) << kErrorRouterNotAvailable;
+ DCHECK(event_router) << kErrorRouterNotAvailable;
InputMethodEngine* engine = static_cast<InputMethodEngine*>(
event_router->GetEngineIfActive(extension_id, error));
return engine;
diff --git a/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc b/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc
index 15ab8552a61..77891527863 100644
--- a/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc
+++ b/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/time/time.h"
#include "chrome/browser/gcm/instance_id/instance_id_profile_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/instance_id.h"
@@ -70,10 +71,7 @@ ExtensionFunction::ResponseAction InstanceIDApiFunction::Run() {
}
bool InstanceIDApiFunction::IsEnabled() const {
- Profile* profile = Profile::FromBrowserContext(browser_context());
-
- return instance_id::InstanceIDProfileService::IsInstanceIDEnabled(
- profile->GetPrefs());
+ return instance_id::InstanceIDProfileService::IsInstanceIDEnabled();
}
instance_id::InstanceID* InstanceIDApiFunction::GetInstanceID() const {
@@ -88,7 +86,7 @@ InstanceIDGetIDFunction::~InstanceIDGetIDFunction() {}
ExtensionFunction::ResponseAction InstanceIDGetIDFunction::DoWork() {
GetInstanceID()->GetID(
- base::Bind(&InstanceIDGetIDFunction::GetIDCompleted, this));
+ base::BindOnce(&InstanceIDGetIDFunction::GetIDCompleted, this));
return RespondLater();
}
@@ -101,9 +99,8 @@ InstanceIDGetCreationTimeFunction::InstanceIDGetCreationTimeFunction() {}
InstanceIDGetCreationTimeFunction::~InstanceIDGetCreationTimeFunction() {}
ExtensionFunction::ResponseAction InstanceIDGetCreationTimeFunction::DoWork() {
- GetInstanceID()->GetCreationTime(
- base::Bind(&InstanceIDGetCreationTimeFunction::GetCreationTimeCompleted,
- this));
+ GetInstanceID()->GetCreationTime(base::BindOnce(
+ &InstanceIDGetCreationTimeFunction::GetCreationTimeCompleted, this));
return RespondLater();
}
@@ -131,9 +128,10 @@ ExtensionFunction::ResponseAction InstanceIDGetTokenFunction::DoWork() {
GetInstanceID()->GetToken(
params->get_token_params.authorized_entity,
- params->get_token_params.scope, options,
+ params->get_token_params.scope, /*time_to_live=*/base::TimeDelta(),
+ options,
/*flags=*/{},
- base::Bind(&InstanceIDGetTokenFunction::GetTokenCompleted, this));
+ base::BindOnce(&InstanceIDGetTokenFunction::GetTokenCompleted, this));
return RespondLater();
}
@@ -159,7 +157,8 @@ ExtensionFunction::ResponseAction InstanceIDDeleteTokenFunction::DoWork() {
GetInstanceID()->DeleteToken(
params->delete_token_params.authorized_entity,
params->delete_token_params.scope,
- base::Bind(&InstanceIDDeleteTokenFunction::DeleteTokenCompleted, this));
+ base::BindOnce(&InstanceIDDeleteTokenFunction::DeleteTokenCompleted,
+ this));
return RespondLater();
}
@@ -178,7 +177,7 @@ InstanceIDDeleteIDFunction::~InstanceIDDeleteIDFunction() {}
ExtensionFunction::ResponseAction InstanceIDDeleteIDFunction::DoWork() {
GetInstanceID()->DeleteID(
- base::Bind(&InstanceIDDeleteIDFunction::DeleteIDCompleted, this));
+ base::BindOnce(&InstanceIDDeleteIDFunction::DeleteIDCompleted, this));
return RespondLater();
}
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/OWNERS b/chromium/chrome/browser/extensions/api/language_settings_private/OWNERS
index 057813143a1..14a91b03c35 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/OWNERS
@@ -1,2 +1,5 @@
michaelpg@chromium.org
-stevenjb@chromium.org
+
+file://chrome/browser/resources/settings/OWNERS
+
+# COMPONENT: UI>Settings
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
index 1c3825e4e88..340c2c0f3c6 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
@@ -38,6 +38,7 @@
#include "components/spellcheck/browser/spellcheck_platform.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_features.h"
+#include "components/spellcheck/spellcheck_buildflags.h"
#include "components/translate/core/browser/translate_download_manager.h"
#include "components/translate/core/browser/translate_prefs.h"
#include "third_party/icu/source/i18n/unicode/coll.h"
@@ -204,10 +205,6 @@ LanguageSettingsPrivateGetLanguageListFunction::Run() {
translate::TranslatePrefs::GetLanguageInfoList(
app_locale, translate_prefs->IsTranslateAllowedByPolicy(), &languages);
- // Get the list of available locales (display languages) and convert to a set.
- const base::flat_set<std::string> locale_set(
- l10n_util::GetAvailableLocales());
-
// Get the list of spell check languages and convert to a set.
std::vector<std::string> spellcheck_languages =
spellcheck::SpellCheckLanguages();
@@ -503,7 +500,8 @@ LanguageSettingsPrivateAddSpellcheckWordFunction::Run() {
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
if (spellcheck::UseBrowserSpellChecker()) {
- spellcheck_platform::AddWord(base::UTF8ToUTF16(params->word));
+ spellcheck_platform::AddWord(service->platform_spell_checker(),
+ base::UTF8ToUTF16(params->word));
}
#endif
@@ -528,7 +526,8 @@ LanguageSettingsPrivateRemoveSpellcheckWordFunction::Run() {
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
if (spellcheck::UseBrowserSpellChecker()) {
- spellcheck_platform::RemoveWord(base::UTF8ToUTF16(params->word));
+ spellcheck_platform::RemoveWord(service->platform_spell_checker(),
+ base::UTF8ToUTF16(params->word));
}
#endif
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
index 634e75751ea..39e7edbf4c8 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
@@ -317,7 +317,7 @@ void LanguageSettingsPrivateDelegate::
void LanguageSettingsPrivateDelegate::RetryDownloadHunspellDictionary(
const std::string& language) {
- for (const base::WeakPtr<SpellcheckHunspellDictionary> dictionary :
+ for (const base::WeakPtr<SpellcheckHunspellDictionary>& dictionary :
GetHunspellDictionaries()) {
if (dictionary && dictionary->GetLanguage() == language) {
dictionary->RetryDownloadDictionary(context_);
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.cc b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.cc
index 05ce0fccf74..dd00dbc5a47 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.cc
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.cc
@@ -55,8 +55,4 @@ bool LanguageSettingsPrivateDelegateFactory::
return true;
}
-bool LanguageSettingsPrivateDelegateFactory::ServiceIsNULLWhileTesting() const {
- return false;
-}
-
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.h b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.h
index 5f3198c36c0..f72ab5c46ed 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.h
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate_factory.h
@@ -33,7 +33,6 @@ class LanguageSettingsPrivateDelegateFactory
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
bool ServiceIsCreatedWithBrowserContext() const override;
- bool ServiceIsNULLWhileTesting() const override;
private:
friend struct base::DefaultSingletonTraits<
diff --git a/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
index 6de9df30f80..cc862ba6cb7 100644
--- a/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc
@@ -50,6 +50,7 @@
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
+#include "extensions/common/api/management.h"
#include "extensions/common/extension.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h"
@@ -64,6 +65,13 @@
#include "components/arc/session/arc_bridge_service.h"
#endif // OS_CHROMEOS
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+// TODO(https://crbug.com/1060801): Here and elsewhere, possibly switch build
+// flag to #if defined(OS_CHROMEOS)
+#include "chrome/browser/supervised_user/supervised_user_service.h"
+#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
+#endif
+
namespace {
#if defined(OS_CHROMEOS)
@@ -227,7 +235,7 @@ class ChromeAppForLinkDelegate : public extensions::AppForLinkDelegate {
auto web_app_info = std::make_unique<WebApplicationInfo>();
web_app_info->title = base::UTF8ToUTF16(title);
web_app_info->app_url = launch_url;
- web_app_info->display_mode = blink::mojom::DisplayMode::kBrowser;
+ web_app_info->display_mode = web_app::DisplayMode::kBrowser;
web_app_info->open_as_window = false;
if (!image_result.image.IsEmpty()) {
@@ -246,6 +254,59 @@ class ChromeAppForLinkDelegate : public extensions::AppForLinkDelegate {
base::RetainedRef(function)));
}
+ extensions::api::management::ExtensionInfo CreateExtensionInfoFromWebApp(
+ const std::string& app_id,
+ content::BrowserContext* context) override {
+ auto* provider = web_app::WebAppProviderBase::GetProviderBase(
+ Profile::FromBrowserContext(context));
+ DCHECK(provider);
+ const web_app::AppRegistrar& registrar = provider->registrar();
+
+ extensions::api::management::ExtensionInfo info;
+ info.id = app_id;
+ info.name = registrar.GetAppShortName(app_id);
+ info.enabled = registrar.IsLocallyInstalled(app_id);
+ info.install_type =
+ extensions::api::management::EXTENSION_INSTALL_TYPE_OTHER;
+ info.is_app = true;
+ info.type = extensions::api::management::EXTENSION_TYPE_HOSTED_APP;
+ info.app_launch_url =
+ std::make_unique<std::string>(registrar.GetAppLaunchURL(app_id).spec());
+
+ info.icons =
+ std::make_unique<std::vector<extensions::api::management::IconInfo>>();
+ std::vector<WebApplicationIconInfo> icon_infos =
+ registrar.GetAppIconInfos(app_id);
+ info.icons->reserve(icon_infos.size());
+ for (const WebApplicationIconInfo& web_app_icon_info : icon_infos) {
+ extensions::api::management::IconInfo icon_info;
+ icon_info.size = web_app_icon_info.square_size_px;
+ icon_info.url = web_app_icon_info.url.spec();
+ info.icons->push_back(std::move(icon_info));
+ }
+
+ switch (registrar.GetAppDisplayMode(app_id)) {
+ case web_app::DisplayMode::kBrowser:
+ info.launch_type =
+ extensions::api::management::LAUNCH_TYPE_OPEN_AS_REGULAR_TAB;
+ break;
+ case web_app::DisplayMode::kMinimalUi:
+ case web_app::DisplayMode::kStandalone:
+ info.launch_type =
+ extensions::api::management::LAUNCH_TYPE_OPEN_AS_WINDOW;
+ break;
+ case web_app::DisplayMode::kFullscreen:
+ info.launch_type =
+ extensions::api::management::LAUNCH_TYPE_OPEN_FULL_SCREEN;
+ break;
+ case web_app::DisplayMode::kUndefined:
+ info.launch_type = extensions::api::management::LAUNCH_TYPE_NONE;
+ break;
+ }
+
+ return info;
+ }
+
// Used for favicon loading tasks.
base::CancelableTaskTracker cancelable_task_tracker_;
@@ -422,9 +483,9 @@ ChromeManagementAPIDelegate::GenerateAppForLinkFunctionDelegate(
favicon_service->GetFaviconImageForPageURL(
launch_url,
- base::Bind(&ChromeAppForLinkDelegate::OnFaviconForApp,
- base::Unretained(delegate), base::RetainedRef(function),
- context, title, launch_url),
+ base::BindOnce(&ChromeAppForLinkDelegate::OnFaviconForApp,
+ base::Unretained(delegate), base::RetainedRef(function),
+ context, title, launch_url),
&delegate->cancelable_task_tracker_);
return std::unique_ptr<extensions::AppForLinkDelegate>(delegate);
@@ -524,6 +585,16 @@ void ChromeManagementAPIDelegate::EnableExtension(
const extensions::Extension* extension =
extensions::ExtensionRegistry::Get(context)->GetExtensionById(
extension_id, extensions::ExtensionRegistry::EVERYTHING);
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+ // We add approval for the extension here under the assumption that prior
+ // to this point, the supervised child user has already been prompted
+ // for, and received parent permission to install the extension.
+ SupervisedUserService* supervised_user_service =
+ SupervisedUserServiceFactory::GetForBrowserContext(context);
+ supervised_user_service->AddOrUpdateExtensionApproval(*extension);
+#endif
+
// If the extension was disabled for a permissions increase, the Management
// API will have displayed a re-enable prompt to the user, so we know it's
// safe to grant permissions here.
diff --git a/chromium/chrome/browser/extensions/api/management/management_api_non_persistent_apitest.cc b/chromium/chrome/browser/extensions/api/management/management_api_non_persistent_apitest.cc
index 3d664ad345b..f0bea4f5dab 100644
--- a/chromium/chrome/browser/extensions/api/management/management_api_non_persistent_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/management/management_api_non_persistent_apitest.cc
@@ -64,7 +64,12 @@ IN_PROC_BROWSER_TEST_P(ManagementApiNonPersistentApiTest, UninstallSelf) {
extensions::ExtensionRegistry::Get(browser()->profile()));
base::FilePath path = test_dir.Pack();
- scoped_refptr<const Extension> extension = LoadExtension(path);
+ // Note: We pass kFlagDontWaitForExtensionRenderers because the extension
+ // uninstalls itself, so the ExtensionHost never fully finishes loading. Since
+ // we wait for the uninstall explicitly, this isn't racy.
+ scoped_refptr<const Extension> extension =
+ LoadExtensionWithFlags(path, kFlagDontWaitForExtensionRenderers);
+
EXPECT_EQ(extension, observer.WaitForExtensionUninstalled());
}
diff --git a/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc b/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc
index badfd1880a9..9fd1957f6b0 100644
--- a/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc
@@ -8,6 +8,8 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -20,6 +22,7 @@
#include "content/public/test/web_contents_tester.h"
#include "extensions/browser/api/management/management_api.h"
#include "extensions/browser/api/management/management_api_constants.h"
+#include "extensions/browser/disable_reason.h"
#include "extensions/browser/event_router_factory.h"
#include "extensions/browser/extension_dialog_auto_confirm.h"
#include "extensions/browser/extension_prefs.h"
@@ -34,6 +37,13 @@
#include "extensions/common/extension_set.h"
#include "extensions/common/permissions/permission_set.h"
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+#include "chrome/browser/supervised_user/supervised_user_service.h"
+#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/gpu_data_manager.h"
+#endif
+
namespace extensions {
namespace {
@@ -49,8 +59,6 @@ std::unique_ptr<KeyedService> BuildEventRouter(
profile, ExtensionPrefs::Get(profile));
}
-} // namespace
-
namespace constants = extension_management_api_constants;
// TODO(devlin): Unittests are awesome. Test more with unittests and less with
@@ -65,13 +73,25 @@ class ManagementApiUnitTest : public ExtensionServiceTestWithInstall {
bool RunFunction(const scoped_refptr<ExtensionFunction>& function,
const base::ListValue& args);
+ // Runs the management.setEnabled() function to enable an extension.
+ bool RunSetEnabledFunction(content::WebContents* web_contents,
+ const std::string& extension_id,
+ bool use_user_gesture,
+ bool accept_dialog,
+ std::string* error);
+
Browser* browser() { return browser_.get(); }
- private:
+ // Returns the initialization parameters for the extension service.
+ virtual ExtensionServiceInitParams GetExtensionServiceInitParams() {
+ return CreateDefaultInitParams();
+ }
+
// ExtensionServiceTestBase:
void SetUp() override;
void TearDown() override;
+ private:
// The browser (and accompanying window).
std::unique_ptr<TestBrowserWindow> browser_window_;
std::unique_ptr<Browser> browser_;
@@ -87,9 +107,34 @@ bool ManagementApiUnitTest::RunFunction(
api_test_utils::NONE);
}
+bool ManagementApiUnitTest::RunSetEnabledFunction(
+ content::WebContents* web_contents,
+ const std::string& extension_id,
+ bool use_user_gesture,
+ bool accept_dialog,
+ std::string* error) {
+ ScopedTestDialogAutoConfirm auto_confirm(
+ accept_dialog ? ScopedTestDialogAutoConfirm::ACCEPT
+ : ScopedTestDialogAutoConfirm::CANCEL);
+ base::Optional<ExtensionFunction::ScopedUserGestureForTests> gesture =
+ base::nullopt;
+ if (use_user_gesture)
+ gesture.emplace();
+ scoped_refptr<ManagementSetEnabledFunction> function =
+ base::MakeRefCounted<ManagementSetEnabledFunction>();
+ function->set_browser_context(profile());
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ base::ListValue args;
+ args.AppendString(extension_id);
+ args.AppendBoolean(/*enabled=*/true);
+ bool result = RunFunction(function, args);
+ *error = function->GetError();
+ return result;
+}
+
void ManagementApiUnitTest::SetUp() {
ExtensionServiceTestBase::SetUp();
- InitializeEmptyExtensionService();
+ InitializeExtensionService(GetExtensionServiceInitParams());
ManagementAPI::GetFactoryInstance()->SetTestingFactory(
profile(), base::BindRepeating(&BuildManagementApi));
@@ -631,35 +676,15 @@ TEST_F(ManagementApiUnitTest, SetEnabledAfterIncreasedPermissions) {
// Due to a permission increase, prefs will contain escalation information.
EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
- auto enable_extension_via_management_api = [this, &web_contents](
- const std::string& extension_id, bool use_user_gesture,
- bool accept_dialog, bool expect_success) {
- ScopedTestDialogAutoConfirm auto_confirm(
- accept_dialog ? ScopedTestDialogAutoConfirm::ACCEPT
- : ScopedTestDialogAutoConfirm::CANCEL);
- std::unique_ptr<ExtensionFunction::ScopedUserGestureForTests> gesture;
- if (use_user_gesture)
- gesture.reset(new ExtensionFunction::ScopedUserGestureForTests);
- scoped_refptr<ManagementSetEnabledFunction> function(
- new ManagementSetEnabledFunction());
- function->set_browser_context(profile());
- function->SetRenderFrameHost(web_contents->GetMainFrame());
- base::ListValue args;
- args.AppendString(extension_id);
- args.AppendBoolean(true);
- if (expect_success) {
- EXPECT_TRUE(RunFunction(function, args)) << function->GetError();
- } else {
- EXPECT_FALSE(RunFunction(function, args)) << function->GetError();
- }
- };
-
// 1) Confirm re-enable prompt without user gesture, expect the extension to
// stay disabled.
{
- enable_extension_via_management_api(
- extension_id, false /* use_user_gesture */, true /* accept_dialog */,
- false /* expect_success */);
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents.get(), extension_id,
+ false /* use_user_gesture */,
+ true /* accept_dialog */, &error);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(error.empty());
EXPECT_FALSE(registry()->enabled_extensions().Contains(extension_id));
// Prefs should still contain permissions escalation information.
EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
@@ -668,9 +693,12 @@ TEST_F(ManagementApiUnitTest, SetEnabledAfterIncreasedPermissions) {
// 2) Deny re-enable prompt without user gesture, expect the extension to stay
// disabled.
{
- enable_extension_via_management_api(
- extension_id, false /* use_user_gesture */, false /* accept_dialog */,
- false /* expect_success */);
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents.get(), extension_id,
+ false /* use_user_gesture */,
+ false /* accept_dialog */, &error);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(error.empty());
EXPECT_FALSE(registry()->enabled_extensions().Contains(extension_id));
// Prefs should still contain permissions escalation information.
EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
@@ -679,9 +707,12 @@ TEST_F(ManagementApiUnitTest, SetEnabledAfterIncreasedPermissions) {
// 3) Deny re-enable prompt with user gesture, expect the extension to stay
// disabled.
{
- enable_extension_via_management_api(
- extension_id, true /* use_user_gesture */, false /* accept_dialog */,
- false /* expect_success */);
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents.get(), extension_id,
+ true /* use_user_gesture */,
+ false /* accept_dialog */, &error);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(error.empty());
EXPECT_FALSE(registry()->enabled_extensions().Contains(extension_id));
// Prefs should still contain permissions escalation information.
EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
@@ -690,9 +721,12 @@ TEST_F(ManagementApiUnitTest, SetEnabledAfterIncreasedPermissions) {
// 4) Accept re-enable prompt with user gesture, expect the extension to be
// enabled.
{
- enable_extension_via_management_api(
- extension_id, true /* use_user_gesture */, true /* accept_dialog */,
- true /* expect_success */);
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents.get(), extension_id,
+ true /* use_user_gesture */,
+ true /* accept_dialog */, &error);
+ EXPECT_TRUE(success) << error;
+ EXPECT_TRUE(error.empty());
EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
// Prefs will no longer contain the escalation information as user has
// accepted increased permissions.
@@ -705,4 +739,587 @@ TEST_F(ManagementApiUnitTest, SetEnabledAfterIncreasedPermissions) {
EXPECT_FALSE(known_perms->IsEmpty());
}
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+
+// A delegate that senses when extensions are enabled or disabled.
+class TestManagementAPIDelegate : public ManagementAPIDelegate {
+ public:
+ TestManagementAPIDelegate() = default;
+ ~TestManagementAPIDelegate() override = default;
+
+ void LaunchAppFunctionDelegate(
+ const Extension* extension,
+ content::BrowserContext* context) const override {}
+ GURL GetFullLaunchURL(const Extension* extension) const override {
+ return GURL();
+ }
+ LaunchType GetLaunchType(const ExtensionPrefs* prefs,
+ const Extension* extension) const override {
+ return LaunchType::LAUNCH_TYPE_DEFAULT;
+ }
+ void GetPermissionWarningsByManifestFunctionDelegate(
+ ManagementGetPermissionWarningsByManifestFunction* function,
+ const std::string& manifest_str) const override {}
+ std::unique_ptr<InstallPromptDelegate> SetEnabledFunctionDelegate(
+ content::WebContents* web_contents,
+ content::BrowserContext* browser_context,
+ const Extension* extension,
+ const base::Callback<void(bool)>& callback) const override {
+ return nullptr;
+ }
+ void EnableExtension(content::BrowserContext* context,
+ const std::string& extension_id) const override {
+ ++enable_count_;
+ }
+ void DisableExtension(
+ content::BrowserContext* context,
+ const Extension* source_extension,
+ const std::string& extension_id,
+ disable_reason::DisableReason disable_reason) const override {}
+ std::unique_ptr<UninstallDialogDelegate> UninstallFunctionDelegate(
+ ManagementUninstallFunctionBase* function,
+ const Extension* target_extension,
+ bool show_programmatic_uninstall_ui) const override {
+ return nullptr;
+ }
+ bool UninstallExtension(content::BrowserContext* context,
+ const std::string& transient_extension_id,
+ UninstallReason reason,
+ base::string16* error) const override {
+ return true;
+ }
+ bool CreateAppShortcutFunctionDelegate(
+ ManagementCreateAppShortcutFunction* function,
+ const Extension* extension,
+ std::string* error) const override {
+ return true;
+ }
+ void SetLaunchType(content::BrowserContext* context,
+ const std::string& extension_id,
+ LaunchType launch_type) const override {}
+ std::unique_ptr<AppForLinkDelegate> GenerateAppForLinkFunctionDelegate(
+ ManagementGenerateAppForLinkFunction* function,
+ content::BrowserContext* context,
+ const std::string& title,
+ const GURL& launch_url) const override {
+ return nullptr;
+ }
+ bool CanContextInstallWebApps(
+ content::BrowserContext* context) const override {
+ return true;
+ }
+ void InstallOrLaunchReplacementWebApp(
+ content::BrowserContext* context,
+ const GURL& web_app_url,
+ InstallOrLaunchWebAppCallback callback) const override {}
+ bool CanContextInstallAndroidApps(
+ content::BrowserContext* context) const override {
+ return true;
+ }
+ void CheckAndroidAppInstallStatus(
+ const std::string& package_name,
+ AndroidAppInstallStatusCallback callback) const override {}
+ void InstallReplacementAndroidApp(
+ const std::string& package_name,
+ InstallAndroidAppCallback callback) const override {}
+ GURL GetIconURL(const Extension* extension,
+ int icon_size,
+ ExtensionIconSet::MatchType match,
+ bool grayscale) const override {
+ return GURL();
+ }
+
+ // EnableExtension is const, so this is mutable.
+ mutable int enable_count_ = 0;
+};
+
+// A delegate that allows a child to try to install an extension and tracks
+// whether the parent permission dialog would have opened.
+class TestSupervisedUserServiceDelegate : public SupervisedUserServiceDelegate {
+ public:
+ TestSupervisedUserServiceDelegate() = default;
+ ~TestSupervisedUserServiceDelegate() override = default;
+
+ // SupervisedUserServiceDelegate:
+ bool IsSupervisedChildWhoMayInstallExtensions(
+ content::BrowserContext* context) const override {
+ return true;
+ }
+ bool IsExtensionAllowedByParent(
+ const extensions::Extension& extension,
+ content::BrowserContext* context) const override {
+ return false;
+ }
+ void ShowParentPermissionDialogForExtension(
+ const extensions::Extension& extension,
+ content::BrowserContext* context,
+ content::WebContents* contents,
+ ParentPermissionDialogDoneCallback done_callback) override {
+ ++show_dialog_count_;
+ std::move(done_callback).Run(dialog_result_);
+ }
+
+ int show_dialog_count_ = 0;
+ ParentPermissionDialogResult dialog_result_ =
+ ParentPermissionDialogResult::kParentPermissionFailed;
+};
+
+// Tests for supervised users (child accounts). Supervised users are not allowed
+// to install apps or extensions unless their parent approves.
+class ManagementApiSupervisedUserTest : public ManagementApiUnitTest {
+ public:
+ ManagementApiSupervisedUserTest() = default;
+ ~ManagementApiSupervisedUserTest() override = default;
+
+ // ManagementApiUnitTest:
+ ExtensionServiceInitParams GetExtensionServiceInitParams() override {
+ ExtensionServiceInitParams params = CreateDefaultInitParams();
+ // Force a TestingPrefServiceSyncable to be created.
+ params.pref_file.clear();
+ params.profile_is_supervised = true;
+ return params;
+ }
+
+ SupervisedUserService* GetSupervisedUserService() {
+ return SupervisedUserServiceFactory::GetForProfile(profile());
+ }
+
+ void SetUp() override {
+ ManagementApiUnitTest::SetUp();
+
+ // Ensure the child has a custodian.
+ PrefService* prefs = browser()->profile()->GetPrefs();
+ prefs->SetString(prefs::kSupervisedUserCustodianEmail,
+ "test_parent_0@google.com");
+ prefs->SetString(prefs::kSupervisedUserCustodianObfuscatedGaiaId,
+ "239029320");
+
+ GetSupervisedUserService()->Init();
+ // Set the pref to allow the child to request extension install.
+ GetSupervisedUserService()
+ ->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(true);
+
+ // Create a WebContents to simulate the Chrome Web Store.
+ web_contents_ =
+ content::WebContentsTester::CreateTestWebContents(profile(), nullptr);
+
+ management_api_ = ManagementAPI::GetFactoryInstance()->Get(profile());
+
+ // Install a SupervisedUserServiceDelegate to sense the dialog state.
+ supervised_user_delegate_ = new TestSupervisedUserServiceDelegate;
+ management_api_->set_supervised_user_service_delegate_for_test(
+ base::WrapUnique(supervised_user_delegate_));
+ }
+
+ std::unique_ptr<content::WebContents> web_contents_;
+ ManagementAPI* management_api_ = nullptr;
+ TestSupervisedUserServiceDelegate* supervised_user_delegate_ = nullptr;
+};
+
+// Tests enabling an extension via management API after it was disabled due to
+// permission increase for supervised users.
+// Prevents a regression to crbug/1068660.
+TEST_F(ManagementApiSupervisedUserTest, SetEnabled_AfterIncreasedPermissions) {
+ // Preconditions.
+ ASSERT_TRUE(profile()->IsChild());
+
+ base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
+ base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
+
+ base::FilePath path = base_path.AppendASCII("v1");
+ const Extension* extension =
+ PackAndInstallCRX(path, pem_path, INSTALL_WITHOUT_LOAD);
+ ASSERT_TRUE(extension);
+ // The extension should be installed but disabled pending custodian approval.
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
+ // Save the id, as |extension| will be destroyed during updating.
+ const std::string extension_id = extension->id();
+
+ // Simulate parent approval for the extension installation.
+ GetSupervisedUserService()->AddOrUpdateExtensionApproval(*extension);
+ // The extension should be enabled now.
+ EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
+
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+ std::unique_ptr<const PermissionSet> known_perms =
+ prefs->GetGrantedPermissions(extension_id);
+ ASSERT_TRUE(known_perms);
+ // v1 extension doesn't have any permissions.
+ EXPECT_TRUE(known_perms->IsEmpty());
+
+ // Update to a new version with increased permissions.
+ path = base_path.AppendASCII("v2");
+ PackCRXAndUpdateExtension(extension_id, path, pem_path, DISABLED);
+ // The extension should be disabled.
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
+ // Due to a permission increase, prefs will contain escalation information.
+ EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
+
+ // Accept re-enable prompt with user gesture, expect the extension to be
+ // enabled.
+ {
+ // The supervised user will approve the additional permissions without
+ // parent approval.
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents_.get(), extension_id,
+ /*use_user_gesture=*/true,
+ /*accept_dialog=*/true, &error);
+ EXPECT_TRUE(success) << error;
+ EXPECT_TRUE(error.empty());
+ EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
+ // Prefs will no longer contain the escalation information as the supervised
+ // user has accepted the increased permissions.
+ EXPECT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id));
+ }
+
+ // Permissions for v2 extension should be granted now.
+ known_perms = prefs->GetGrantedPermissions(extension_id);
+ ASSERT_TRUE(known_perms);
+ EXPECT_FALSE(known_perms->IsEmpty());
+
+ // The parent approval dialog should have not appeared.
+ EXPECT_EQ(0, supervised_user_delegate_->show_dialog_count_);
+}
+
+// Tests that supervised users can't approve permission updates by themselves
+// when the "Permissions for sites, apps and extensions" toggle is off.
+TEST_F(ManagementApiSupervisedUserTest,
+ SetEnabled_CantApprovePermissionUpdatesToggleOff) {
+ // Preconditions.
+ ASSERT_TRUE(profile()->IsChild());
+
+ base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
+ base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
+
+ base::FilePath path = base_path.AppendASCII("v1");
+ const Extension* extension =
+ PackAndInstallCRX(path, pem_path, INSTALL_WITHOUT_LOAD);
+ ASSERT_TRUE(extension);
+ // The extension should be installed but disabled pending custodian approval.
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
+ // Save the id, as |extension| will be destroyed during updating.
+ const std::string extension_id = extension->id();
+
+ // Simulate parent approval for the extension installation.
+ GetSupervisedUserService()->AddOrUpdateExtensionApproval(*extension);
+ // The extension should be enabled now.
+ EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
+
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+ std::unique_ptr<const PermissionSet> known_perms =
+ prefs->GetGrantedPermissions(extension_id);
+ ASSERT_TRUE(known_perms);
+ // v1 extension doesn't have any permissions.
+ EXPECT_TRUE(known_perms->IsEmpty());
+
+ // Update to a new version with increased permissions.
+ path = base_path.AppendASCII("v2");
+ PackCRXAndUpdateExtension(extension_id, path, pem_path, DISABLED);
+ // The extension should be disabled.
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
+ // Due to a permission increase, prefs will contain escalation information.
+ EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
+
+ // If the "Permissions for sites, apps and extensions" toggle is off, then the
+ // enable attempt should fail.
+ {
+ GetSupervisedUserService()
+ ->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(false);
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents_.get(), extension_id,
+ /*use_user_gesture=*/true,
+ /*accept_dialog=*/true, &error);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(error.empty());
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
+ // Prefs will still contain the escalation information as the enable attempt
+ // failed.
+ EXPECT_TRUE(prefs->DidExtensionEscalatePermissions(extension_id));
+ }
+
+ // Permissions for v2 extension should not be granted.
+ known_perms = prefs->GetGrantedPermissions(extension_id);
+ ASSERT_TRUE(known_perms);
+ EXPECT_TRUE(known_perms->IsEmpty());
+
+ // The parent approval dialog should have not appeared. The parent approval
+ // dialog should never appear when the "Permissions for sites, apps and
+ // extensions" toggle is off.
+ EXPECT_EQ(0, supervised_user_delegate_->show_dialog_count_);
+}
+
+// Tests that if an extension still requires parental consent, the supervised
+// user approving it for permissions increase won't enable the extension and
+// bypass parental consent.
+// Prevents a regression to crbug/1070760.
+TEST_F(ManagementApiSupervisedUserTest,
+ SetEnabled_CustodianApprovalRequiredAndPermissionsIncrease) {
+ // Preconditions.
+ ASSERT_TRUE(profile()->IsChild());
+
+ base::FilePath base_path = data_dir().AppendASCII("permissions_increase");
+ base::FilePath pem_path = base_path.AppendASCII("permissions.pem");
+
+ base::FilePath path = base_path.AppendASCII("v1");
+ const Extension* extension =
+ PackAndInstallCRX(path, pem_path, INSTALL_WITHOUT_LOAD);
+ ASSERT_TRUE(extension);
+ // The extension should be installed but disabled pending custodian approval.
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
+ // Save the id, as |extension| will be destroyed during updating.
+ const std::string extension_id = extension->id();
+
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+ std::unique_ptr<const PermissionSet> known_perms =
+ prefs->GetGrantedPermissions(extension_id);
+ ASSERT_TRUE(known_perms);
+ // v1 extension doesn't have any permissions.
+ EXPECT_TRUE(known_perms->IsEmpty());
+
+ // Update to a new version with increased permissions.
+ path = base_path.AppendASCII("v2");
+ PackCRXAndUpdateExtension(extension_id, path, pem_path, DISABLED);
+ // The extension should still be disabled.
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
+ // This extension has two concurrent disable reasons.
+ EXPECT_TRUE(prefs->HasDisableReason(
+ extension_id, disable_reason::DISABLE_PERMISSIONS_INCREASE));
+ EXPECT_TRUE(prefs->HasDisableReason(
+ extension_id, disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
+
+ // The supervised user trying to enable without parent approval should fail.
+ {
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents_.get(), extension_id,
+ /*use_user_gesture=*/true,
+ /*accept_dialog=*/true, &error);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(error.empty());
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension_id));
+ // Both disable reasons should still be present.
+ EXPECT_TRUE(prefs->HasDisableReason(
+ extension_id, disable_reason::DISABLE_PERMISSIONS_INCREASE));
+ EXPECT_TRUE(prefs->HasDisableReason(
+ extension_id, disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
+ }
+
+ // Permissions for v2 extension should not be granted.
+ known_perms = prefs->GetGrantedPermissions(extension_id);
+ ASSERT_TRUE(known_perms);
+ EXPECT_TRUE(known_perms->IsEmpty());
+
+ // The parent approval dialog should have appeared.
+ EXPECT_EQ(1, supervised_user_delegate_->show_dialog_count_);
+
+ // Now try again with parent approval, and this should succeed.
+ {
+ supervised_user_delegate_->dialog_result_ = SupervisedUserServiceDelegate::
+ ParentPermissionDialogResult::kParentPermissionReceived;
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents_.get(), extension_id,
+ /*use_user_gesture=*/true,
+ /*accept_dialog=*/true, &error);
+ EXPECT_TRUE(success) << error;
+ EXPECT_TRUE(error.empty());
+ EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_id));
+ // All disable reasons are gone.
+ EXPECT_FALSE(prefs->DidExtensionEscalatePermissions(extension_id));
+ EXPECT_FALSE(prefs->HasDisableReason(
+ extension_id, disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
+ }
+
+ // Permissions for v2 extension should now be granted.
+ known_perms = prefs->GetGrantedPermissions(extension_id);
+ ASSERT_TRUE(known_perms);
+ EXPECT_FALSE(known_perms->IsEmpty());
+
+ // The parent approval dialog should have appeared again.
+ EXPECT_EQ(2, supervised_user_delegate_->show_dialog_count_);
+}
+
+// Tests that trying to enable an extension with parent approval for supervised
+// users still fails, if there's unsupported requirements.
+TEST_F(ManagementApiSupervisedUserTest, SetEnabled_UnsupportedRequirement) {
+ // Preconditions.
+ ASSERT_TRUE(profile()->IsChild());
+ ASSERT_EQ(0, supervised_user_delegate_->show_dialog_count_);
+
+ // No WebGL will be the unsupported requirement.
+ content::GpuDataManager::GetInstance()->BlacklistWebGLForTesting();
+
+ base::FilePath base_path = data_dir().AppendASCII("requirements");
+ base::FilePath pem_path = base_path.AppendASCII("v1_good.pem");
+ base::FilePath path = base_path.AppendASCII("v2_bad_requirements");
+ const Extension* extension =
+ PackAndInstallCRX(path, pem_path, INSTALL_WITHOUT_LOAD);
+ ASSERT_TRUE(extension);
+ // The extension should be installed but disabled pending custodian approval
+ // and unsupported requirements.
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+ EXPECT_TRUE(prefs->HasDisableReason(
+ extension->id(), disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
+ EXPECT_TRUE(prefs->HasDisableReason(
+ extension->id(), disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT));
+
+ // Parent approval should fail because of the unsupported requirements.
+ {
+ supervised_user_delegate_->dialog_result_ = SupervisedUserServiceDelegate::
+ ParentPermissionDialogResult::kParentPermissionReceived;
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents_.get(), extension->id(),
+ /*user_user_gesture=*/true,
+ /*accept_dialog=*/true, &error);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(error.empty());
+ // The parent permission dialog was never opened.
+ EXPECT_EQ(0, supervised_user_delegate_->show_dialog_count_);
+ EXPECT_TRUE(registry()->disabled_extensions().Contains(extension->id()));
+ // The extension should still require parent approval.
+ EXPECT_TRUE(prefs->HasDisableReason(
+ extension->id(), disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED));
+ EXPECT_TRUE(prefs->HasDisableReason(
+ extension->id(), disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT));
+ }
+}
+
+// Tests for supervised users (child accounts) with additional setup code.
+class ManagementApiSupervisedUserTestWithSetup
+ : public ManagementApiSupervisedUserTest {
+ public:
+ ManagementApiSupervisedUserTestWithSetup() = default;
+ ~ManagementApiSupervisedUserTestWithSetup() override = default;
+
+ void SetUp() override {
+ ManagementApiSupervisedUserTest::SetUp();
+
+ // Install a ManagementAPIDelegate to sense extension enable.
+ delegate_ = new TestManagementAPIDelegate;
+ management_api_->set_delegate_for_test(base::WrapUnique(delegate_));
+
+ // Install a policy provider that requires parent approval for extensions.
+ provider_ = std::make_unique<TestManagementPolicyProvider>();
+ provider_->SetProhibitedActions(
+ TestManagementPolicyProvider::MUST_REMAIN_DISABLED);
+ provider_->SetDisableReason(
+ disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
+ ExtensionSystem::Get(profile())->management_policy()->RegisterProvider(
+ provider_.get());
+
+ // Add a generic extension.
+ extension_ = ExtensionBuilder("Test").Build();
+ service()->AddExtension(extension_.get());
+ EXPECT_TRUE(registry()->enabled_extensions().Contains(extension_->id()));
+ }
+
+ void TearDown() override {
+ ExtensionSystem::Get(profile())->management_policy()->UnregisterProvider(
+ provider_.get());
+ ManagementApiSupervisedUserTest::TearDown();
+ }
+
+ TestManagementAPIDelegate* delegate_ = nullptr;
+ scoped_refptr<const Extension> extension_;
+ std::unique_ptr<TestManagementPolicyProvider> provider_;
+};
+
+TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_ParentApproves) {
+ // Preconditions.
+ ASSERT_TRUE(profile()->IsChild());
+ ASSERT_EQ(0, delegate_->enable_count_);
+ ASSERT_EQ(0, supervised_user_delegate_->show_dialog_count_);
+
+ // Start with a disabled extension that needs parent permission.
+ service()->DisableExtension(
+ extension_->id(), disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
+
+ // The parent will approve.
+ supervised_user_delegate_->dialog_result_ = SupervisedUserServiceDelegate::
+ ParentPermissionDialogResult::kParentPermissionReceived;
+
+ // Simulate a call to chrome.management.setEnabled(). It should succeed.
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents_.get(), extension_->id(),
+ /*use_user_gesture=*/true,
+ /*accept_dialog=*/true, &error);
+ EXPECT_TRUE(success) << error;
+ EXPECT_TRUE(error.empty());
+
+ // Parent permission dialog was opened.
+ EXPECT_EQ(1, supervised_user_delegate_->show_dialog_count_);
+
+ // Extension was enabled.
+ EXPECT_EQ(1, delegate_->enable_count_);
+}
+
+TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_ParentDenies) {
+ // Start with a disabled extension that needs parent permission.
+ service()->DisableExtension(
+ extension_->id(), disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
+
+ // The parent will deny the next dialog.
+ supervised_user_delegate_->dialog_result_ = SupervisedUserServiceDelegate::
+ ParentPermissionDialogResult::kParentPermissionCanceled;
+
+ // Simulate a call to chrome.management.setEnabled(). It should not succeed.
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents_.get(), extension_->id(),
+ /*use_user_gesture=*/true,
+ /*accept_dialog=*/true, &error);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(error.empty());
+
+ // Parent permission dialog was opened.
+ EXPECT_EQ(1, supervised_user_delegate_->show_dialog_count_);
+
+ // Extension was not enabled.
+ EXPECT_EQ(0, delegate_->enable_count_);
+}
+
+TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_DialogFails) {
+ // Start with a disabled extension that needs parent permission.
+ service()->DisableExtension(
+ extension_->id(), disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
+
+ // The next dialog will close due to a failure (e.g. network failure while
+ // looking up parent information).
+ supervised_user_delegate_->dialog_result_ = SupervisedUserServiceDelegate::
+ ParentPermissionDialogResult::kParentPermissionFailed;
+
+ // Simulate a call to chrome.management.setEnabled(). It should not succeed.
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents_.get(), extension_->id(),
+ /*use_user_gesture=*/true,
+ /*accept_dialog=*/true, &error);
+ EXPECT_FALSE(success);
+ EXPECT_FALSE(error.empty());
+
+ // Extension was not enabled.
+ EXPECT_EQ(0, delegate_->enable_count_);
+}
+
+TEST_F(ManagementApiSupervisedUserTestWithSetup, SetEnabled_PreviouslyAllowed) {
+ // Disable the extension.
+ service()->DisableExtension(extension_->id(),
+ disable_reason::DISABLE_USER_ACTION);
+
+ // Allow the extension to be enabled.
+ provider_->SetProhibitedActions(TestManagementPolicyProvider::ALLOW_ALL);
+ // Simulate previous parent approval.
+ GetSupervisedUserService()->AddOrUpdateExtensionApproval(*extension_);
+
+ // Simulate a call to chrome.management.setEnabled().
+ std::string error;
+ bool success = RunSetEnabledFunction(web_contents_.get(), extension_->id(),
+ /*use_user_gesture=*/true,
+ /*accept_dialog=*/true, &error);
+ EXPECT_TRUE(success) << error;
+ EXPECT_TRUE(error.empty());
+
+ // Parent permission dialog was not opened.
+ EXPECT_EQ(0, supervised_user_delegate_->show_dialog_count_);
+}
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
+
+} // namespace
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/management/management_apitest.cc b/chromium/chrome/browser/extensions/api/management/management_apitest.cc
index d97fde85f27..122cd889da7 100644
--- a/chromium/chrome/browser/extensions/api/management/management_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/management/management_apitest.cc
@@ -17,8 +17,12 @@
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/web_applications/components/app_registrar.h"
+#include "chrome/browser/web_applications/components/app_shortcut_manager.h"
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/components/web_app_provider_base.h"
#include "chrome/browser/web_applications/test/test_web_app_ui_manager.h"
+#include "chrome/browser/web_applications/test/web_app_test.h"
+#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_constants.h"
#include "extensions/browser/api/management/management_api.h"
@@ -34,6 +38,7 @@
using extensions::Extension;
using extensions::Manifest;
+using web_app::ProviderType;
namespace {
@@ -147,11 +152,38 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, CreateAppShortcut) {
"createAppShortcut.html"));
}
-IN_PROC_BROWSER_TEST_F(ExtensionManagementApiTest, GenerateAppForLink) {
+class GenerateAppManagementApiTest
+ : public ExtensionManagementApiTest,
+ public ::testing::WithParamInterface<ProviderType> {
+ public:
+ void SetUp() override {
+ if (GetParam() == ProviderType::kWebApps) {
+ scoped_feature_list_.InitWithFeatures(
+ {features::kDesktopPWAsWithoutExtensions}, {});
+ } else {
+ DCHECK_EQ(GetParam(), ProviderType::kBookmarkApps);
+ scoped_feature_list_.InitWithFeatures(
+ {}, {features::kDesktopPWAsWithoutExtensions});
+ }
+
+ ExtensionManagementApiTest::SetUp();
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_P(GenerateAppManagementApiTest, GenerateAppForLink) {
ASSERT_TRUE(RunExtensionSubtest("management/test",
"generateAppForLink.html"));
}
+INSTANTIATE_TEST_SUITE_P(All,
+ GenerateAppManagementApiTest,
+ ::testing::Values(ProviderType::kBookmarkApps,
+ ProviderType::kWebApps),
+ web_app::ProviderTypeParamToString);
+
class InstallReplacementWebAppApiTest : public ExtensionManagementApiTest {
public:
InstallReplacementWebAppApiTest()
@@ -166,6 +198,10 @@ class InstallReplacementWebAppApiTest : public ExtensionManagementApiTest {
ExtensionManagementApiTest::SetUpOnMainThread();
https_test_server_.ServeFilesFromDirectory(test_data_dir_);
ASSERT_TRUE(https_test_server_.Start());
+
+ web_app::WebAppProviderBase::GetProviderBase(profile())
+ ->shortcut_manager()
+ .SuppressShortcutsForTesting();
}
void RunTest(const char* manifest,
diff --git a/chromium/chrome/browser/extensions/api/management/management_browsertest.cc b/chromium/chrome/browser/extensions/api/management/management_browsertest.cc
index 265e4a24847..9654ebb2bc7 100644
--- a/chromium/chrome/browser/extensions/api/management/management_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -31,6 +31,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
#include "content/public/test/url_loader_interceptor.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_host_observer.h"
@@ -42,7 +43,6 @@
#include "extensions/browser/updater/extension_downloader.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/test_background_page_first_load_observer.h"
-#include "net/url_request/test_url_request_interceptor.h"
#include "testing/gmock/include/gmock/gmock.h"
using content::BrowserThread;
@@ -250,13 +250,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallThenCancel) {
EXPECT_TRUE(IsExtensionAtVersion(extension, "1.0"));
}
-#if defined(OS_WIN)
-// http://crbug.com/141913
-#define MAYBE_InstallRequiresConfirm DISABLED_InstallRequiresConfirm
-#else
-#define MAYBE_InstallRequiresConfirm InstallRequiresConfirm
-#endif
-IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_InstallRequiresConfirm) {
+IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, InstallRequiresConfirm) {
// Installing the extension without an auto confirming UI should result in
// it being disabled, since good.crx has permissions that require approval.
std::string id = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
@@ -460,8 +454,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_AutoUpdate) {
extensions::ExtensionUpdater::CheckParams params2;
params2.callback = base::BindOnce(&NotificationListener::OnFinished,
base::Unretained(&notification_listener));
- service->updater()->CheckNow(std::move(params2));
- ASSERT_TRUE(WaitForExtensionInstallError());
+
+ {
+ content::WindowedNotificationObserver install_error_observer(
+ extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
+ content::NotificationService::AllSources());
+ service->updater()->CheckNow(std::move(params2));
+ install_error_observer.Wait();
+ }
ASSERT_TRUE(notification_listener.started());
ASSERT_TRUE(notification_listener.finished());
ASSERT_TRUE(base::Contains(notification_listener.updates(),
@@ -761,6 +761,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalPolicyRefresh) {
#define MAYBE_PolicyOverridesUserInstall PolicyOverridesUserInstall
#endif
+// Tests the behavior of force-installing extensions that the user has already
+// installed.
IN_PROC_BROWSER_TEST_F(ExtensionManagementTest,
MAYBE_PolicyOverridesUserInstall) {
extensions::ExtensionService* service =
@@ -823,7 +825,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest,
nullptr);
extensions::TestExtensionRegistryObserver install_observer(registry);
UpdateProviderPolicy(policies);
- install_observer.WaitForExtensionWillBeInstalled();
ASSERT_EQ(size_before + 1, registry->enabled_extensions().size());
extension = registry->enabled_extensions().GetByID(kExtensionId);
@@ -866,7 +867,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest,
extensions::TestExtensionRegistryObserver extension_observer(registry);
UpdateProviderPolicy(policies);
- extension_observer.WaitForExtensionWillBeInstalled();
ASSERT_EQ(size_before + 1, registry->enabled_extensions().size());
extension = registry->enabled_extensions().GetByID(kExtensionId);
diff --git a/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc b/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc
index 5c7a8777164..14260f0d312 100644
--- a/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc
@@ -116,9 +116,9 @@ void MediaPerceptionAPIDelegateChromeOS::SetMediaPerceptionRequestHandler(
}
void MediaPerceptionAPIDelegateChromeOS::ForwardMediaPerceptionReceiver(
+ content::RenderFrameHost* render_frame_host,
mojo::PendingReceiver<chromeos::media_perception::mojom::MediaPerception>
- receiver,
- content::RenderFrameHost* render_frame_host) {
+ receiver) {
if (!handler_) {
DLOG(ERROR) << "Got receiver but the handler is not set.";
return;
diff --git a/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.h b/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.h
index e27bff40f42..9d00f311e49 100644
--- a/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.h
+++ b/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.h
@@ -27,9 +27,9 @@ class MediaPerceptionAPIDelegateChromeOS
void SetMediaPerceptionRequestHandler(
MediaPerceptionRequestHandler handler) override;
void ForwardMediaPerceptionReceiver(
+ content::RenderFrameHost* render_frame_host,
mojo::PendingReceiver<chromeos::media_perception::mojom::MediaPerception>
- receiver,
- content::RenderFrameHost* render_frame_host) override;
+ receiver) override;
private:
MediaPerceptionRequestHandler handler_;
diff --git a/chromium/chrome/browser/extensions/api/messaging/incognito_connectability_infobar_delegate.cc b/chromium/chrome/browser/extensions/api/messaging/incognito_connectability_infobar_delegate.cc
index 7171d6263c3..9cb9f98e5e7 100644
--- a/chromium/chrome/browser/extensions/api/messaging/incognito_connectability_infobar_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/incognito_connectability_infobar_delegate.cc
@@ -5,8 +5,8 @@
#include "chrome/browser/extensions/api/messaging/incognito_connectability_infobar_delegate.h"
#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/grit/generated_resources.h"
#include "components/infobars/core/infobar.h"
+#include "components/strings/grit/components_strings.h"
#include "ui/base/l10n/l10n_util.h"
namespace extensions {
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc b/chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
index 017b5dd0ba7..ccfb4199428 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
@@ -111,13 +111,6 @@ std::unique_ptr<NativeMessageHost> CreateIt2MeHost(
// chrome and fetch the list of allowed_origins from the manifest (see
// crbug/424743).
const char* const kRemotingIt2MeOrigins[] = {
- "chrome-extension://ljacajndfccfgnfohlgkdphmbnpkjflk/",
- "chrome-extension://gbchcmhmhahfdphkhkmpfmihenigjmpp/",
- "chrome-extension://kgngmbheleoaphbjbaiobfdepmghbfah/",
- "chrome-extension://odkaodonbgfohohmklejpjiejmcipmib/",
- "chrome-extension://dokpleeekgeeiehdhmdkeimnkmoifgdd/",
- "chrome-extension://ajoainacpilcemgiakehflpbkbfipojk/",
- "chrome-extension://hmboipgjngjoiaeicfdifdoeacilalgc/",
"chrome-extension://inomeogfingihgjfjlpeplalcfajhgai/",
"chrome-extension://hpodccmdligbeohchckkeajbfohibipg/"};
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc
index fb78b037b9a..8d1911b6118 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -14,6 +14,7 @@
#include "base/logging.h"
#include "base/process/kill.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_launch_from_native.h"
@@ -83,9 +84,8 @@ NativeMessageProcessHost::~NativeMessageProcessHost() {
// TODO(https://crbug.com/806451): On OSX EnsureProcessTerminated() may
// block, so we have to post a task on the blocking pool.
#if defined(OS_MACOSX)
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&base::EnsureProcessTerminated, Passed(&process_)));
#else
base::EnsureProcessTerminated(std::move(process_));
@@ -164,9 +164,10 @@ void NativeMessageProcessHost::OnHostProcessLaunched(
read_file_ = read_file.GetPlatformFile();
#endif
- scoped_refptr<base::TaskRunner> task_runner(base::CreateTaskRunner(
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
+ scoped_refptr<base::TaskRunner> task_runner(
+ base::ThreadPool::CreateTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
read_stream_.reset(new net::FileStream(std::move(read_file), task_runner));
write_stream_.reset(new net::FileStream(std::move(write_file), task_runner));
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc b/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc
index 4dbc135be3c..e9aa21e5e20 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.cc
@@ -28,12 +28,10 @@ bool NativeMessagingHostListPolicyHandler::CheckListEntry(
return NativeMessagingHostManifest::IsValidName(str);
}
-void NativeMessagingHostListPolicyHandler::ApplyList(
- std::unique_ptr<base::ListValue> filtered_list,
- PrefValueMap* prefs) {
- DCHECK(filtered_list);
- prefs->SetValue(pref_path_,
- base::Value::FromUniquePtrValue(std::move(filtered_list)));
+void NativeMessagingHostListPolicyHandler::ApplyList(base::Value filtered_list,
+ PrefValueMap* prefs) {
+ DCHECK(filtered_list.is_list());
+ prefs->SetValue(pref_path_, std::move(filtered_list));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.h b/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.h
index 456f60a4476..b6ab5cefa29 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.h
+++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_policy_handler.h
@@ -29,8 +29,7 @@ class NativeMessagingHostListPolicyHandler : public policy::ListPolicyHandler {
bool CheckListEntry(const base::Value& value) override;
// Sets |prefs| at pref_path() to |filtered_list|.
- void ApplyList(std::unique_ptr<base::ListValue> filtered_list,
- PrefValueMap* prefs) override;
+ void ApplyList(base::Value filtered_list, PrefValueMap* prefs) override;
private:
const char* pref_path_;
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc
index b496b8c75d3..5b5b39a5567 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -24,6 +24,7 @@
#include "base/strings/strcat.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
@@ -145,9 +146,8 @@ void NativeProcessLauncherImpl::Core::Launch(
const GURL& origin,
const std::string& native_host_name,
const LaunchedCallback& callback) {
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&Core::DoLaunchOnThreadPool, this, origin,
native_host_name, callback));
}
@@ -267,7 +267,6 @@ void NativeProcessLauncherImpl::Core::DoLaunchOnThreadPool(
::switches::kPrefetchArgumentBrowserBackground);
#endif
base::Value args(base::Value::Type::LIST);
- args.GetList().reserve(reconnect_command_line.argv().size());
for (const auto& arg : reconnect_command_line.argv()) {
args.Append(arg);
}
diff --git a/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc b/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
index db66f4b2e6b..ca9cdc7ea9e 100644
--- a/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
@@ -6,6 +6,8 @@
#include <stdint.h>
+#include <utility>
+
#include "base/base64.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -14,6 +16,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_crypto.h"
#include "content/public/browser/browser_task_traits.h"
@@ -133,12 +136,11 @@ void ChromeNetworkingCastPrivateDelegate::VerifyDestination(
std::unique_ptr<Credentials> credentials,
const VerifiedCallback& success_callback,
const FailureCallback& failure_callback) {
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
- base::Bind(&RunDecodeAndVerifyCredentials, base::Passed(&credentials)),
- base::Bind(&VerifyDestinationCompleted, success_callback,
- failure_callback));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(&RunDecodeAndVerifyCredentials, std::move(credentials)),
+ base::BindOnce(&VerifyDestinationCompleted, success_callback,
+ failure_callback));
}
void ChromeNetworkingCastPrivateDelegate::VerifyAndEncryptData(
@@ -146,12 +148,11 @@ void ChromeNetworkingCastPrivateDelegate::VerifyAndEncryptData(
std::unique_ptr<Credentials> credentials,
const DataCallback& success_callback,
const FailureCallback& failure_callback) {
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
- base::Bind(&RunVerifyAndEncryptData, data, base::Passed(&credentials)),
- base::Bind(&VerifyAndEncryptDataCompleted, success_callback,
- failure_callback));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(&RunVerifyAndEncryptData, data, std::move(credentials)),
+ base::BindOnce(&VerifyAndEncryptDataCompleted, success_callback,
+ failure_callback));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc b/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
index c27a9c45862..329849630be 100644
--- a/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc
@@ -20,7 +20,7 @@
#include "chromeos/dbus/shill/shill_device_client.h"
#include "chromeos/dbus/shill/shill_profile_client.h"
#include "chromeos/dbus/shill/shill_service_client.h"
-#include "components/captive_portal/captive_portal_testing_utils.h"
+#include "components/captive_portal/core/captive_portal_testing_utils.h"
#include "content/public/test/test_utils.h"
#include "extensions/test/result_catcher.h"
#include "net/base/net_errors.h"
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
index 6daad8781d2..630af69f36d 100644
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_apitest.cc
@@ -360,9 +360,8 @@ class NetworkingPrivateApiTest : public ExtensionApiTest {
protected:
bool RunNetworkingSubtest(const std::string& subtest) {
- return RunExtensionSubtest("networking_private",
- "main.html?" + subtest,
- kFlagEnableFileAccess | kFlagLoadAsComponent);
+ return RunExtensionSubtest("networking_private", "main.html?" + subtest,
+ kFlagEnableFileAccess, kFlagLoadAsComponent);
}
private:
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index 282c0c96f0f..4fe9d8d7ef9 100644
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -33,6 +33,7 @@
#include "chromeos/network/managed_network_configuration_handler.h"
#include "chromeos/network/network_certificate_handler.h"
#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_metadata_store.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/network_type_pattern.h"
@@ -475,6 +476,8 @@ class NetworkingPrivateChromeOSApiTest : public extensions::ExtensionApiTest {
PrefProxyConfigTrackerImpl::RegisterPrefs(local_state_.registry());
::onc::RegisterProfilePrefs(user_prefs_.registry());
::onc::RegisterPrefs(local_state_.registry());
+ chromeos::NetworkMetadataStore::RegisterPrefs(user_prefs_.registry());
+ chromeos::NetworkMetadataStore::RegisterPrefs(local_state_.registry());
chromeos::NetworkHandler::Get()->InitializePrefServices(&user_prefs_,
&local_state_);
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
index 1a61a78cb6d..ab1b1578905 100644
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc
@@ -88,8 +88,8 @@ class NetworkingPrivateServiceClientApiTest
bool RunNetworkingSubtest(const std::string& subtest) {
return RunExtensionSubtest("networking_private/service_client",
- "main.html?" + subtest,
- kFlagEnableFileAccess | kFlagLoadAsComponent);
+ "main.html?" + subtest, kFlagEnableFileAccess,
+ kFlagLoadAsComponent);
}
void SetUpCommandLine(base::CommandLine* command_line) override {
diff --git a/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc b/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc
index 752316e49f8..5e865b563c4 100644
--- a/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc
+++ b/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -225,21 +225,22 @@ NotificationsApiFunction::~NotificationsApiFunction() {
bool NotificationsApiFunction::CreateNotification(
const std::string& id,
- api::notifications::NotificationOptions* options) {
+ api::notifications::NotificationOptions* options,
+ std::string* error) {
// First, make sure the required fields exist: type, title, message, icon.
// These fields are defined as optional in IDL such that they can be used as
// optional for notification updates. But for notification creations, they
// should be present.
if (options->type == api::notifications::TEMPLATE_TYPE_NONE ||
!options->icon_url || !options->title || !options->message) {
- SetError(kMissingRequiredPropertiesForCreateNotification);
+ *error = kMissingRequiredPropertiesForCreateNotification;
return false;
}
#if !defined(OS_CHROMEOS)
if (options->priority &&
*options->priority < message_center::DEFAULT_PRIORITY) {
- SetError(kLowPriorityDeprecatedOnPlatform);
+ *error = kLowPriorityDeprecatedOnPlatform;
return false;
}
#endif
@@ -262,7 +263,7 @@ bool NotificationsApiFunction::CreateNotification(
if (!options->icon_bitmap.get() ||
!NotificationBitmapToGfxImage(
image_scale, bitmap_sizes.icon_size, *options->icon_bitmap, &icon)) {
- SetError(kUnableToDecodeIconError);
+ *error = kUnableToDecodeIconError;
return false;
}
@@ -273,7 +274,7 @@ bool NotificationsApiFunction::CreateNotification(
if (!NotificationBitmapToGfxImage(
image_scale, bitmap_sizes.app_icon_mask_size,
*options->app_icon_mask_bitmap, &small_icon_mask)) {
- SetError(kUnableToDecodeIconError);
+ *error = kUnableToDecodeIconError;
return false;
}
optional_fields.small_image =
@@ -327,27 +328,27 @@ bool NotificationsApiFunction::CreateNotification(
// We should have an image if and only if the type is an image type.
if (has_image != (type == message_center::NOTIFICATION_TYPE_IMAGE)) {
- SetError(kExtraImageProvided);
+ *error = kExtraImageProvided;
return false;
}
// We should have list items if and only if the type is a multiple type.
bool has_list_items = options->items.get() && !options->items->empty();
if (has_list_items != (type == message_center::NOTIFICATION_TYPE_MULTIPLE)) {
- SetError(kExtraListItemsProvided);
+ *error = kExtraListItemsProvided;
return false;
}
if (options->progress.get() != NULL) {
// We should have progress if and only if the type is a progress type.
if (type != message_center::NOTIFICATION_TYPE_PROGRESS) {
- SetError(kUnexpectedProgressValueForNonProgressType);
+ *error = kUnexpectedProgressValueForNonProgressType;
return false;
}
optional_fields.progress = *options->progress;
// Progress value should range from 0 to 100.
if (optional_fields.progress < 0 || optional_fields.progress > 100) {
- SetError(kInvalidProgressValue);
+ *error = kInvalidProgressValue;
return false;
}
}
@@ -366,8 +367,8 @@ bool NotificationsApiFunction::CreateNotification(
// TODO(crbug.com/772004): Remove the manual limitation in favor of an IDL
// annotation once supported.
if (id.size() > kNotificationIdLengthLimit) {
- SetError(
- base::StringPrintf(kNotificationIdTooLong, kNotificationIdLengthLimit));
+ *error =
+ base::StringPrintf(kNotificationIdTooLong, kNotificationIdLengthLimit);
return false;
}
@@ -396,11 +397,12 @@ bool NotificationsApiFunction::CreateNotification(
bool NotificationsApiFunction::UpdateNotification(
const std::string& id,
api::notifications::NotificationOptions* options,
- message_center::Notification* notification) {
+ message_center::Notification* notification,
+ std::string* error) {
#if !defined(OS_CHROMEOS)
if (options->priority &&
*options->priority < message_center::DEFAULT_PRIORITY) {
- SetError(kLowPriorityDeprecatedOnPlatform);
+ *error = kLowPriorityDeprecatedOnPlatform;
return false;
}
#endif
@@ -422,7 +424,7 @@ bool NotificationsApiFunction::UpdateNotification(
if (!NotificationBitmapToGfxImage(
image_scale, bitmap_sizes.icon_size, *options->icon_bitmap,
&icon)) {
- SetError(kUnableToDecodeIconError);
+ *error = kUnableToDecodeIconError;
return false;
}
notification->set_icon(icon);
@@ -433,7 +435,7 @@ bool NotificationsApiFunction::UpdateNotification(
if (!NotificationBitmapToGfxImage(
image_scale, bitmap_sizes.app_icon_mask_size,
*options->app_icon_mask_bitmap, &app_icon_mask)) {
- SetError(kUnableToDecodeIconError);
+ *error = kUnableToDecodeIconError;
return false;
}
notification->set_small_image(
@@ -484,7 +486,7 @@ bool NotificationsApiFunction::UpdateNotification(
if (has_image) {
// We should have an image if and only if the type is an image type.
if (notification->type() != message_center::NOTIFICATION_TYPE_IMAGE) {
- SetError(kExtraImageProvided);
+ *error = kExtraImageProvided;
return false;
}
notification->set_image(image);
@@ -493,13 +495,13 @@ bool NotificationsApiFunction::UpdateNotification(
if (options->progress) {
// We should have progress if and only if the type is a progress type.
if (notification->type() != message_center::NOTIFICATION_TYPE_PROGRESS) {
- SetError(kUnexpectedProgressValueForNonProgressType);
+ *error = kUnexpectedProgressValueForNonProgressType;
return false;
}
int progress = *options->progress;
// Progress value should range from 0 to 100.
if (progress < 0 || progress > 100) {
- SetError(kInvalidProgressValue);
+ *error = kInvalidProgressValue;
return false;
}
notification->set_progress(progress);
@@ -508,7 +510,7 @@ bool NotificationsApiFunction::UpdateNotification(
if (options->items.get() && !options->items->empty()) {
// We should have list items if and only if the type is a multiple type.
if (notification->type() != message_center::NOTIFICATION_TYPE_MULTIPLE) {
- SetError(kExtraListItemsProvided);
+ *error = kExtraListItemsProvided;
return false;
}
@@ -549,12 +551,15 @@ ExtensionNotificationDisplayHelper* NotificationsApiFunction::GetDisplayHelper()
return ExtensionNotificationDisplayHelperFactory::GetForProfile(GetProfile());
}
-bool NotificationsApiFunction::RunAsync() {
+Profile* NotificationsApiFunction::GetProfile() const {
+ return details_.GetProfile();
+}
+
+ExtensionFunction::ResponseAction NotificationsApiFunction::Run() {
if (IsNotificationsApiAvailable() && IsNotificationsApiEnabled()) {
return RunNotificationsApi();
} else {
- SendResponse(false);
- return true;
+ return RespondNow(Error(""));
}
}
@@ -584,7 +589,8 @@ NotificationsCreateFunction::NotificationsCreateFunction() {
NotificationsCreateFunction::~NotificationsCreateFunction() {
}
-bool NotificationsCreateFunction::RunNotificationsApi() {
+ExtensionFunction::ResponseAction
+NotificationsCreateFunction::RunNotificationsApi() {
params_ = api::notifications::Create::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params_.get());
@@ -601,15 +607,15 @@ bool NotificationsCreateFunction::RunNotificationsApi() {
notification_id = base::RandBytesAsString(16);
}
- SetResult(std::make_unique<base::Value>(notification_id));
-
// TODO(dewittj): Add more human-readable error strings if this fails.
- if (!CreateNotification(notification_id, &params_->options))
- return false;
-
- SendResponse(true);
+ std::string error;
+ if (!CreateNotification(notification_id, &params_->options, &error)) {
+ return RespondNow(ErrorWithArguments(
+ api::notifications::Create::Results::Create(notification_id), error));
+ }
- return true;
+ return RespondNow(
+ OneArgument(std::make_unique<base::Value>(notification_id)));
}
NotificationsUpdateFunction::NotificationsUpdateFunction() {
@@ -618,7 +624,8 @@ NotificationsUpdateFunction::NotificationsUpdateFunction() {
NotificationsUpdateFunction::~NotificationsUpdateFunction() {
}
-bool NotificationsUpdateFunction::RunNotificationsApi() {
+ExtensionFunction::ResponseAction
+NotificationsUpdateFunction::RunNotificationsApi() {
params_ = api::notifications::Update::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params_.get());
@@ -629,9 +636,7 @@ bool NotificationsUpdateFunction::RunNotificationsApi() {
CreateScopedIdentifier(extension_->id(), params_->notification_id));
if (!matched_notification) {
- SetResult(std::make_unique<base::Value>(false));
- SendResponse(true);
- return true;
+ return RespondNow(OneArgument(std::make_unique<base::Value>(false)));
}
// Copy the existing notification to get a writable version of it.
@@ -641,16 +646,17 @@ bool NotificationsUpdateFunction::RunNotificationsApi() {
// or some other reason), mark the function as failed, calling the callback
// with false.
// TODO(dewittj): Add more human-readable error strings if this fails.
+ std::string error;
bool could_update_notification = UpdateNotification(
- params_->notification_id, &params_->options, &notification);
- SetResult(std::make_unique<base::Value>(could_update_notification));
- if (!could_update_notification)
- return false;
+ params_->notification_id, &params_->options, &notification, &error);
+ if (!could_update_notification) {
+ return RespondNow(ErrorWithArguments(
+ api::notifications::Update::Results::Create(false), error));
+ }
// No trouble, created the notification, send true to the callback and
// succeed.
- SendResponse(true);
- return true;
+ return RespondNow(OneArgument(std::make_unique<base::Value>(true)));
}
NotificationsClearFunction::NotificationsClearFunction() {
@@ -659,24 +665,23 @@ NotificationsClearFunction::NotificationsClearFunction() {
NotificationsClearFunction::~NotificationsClearFunction() {
}
-bool NotificationsClearFunction::RunNotificationsApi() {
+ExtensionFunction::ResponseAction
+NotificationsClearFunction::RunNotificationsApi() {
params_ = api::notifications::Clear::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params_.get());
bool cancel_result = GetDisplayHelper()->Close(
CreateScopedIdentifier(extension_->id(), params_->notification_id));
- SetResult(std::make_unique<base::Value>(cancel_result));
- SendResponse(true);
-
- return true;
+ return RespondNow(OneArgument(std::make_unique<base::Value>(cancel_result)));
}
NotificationsGetAllFunction::NotificationsGetAllFunction() {}
NotificationsGetAllFunction::~NotificationsGetAllFunction() {}
-bool NotificationsGetAllFunction::RunNotificationsApi() {
+ExtensionFunction::ResponseAction
+NotificationsGetAllFunction::RunNotificationsApi() {
std::set<std::string> notification_ids =
GetDisplayHelper()->GetNotificationIdsForExtension(extension_->url());
@@ -688,10 +693,7 @@ bool NotificationsGetAllFunction::RunNotificationsApi() {
base::Value(true));
}
- SetResult(std::move(result));
- SendResponse(true);
-
- return true;
+ return RespondNow(OneArgument(std::move(result)));
}
NotificationsGetPermissionLevelFunction::
@@ -704,17 +706,15 @@ bool NotificationsGetPermissionLevelFunction::CanRunWhileDisabled() const {
return true;
}
-bool NotificationsGetPermissionLevelFunction::RunNotificationsApi() {
+ExtensionFunction::ResponseAction
+NotificationsGetPermissionLevelFunction::RunNotificationsApi() {
api::notifications::PermissionLevel result =
AreExtensionNotificationsAllowed()
? api::notifications::PERMISSION_LEVEL_GRANTED
: api::notifications::PERMISSION_LEVEL_DENIED;
- SetResult(
- std::make_unique<base::Value>(api::notifications::ToString(result)));
- SendResponse(true);
-
- return true;
+ return RespondNow(OneArgument(
+ std::make_unique<base::Value>(api::notifications::ToString(result))));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/notifications/notifications_api.h b/chromium/chrome/browser/extensions/api/notifications/notifications_api.h
index 3cda4331208..fe44ce856e1 100644
--- a/chromium/chrome/browser/extensions/api/notifications/notifications_api.h
+++ b/chromium/chrome/browser/extensions/api/notifications/notifications_api.h
@@ -8,7 +8,7 @@
#include <string>
#include "base/memory/ref_counted.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
+#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "chrome/common/extensions/api/notifications.h"
#include "extensions/browser/extension_function.h"
#include "ui/message_center/public/cpp/notification_types.h"
@@ -21,7 +21,7 @@ namespace extensions {
class ExtensionNotificationDisplayHelper;
-class NotificationsApiFunction : public ChromeAsyncExtensionFunction {
+class NotificationsApiFunction : public ExtensionFunction {
public:
// Whether the current extension and channel allow the API. Public for
// testing.
@@ -32,15 +32,19 @@ class NotificationsApiFunction : public ChromeAsyncExtensionFunction {
~NotificationsApiFunction() override;
bool CreateNotification(const std::string& id,
- api::notifications::NotificationOptions* options);
+ api::notifications::NotificationOptions* options,
+ std::string* error);
bool UpdateNotification(const std::string& id,
api::notifications::NotificationOptions* options,
- message_center::Notification* notification);
+ message_center::Notification* notification,
+ std::string* error);
bool IsNotificationsApiEnabled() const;
bool AreExtensionNotificationsAllowed() const;
+ Profile* GetProfile() const;
+
// Returns the display helper that should be used for interacting with the
// common notification system.
ExtensionNotificationDisplayHelper* GetDisplayHelper() const;
@@ -49,14 +53,17 @@ class NotificationsApiFunction : public ChromeAsyncExtensionFunction {
// notifications for a notifier have been disabled.
virtual bool CanRunWhileDisabled() const;
- // Called inside of RunAsync.
- virtual bool RunNotificationsApi() = 0;
+ // Called inside of Run().
+ virtual ResponseAction RunNotificationsApi() = 0;
- // UITHreadExtensionFunction:
- bool RunAsync() override;
+ // ExtensionFunction:
+ ResponseAction Run() override;
message_center::NotificationType MapApiTemplateTypeToType(
api::notifications::TemplateType type);
+
+ private:
+ ChromeExtensionFunctionDetails details_{this};
};
class NotificationsCreateFunction : public NotificationsApiFunction {
@@ -64,7 +71,7 @@ class NotificationsCreateFunction : public NotificationsApiFunction {
NotificationsCreateFunction();
// NotificationsApiFunction:
- bool RunNotificationsApi() override;
+ ResponseAction RunNotificationsApi() override;
protected:
~NotificationsCreateFunction() override;
@@ -80,7 +87,7 @@ class NotificationsUpdateFunction : public NotificationsApiFunction {
NotificationsUpdateFunction();
// NotificationsApiFunction:
- bool RunNotificationsApi() override;
+ ResponseAction RunNotificationsApi() override;
protected:
~NotificationsUpdateFunction() override;
@@ -96,7 +103,7 @@ class NotificationsClearFunction : public NotificationsApiFunction {
NotificationsClearFunction();
// NotificationsApiFunction:
- bool RunNotificationsApi() override;
+ ResponseAction RunNotificationsApi() override;
protected:
~NotificationsClearFunction() override;
@@ -112,7 +119,7 @@ class NotificationsGetAllFunction : public NotificationsApiFunction {
NotificationsGetAllFunction();
// NotificationsApiFunction:
- bool RunNotificationsApi() override;
+ ResponseAction RunNotificationsApi() override;
protected:
~NotificationsGetAllFunction() override;
@@ -128,7 +135,7 @@ class NotificationsGetPermissionLevelFunction
// NotificationsApiFunction:
bool CanRunWhileDisabled() const override;
- bool RunNotificationsApi() override;
+ ResponseAction RunNotificationsApi() override;
protected:
~NotificationsGetPermissionLevelFunction() override;
diff --git a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api.h b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api.h
index 9a648b7e6fb..37f4d2de7e9 100644
--- a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api.h
+++ b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api.h
@@ -12,12 +12,12 @@
#include "base/macros.h"
#include "base/scoped_observer.h"
#include "base/strings/string16.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/extensions/extension_icon_manager.h"
#include "chrome/common/extensions/api/omnibox.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/search_engines/template_url_service.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
+#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_registry_observer.h"
#include "ui/base/window_open_disposition.h"
diff --git a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
index 87a86d9ce2d..a62034dc7d3 100644
--- a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
+++ b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc
@@ -309,10 +309,16 @@ IN_PROC_BROWSER_TEST_F(OmniboxApiTest, DISABLED_IncognitoSplitMode) {
}
}
+// The test is flaky on Win10. crbug.com/1045731.
+#if defined(OS_WIN)
+#define MAYBE_PopupStaysClosed DISABLED_PopupStaysClosed
+#else
+#define MAYBE_PopupStaysClosed PopupStaysClosed
+#endif
// Tests that the autocomplete popup doesn't reopen after accepting input for
// a given query.
// http://crbug.com/88552
-IN_PROC_BROWSER_TEST_F(OmniboxApiTest, PopupStaysClosed) {
+IN_PROC_BROWSER_TEST_F(OmniboxApiTest, MAYBE_PopupStaysClosed) {
ASSERT_TRUE(RunExtensionTest("omnibox")) << message_;
// The results depend on the TemplateURLService being loaded. Make sure it is
diff --git a/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc b/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc
index 9ea3a3c7610..617931c6788 100644
--- a/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc
+++ b/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc
@@ -11,12 +11,13 @@
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profiles_state.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
@@ -52,7 +53,6 @@ const char kPageCaptureNotAllowed[] =
const char kUserDenied[] = "User denied request.";
#endif
constexpr base::TaskTraits kCreateTemporaryFileTaskTraits = {
- base::ThreadPool(),
// Requires IO.
base::MayBlock(),
@@ -85,11 +85,18 @@ void PageCaptureSaveAsMHTMLFunction::SetTestDelegate(TestDelegate* delegate) {
test_delegate_ = delegate;
}
-bool PageCaptureSaveAsMHTMLFunction::RunAsync() {
+ExtensionFunction::ResponseAction PageCaptureSaveAsMHTMLFunction::Run() {
params_ = SaveAsMHTML::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params_.get());
- AddRef(); // Balanced in ReturnFailure/ReturnSuccess()
+ // Add a reference, extending the lifespan of this extension function until
+ // the response has been received by the renderer. This function generates a
+ // blob which contains a reference scoped to this object. In order for the
+ // blob to remain alive, we have to stick around until a reference has
+ // been obtained by the renderer. The response ack is the signal that the
+ // renderer has it's reference, so we can release ours.
+ // TODO(crbug.com/1050887): Potential memory leak here.
+ AddRef(); // Balanced in OnMessageReceived()
// In Public Sessions, extensions (and apps) are force-installed by admin
// policy so the user does not get a chance to review the permissions for
@@ -101,8 +108,7 @@ bool PageCaptureSaveAsMHTMLFunction::RunAsync() {
if (profiles::ArePublicSessionRestrictionsEnabled()) {
WebContents* web_contents = GetWebContents();
if (!web_contents) {
- ReturnFailure(kTabClosedError);
- return true;
+ return RespondNow(Error(kTabClosedError));
}
// This Unretained is safe because this object is Released() in
// OnMessageReceived which gets called at some point after callback is run.
@@ -112,24 +118,25 @@ bool PageCaptureSaveAsMHTMLFunction::RunAsync() {
permission_helper::HandlePermissionRequest(
*extension(), {APIPermission::kPageCapture}, web_contents, callback,
permission_helper::PromptFactory());
- return true;
+ return RespondLater();
}
#endif
- if (!CanCaptureCurrentPage()) {
- return false;
+ std::string error;
+ if (!CanCaptureCurrentPage(&error)) {
+ return RespondNow(Error(error));
}
- base::PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE, kCreateTemporaryFileTaskTraits,
base::BindOnce(&PageCaptureSaveAsMHTMLFunction::CreateTemporaryFile,
this));
- return true;
+ return RespondLater();
}
-bool PageCaptureSaveAsMHTMLFunction::CanCaptureCurrentPage() {
+bool PageCaptureSaveAsMHTMLFunction::CanCaptureCurrentPage(std::string* error) {
WebContents* web_contents = GetWebContents();
if (!web_contents) {
- error_ = kTabClosedError;
+ *error = kTabClosedError;
return false;
}
const GURL& url = web_contents->GetLastCommittedURL();
@@ -142,14 +149,14 @@ bool PageCaptureSaveAsMHTMLFunction::CanCaptureCurrentPage() {
can_capture_page = extensions::util::AllowFileAccess(
extension()->id(), web_contents->GetBrowserContext());
} else {
- std::string error;
+ std::string unused_error;
can_capture_page = extension()->permissions_data()->CanCaptureVisiblePage(
- url, SessionTabHelper::IdForTab(web_contents).id(), &error,
- extensions::CaptureRequirement::kPageCapture);
+ url, sessions::SessionTabHelper::IdForTab(web_contents).id(),
+ &unused_error, extensions::CaptureRequirement::kPageCapture);
}
if (!can_capture_page) {
- error_ = kPageCaptureNotAllowed;
+ *error = kPageCaptureNotAllowed;
}
return can_capture_page;
}
@@ -180,7 +187,7 @@ bool PageCaptureSaveAsMHTMLFunction::OnMessageReceived(
void PageCaptureSaveAsMHTMLFunction::ResolvePermissionRequest(
const PermissionIDSet& allowed_permissions) {
if (allowed_permissions.ContainsID(APIPermission::kPageCapture)) {
- base::PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE, kCreateTemporaryFileTaskTraits,
base::BindOnce(&PageCaptureSaveAsMHTMLFunction::CreateTemporaryFile,
this));
@@ -205,8 +212,8 @@ void PageCaptureSaveAsMHTMLFunction::TemporaryFileCreatedOnIO(bool success) {
// once it is no longer used.
mhtml_file_ = ShareableFileReference::GetOrCreate(
mhtml_path_, ShareableFileReference::DELETE_ON_FINAL_RELEASE,
- base::CreateSequencedTaskRunner(
- {base::ThreadPool(), // Requires IO.
+ base::ThreadPool::CreateSequencedTaskRunner(
+ {// Requires IO.
base::MayBlock(),
// TaskPriority: Inherit.
@@ -262,9 +269,7 @@ void PageCaptureSaveAsMHTMLFunction::MHTMLGenerated(int64_t mhtml_file_size) {
void PageCaptureSaveAsMHTMLFunction::ReturnFailure(const std::string& error) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- error_ = error;
-
- SendResponse(false);
+ Respond(Error(error));
// Must not Release() here, OnMessageReceived will call it eventually.
}
@@ -284,9 +289,7 @@ void PageCaptureSaveAsMHTMLFunction::ReturnSuccess(int64_t file_size) {
std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetString("mhtmlFilePath", mhtml_path_.value());
dict->SetInteger("mhtmlFileLength", file_size);
- SetResult(std::move(dict));
-
- SendResponse(true);
+ Respond(OneArgument(std::move(dict)));
// Note that we'll wait for a response ack message received in
// OnMessageReceived before we call Release() (to prevent the blob file from
@@ -297,7 +300,7 @@ WebContents* PageCaptureSaveAsMHTMLFunction::GetWebContents() {
Browser* browser = NULL;
content::WebContents* web_contents = NULL;
- if (!ExtensionTabUtil::GetTabById(params_->details.tab_id, GetProfile(),
+ if (!ExtensionTabUtil::GetTabById(params_->details.tab_id, browser_context(),
include_incognito_information(), &browser,
NULL, &web_contents, NULL)) {
return NULL;
diff --git a/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.h b/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.h
index bf79224a472..9e81b481908 100644
--- a/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.h
+++ b/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.h
@@ -10,8 +10,8 @@
#include <string>
#include "base/memory/ref_counted.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/common/extensions/api/page_capture.h"
+#include "extensions/browser/extension_function.h"
#include "storage/browser/blob/shareable_file_reference.h"
namespace base {
@@ -24,7 +24,7 @@ class WebContents;
namespace extensions {
-class PageCaptureSaveAsMHTMLFunction : public ChromeAsyncExtensionFunction {
+class PageCaptureSaveAsMHTMLFunction : public ExtensionFunction {
public:
PageCaptureSaveAsMHTMLFunction();
@@ -39,7 +39,7 @@ class PageCaptureSaveAsMHTMLFunction : public ChromeAsyncExtensionFunction {
private:
~PageCaptureSaveAsMHTMLFunction() override;
- bool RunAsync() override;
+ ResponseAction Run() override;
bool OnMessageReceived(const IPC::Message& message) override;
#if defined(OS_CHROMEOS)
@@ -48,8 +48,8 @@ class PageCaptureSaveAsMHTMLFunction : public ChromeAsyncExtensionFunction {
#endif
// Returns whether or not the extension has permission to capture the current
- // page.
- bool CanCaptureCurrentPage();
+ // page. Sets |*error| to an error value on failure.
+ bool CanCaptureCurrentPage(std::string* error);
// Called on the file thread.
void CreateTemporaryFile();
diff --git a/chromium/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc b/chromium/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
index 387f41fc569..db06b1b95ee 100644
--- a/chromium/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc
@@ -78,7 +78,7 @@ class PageCaptureSaveAsMHTMLDelegate
// TODO(crbug.com/961017): Fix memory leaks in tests and re-enable on LSAN.
// Also flaky-failing on slow (debug) bots: https://crbug.com/1017305
#if defined(LEAK_SANITIZER) || !defined(NDEBUG) || \
- defined(ADDRESS_SANITIZER) || defined(OS_WIN)
+ defined(ADDRESS_SANITIZER) || defined(OS_MACOSX) || defined(OS_WIN)
#define MAYBE_SaveAsMHTML DISABLED_SaveAsMHTML
#else
#define MAYBE_SaveAsMHTML SaveAsMHTML
@@ -87,8 +87,8 @@ class PageCaptureSaveAsMHTMLDelegate
IN_PROC_BROWSER_TEST_F(ExtensionPageCaptureApiTest, MAYBE_SaveAsMHTML) {
ASSERT_TRUE(StartEmbeddedTestServer());
PageCaptureSaveAsMHTMLDelegate delegate;
- ASSERT_TRUE(RunExtensionTestWithFlagsAndArg(
- "page_capture", "ONLY_PAGE_CAPTURE_PERMISSION", kFlagNone))
+ ASSERT_TRUE(
+ RunExtensionTestWithArg("page_capture", "ONLY_PAGE_CAPTURE_PERMISSION"))
<< message_;
// Make sure the MHTML data gets written to the temporary file.
ASSERT_FALSE(delegate.temp_file_.empty());
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/OWNERS b/chromium/chrome/browser/extensions/api/passwords_private/OWNERS
index aa215c7d505..e123d19737f 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/passwords_private/OWNERS
@@ -1 +1,5 @@
-stevenjb@chromium.org
+file://chrome/browser/resources/settings/OWNERS
+
+jdoerrie@chromium.org
+
+# COMPONENT: UI>Settings
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc b/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
new file mode 100644
index 00000000000..413965efe9b
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
@@ -0,0 +1,646 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/passwords_private/password_check_delegate.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <memory>
+#include <utility>
+
+#include "base/containers/flat_set.h"
+#include "base/memory/ref_counted.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/optional.h"
+#include "base/stl_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/time/time.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_utils.h"
+#include "chrome/browser/password_manager/bulk_leak_check_service_factory.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/api/passwords_private.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
+#include "components/password_manager/core/browser/bulk_leak_check_service.h"
+#include "components/password_manager/core/browser/compromised_credentials_table.h"
+#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
+#include "components/password_manager/core/browser/leak_detection/encryption_utils.h"
+#include "components/password_manager/core/browser/ui/compromised_credentials_provider.h"
+#include "components/password_manager/core/browser/ui/credential_utils.h"
+#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "components/url_formatter/elide_url.h"
+#include "components/url_formatter/url_formatter.h"
+#include "net/base/escape.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/l10n/time_format.h"
+#include "url/gurl.h"
+
+namespace extensions {
+
+namespace {
+
+using autofill::PasswordForm;
+using password_manager::CanonicalizeUsername;
+using password_manager::CompromiseType;
+using password_manager::CredentialWithPassword;
+using password_manager::LeakCheckCredential;
+using password_manager::PasswordCredentialLess;
+using ui::TimeFormat;
+
+using CompromisedCredentialsView =
+ password_manager::CompromisedCredentialsProvider::CredentialsView;
+using SavedPasswordsView =
+ password_manager::SavedPasswordsPresenter::SavedPasswordsView;
+using State = password_manager::BulkLeakCheckService::State;
+
+using CompromisedCredentialSet =
+ base::flat_set<CredentialWithPassword, PasswordCredentialLess>;
+
+} // namespace
+
+// Key used to attach UserData to a LeakCheckCredential.
+constexpr char kPasswordCheckDataKey[] = "password-check-data-key";
+
+// Class remembering the state required to update the progress of an ongoing
+// Password Check.
+class PasswordCheckProgress : public base::RefCounted<PasswordCheckProgress> {
+ public:
+ base::WeakPtr<PasswordCheckProgress> GetWeakPtr() {
+ return weak_ptr_factory_.GetWeakPtr();
+ }
+
+ size_t remaining_in_queue() const { return remaining_in_queue_; }
+ size_t already_processed() const { return already_processed_; }
+
+ // Increments the counts corresponding to |password|. Intended to be called
+ // for each credential that is passed to the bulk check.
+ void IncrementCounts(const PasswordForm& password) {
+ ++remaining_in_queue_;
+ ++counts_[password];
+ }
+
+ // Updates the counts after a |credential| has been processed by the bulk
+ // check.
+ void OnProcessed(const LeakCheckCredential& credential) {
+ auto it = counts_.find(credential);
+ const int num_matching = it != counts_.end() ? it->second : 0;
+ already_processed_ += num_matching;
+ remaining_in_queue_ -= num_matching;
+ }
+
+ private:
+ friend class base::RefCounted<PasswordCheckProgress>;
+ ~PasswordCheckProgress() = default;
+
+ // Count variables needed to correctly show the progress of the check to the
+ // user. |already_processed_| contains the number of credentials that have
+ // been checked already, while |remaining_in_queue_| remembers how many
+ // passwords still need to be checked.
+ // Since the bulk leak check tries to be as efficient as possible, it performs
+ // a deduplication step before starting to check passwords. In this step it
+ // canonicalizes each credential, and only processes the combinations that are
+ // unique. Since this number likely does not match the total number of saved
+ // passwords, we remember in |counts_| how many saved passwords a given
+ // canonicalized credential corresponds to.
+ size_t already_processed_ = 0;
+ size_t remaining_in_queue_ = 0;
+ std::map<password_manager::CanonicalizedCredential, size_t> counts_;
+
+ base::WeakPtrFactory<PasswordCheckProgress> weak_ptr_factory_{this};
+};
+
+namespace {
+
+// A class attached to each LeakCheckCredential that holds a shared handle to
+// the PasswordCheckProgress and is able to update the progress accordingly.
+class PasswordCheckData : public LeakCheckCredential::Data {
+ public:
+ explicit PasswordCheckData(scoped_refptr<PasswordCheckProgress> progress)
+ : progress_(std::move(progress)) {}
+ ~PasswordCheckData() override = default;
+
+ std::unique_ptr<Data> Clone() override {
+ return std::make_unique<PasswordCheckData>(progress_);
+ }
+
+ private:
+ scoped_refptr<PasswordCheckProgress> progress_;
+};
+
+api::passwords_private::PasswordCheckState ConvertPasswordCheckState(
+ State state) {
+ switch (state) {
+ case State::kIdle:
+ return api::passwords_private::PASSWORD_CHECK_STATE_IDLE;
+ case State::kRunning:
+ return api::passwords_private::PASSWORD_CHECK_STATE_RUNNING;
+ case State::kCanceled:
+ return api::passwords_private::PASSWORD_CHECK_STATE_CANCELED;
+ case State::kSignedOut:
+ return api::passwords_private::PASSWORD_CHECK_STATE_SIGNED_OUT;
+ case State::kNetworkError:
+ return api::passwords_private::PASSWORD_CHECK_STATE_OFFLINE;
+ case State::kQuotaLimit:
+ return api::passwords_private::PASSWORD_CHECK_STATE_QUOTA_LIMIT;
+ case State::kTokenRequestFailure:
+ case State::kHashingFailure:
+ case State::kServiceError:
+ return api::passwords_private::PASSWORD_CHECK_STATE_OTHER_ERROR;
+ }
+
+ NOTREACHED();
+ return api::passwords_private::PASSWORD_CHECK_STATE_NONE;
+}
+
+// Computes a map that matches compromised credentials with corresponding saved
+// passwords in the store. This is needed to reflect changes to the underlying
+// password store when a compromised credential gets modified or removed through
+// the UI. Also it allows to inject affiliation information to be displayed in
+// the UI.
+PasswordCheckDelegate::CredentialPasswordsMap
+MapCompromisedCredentialsToSavedPasswords(
+ CompromisedCredentialsView compromised_credentials_view,
+ SavedPasswordsView saved_passwords) {
+ // Create a set to turn queries to look up a matching credential from O(n) to
+ // O(log n).
+ CompromisedCredentialSet compromised_credentials(
+ compromised_credentials_view.begin(), compromised_credentials_view.end());
+
+ // Populate the map. The values are vectors, because it is possible that
+ // multiple saved passwords match to the same compromised credential. In most
+ // cases there should be a 1-1 relationship, though.
+ PasswordCheckDelegate::CredentialPasswordsMap passwords_map;
+ for (const auto& saved_password : saved_passwords) {
+ auto it = compromised_credentials.find(
+ password_manager::CredentialView(saved_password));
+ if (it != compromised_credentials.end()) {
+ passwords_map[*it].push_back(saved_password);
+ }
+ }
+
+ return passwords_map;
+}
+
+std::string FormatElapsedTime(base::Time time) {
+ const base::TimeDelta elapsed_time = base::Time::Now() - time;
+ if (elapsed_time < base::TimeDelta::FromMinutes(1))
+ return l10n_util::GetStringUTF8(IDS_SETTINGS_PASSWORDS_JUST_NOW);
+
+ return base::UTF16ToUTF8(TimeFormat::SimpleWithMonthAndYear(
+ TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG, elapsed_time, true));
+}
+
+// Helper struct that bundles a CredentialWithPassword with a corresponding
+// passwords_private::CompromiseType. This is necessary to support the both
+// PHISHED_AND_LEAKED case, which does not exists in password_manager's
+// CompromiseType.
+struct CompromisedCredentialAndType {
+ CredentialWithPassword credential;
+ api::passwords_private::CompromiseType type;
+};
+
+// Orders |compromised_credentials| in such a way that phished credentials
+// precede leaked credentials, and that credentials of the same compromise type
+// are ordered by recency. Furthermore it de-duplicates credentials that are
+// both phished and leaked, making sure they only appear once in the final list.
+std::vector<CompromisedCredentialAndType> OrderCompromisedCredentials(
+ CompromisedCredentialsView compromised_credentials) {
+ // Partition the compromised credentials into phished and leaked.
+ std::vector<CredentialWithPassword> phished_storage;
+ std::vector<CredentialWithPassword> leaked_storage;
+ std::partition_copy(
+ compromised_credentials.begin(), compromised_credentials.end(),
+ std::back_inserter(phished_storage), std::back_inserter(leaked_storage),
+ [](const auto& credential) {
+ return credential.compromise_type == CompromiseType::kPhished;
+ });
+
+ // Perform a set intersection to find credentials that are both phished and
+ // leaked. Operate on flat_sets, since they provide a more convenient API.
+ CompromisedCredentialSet phished = std::move(phished_storage);
+ CompromisedCredentialSet leaked = std::move(leaked_storage);
+ CompromisedCredentialSet phished_and_leaked;
+ std::set_intersection(
+ phished.begin(), phished.end(), leaked.begin(), leaked.end(),
+ std::inserter(phished_and_leaked, phished_and_leaked.end()),
+ PasswordCredentialLess());
+
+ // Iterate through the phished and leaked credentials and update their
+ // timestamp to be the most recent compromise event.
+ for (auto& phished_and_leaked : phished_and_leaked) {
+ phished_and_leaked.create_time =
+ std::max(phished.find(phished_and_leaked)->create_time,
+ leaked.find(phished_and_leaked)->create_time);
+ }
+
+ // Erase phished and leaked credentials from the other two sets.
+ auto is_phished_and_leaked = [&](const auto& credential) {
+ return phished_and_leaked.contains(credential);
+ };
+ base::EraseIf(phished, is_phished_and_leaked);
+ base::EraseIf(leaked, is_phished_and_leaked);
+
+ // Finally move all credentials into a single list, associating with the
+ // corresponding CompromiseType.
+ const size_t num_phished = phished.size() + phished_and_leaked.size();
+ std::vector<CompromisedCredentialAndType> results;
+ results.reserve(compromised_credentials.size());
+ for (auto& credential : std::move(phished).extract()) {
+ results.push_back({std::move(credential),
+ api::passwords_private::COMPROMISE_TYPE_PHISHED});
+ }
+
+ for (auto& credential : std::move(phished_and_leaked).extract()) {
+ results.push_back(
+ {std::move(credential),
+ api::passwords_private::COMPROMISE_TYPE_PHISHED_AND_LEAKED});
+ }
+
+ for (auto& credential : std::move(leaked).extract()) {
+ results.push_back({std::move(credential),
+ api::passwords_private::COMPROMISE_TYPE_LEAKED});
+ }
+
+ // By construction the phished credentials precede the leaked credentials in
+ // |results|. Now sort both groups by their creation date so that most recent
+ // compromises appear first in both lists.
+ auto create_time_cmp = [](const auto& lhs, const auto& rhs) {
+ return lhs.credential.create_time > rhs.credential.create_time;
+ };
+ std::sort(results.begin(), results.begin() + num_phished, create_time_cmp);
+ std::sort(results.begin() + num_phished, results.end(), create_time_cmp);
+ return results;
+}
+
+} // namespace
+
+PasswordCheckDelegate::PasswordCheckDelegate(Profile* profile)
+ : profile_(profile),
+ password_store_(PasswordStoreFactory::GetForProfile(
+ profile,
+ ServiceAccessType::EXPLICIT_ACCESS)),
+ saved_passwords_presenter_(password_store_),
+ compromised_credentials_provider_(password_store_,
+ &saved_passwords_presenter_),
+ bulk_leak_check_service_adapter_(
+ &saved_passwords_presenter_,
+ BulkLeakCheckServiceFactory::GetForProfile(profile_),
+ profile_->GetPrefs()) {
+ observed_saved_passwords_presenter_.Add(&saved_passwords_presenter_);
+ observed_compromised_credentials_provider_.Add(
+ &compromised_credentials_provider_);
+ observed_bulk_leak_check_service_.Add(
+ BulkLeakCheckServiceFactory::GetForProfile(profile_));
+
+ // Instructs the presenter and provider to initialize and built their caches.
+ // This will soon after invoke OnCompromisedCredentialsChanged(), which then
+ // initializes |credentials_to_forms_| as well. Calls to
+ // GetCompromisedCredentials() that might happen until then will return an
+ // empty list.
+ saved_passwords_presenter_.Init();
+ compromised_credentials_provider_.Init();
+}
+
+PasswordCheckDelegate::~PasswordCheckDelegate() = default;
+
+std::vector<api::passwords_private::CompromisedCredential>
+PasswordCheckDelegate::GetCompromisedCredentials() {
+ std::vector<CompromisedCredentialAndType>
+ ordered_compromised_credential_and_types = OrderCompromisedCredentials(
+ compromised_credentials_provider_.GetCompromisedCredentials());
+
+ std::vector<api::passwords_private::CompromisedCredential>
+ compromised_credentials;
+ compromised_credentials.reserve(
+ ordered_compromised_credential_and_types.size());
+ for (const auto& credential_and_type :
+ ordered_compromised_credential_and_types) {
+ const auto& credential = credential_and_type.credential;
+ api::passwords_private::CompromisedCredential api_credential;
+ auto facet = password_manager::FacetURI::FromPotentiallyInvalidSpec(
+ credential.signon_realm);
+ if (facet.IsValidAndroidFacetURI()) {
+ api_credential.is_android_credential = true;
+ // |formatted_orgin|, |detailed_origin| and |change_password_url| need
+ // special handling for Android. Here we use affiliation information
+ // instead of the signon_realm.
+ const PasswordForm& android_form =
+ credentials_to_forms_.at(credential).at(0);
+ if (!android_form.app_display_name.empty()) {
+ api_credential.formatted_origin = android_form.app_display_name;
+ api_credential.detailed_origin = android_form.app_display_name;
+ api_credential.change_password_url =
+ std::make_unique<std::string>(android_form.affiliated_web_realm);
+ } else {
+ // In case no affiliation information could be obtained show the
+ // formatted package name to the user. An empty change_password_url will
+ // be handled by the frontend, by not including a link in this case.
+ api_credential.formatted_origin = l10n_util::GetStringFUTF8(
+ IDS_SETTINGS_PASSWORDS_ANDROID_APP,
+ base::UTF8ToUTF16(facet.android_package_name()));
+ api_credential.detailed_origin = facet.android_package_name();
+ }
+ } else {
+ api_credential.is_android_credential = false;
+ api_credential.formatted_origin =
+ base::UTF16ToUTF8(url_formatter::FormatUrl(
+ GURL(credential.signon_realm),
+ url_formatter::kFormatUrlOmitDefaults |
+ url_formatter::kFormatUrlOmitHTTPS |
+ url_formatter::kFormatUrlOmitTrivialSubdomains |
+ url_formatter::kFormatUrlTrimAfterHost,
+ net::UnescapeRule::SPACES, nullptr, nullptr, nullptr));
+ api_credential.detailed_origin =
+ base::UTF16ToUTF8(url_formatter::FormatUrlForSecurityDisplay(
+ GURL(credential.signon_realm)));
+ api_credential.change_password_url =
+ std::make_unique<std::string>(credential.signon_realm);
+ }
+
+ api_credential.id =
+ compromised_credential_id_generator_.GenerateId(credential);
+ api_credential.signon_realm = credential.signon_realm;
+ api_credential.username = base::UTF16ToUTF8(credential.username);
+ api_credential.compromise_time =
+ credential.create_time.ToJsTimeIgnoringNull();
+ api_credential.compromise_type = credential_and_type.type;
+ api_credential.elapsed_time_since_compromise =
+ FormatElapsedTime(credential.create_time);
+ compromised_credentials.push_back(std::move(api_credential));
+ }
+
+ return compromised_credentials;
+}
+
+base::Optional<api::passwords_private::CompromisedCredential>
+PasswordCheckDelegate::GetPlaintextCompromisedPassword(
+ api::passwords_private::CompromisedCredential credential) const {
+ const CredentialWithPassword* compromised_credential =
+ FindMatchingCompromisedCredential(credential);
+ if (!compromised_credential)
+ return base::nullopt;
+
+ credential.password = std::make_unique<std::string>(
+ base::UTF16ToUTF8(compromised_credential->password));
+ return credential;
+}
+
+bool PasswordCheckDelegate::ChangeCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential,
+ base::StringPiece new_password) {
+ // Try to obtain the original CredentialWithPassword and try to find it in
+ // |credentials_to_forms_|. Return false if either one fails.
+ const CredentialWithPassword* compromised_credential =
+ FindMatchingCompromisedCredential(credential);
+ if (!compromised_credential)
+ return false;
+
+ auto it = credentials_to_forms_.find(*compromised_credential);
+ if (it == credentials_to_forms_.end())
+ return false;
+
+ // Make sure there are matching password forms. Also erase duplicates if there
+ // are any.
+ const auto& forms = it->second;
+ if (forms.empty())
+ return false;
+
+ for (size_t i = 1; i < forms.size(); ++i)
+ password_store_->RemoveLogin(forms[i]);
+
+ // Note: We Invoke EditPassword on the presenter rather than UpdateLogin() on
+ // the store, so that observers of the presenter get notified of this event.
+ return saved_passwords_presenter_.EditPassword(
+ forms[0], base::UTF8ToUTF16(new_password));
+}
+
+bool PasswordCheckDelegate::RemoveCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential) {
+ // Try to obtain the original CredentialWithPassword and try to find it in
+ // |credentials_to_forms_|. Return false if either one fails.
+ const CredentialWithPassword* compromised_credential =
+ FindMatchingCompromisedCredential(credential);
+ if (!compromised_credential)
+ return false;
+
+ auto it = credentials_to_forms_.find(*compromised_credential);
+ if (it == credentials_to_forms_.end())
+ return false;
+
+ // Erase all matching credentials from the store. Return whether any
+ // credentials were deleted.
+ SavedPasswordsView saved_passwords = it->second;
+ for (const PasswordForm& saved_password : saved_passwords)
+ password_store_->RemoveLogin(saved_password);
+
+ return !saved_passwords.empty();
+}
+
+void PasswordCheckDelegate::StartPasswordCheck(
+ StartPasswordCheckCallback callback) {
+ // If the delegate isn't initialized yet, enqueue the callback and return
+ // early.
+ if (!is_initialized_) {
+ start_check_callbacks_.push_back(std::move(callback));
+ return;
+ }
+
+ // Also return early if the check is already running.
+ if (bulk_leak_check_service_adapter_.GetBulkLeakCheckState() ==
+ State::kRunning) {
+ std::move(callback).Run(State::kRunning);
+ return;
+ }
+
+ auto progress = base::MakeRefCounted<PasswordCheckProgress>();
+ for (const auto& password : saved_passwords_presenter_.GetSavedPasswords())
+ progress->IncrementCounts(password);
+
+ password_check_progress_ = progress->GetWeakPtr();
+ PasswordCheckData data(std::move(progress));
+ is_check_running_ = bulk_leak_check_service_adapter_.StartBulkLeakCheck(
+ kPasswordCheckDataKey, &data);
+ DCHECK(is_check_running_);
+ std::move(callback).Run(
+ bulk_leak_check_service_adapter_.GetBulkLeakCheckState());
+}
+
+void PasswordCheckDelegate::StopPasswordCheck() {
+ if (!is_initialized_) {
+ for (auto&& callback : std::exchange(start_check_callbacks_, {}))
+ std::move(callback).Run(State::kIdle);
+ return;
+ }
+
+ bulk_leak_check_service_adapter_.StopBulkLeakCheck();
+}
+
+api::passwords_private::PasswordCheckStatus
+PasswordCheckDelegate::GetPasswordCheckStatus() const {
+ api::passwords_private::PasswordCheckStatus result;
+
+ // Obtain the timestamp of the last completed check. This is 0.0 in case the
+ // check never completely ran before.
+ const double last_check_completed = profile_->GetPrefs()->GetDouble(
+ password_manager::prefs::kLastTimePasswordCheckCompleted);
+ if (last_check_completed) {
+ result.elapsed_time_since_last_check = std::make_unique<std::string>(
+ FormatElapsedTime(base::Time::FromDoubleT(last_check_completed)));
+ }
+
+ State state = bulk_leak_check_service_adapter_.GetBulkLeakCheckState();
+ SavedPasswordsView saved_passwords =
+ saved_passwords_presenter_.GetSavedPasswords();
+
+ // Handle the currently running case first, only then consider errors.
+ if (state == State::kRunning) {
+ result.state = api::passwords_private::PASSWORD_CHECK_STATE_RUNNING;
+
+ if (password_check_progress_) {
+ result.already_processed =
+ std::make_unique<int>(password_check_progress_->already_processed());
+ result.remaining_in_queue =
+ std::make_unique<int>(password_check_progress_->remaining_in_queue());
+ } else {
+ result.already_processed = std::make_unique<int>(0);
+ result.remaining_in_queue = std::make_unique<int>(0);
+ }
+
+ return result;
+ }
+
+ if (saved_passwords.empty()) {
+ result.state = api::passwords_private::PASSWORD_CHECK_STATE_NO_PASSWORDS;
+ return result;
+ }
+
+ result.state = ConvertPasswordCheckState(state);
+ return result;
+}
+
+void PasswordCheckDelegate::OnSavedPasswordsChanged(SavedPasswordsView) {
+ // Getting the first notification about a change in saved passwords implies
+ // that the delegate is initialized, and start check callbacks can be invoked,
+ // if any.
+ if (!std::exchange(is_initialized_, true)) {
+ for (auto&& callback : std::exchange(start_check_callbacks_, {}))
+ StartPasswordCheck(std::move(callback));
+ }
+
+ // A change in the saved passwords might result in leaving or entering the
+ // NO_PASSWORDS state, thus we need to trigger a notification.
+ NotifyPasswordCheckStatusChanged();
+}
+
+void PasswordCheckDelegate::OnCompromisedCredentialsChanged(
+ CompromisedCredentialsView credentials) {
+ credentials_to_forms_ = MapCompromisedCredentialsToSavedPasswords(
+ credentials, saved_passwords_presenter_.GetSavedPasswords());
+ if (auto* event_router =
+ PasswordsPrivateEventRouterFactory::GetForProfile(profile_)) {
+ event_router->OnCompromisedCredentialsChanged(GetCompromisedCredentials());
+ }
+}
+
+void PasswordCheckDelegate::OnStateChanged(State state) {
+ if (state == State::kIdle && std::exchange(is_check_running_, false)) {
+ // When the service transitions from running into idle it has finished a
+ // check.
+ profile_->GetPrefs()->SetDouble(
+ password_manager::prefs::kLastTimePasswordCheckCompleted,
+ base::Time::Now().ToDoubleT());
+
+ // In case the check run to completion delay the last Check Status update by
+ // a second. This avoids flickering of the UI if the full check ran from
+ // start to finish almost immediately.
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::BindOnce(&PasswordCheckDelegate::NotifyPasswordCheckStatusChanged,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::TimeDelta::FromSeconds(1));
+ return;
+ }
+
+ // NotifyPasswordCheckStatusChanged() invokes GetPasswordCheckStatus()
+ // obtaining the relevant information. Thus there is no need to forward the
+ // arguments passed to OnStateChanged().
+ NotifyPasswordCheckStatusChanged();
+}
+
+void PasswordCheckDelegate::OnCredentialDone(
+ const LeakCheckCredential& credential,
+ password_manager::IsLeaked is_leaked) {
+ if (is_leaked) {
+ // In case the credential is leaked, iterate over all currently saved
+ // credentials and mark those as compromised that have the same
+ // canonicalized username and password.
+ const base::string16 canocalized_username =
+ CanonicalizeUsername(credential.username());
+ for (const PasswordForm& saved_password :
+ saved_passwords_presenter_.GetSavedPasswords()) {
+ if (saved_password.password_value == credential.password() &&
+ CanonicalizeUsername(saved_password.username_value) ==
+ canocalized_username) {
+ password_store_->AddCompromisedCredentials({
+ .signon_realm = saved_password.signon_realm,
+ .username = saved_password.username_value,
+ .create_time = base::Time::Now(),
+ .compromise_type = CompromiseType::kLeaked,
+ });
+ }
+ }
+ }
+
+ // Update the progress in case there is one.
+ if (password_check_progress_)
+ password_check_progress_->OnProcessed(credential);
+
+ // While the check is still running trigger an update of the check status,
+ // considering that the progress has changed.
+ if (bulk_leak_check_service_adapter_.GetBulkLeakCheckState() ==
+ State::kRunning) {
+ NotifyPasswordCheckStatusChanged();
+ }
+}
+
+const CredentialWithPassword*
+PasswordCheckDelegate::FindMatchingCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential) const {
+ const CredentialWithPassword* compromised_credential =
+ compromised_credential_id_generator_.TryGetKey(credential.id);
+ if (!compromised_credential)
+ return nullptr;
+
+ if (credential.signon_realm != compromised_credential->signon_realm ||
+ credential.username !=
+ base::UTF16ToUTF8(compromised_credential->username) ||
+ (credential.password &&
+ *credential.password !=
+ base::UTF16ToUTF8(compromised_credential->password))) {
+ return nullptr;
+ }
+
+ return compromised_credential;
+}
+
+void PasswordCheckDelegate::NotifyPasswordCheckStatusChanged() {
+ if (auto* event_router =
+ PasswordsPrivateEventRouterFactory::GetForProfile(profile_)) {
+ event_router->OnPasswordCheckStatusChanged(GetPasswordCheckStatus());
+ }
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.h b/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
new file mode 100644
index 00000000000..c2ec8b18e99
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
@@ -0,0 +1,194 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_PASSWORD_CHECK_DELEGATE_H_
+#define CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_PASSWORD_CHECK_DELEGATE_H_
+
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_utils.h"
+#include "chrome/common/extensions/api/passwords_private.h"
+#include "components/password_manager/core/browser/bulk_leak_check_service.h"
+#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "components/password_manager/core/browser/password_store.h"
+#include "components/password_manager/core/browser/ui/bulk_leak_check_service_adapter.h"
+#include "components/password_manager/core/browser/ui/compromised_credentials_provider.h"
+#include "components/password_manager/core/browser/ui/credential_utils.h"
+#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h"
+
+class Profile;
+
+namespace password_manager {
+class PasswordStore;
+}
+
+namespace extensions {
+
+extern const char kPasswordCheckDataKey[];
+
+class PasswordCheckProgress;
+
+// This class handles the part of the passwordsPrivate extension API that deals
+// with the bulk password check feature.
+class PasswordCheckDelegate
+ : public password_manager::SavedPasswordsPresenter::Observer,
+ public password_manager::CompromisedCredentialsProvider::Observer,
+ public password_manager::BulkLeakCheckService::Observer {
+ public:
+ using StartPasswordCheckCallback =
+ PasswordsPrivateDelegate::StartPasswordCheckCallback;
+
+ using CredentialPasswordsMap =
+ std::map<password_manager::CredentialWithPassword,
+ std::vector<autofill::PasswordForm>,
+ password_manager::PasswordCredentialLess>;
+
+ explicit PasswordCheckDelegate(Profile* profile);
+ PasswordCheckDelegate(const PasswordCheckDelegate&) = delete;
+ PasswordCheckDelegate& operator=(const PasswordCheckDelegate&) = delete;
+ ~PasswordCheckDelegate() override;
+
+ // Obtains information about compromised credentials. This includes the last
+ // time a check was run, as well as all compromised credentials that are
+ // present in the password store.
+ std::vector<api::passwords_private::CompromisedCredential>
+ GetCompromisedCredentials();
+
+ // Requests the plaintext password for |credential|. If successful, this
+ // returns |credential| with its |password| member set. This can fail if no
+ // matching compromised credential can be found in the password store.
+ base::Optional<api::passwords_private::CompromisedCredential>
+ GetPlaintextCompromisedPassword(
+ api::passwords_private::CompromisedCredential credential) const;
+
+ // Attempts to change the stored password of |credential| to |new_password|.
+ // Returns whether the change succeeded.
+ bool ChangeCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential,
+ base::StringPiece new_password);
+
+ // Attempts to remove |credential| from the password store. Returns whether
+ // the remove succeeded.
+ bool RemoveCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential);
+
+ // Requests to start a check for compromised passwords. Invokes |callback|
+ // once a check is running or the request was stopped via StopPasswordCheck().
+ void StartPasswordCheck(
+ StartPasswordCheckCallback callback = base::DoNothing());
+ // Stops checking for compromised passwords.
+ void StopPasswordCheck();
+
+ // Returns the current status of the password check.
+ api::passwords_private::PasswordCheckStatus GetPasswordCheckStatus() const;
+
+ private:
+ // password_manager::SavedPasswordsPresenter::Observer:
+ void OnSavedPasswordsChanged(
+ password_manager::SavedPasswordsPresenter::SavedPasswordsView passwords)
+ override;
+
+ // password_manager::CompromisedCredentialsProvider::Observer:
+ // Invokes PasswordsPrivateEventRouter::OnCompromisedCredentialsChanged if
+ // a valid pointer can be obtained.
+ void OnCompromisedCredentialsChanged(
+ password_manager::CompromisedCredentialsProvider::CredentialsView
+ credentials) override;
+
+ // password_manager::BulkLeakCheckService::Observer:
+ void OnStateChanged(
+ password_manager::BulkLeakCheckService::State state) override;
+ void OnCredentialDone(const password_manager::LeakCheckCredential& credential,
+ password_manager::IsLeaked is_leaked) override;
+
+ // Tries to find the matching CredentialWithPassword for |credential|. It
+ // performs a look-up in |compromised_credential_id_generator_| using
+ // |credential.id|. If a matching value exists it also verifies that signon
+ // realm, username and when possible password match.
+ // Returns a pointer to the matching CredentialWithPassword on success or
+ // nullptr otherwise.
+ const password_manager::CredentialWithPassword*
+ FindMatchingCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential) const;
+
+ // Tries to notify the PasswordsPrivateEventRouter that the password check
+ // status has changed. Invoked after OnSavedPasswordsChanged and
+ // OnStateChanged.
+ void NotifyPasswordCheckStatusChanged();
+
+ // Raw pointer to the underlying profile. Needs to outlive this instance.
+ Profile* profile_ = nullptr;
+
+ // Handle to the password store, powering both |saved_passwords_presenter_|
+ // and |compromised_credentials_provider_|.
+ scoped_refptr<password_manager::PasswordStore> password_store_;
+
+ // Used by |compromised_credentials_provider_| to obtain the list of saved
+ // passwords.
+ password_manager::SavedPasswordsPresenter saved_passwords_presenter_;
+
+ // Used to obtain the list of compromised credentials.
+ password_manager::CompromisedCredentialsProvider
+ compromised_credentials_provider_;
+
+ // Adapter used to start, monitor and stop a bulk leak check.
+ password_manager::BulkLeakCheckServiceAdapter
+ bulk_leak_check_service_adapter_;
+
+ // Boolean that remembers whether the delegate is initialized. This is done
+ // when the delegate obtains the list of saved passwords for the first time.
+ bool is_initialized_ = false;
+
+ // List of callbacks that were passed to StartPasswordCheck() prior to the
+ // delegate being initialized. These will be run when either initialization
+ // finishes, or StopPasswordCheck() gets invoked before hand.
+ std::vector<StartPasswordCheckCallback> start_check_callbacks_;
+
+ // Remembers the progress of the ongoing check. Null if no check is currently
+ // running.
+ base::WeakPtr<PasswordCheckProgress> password_check_progress_;
+
+ // Remembers whether a password check is running right now.
+ bool is_check_running_ = false;
+
+ // A scoped observer for |saved_passwords_presenter_|.
+ ScopedObserver<password_manager::SavedPasswordsPresenter,
+ password_manager::SavedPasswordsPresenter::Observer>
+ observed_saved_passwords_presenter_{this};
+
+ // A scoped observer for |compromised_credentials_provider_|.
+ ScopedObserver<password_manager::CompromisedCredentialsProvider,
+ password_manager::CompromisedCredentialsProvider::Observer>
+ observed_compromised_credentials_provider_{this};
+
+ // A scoped observer for the BulkLeakCheckService.
+ ScopedObserver<password_manager::BulkLeakCheckService,
+ password_manager::BulkLeakCheckService::Observer>
+ observed_bulk_leak_check_service_{this};
+
+ // A map that matches CredentialWithPasswords to corresponding PasswordForms.
+ // This is required to inject affiliation information into Android
+ // credentials, as well as being able to reflect edits and removals of
+ // compromised credentials in the underlying password store.
+ CredentialPasswordsMap credentials_to_forms_;
+
+ // An id generator for compromised credentials. Required to match
+ // api::passwords_private::CompromisedCredential instances passed to the UI
+ // with the underlying CredentialWithPassword they are based on.
+ IdGenerator<password_manager::CredentialWithPassword,
+ int,
+ password_manager::PasswordCredentialLess>
+ compromised_credential_id_generator_;
+
+ base::WeakPtrFactory<PasswordCheckDelegate> weak_ptr_factory_{this};
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_PASSWORD_CHECK_DELEGATE_H_
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc b/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc
new file mode 100644
index 00000000000..067b79f09b7
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc
@@ -0,0 +1,1008 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/passwords_private/password_check_delegate.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
+#include "base/stl_util.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/time/time.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h"
+#include "chrome/browser/password_manager/bulk_leak_check_service_factory.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/common/extensions/api/passwords_private.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/password_manager/core/browser/bulk_leak_check_service.h"
+#include "components/password_manager/core/browser/compromised_credentials_table.h"
+#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
+#include "components/password_manager/core/browser/leak_detection/leak_detection_delegate_interface.h"
+#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/test_password_store.h"
+#include "components/password_manager/core/common/password_manager_features.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/browser_task_environment.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_event_histogram_value.h"
+#include "extensions/browser/test_event_router.h"
+#include "extensions/browser/test_event_router_observer.h"
+#include "services/network/test/test_shared_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+namespace {
+
+constexpr char kExampleCom[] = "https://example.com";
+constexpr char kExampleOrg[] = "http://www.example.org";
+constexpr char kExampleApp[] = "com.example.app";
+
+constexpr char kTestEmail[] = "user@gmail.com";
+
+constexpr char kUsername1[] = "alice";
+constexpr char kUsername2[] = "bob";
+
+constexpr char kPassword1[] = "s3cre3t";
+constexpr char kPassword2[] = "f00b4r";
+
+using api::passwords_private::CompromisedCredential;
+using api::passwords_private::PasswordCheckStatus;
+using autofill::PasswordForm;
+using password_manager::BulkLeakCheckDelegateInterface;
+using password_manager::BulkLeakCheckService;
+using password_manager::CompromisedCredentials;
+using password_manager::CompromiseType;
+using password_manager::IsLeaked;
+using password_manager::LeakCheckCredential;
+using password_manager::TestPasswordStore;
+using password_manager::prefs::kLastTimePasswordCheckCompleted;
+using signin::IdentityTestEnvironment;
+using ::testing::AllOf;
+using ::testing::AtLeast;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::IsEmpty;
+using ::testing::IsNull;
+using ::testing::Mock;
+using ::testing::Pointee;
+using ::testing::UnorderedElementsAre;
+
+using MockStartPasswordCheckCallback =
+ base::MockCallback<PasswordCheckDelegate::StartPasswordCheckCallback>;
+
+PasswordsPrivateEventRouter* CreateAndUsePasswordsPrivateEventRouter(
+ Profile* profile) {
+ return static_cast<PasswordsPrivateEventRouter*>(
+ PasswordsPrivateEventRouterFactory::GetInstance()
+ ->SetTestingFactoryAndUse(
+ profile,
+ base::BindRepeating([](content::BrowserContext* context) {
+ return std::unique_ptr<KeyedService>(
+ PasswordsPrivateEventRouter::Create(context));
+ })));
+}
+
+EventRouter* CreateAndUseEventRouter(Profile* profile) {
+ // The factory function only requires that T be a KeyedService. Ensure it is
+ // actually derived from EventRouter to avoid undefined behavior.
+ return static_cast<EventRouter*>(
+ extensions::EventRouterFactory::GetInstance()->SetTestingFactoryAndUse(
+ profile, base::BindRepeating([](content::BrowserContext* context) {
+ return std::unique_ptr<KeyedService>(
+ std::make_unique<EventRouter>(context, nullptr));
+ })));
+}
+
+scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore(
+ Profile* profile) {
+ return base::WrapRefCounted(static_cast<TestPasswordStore*>(
+ PasswordStoreFactory::GetInstance()
+ ->SetTestingFactoryAndUse(
+ profile,
+ base::BindRepeating(&password_manager::BuildPasswordStore<
+ content::BrowserContext, TestPasswordStore>))
+ .get()));
+}
+
+BulkLeakCheckService* CreateAndUseBulkLeakCheckService(
+ signin::IdentityManager* identity_manager,
+ Profile* profile) {
+ return static_cast<BulkLeakCheckService*>(
+ BulkLeakCheckServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+ profile, base::BindLambdaForTesting([identity_manager](
+ content::BrowserContext*) {
+ return std::unique_ptr<
+ KeyedService>(std::make_unique<BulkLeakCheckService>(
+ identity_manager,
+ base::MakeRefCounted<network::TestSharedURLLoaderFactory>()));
+ })));
+}
+
+CompromisedCredentials MakeCompromised(
+ base::StringPiece signon_realm,
+ base::StringPiece username,
+ base::TimeDelta time_since_creation = base::TimeDelta(),
+ CompromiseType compromise_type = CompromiseType::kLeaked) {
+ return {
+ std::string(signon_realm),
+ base::ASCIIToUTF16(username),
+ base::Time::Now() - time_since_creation,
+ compromise_type,
+ };
+}
+
+PasswordForm MakeSavedPassword(base::StringPiece signon_realm,
+ base::StringPiece username,
+ base::StringPiece password = kPassword1,
+ base::StringPiece username_element = "") {
+ PasswordForm form;
+ form.signon_realm = std::string(signon_realm);
+ form.username_value = base::ASCIIToUTF16(username);
+ form.password_value = base::ASCIIToUTF16(password);
+ form.username_element = base::ASCIIToUTF16(username_element);
+ return form;
+}
+
+std::string MakeAndroidRealm(base::StringPiece package_name) {
+ return base::StrCat({"android://hash@", package_name});
+}
+
+PasswordForm MakeSavedAndroidPassword(
+ base::StringPiece package_name,
+ base::StringPiece username,
+ base::StringPiece app_display_name = "",
+ base::StringPiece affiliated_web_realm = "") {
+ PasswordForm form;
+ form.signon_realm = MakeAndroidRealm(package_name);
+ form.username_value = base::ASCIIToUTF16(username);
+ form.app_display_name = std::string(app_display_name);
+ form.affiliated_web_realm = std::string(affiliated_web_realm);
+ return form;
+}
+
+// Creates matcher for a given compromised credential
+auto ExpectCompromisedCredential(
+ const std::string& formatted_origin,
+ const std::string& detailed_origin,
+ const base::Optional<std::string>& change_password_url,
+ const std::string& username,
+ base::TimeDelta elapsed_time_since_compromise,
+ const std::string& elapsed_time_since_compromise_str,
+ api::passwords_private::CompromiseType compromise_type) {
+ auto change_password_url_field_matcher =
+ change_password_url.has_value()
+ ? Field(&CompromisedCredential::change_password_url,
+ Pointee(change_password_url.value()))
+ : Field(&CompromisedCredential::change_password_url, IsNull());
+ return AllOf(
+ Field(&CompromisedCredential::formatted_origin, formatted_origin),
+ Field(&CompromisedCredential::detailed_origin, detailed_origin),
+ change_password_url_field_matcher,
+ Field(&CompromisedCredential::username, username),
+ Field(&CompromisedCredential::compromise_time,
+ (base::Time::Now() - elapsed_time_since_compromise)
+ .ToJsTimeIgnoringNull()),
+ Field(&CompromisedCredential::elapsed_time_since_compromise,
+ elapsed_time_since_compromise_str),
+ Field(&CompromisedCredential::compromise_type, compromise_type));
+}
+
+class PasswordCheckDelegateTest : public ::testing::Test {
+ public:
+ PasswordCheckDelegateTest() {
+ prefs_.registry()->RegisterDoublePref(kLastTimePasswordCheckCompleted, 0.0);
+ scoped_feature_list_.InitAndEnableFeature(
+ password_manager::features::kPasswordCheck);
+ }
+
+ void RunUntilIdle() { task_env_.RunUntilIdle(); }
+ TestEventRouterObserver& event_router_observer() {
+ return event_router_observer_;
+ }
+ IdentityTestEnvironment& identity_test_env() { return identity_test_env_; }
+ TestingPrefServiceSimple prefs_;
+ TestingProfile& profile() { return profile_; }
+ TestPasswordStore& store() { return *store_; }
+ BulkLeakCheckService* service() { return bulk_leak_check_service_; }
+ PasswordCheckDelegate& delegate() { return delegate_; }
+
+ private:
+ content::BrowserTaskEnvironment task_env_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ signin::IdentityTestEnvironment identity_test_env_;
+ TestingProfile profile_;
+ EventRouter* event_router_ = CreateAndUseEventRouter(&profile_);
+ PasswordsPrivateEventRouter* password_router_ =
+ CreateAndUsePasswordsPrivateEventRouter(&profile_);
+ TestEventRouterObserver event_router_observer_{event_router_};
+ BulkLeakCheckService* bulk_leak_check_service_ =
+ CreateAndUseBulkLeakCheckService(identity_test_env_.identity_manager(),
+ &profile_);
+ scoped_refptr<TestPasswordStore> store_ =
+ CreateAndUseTestPasswordStore(&profile_);
+ base::test::ScopedFeatureList scoped_feature_list_;
+ PasswordCheckDelegate delegate_{&profile_};
+};
+
+} // namespace
+
+// Sets up the password store with a couple of passwords and compromised
+// credentials. Verifies that the result is ordered in such a way that phished
+// credentials are before leaked credentials and that within each group
+// credentials are ordered by recency.
+TEST_F(PasswordCheckDelegateTest, GetCompromisedCredentialsOrders) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername2));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername1));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername2));
+
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleCom, kUsername1, base::TimeDelta::FromMinutes(1),
+ CompromiseType::kLeaked));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleCom, kUsername2, base::TimeDelta::FromMinutes(2),
+ CompromiseType::kPhished));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleOrg, kUsername2, base::TimeDelta::FromMinutes(3),
+ CompromiseType::kLeaked));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleOrg, kUsername1, base::TimeDelta::FromMinutes(4),
+ CompromiseType::kPhished));
+ RunUntilIdle();
+
+ EXPECT_THAT(
+ delegate().GetCompromisedCredentials(),
+ ElementsAre(ExpectCompromisedCredential(
+ "example.com", kExampleCom, kExampleCom, kUsername2,
+ base::TimeDelta::FromMinutes(2), "2 minutes ago",
+ api::passwords_private::COMPROMISE_TYPE_PHISHED),
+ ExpectCompromisedCredential(
+ "example.org", kExampleOrg, kExampleOrg, kUsername1,
+ base::TimeDelta::FromMinutes(4), "4 minutes ago",
+ api::passwords_private::COMPROMISE_TYPE_PHISHED),
+ ExpectCompromisedCredential(
+ "example.com", kExampleCom, kExampleCom, kUsername1,
+ base::TimeDelta::FromMinutes(1), "1 minute ago",
+ api::passwords_private::COMPROMISE_TYPE_LEAKED),
+ ExpectCompromisedCredential(
+ "example.org", kExampleOrg, kExampleOrg, kUsername2,
+ base::TimeDelta::FromMinutes(3), "3 minutes ago",
+ api::passwords_private::COMPROMISE_TYPE_LEAKED)));
+}
+
+// Verifies that the formatted timestamp associated with a compromised
+// credential covers the "Just now" cases (less than a minute ago), as well as
+// months and years.
+TEST_F(PasswordCheckDelegateTest, GetCompromisedCredentialsHandlesTimes) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername2));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername1));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername2));
+
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleCom, kUsername1, base::TimeDelta::FromSeconds(59),
+ CompromiseType::kLeaked));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleCom, kUsername2, base::TimeDelta::FromSeconds(60),
+ CompromiseType::kLeaked));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleOrg, kUsername1, base::TimeDelta::FromDays(100),
+ CompromiseType::kLeaked));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleOrg, kUsername2, base::TimeDelta::FromDays(800),
+ CompromiseType::kLeaked));
+ RunUntilIdle();
+
+ EXPECT_THAT(
+ delegate().GetCompromisedCredentials(),
+ ElementsAre(ExpectCompromisedCredential(
+ "example.com", kExampleCom, kExampleCom, kUsername1,
+ base::TimeDelta::FromSeconds(59), "Just now",
+ api::passwords_private::COMPROMISE_TYPE_LEAKED),
+ ExpectCompromisedCredential(
+ "example.com", kExampleCom, kExampleCom, kUsername2,
+ base::TimeDelta::FromSeconds(60), "1 minute ago",
+ api::passwords_private::COMPROMISE_TYPE_LEAKED),
+ ExpectCompromisedCredential(
+ "example.org", kExampleOrg, kExampleOrg, kUsername1,
+ base::TimeDelta::FromDays(100), "3 months ago",
+ api::passwords_private::COMPROMISE_TYPE_LEAKED),
+ ExpectCompromisedCredential(
+ "example.org", kExampleOrg, kExampleOrg, kUsername2,
+ base::TimeDelta::FromDays(800), "2 years ago",
+ api::passwords_private::COMPROMISE_TYPE_LEAKED)));
+}
+
+// Verifies that both leaked and phished credentials are ordered correctly
+// within the list of compromised credentials. These credentials should be
+// listed before just leaked ones and have a timestamp that corresponds to the
+// most recent compromise.
+TEST_F(PasswordCheckDelegateTest,
+ GetCompromisedCredentialsDedupesLeakedAndCompromised) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername2));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername1));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername2));
+
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleCom, kUsername1, base::TimeDelta::FromMinutes(1),
+ CompromiseType::kLeaked));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleCom, kUsername2, base::TimeDelta::FromMinutes(2),
+ CompromiseType::kLeaked));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleOrg, kUsername1, base::TimeDelta::FromMinutes(3),
+ CompromiseType::kPhished));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleOrg, kUsername2, base::TimeDelta::FromMinutes(4),
+ CompromiseType::kPhished));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleCom, kUsername1, base::TimeDelta::FromMinutes(5),
+ CompromiseType::kPhished));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleOrg, kUsername2, base::TimeDelta::FromMinutes(6),
+ CompromiseType::kLeaked));
+ RunUntilIdle();
+
+ EXPECT_THAT(
+ delegate().GetCompromisedCredentials(),
+ ElementsAre(
+ ExpectCompromisedCredential(
+ "example.com", kExampleCom, kExampleCom, kUsername1,
+ base::TimeDelta::FromMinutes(1), "1 minute ago",
+ api::passwords_private::COMPROMISE_TYPE_PHISHED_AND_LEAKED),
+ ExpectCompromisedCredential(
+ "example.org", kExampleOrg, kExampleOrg, kUsername1,
+ base::TimeDelta::FromMinutes(3), "3 minutes ago",
+ api::passwords_private::COMPROMISE_TYPE_PHISHED),
+ ExpectCompromisedCredential(
+ "example.org", kExampleOrg, kExampleOrg, kUsername2,
+ base::TimeDelta::FromMinutes(4), "4 minutes ago",
+ api::passwords_private::COMPROMISE_TYPE_PHISHED_AND_LEAKED),
+ ExpectCompromisedCredential(
+ "example.com", kExampleCom, kExampleCom, kUsername2,
+ base::TimeDelta::FromMinutes(2), "2 minutes ago",
+ api::passwords_private::COMPROMISE_TYPE_LEAKED)));
+}
+
+TEST_F(PasswordCheckDelegateTest, GetCompromisedCredentialsInjectsAndroid) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddLogin(MakeSavedAndroidPassword(kExampleApp, kUsername2,
+ "Example App", kExampleCom));
+ // Test Android credential without affiliation information.
+ store().AddLogin(MakeSavedAndroidPassword(kExampleApp, kUsername1));
+ store().AddCompromisedCredentials(
+ MakeCompromised(kExampleCom, kUsername1, base::TimeDelta::FromMinutes(5),
+ CompromiseType::kLeaked));
+ store().AddCompromisedCredentials(
+ MakeCompromised(MakeAndroidRealm(kExampleApp), kUsername2,
+ base::TimeDelta::FromDays(3), CompromiseType::kPhished));
+ store().AddCompromisedCredentials(
+ MakeCompromised(MakeAndroidRealm(kExampleApp), kUsername1,
+ base::TimeDelta::FromDays(4), CompromiseType::kPhished));
+ RunUntilIdle();
+
+ // Verify that the compromised credentials match what is stored in the
+ // password store.
+ EXPECT_THAT(
+ delegate().GetCompromisedCredentials(),
+ ElementsAre(ExpectCompromisedCredential(
+ "Example App", "Example App", kExampleCom, kUsername2,
+ base::TimeDelta::FromDays(3), "3 days ago",
+ api::passwords_private::COMPROMISE_TYPE_PHISHED),
+ ExpectCompromisedCredential(
+ "App (com.example.app)", kExampleApp, base::nullopt,
+ kUsername1, base::TimeDelta::FromDays(4), "4 days ago",
+ api::passwords_private::COMPROMISE_TYPE_PHISHED),
+ ExpectCompromisedCredential(
+ "example.com", kExampleCom, kExampleCom, kUsername1,
+ base::TimeDelta::FromMinutes(5), "5 minutes ago",
+ api::passwords_private::COMPROMISE_TYPE_LEAKED)));
+}
+
+// Test that a change to compromised credential notifies observers.
+TEST_F(PasswordCheckDelegateTest, OnGetCompromisedCredentials) {
+ const char* const kEventName =
+ api::passwords_private::OnCompromisedCredentialsChanged::kEventName;
+
+ // Verify that the event was not fired during construction.
+ EXPECT_FALSE(base::Contains(event_router_observer().events(), kEventName));
+
+ // Verify that the event gets fired once the compromised credential provider
+ // is initialized.
+ RunUntilIdle();
+ EXPECT_EQ(events::PASSWORDS_PRIVATE_ON_COMPROMISED_CREDENTIALS_INFO_CHANGED,
+ event_router_observer().events().at(kEventName)->histogram_value);
+ event_router_observer().ClearEvents();
+
+ // Verify that a subsequent call to AddCompromisedCredentials results in the
+ // expected event.
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+ EXPECT_EQ(events::PASSWORDS_PRIVATE_ON_COMPROMISED_CREDENTIALS_INFO_CHANGED,
+ event_router_observer().events().at(kEventName)->histogram_value);
+}
+
+TEST_F(PasswordCheckDelegateTest,
+ GetPlaintextCompromisedPasswordRejectsWrongId) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ EXPECT_EQ(0, credential.id);
+
+ // Purposefully set a wrong id and verify that trying to get a plaintext
+ // password fails.
+ credential.id = 1;
+ EXPECT_EQ(base::nullopt,
+ delegate().GetPlaintextCompromisedPassword(std::move(credential)));
+}
+
+TEST_F(PasswordCheckDelegateTest,
+ GetPlaintextCompromisedPasswordRejectsWrongSignonRealm) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ EXPECT_EQ(kExampleCom, credential.signon_realm);
+
+ // Purposefully set a wrong signon realm and verify that trying to get a
+ // plaintext password fails.
+ credential.signon_realm = kExampleOrg;
+ EXPECT_EQ(base::nullopt,
+ delegate().GetPlaintextCompromisedPassword(std::move(credential)));
+}
+
+TEST_F(PasswordCheckDelegateTest,
+ GetPlaintextCompromisedPasswordRejectsWrongUsername) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ EXPECT_EQ(kUsername1, credential.username);
+
+ // Purposefully set a wrong username and verify that trying to get a
+ // plaintext password fails.
+ credential.signon_realm = kUsername2;
+ EXPECT_EQ(base::nullopt,
+ delegate().GetPlaintextCompromisedPassword(std::move(credential)));
+}
+
+TEST_F(PasswordCheckDelegateTest,
+ GetPlaintextCompromisedPasswordReturnsCorrectPassword) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ EXPECT_EQ(0, credential.id);
+ EXPECT_EQ(kExampleCom, credential.signon_realm);
+ EXPECT_EQ(kUsername1, credential.username);
+ EXPECT_EQ(nullptr, credential.password);
+
+ base::Optional<CompromisedCredential> opt_credential =
+ delegate().GetPlaintextCompromisedPassword(std::move(credential));
+ ASSERT_TRUE(opt_credential.has_value());
+ EXPECT_EQ(0, opt_credential->id);
+ EXPECT_EQ(kExampleCom, opt_credential->signon_realm);
+ EXPECT_EQ(kUsername1, opt_credential->username);
+ EXPECT_EQ(kPassword1, *opt_credential->password);
+}
+
+// Test that changing a compromised password fails if the ids don't match.
+TEST_F(PasswordCheckDelegateTest, ChangeCompromisedCredentialIdMismatch) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ EXPECT_EQ(0, credential.id);
+ credential.id = 1;
+
+ EXPECT_FALSE(delegate().ChangeCompromisedCredential(credential, "new_pass"));
+}
+
+// Test that changing a compromised password fails if the underlying compromised
+// credential no longer exists.
+TEST_F(PasswordCheckDelegateTest, ChangeCompromisedCredentialStaleData) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+
+ store().RemoveLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ EXPECT_FALSE(delegate().ChangeCompromisedCredential(credential, "new_pass"));
+}
+
+// Test that changing a compromised password succeeds.
+TEST_F(PasswordCheckDelegateTest, ChangeCompromisedCredentialSuccess) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ EXPECT_EQ(0, credential.id);
+ EXPECT_EQ(kExampleCom, credential.signon_realm);
+ EXPECT_EQ(kUsername1, credential.username);
+ EXPECT_EQ(base::UTF8ToUTF16(kPassword1),
+ store().stored_passwords().at(kExampleCom).at(0).password_value);
+
+ EXPECT_TRUE(delegate().ChangeCompromisedCredential(credential, kPassword2));
+ RunUntilIdle();
+
+ EXPECT_EQ(base::UTF8ToUTF16(kPassword2),
+ store().stored_passwords().at(kExampleCom).at(0).password_value);
+}
+
+// Test that changing a compromised password removes duplicates from store.
+TEST_F(PasswordCheckDelegateTest, ChangeCompromisedCredentialRemovesDupes) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1,
+ "different_element"));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ EXPECT_EQ(2u, store().stored_passwords().at(kExampleCom).size());
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ EXPECT_TRUE(delegate().ChangeCompromisedCredential(credential, kPassword2));
+ RunUntilIdle();
+
+ EXPECT_EQ(1u, store().stored_passwords().at(kExampleCom).size());
+ EXPECT_EQ(
+ kPassword2,
+ base::UTF16ToUTF8(
+ store().stored_passwords().at(kExampleCom).at(0).password_value));
+}
+
+// Test that removing a compromised password fails if the ids don't match.
+TEST_F(PasswordCheckDelegateTest, RemoveCompromisedCredentialIdMismatch) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ EXPECT_EQ(0, credential.id);
+ credential.id = 1;
+
+ EXPECT_FALSE(delegate().RemoveCompromisedCredential(credential));
+}
+
+// Test that removing a compromised password fails if the underlying compromised
+// credential no longer exists.
+TEST_F(PasswordCheckDelegateTest, RemoveCompromisedCredentialStaleData) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ store().RemoveLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ EXPECT_FALSE(delegate().RemoveCompromisedCredential(credential));
+}
+
+// Test that removing a compromised password succeeds.
+TEST_F(PasswordCheckDelegateTest, RemoveCompromisedCredentialSuccess) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ CompromisedCredential credential =
+ std::move(delegate().GetCompromisedCredentials().at(0));
+ EXPECT_TRUE(delegate().RemoveCompromisedCredential(credential));
+ RunUntilIdle();
+ EXPECT_TRUE(store().IsEmpty());
+
+ // Expect another removal of the same credential to fail.
+ EXPECT_FALSE(delegate().RemoveCompromisedCredential(credential));
+}
+
+// Tests that we don't create an entry in the database if there is no matching
+// saved password.
+TEST_F(PasswordCheckDelegateTest, OnLeakFoundDoesNotCreateCredential) {
+ identity_test_env().MakeAccountAvailable(kTestEmail);
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ RunUntilIdle();
+ delegate().StartPasswordCheck();
+ store().RemoveLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ RunUntilIdle();
+ static_cast<BulkLeakCheckDelegateInterface*>(service())->OnFinishedCredential(
+ LeakCheckCredential(base::ASCIIToUTF16(kUsername1),
+ base::ASCIIToUTF16(kPassword1)),
+ IsLeaked(true));
+ RunUntilIdle();
+
+ EXPECT_THAT(store().compromised_credentials(), IsEmpty());
+}
+
+// Test that we don't create an entry in the password store if IsLeaked is
+// false.
+TEST_F(PasswordCheckDelegateTest, NoLeakedFound) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ RunUntilIdle();
+
+ static_cast<BulkLeakCheckDelegateInterface*>(service())->OnFinishedCredential(
+ LeakCheckCredential(base::ASCIIToUTF16(kUsername1),
+ base::ASCIIToUTF16(kPassword1)),
+ IsLeaked(false));
+ RunUntilIdle();
+
+ EXPECT_THAT(store().compromised_credentials(), IsEmpty());
+}
+
+// Test that a found leak creates a compromised credential in the password
+// store.
+TEST_F(PasswordCheckDelegateTest, OnLeakFoundCreatesCredential) {
+ identity_test_env().MakeAccountAvailable(kTestEmail);
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ RunUntilIdle();
+
+ delegate().StartPasswordCheck();
+ static_cast<BulkLeakCheckDelegateInterface*>(service())->OnFinishedCredential(
+ LeakCheckCredential(base::ASCIIToUTF16(kUsername1),
+ base::ASCIIToUTF16(kPassword1)),
+ IsLeaked(true));
+ RunUntilIdle();
+
+ EXPECT_THAT(store().compromised_credentials(),
+ ElementsAre(CompromisedCredentials{
+ .signon_realm = kExampleCom,
+ .username = base::ASCIIToUTF16(kUsername1),
+ .create_time = base::Time::Now(),
+ .compromise_type = CompromiseType::kLeaked,
+ }));
+}
+
+// Test that a found leak creates a compromised credential in the password
+// store for each combination of the same canonicalized username and password.
+TEST_F(PasswordCheckDelegateTest, OnLeakFoundCreatesMultipleCredential) {
+ const std::string kUsername2Upper = base::ToUpperASCII(kUsername2);
+ const std::string kUsername2Email = base::StrCat({kUsername2, "@email.com"});
+
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername1, kPassword1));
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername2Upper, kPassword2));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername2Email, kPassword2));
+ RunUntilIdle();
+
+ identity_test_env().MakeAccountAvailable(kTestEmail);
+ delegate().StartPasswordCheck();
+ static_cast<BulkLeakCheckDelegateInterface*>(service())->OnFinishedCredential(
+ LeakCheckCredential(base::ASCIIToUTF16(kUsername1),
+ base::ASCIIToUTF16(kPassword1)),
+ IsLeaked(true));
+ static_cast<BulkLeakCheckDelegateInterface*>(service())->OnFinishedCredential(
+ LeakCheckCredential(base::ASCIIToUTF16(kUsername2Email),
+ base::ASCIIToUTF16(kPassword2)),
+ IsLeaked(true));
+ RunUntilIdle();
+
+ EXPECT_THAT(store().compromised_credentials(),
+ UnorderedElementsAre(
+ CompromisedCredentials{
+ .signon_realm = kExampleCom,
+ .username = base::ASCIIToUTF16(kUsername1),
+ .create_time = base::Time::Now(),
+ .compromise_type = CompromiseType::kLeaked,
+ },
+ CompromisedCredentials{
+ .signon_realm = kExampleOrg,
+ .username = base::ASCIIToUTF16(kUsername1),
+ .create_time = base::Time::Now(),
+ .compromise_type = CompromiseType::kLeaked,
+ },
+ CompromisedCredentials{
+ .signon_realm = kExampleCom,
+ .username = base::ASCIIToUTF16(kUsername2Upper),
+ .create_time = base::Time::Now(),
+ .compromise_type = CompromiseType::kLeaked,
+ },
+ CompromisedCredentials{
+ .signon_realm = kExampleOrg,
+ .username = base::ASCIIToUTF16(kUsername2Email),
+ .create_time = base::Time::Now(),
+ .compromise_type = CompromiseType::kLeaked,
+ }));
+}
+
+// Verifies that the case where the user has no saved passwords is reported
+// correctly.
+TEST_F(PasswordCheckDelegateTest, GetPasswordCheckStatusNoPasswords) {
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_NO_PASSWORDS,
+ delegate().GetPasswordCheckStatus().state);
+}
+
+// Verifies that the case where the check is idle is reported correctly.
+TEST_F(PasswordCheckDelegateTest, GetPasswordCheckStatusIdle) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_IDLE,
+ delegate().GetPasswordCheckStatus().state);
+}
+
+// Verifies that the case where the user is signed out is reported correctly.
+TEST_F(PasswordCheckDelegateTest, GetPasswordCheckStatusSignedOut) {
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ delegate().StartPasswordCheck();
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_SIGNED_OUT,
+ delegate().GetPasswordCheckStatus().state);
+}
+
+// Verifies that the case where the check is running is reported correctly and
+// the progress indicator matches expectations.
+TEST_F(PasswordCheckDelegateTest, GetPasswordCheckStatusRunning) {
+ identity_test_env().MakeAccountAvailable(kTestEmail);
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ delegate().StartPasswordCheck();
+ PasswordCheckStatus status = delegate().GetPasswordCheckStatus();
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_RUNNING, status.state);
+ EXPECT_EQ(0, *status.already_processed);
+ EXPECT_EQ(1, *status.remaining_in_queue);
+
+ // Make sure that even though the store is emptied after starting a check we
+ // don't report a negative number for already processed.
+ store().RemoveLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ status = delegate().GetPasswordCheckStatus();
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_RUNNING, status.state);
+ EXPECT_EQ(0, *status.already_processed);
+ EXPECT_EQ(1, *status.remaining_in_queue);
+}
+
+// Verifies that the case where the check is canceled is reported correctly.
+TEST_F(PasswordCheckDelegateTest, GetPasswordCheckStatusCanceled) {
+ identity_test_env().MakeAccountAvailable(kTestEmail);
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ delegate().StartPasswordCheck();
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_RUNNING,
+ delegate().GetPasswordCheckStatus().state);
+
+ delegate().StopPasswordCheck();
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_CANCELED,
+ delegate().GetPasswordCheckStatus().state);
+}
+
+// Verifies that the case where the user is offline is reported correctly.
+TEST_F(PasswordCheckDelegateTest, GetPasswordCheckStatusOffline) {
+ identity_test_env().MakeAccountAvailable(kTestEmail);
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ delegate().StartPasswordCheck();
+ identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ GoogleServiceAuthError::FromConnectionError(net::ERR_TIMED_OUT));
+
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_OFFLINE,
+ delegate().GetPasswordCheckStatus().state);
+}
+
+// Verifies that the case where the user hits another error (e.g. invalid
+// credentials) is reported correctly.
+TEST_F(PasswordCheckDelegateTest, GetPasswordCheckStatusOther) {
+ identity_test_env().MakeAccountAvailable(kTestEmail);
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ delegate().StartPasswordCheck();
+ identity_test_env().WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
+ GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
+ GoogleServiceAuthError::InvalidGaiaCredentialsReason::
+ CREDENTIALS_REJECTED_BY_SERVER));
+
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_SIGNED_OUT,
+ delegate().GetPasswordCheckStatus().state);
+}
+
+// Test that a change to the saved passwords notifies observers.
+TEST_F(PasswordCheckDelegateTest,
+ NotifyPasswordCheckStatusChangedAfterPasswordChange) {
+ const char* const kEventName =
+ api::passwords_private::OnPasswordCheckStatusChanged::kEventName;
+
+ // Verify that the event was not fired during construction.
+ EXPECT_FALSE(base::Contains(event_router_observer().events(), kEventName));
+
+ // Verify that the event gets fired once the saved passwords provider is
+ // initialized.
+ RunUntilIdle();
+ EXPECT_EQ(events::PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED,
+ event_router_observer().events().at(kEventName)->histogram_value);
+ event_router_observer().ClearEvents();
+
+ // Verify that a subsequent call to AddLogin() results in the expected event.
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+ EXPECT_EQ(events::PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED,
+ event_router_observer().events().at(kEventName)->histogram_value);
+}
+
+// Test that a change to the bulk leak check notifies observers.
+TEST_F(PasswordCheckDelegateTest,
+ NotifyPasswordCheckStatusChangedAfterStateChange) {
+ const char* const kEventName =
+ api::passwords_private::OnPasswordCheckStatusChanged::kEventName;
+
+ // Verify that the event was not fired during construction.
+ EXPECT_FALSE(base::Contains(event_router_observer().events(), kEventName));
+
+ // Verify that the event gets fired once the saved passwords provider is
+ // initialized.
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+ EXPECT_EQ(events::PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED,
+ event_router_observer().events().at(kEventName)->histogram_value);
+ event_router_observer().ClearEvents();
+
+ // Verify that a subsequent call to StartPasswordCheck() results in the
+ // expected event.
+ delegate().StartPasswordCheck();
+ EXPECT_EQ(events::PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED,
+ event_router_observer().events().at(kEventName)->histogram_value);
+}
+
+// Checks that the default kLastTimePasswordCheckCompleted pref value is
+// treated as no completed run yet.
+TEST_F(PasswordCheckDelegateTest, LastTimePasswordCheckCompletedNotSet) {
+ PasswordCheckStatus status = delegate().GetPasswordCheckStatus();
+ EXPECT_THAT(status.elapsed_time_since_last_check, IsNull());
+}
+
+// Checks that a non-default kLastTimePasswordCheckCompleted pref value is
+// treated as a completed run, and formatted accordingly.
+TEST_F(PasswordCheckDelegateTest, LastTimePasswordCheckCompletedIsSet) {
+ profile().GetPrefs()->SetDouble(
+ kLastTimePasswordCheckCompleted,
+ (base::Time::Now() - base::TimeDelta::FromMinutes(5)).ToDoubleT());
+
+ PasswordCheckStatus status = delegate().GetPasswordCheckStatus();
+ EXPECT_THAT(status.elapsed_time_since_last_check,
+ Pointee(std::string("5 minutes ago")));
+}
+
+// Checks that a transition into the idle state after starting a check results
+// in resetting the kLastTimePasswordCheckCompleted pref to the current time.
+TEST_F(PasswordCheckDelegateTest, LastTimePasswordCheckCompletedReset) {
+ delegate().StartPasswordCheck();
+ RunUntilIdle();
+
+ service()->set_state_and_notify(BulkLeakCheckService::State::kIdle);
+ PasswordCheckStatus status = delegate().GetPasswordCheckStatus();
+ EXPECT_THAT(status.elapsed_time_since_last_check,
+ Pointee(std::string("Just now")));
+}
+
+// Checks that processing a credential by the leak check updates the progress
+// correctly and raises the expected event.
+TEST_F(PasswordCheckDelegateTest, OnCredentialDoneUpdatesProgress) {
+ const char* const kEventName =
+ api::passwords_private::OnPasswordCheckStatusChanged::kEventName;
+
+ identity_test_env().MakeAccountAvailable(kTestEmail);
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1, kPassword1));
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername2, kPassword2));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername1, kPassword1));
+ store().AddLogin(MakeSavedPassword(kExampleOrg, kUsername2, kPassword2));
+ RunUntilIdle();
+
+ const auto event_iter = event_router_observer().events().find(kEventName);
+ delegate().StartPasswordCheck();
+ EXPECT_EQ(events::PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED,
+ event_iter->second->histogram_value);
+ auto status = PasswordCheckStatus::FromValue(
+ event_iter->second->event_args->GetList().front());
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_RUNNING,
+ status->state);
+ EXPECT_EQ(0, *status->already_processed);
+ EXPECT_EQ(4, *status->remaining_in_queue);
+
+ static_cast<BulkLeakCheckDelegateInterface*>(service())->OnFinishedCredential(
+ LeakCheckCredential(base::ASCIIToUTF16(kUsername1),
+ base::ASCIIToUTF16(kPassword1)),
+ IsLeaked(false));
+
+ status = PasswordCheckStatus::FromValue(
+ event_iter->second->event_args->GetList().front());
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_RUNNING,
+ status->state);
+ EXPECT_EQ(2, *status->already_processed);
+ EXPECT_EQ(2, *status->remaining_in_queue);
+
+ static_cast<BulkLeakCheckDelegateInterface*>(service())->OnFinishedCredential(
+ LeakCheckCredential(base::ASCIIToUTF16(kUsername2),
+ base::ASCIIToUTF16(kPassword2)),
+ IsLeaked(false));
+
+ status = PasswordCheckStatus::FromValue(
+ event_iter->second->event_args->GetList().front());
+ EXPECT_EQ(api::passwords_private::PASSWORD_CHECK_STATE_RUNNING,
+ status->state);
+ EXPECT_EQ(4, *status->already_processed);
+ EXPECT_EQ(0, *status->remaining_in_queue);
+}
+
+// Tests that StopPasswordCheck() invokes pending callbacks before
+// initialization finishes.
+TEST_F(PasswordCheckDelegateTest,
+ StopPasswordCheckRespondsCancelsBeforeInitialization) {
+ MockStartPasswordCheckCallback callback1;
+ MockStartPasswordCheckCallback callback2;
+ delegate().StartPasswordCheck(callback1.Get());
+ delegate().StartPasswordCheck(callback2.Get());
+
+ EXPECT_CALL(callback1, Run(BulkLeakCheckService::State::kIdle));
+ EXPECT_CALL(callback2, Run(BulkLeakCheckService::State::kIdle));
+ delegate().StopPasswordCheck();
+
+ Mock::VerifyAndClearExpectations(&callback1);
+ Mock::VerifyAndClearExpectations(&callback2);
+ RunUntilIdle();
+}
+
+// Tests that pending callbacks get invoked once initialization finishes.
+TEST_F(PasswordCheckDelegateTest,
+ StartPasswordCheckRunsCallbacksAfterInitialization) {
+ identity_test_env().MakeAccountAvailable(kTestEmail);
+ store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1));
+ RunUntilIdle();
+
+ MockStartPasswordCheckCallback callback1;
+ MockStartPasswordCheckCallback callback2;
+ EXPECT_CALL(callback1, Run(BulkLeakCheckService::State::kRunning));
+ EXPECT_CALL(callback2, Run(BulkLeakCheckService::State::kRunning));
+
+ // Use a local delegate instead of |delegate()| so that the Password Store can
+ // be set-up prior to constructing the object.
+ PasswordCheckDelegate delegate(&profile());
+ delegate.StartPasswordCheck(callback1.Get());
+ delegate.StartPasswordCheck(callback2.Get());
+ RunUntilIdle();
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
index fa32e0dad11..15df0b1ca92 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/metrics/histogram_macros.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
@@ -25,13 +26,20 @@
namespace extensions {
-////////////////////////////////////////////////////////////////////////////////
-// PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction
+namespace {
+
+using ResponseAction = ExtensionFunction::ResponseAction;
-PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction::
- ~PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction() {}
+PasswordsPrivateDelegate* GetDelegate(
+ content::BrowserContext* browser_context) {
+ return PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context,
+ /*create=*/true);
+}
-ExtensionFunction::ResponseAction
+} // namespace
+
+// PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction
+ResponseAction
PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction::Run() {
UMA_HISTOGRAM_ENUMERATION(
"PasswordManager.ManagePasswordsReferrer",
@@ -48,21 +56,13 @@ PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction::Run() {
return RespondNow(NoArguments());
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateChangeSavedPasswordFunction
+ResponseAction PasswordsPrivateChangeSavedPasswordFunction::Run() {
+ auto parameters =
+ api::passwords_private::ChangeSavedPassword::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
-PasswordsPrivateChangeSavedPasswordFunction::
- ~PasswordsPrivateChangeSavedPasswordFunction() {}
-
-ExtensionFunction::ResponseAction
-PasswordsPrivateChangeSavedPasswordFunction::Run() {
- std::unique_ptr<api::passwords_private::ChangeSavedPassword::Params>
- parameters =
- api::passwords_private::ChangeSavedPassword::Params::Create(*args_);
- EXTENSION_FUNCTION_VALIDATE(parameters.get());
-
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */)
+ GetDelegate(browser_context())
->ChangeSavedPassword(
parameters->id, base::UTF8ToUTF16(parameters->new_username),
parameters->new_password ? base::make_optional(base::UTF8ToUTF16(
@@ -72,88 +72,44 @@ PasswordsPrivateChangeSavedPasswordFunction::Run() {
return RespondNow(NoArguments());
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateRemoveSavedPasswordFunction
-
-PasswordsPrivateRemoveSavedPasswordFunction::
- ~PasswordsPrivateRemoveSavedPasswordFunction() {}
-
-ExtensionFunction::ResponseAction
- PasswordsPrivateRemoveSavedPasswordFunction::Run() {
- std::unique_ptr<api::passwords_private::RemoveSavedPassword::Params>
- parameters =
- api::passwords_private::RemoveSavedPassword::Params::Create(*args_);
- EXTENSION_FUNCTION_VALIDATE(parameters.get());
-
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
-
- delegate->RemoveSavedPassword(parameters->id);
-
+ResponseAction PasswordsPrivateRemoveSavedPasswordFunction::Run() {
+ auto parameters =
+ api::passwords_private::RemoveSavedPassword::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
+ GetDelegate(browser_context())->RemoveSavedPassword(parameters->id);
return RespondNow(NoArguments());
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateRemovePasswordExceptionFunction
-
-PasswordsPrivateRemovePasswordExceptionFunction::
- ~PasswordsPrivateRemovePasswordExceptionFunction() {}
-
-ExtensionFunction::ResponseAction
- PasswordsPrivateRemovePasswordExceptionFunction::Run() {
- std::unique_ptr<api::passwords_private::RemovePasswordException::Params>
- parameters =
- api::passwords_private::RemovePasswordException::Params::Create(
- *args_);
- EXTENSION_FUNCTION_VALIDATE(parameters.get());
-
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
- delegate->RemovePasswordException(parameters->id);
-
+ResponseAction PasswordsPrivateRemovePasswordExceptionFunction::Run() {
+ auto parameters =
+ api::passwords_private::RemovePasswordException::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
+ GetDelegate(browser_context())->RemovePasswordException(parameters->id);
return RespondNow(NoArguments());
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction
-
-PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction::
- ~PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction() {}
-
-ExtensionFunction::ResponseAction
+ResponseAction
PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction::Run() {
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
- delegate->UndoRemoveSavedPasswordOrException();
-
+ GetDelegate(browser_context())->UndoRemoveSavedPasswordOrException();
return RespondNow(NoArguments());
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateRequestPlaintextPasswordFunction
-
-PasswordsPrivateRequestPlaintextPasswordFunction::
- ~PasswordsPrivateRequestPlaintextPasswordFunction() {}
-
-ExtensionFunction::ResponseAction
- PasswordsPrivateRequestPlaintextPasswordFunction::Run() {
- std::unique_ptr<api::passwords_private::RequestPlaintextPassword::Params>
- parameters =
- api::passwords_private::RequestPlaintextPassword::Params::Create(
- *args_);
- EXTENSION_FUNCTION_VALIDATE(parameters.get());
-
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
- delegate->RequestShowPassword(
- parameters->id,
- base::BindOnce(
- &PasswordsPrivateRequestPlaintextPasswordFunction::GotPassword, this),
- GetSenderWebContents());
+ResponseAction PasswordsPrivateRequestPlaintextPasswordFunction::Run() {
+ auto parameters =
+ api::passwords_private::RequestPlaintextPassword::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
+
+ GetDelegate(browser_context())
+ ->RequestPlaintextPassword(
+ parameters->id, parameters->reason,
+ base::BindOnce(
+ &PasswordsPrivateRequestPlaintextPasswordFunction::GotPassword,
+ this),
+ GetSenderWebContents());
// GotPassword() might respond before we reach this point.
return did_respond() ? AlreadyResponded() : RespondLater();
@@ -161,20 +117,20 @@ ExtensionFunction::ResponseAction
void PasswordsPrivateRequestPlaintextPasswordFunction::GotPassword(
base::Optional<base::string16> password) {
- if (password)
+ if (password) {
Respond(OneArgument(std::make_unique<base::Value>(std::move(*password))));
- else
- Respond(NoArguments());
+ return;
+ }
+
+ Respond(Error(base::StringPrintf(
+ "Could not obtain plaintext password. Either the user is not "
+ "authenticated or no password with id = %d could be found.",
+ api::passwords_private::RequestPlaintextPassword::Params::Create(*args_)
+ ->id)));
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateGetSavedPasswordListFunction
-
-PasswordsPrivateGetSavedPasswordListFunction::
- ~PasswordsPrivateGetSavedPasswordListFunction() {}
-
-ExtensionFunction::ResponseAction
-PasswordsPrivateGetSavedPasswordListFunction::Run() {
+ResponseAction PasswordsPrivateGetSavedPasswordListFunction::Run() {
// GetList() can immediately call GotList() (which would Respond() before
// RespondLater()). So we post a task to preserve order.
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -185,11 +141,9 @@ PasswordsPrivateGetSavedPasswordListFunction::Run() {
}
void PasswordsPrivateGetSavedPasswordListFunction::GetList() {
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
- delegate->GetSavedPasswordsList(base::BindOnce(
- &PasswordsPrivateGetSavedPasswordListFunction::GotList, this));
+ GetDelegate(browser_context())
+ ->GetSavedPasswordsList(base::BindOnce(
+ &PasswordsPrivateGetSavedPasswordListFunction::GotList, this));
}
void PasswordsPrivateGetSavedPasswordListFunction::GotList(
@@ -198,14 +152,8 @@ void PasswordsPrivateGetSavedPasswordListFunction::GotList(
api::passwords_private::GetSavedPasswordList::Results::Create(list)));
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateGetPasswordExceptionListFunction
-
-PasswordsPrivateGetPasswordExceptionListFunction::
- ~PasswordsPrivateGetPasswordExceptionListFunction() {}
-
-ExtensionFunction::ResponseAction
-PasswordsPrivateGetPasswordExceptionListFunction::Run() {
+ResponseAction PasswordsPrivateGetPasswordExceptionListFunction::Run() {
// GetList() can immediately call GotList() (which would Respond() before
// RespondLater()). So we post a task to preserve order.
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -216,11 +164,9 @@ PasswordsPrivateGetPasswordExceptionListFunction::Run() {
}
void PasswordsPrivateGetPasswordExceptionListFunction::GetList() {
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
- delegate->GetPasswordExceptionsList(base::Bind(
- &PasswordsPrivateGetPasswordExceptionListFunction::GotList, this));
+ GetDelegate(browser_context())
+ ->GetPasswordExceptionsList(base::BindOnce(
+ &PasswordsPrivateGetPasswordExceptionListFunction::GotList, this));
}
void PasswordsPrivateGetPasswordExceptionListFunction::GotList(
@@ -230,37 +176,20 @@ void PasswordsPrivateGetPasswordExceptionListFunction::GotList(
entries)));
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateImportPasswordsFunction
-
-PasswordsPrivateImportPasswordsFunction::
- ~PasswordsPrivateImportPasswordsFunction() {}
-
-ExtensionFunction::ResponseAction
-PasswordsPrivateImportPasswordsFunction::Run() {
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
- delegate->ImportPasswords(GetSenderWebContents());
+ResponseAction PasswordsPrivateImportPasswordsFunction::Run() {
+ GetDelegate(browser_context())->ImportPasswords(GetSenderWebContents());
return RespondNow(NoArguments());
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateExportPasswordsFunction
-
-PasswordsPrivateExportPasswordsFunction::
- ~PasswordsPrivateExportPasswordsFunction() {}
-
-ExtensionFunction::ResponseAction
-PasswordsPrivateExportPasswordsFunction::Run() {
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
- delegate->ExportPasswords(
- base::BindOnce(
- &PasswordsPrivateExportPasswordsFunction::ExportRequestCompleted,
- this),
- GetSenderWebContents());
+ResponseAction PasswordsPrivateExportPasswordsFunction::Run() {
+ GetDelegate(browser_context())
+ ->ExportPasswords(
+ base::BindOnce(
+ &PasswordsPrivateExportPasswordsFunction::ExportRequestCompleted,
+ this),
+ GetSenderWebContents());
return RespondLater();
}
@@ -272,34 +201,162 @@ void PasswordsPrivateExportPasswordsFunction::ExportRequestCompleted(
Error(error);
}
-////////////////////////////////////////////////////////////////////////////////
// PasswordsPrivateCancelExportPasswordsFunction
+ResponseAction PasswordsPrivateCancelExportPasswordsFunction::Run() {
+ GetDelegate(browser_context())->CancelExportPasswords();
+ return RespondNow(NoArguments());
+}
-PasswordsPrivateCancelExportPasswordsFunction::
- ~PasswordsPrivateCancelExportPasswordsFunction() {}
+// PasswordsPrivateRequestExportProgressStatusFunction
+ResponseAction PasswordsPrivateRequestExportProgressStatusFunction::Run() {
+ return RespondNow(ArgumentList(
+ api::passwords_private::RequestExportProgressStatus::Results::Create(
+ GetDelegate(browser_context())->GetExportProgressStatus())));
+}
+
+// PasswordsPrivateIsOptedInForAccountStorageFunction
+ResponseAction PasswordsPrivateIsOptedInForAccountStorageFunction::Run() {
+ return RespondNow(OneArgument(std::make_unique<base::Value>(
+ GetDelegate(browser_context())->IsOptedInForAccountStorage())));
+}
+
+// PasswordsPrivateOptInForAccountStorageFunction
+ResponseAction PasswordsPrivateOptInForAccountStorageFunction::Run() {
+ auto parameters =
+ api::passwords_private::OptInForAccountStorage::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters.get());
-ExtensionFunction::ResponseAction
-PasswordsPrivateCancelExportPasswordsFunction::Run() {
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
- delegate->CancelExportPasswords();
+ GetDelegate(browser_context())
+ ->SetAccountStorageOptIn(parameters->opt_in, GetSenderWebContents());
return RespondNow(NoArguments());
}
-////////////////////////////////////////////////////////////////////////////////
-// PasswordsPrivateRequestExportProgressStatusFunction
+// PasswordsPrivateGetCompromisedCredentialsFunction:
+PasswordsPrivateGetCompromisedCredentialsFunction::
+ ~PasswordsPrivateGetCompromisedCredentialsFunction() = default;
-PasswordsPrivateRequestExportProgressStatusFunction::
- ~PasswordsPrivateRequestExportProgressStatusFunction() {}
+ResponseAction PasswordsPrivateGetCompromisedCredentialsFunction::Run() {
+ return RespondNow(ArgumentList(
+ api::passwords_private::GetCompromisedCredentials::Results::Create(
+ GetDelegate(browser_context())->GetCompromisedCredentials())));
+}
-ExtensionFunction::ResponseAction
-PasswordsPrivateRequestExportProgressStatusFunction::Run() {
- PasswordsPrivateDelegate* delegate =
- PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(),
- true /* create */);
- return RespondNow(OneArgument(std::make_unique<base::Value>(
- ToString(delegate->GetExportProgressStatus()))));
+// PasswordsPrivateGetPlaintextCompromisedPasswordFunction:
+PasswordsPrivateGetPlaintextCompromisedPasswordFunction::
+ ~PasswordsPrivateGetPlaintextCompromisedPasswordFunction() = default;
+
+ResponseAction PasswordsPrivateGetPlaintextCompromisedPasswordFunction::Run() {
+ auto parameters =
+ api::passwords_private::GetPlaintextCompromisedPassword::Params::Create(
+ *args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
+
+ GetDelegate(browser_context())
+ ->GetPlaintextCompromisedPassword(
+ std::move(parameters->credential), parameters->reason,
+ GetSenderWebContents(),
+ base::BindOnce(
+ &PasswordsPrivateGetPlaintextCompromisedPasswordFunction::
+ GotCredential,
+ this));
+
+ // GotCredential() might respond before we reach this point.
+ return did_respond() ? AlreadyResponded() : RespondLater();
+}
+
+void PasswordsPrivateGetPlaintextCompromisedPasswordFunction::GotCredential(
+ base::Optional<api::passwords_private::CompromisedCredential> credential) {
+ if (!credential) {
+ Respond(Error(
+ "Could not obtain plaintext compromised password. Either the user is "
+ "not authenticated or no matching password could be found."));
+ return;
+ }
+
+ Respond(ArgumentList(
+ api::passwords_private::GetPlaintextCompromisedPassword::Results::Create(
+ *credential)));
+}
+
+// PasswordsPrivateChangeCompromisedCredentialFunction:
+PasswordsPrivateChangeCompromisedCredentialFunction::
+ ~PasswordsPrivateChangeCompromisedCredentialFunction() = default;
+
+ResponseAction PasswordsPrivateChangeCompromisedCredentialFunction::Run() {
+ auto parameters =
+ api::passwords_private::ChangeCompromisedCredential::Params::Create(
+ *args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
+
+ if (!GetDelegate(browser_context())
+ ->ChangeCompromisedCredential(parameters->credential,
+ parameters->new_password)) {
+ return RespondNow(Error(
+ "Could not change the compromised credential. Either the user is not "
+ "authenticated or no matching password could be found."));
+ }
+
+ return RespondNow(NoArguments());
+}
+
+// PasswordsPrivateRemoveCompromisedCredentialFunction:
+PasswordsPrivateRemoveCompromisedCredentialFunction::
+ ~PasswordsPrivateRemoveCompromisedCredentialFunction() = default;
+
+ResponseAction PasswordsPrivateRemoveCompromisedCredentialFunction::Run() {
+ auto parameters =
+ api::passwords_private::RemoveCompromisedCredential::Params::Create(
+ *args_);
+ EXTENSION_FUNCTION_VALIDATE(parameters);
+
+ if (!GetDelegate(browser_context())
+ ->RemoveCompromisedCredential(parameters->credential)) {
+ return RespondNow(
+ Error("Could not remove the compromised credential. Probably no "
+ "matching password could be found."));
+ }
+
+ return RespondNow(NoArguments());
+}
+
+// PasswordsPrivateStartPasswordCheckFunction:
+PasswordsPrivateStartPasswordCheckFunction::
+ ~PasswordsPrivateStartPasswordCheckFunction() = default;
+
+ResponseAction PasswordsPrivateStartPasswordCheckFunction::Run() {
+ GetDelegate(browser_context())
+ ->StartPasswordCheck(base::BindOnce(
+ &PasswordsPrivateStartPasswordCheckFunction::OnStarted, this));
+
+ // OnStarted() might respond before we reach this point.
+ return did_respond() ? AlreadyResponded() : RespondLater();
+}
+
+void PasswordsPrivateStartPasswordCheckFunction::OnStarted(
+ password_manager::BulkLeakCheckService::State state) {
+ const bool is_running =
+ state == password_manager::BulkLeakCheckService::State::kRunning;
+ Respond(is_running ? NoArguments()
+ : Error("Starting password check failed."));
+}
+
+// PasswordsPrivateStopPasswordCheckFunction:
+PasswordsPrivateStopPasswordCheckFunction::
+ ~PasswordsPrivateStopPasswordCheckFunction() = default;
+
+ResponseAction PasswordsPrivateStopPasswordCheckFunction::Run() {
+ GetDelegate(browser_context())->StopPasswordCheck();
+ return RespondNow(NoArguments());
+}
+
+// PasswordsPrivateGetPasswordCheckStatusFunction:
+PasswordsPrivateGetPasswordCheckStatusFunction::
+ ~PasswordsPrivateGetPasswordCheckStatusFunction() = default;
+
+ResponseAction PasswordsPrivateGetPasswordCheckStatusFunction::Run() {
+ return RespondNow(ArgumentList(
+ api::passwords_private::GetPasswordCheckStatus::Results::Create(
+ GetDelegate(browser_context())->GetPasswordCheckStatus())));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.h b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
index b9521497512..b374835ffa2 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.h
@@ -7,11 +7,10 @@
#include <string>
-#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
-#include "chrome/browser/ui/passwords/settings/password_manager_presenter.h"
+#include "components/password_manager/core/browser/bulk_leak_check_service.h"
#include "extensions/browser/extension_function.h"
namespace extensions {
@@ -19,117 +18,93 @@ namespace extensions {
class PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction
: public ExtensionFunction {
public:
- PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction() {}
DECLARE_EXTENSION_FUNCTION(
"passwordsPrivate.recordPasswordsPageAccessInSettings",
PASSWORDSPRIVATE_RECORDPASSWORDSPAGEACCESSINSETTINGS)
protected:
- ~PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction() override;
+ ~PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction() override =
+ default;
// ExtensionFunction overrides.
ResponseAction Run() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- PasswordsPrivateRecordPasswordsPageAccessInSettingsFunction);
};
class PasswordsPrivateChangeSavedPasswordFunction : public ExtensionFunction {
public:
- PasswordsPrivateChangeSavedPasswordFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.changeSavedPassword",
PASSWORDSPRIVATE_CHANGESAVEDPASSWORD)
protected:
- ~PasswordsPrivateChangeSavedPasswordFunction() override;
+ ~PasswordsPrivateChangeSavedPasswordFunction() override = default;
// ExtensionFunction overrides.
ResponseAction Run() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateChangeSavedPasswordFunction);
};
class PasswordsPrivateRemoveSavedPasswordFunction : public ExtensionFunction {
public:
- PasswordsPrivateRemoveSavedPasswordFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.removeSavedPassword",
PASSWORDSPRIVATE_REMOVESAVEDPASSWORD)
protected:
- ~PasswordsPrivateRemoveSavedPasswordFunction() override;
+ ~PasswordsPrivateRemoveSavedPasswordFunction() override = default;
// ExtensionFunction overrides.
ResponseAction Run() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateRemoveSavedPasswordFunction);
};
class PasswordsPrivateRemovePasswordExceptionFunction
: public ExtensionFunction {
public:
- PasswordsPrivateRemovePasswordExceptionFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.removePasswordException",
PASSWORDSPRIVATE_REMOVEPASSWORDEXCEPTION)
protected:
- ~PasswordsPrivateRemovePasswordExceptionFunction() override;
+ ~PasswordsPrivateRemovePasswordExceptionFunction() override = default;
// ExtensionFunction overrides.
ResponseAction Run() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateRemovePasswordExceptionFunction);
};
class PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction
: public ExtensionFunction {
public:
- PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction() {}
DECLARE_EXTENSION_FUNCTION(
"passwordsPrivate.undoRemoveSavedPasswordOrException",
PASSWORDSPRIVATE_UNDOREMOVESAVEDPASSWORDOREXCEPTION)
protected:
- ~PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction() override;
+ ~PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction() override =
+ default;
// ExtensionFunction overrides.
ResponseAction Run() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(
- PasswordsPrivateUndoRemoveSavedPasswordOrExceptionFunction);
};
class PasswordsPrivateRequestPlaintextPasswordFunction
: public ExtensionFunction {
public:
- PasswordsPrivateRequestPlaintextPasswordFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.requestPlaintextPassword",
PASSWORDSPRIVATE_REQUESTPLAINTEXTPASSWORD)
protected:
- ~PasswordsPrivateRequestPlaintextPasswordFunction() override;
+ ~PasswordsPrivateRequestPlaintextPasswordFunction() override = default;
// ExtensionFunction overrides.
ResponseAction Run() override;
private:
void GotPassword(base::Optional<base::string16> password);
-
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateRequestPlaintextPasswordFunction);
};
class PasswordsPrivateGetSavedPasswordListFunction : public ExtensionFunction {
public:
- PasswordsPrivateGetSavedPasswordListFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.getSavedPasswordList",
PASSWORDSPRIVATE_GETSAVEDPASSWORDLIST)
protected:
- ~PasswordsPrivateGetSavedPasswordListFunction() override;
+ ~PasswordsPrivateGetSavedPasswordListFunction() override = default;
// ExtensionFunction overrides.
ResponseAction Run() override;
@@ -137,19 +112,16 @@ class PasswordsPrivateGetSavedPasswordListFunction : public ExtensionFunction {
private:
void GetList();
void GotList(const PasswordsPrivateDelegate::UiEntries& entries);
-
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateGetSavedPasswordListFunction);
};
class PasswordsPrivateGetPasswordExceptionListFunction
: public ExtensionFunction {
public:
- PasswordsPrivateGetPasswordExceptionListFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.getPasswordExceptionList",
PASSWORDSPRIVATE_GETPASSWORDEXCEPTIONLIST)
protected:
- ~PasswordsPrivateGetPasswordExceptionListFunction() override;
+ ~PasswordsPrivateGetPasswordExceptionListFunction() override = default;
// ExtensionFunction overrides.
ResponseAction Run() override;
@@ -157,75 +129,180 @@ class PasswordsPrivateGetPasswordExceptionListFunction
private:
void GetList();
void GotList(const PasswordsPrivateDelegate::ExceptionEntries& entries);
-
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateGetPasswordExceptionListFunction);
};
class PasswordsPrivateImportPasswordsFunction : public ExtensionFunction {
public:
- PasswordsPrivateImportPasswordsFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.importPasswords",
PASSWORDSPRIVATE_IMPORTPASSWORDS)
protected:
- ~PasswordsPrivateImportPasswordsFunction() override;
+ ~PasswordsPrivateImportPasswordsFunction() override = default;
// ExtensionFunction overrides.
ResponseAction Run() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateImportPasswordsFunction);
};
class PasswordsPrivateExportPasswordsFunction : public ExtensionFunction {
public:
- PasswordsPrivateExportPasswordsFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.exportPasswords",
PASSWORDSPRIVATE_EXPORTPASSWORDS)
protected:
- ~PasswordsPrivateExportPasswordsFunction() override;
+ ~PasswordsPrivateExportPasswordsFunction() override = default;
// ExtensionFunction overrides.
ResponseAction Run() override;
private:
void ExportRequestCompleted(const std::string& error);
-
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateExportPasswordsFunction);
};
class PasswordsPrivateCancelExportPasswordsFunction : public ExtensionFunction {
public:
- PasswordsPrivateCancelExportPasswordsFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.cancelExportPasswords",
PASSWORDSPRIVATE_CANCELEXPORTPASSWORDS)
protected:
- ~PasswordsPrivateCancelExportPasswordsFunction() override;
+ ~PasswordsPrivateCancelExportPasswordsFunction() override = default;
// ExtensionFunction overrides.
ResponseAction Run() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateCancelExportPasswordsFunction);
};
class PasswordsPrivateRequestExportProgressStatusFunction
: public ExtensionFunction {
public:
- PasswordsPrivateRequestExportProgressStatusFunction() {}
DECLARE_EXTENSION_FUNCTION("passwordsPrivate.requestExportProgressStatus",
PASSWORDSPRIVATE_REQUESTEXPORTPROGRESSSTATUS)
protected:
- ~PasswordsPrivateRequestExportProgressStatusFunction() override;
+ ~PasswordsPrivateRequestExportProgressStatusFunction() override = default;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
+class PasswordsPrivateIsOptedInForAccountStorageFunction
+ : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.isOptedInForAccountStorage",
+ PASSWORDSPRIVATE_ISOPTEDINFORACCOUNTSTORAGE)
+
+ protected:
+ ~PasswordsPrivateIsOptedInForAccountStorageFunction() override = default;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
+class PasswordsPrivateOptInForAccountStorageFunction
+ : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.optInForAccountStorage",
+ PASSWORDSPRIVATE_OPTINFORACCOUNTSTORAGE)
+
+ protected:
+ ~PasswordsPrivateOptInForAccountStorageFunction() override = default;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
+class PasswordsPrivateGetCompromisedCredentialsFunction
+ : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.getCompromisedCredentials",
+ PASSWORDSPRIVATE_GETCOMPROMISEDCREDENTIALS)
+
+ protected:
+ ~PasswordsPrivateGetCompromisedCredentialsFunction() override;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
+class PasswordsPrivateGetPlaintextCompromisedPasswordFunction
+ : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.getPlaintextCompromisedPassword",
+ PASSWORDSPRIVATE_GETPLAINTEXTCOMPROMISEDPASSWORD)
+
+ protected:
+ ~PasswordsPrivateGetPlaintextCompromisedPasswordFunction() override;
// ExtensionFunction overrides.
ResponseAction Run() override;
private:
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateRequestExportProgressStatusFunction);
+ void GotCredential(
+ base::Optional<api::passwords_private::CompromisedCredential> credential);
+};
+
+class PasswordsPrivateChangeCompromisedCredentialFunction
+ : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.changeCompromisedCredential",
+ PASSWORDSPRIVATE_CHANGECOMPROMISEDCREDENTIAL)
+
+ protected:
+ ~PasswordsPrivateChangeCompromisedCredentialFunction() override;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
+class PasswordsPrivateRemoveCompromisedCredentialFunction
+ : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.removeCompromisedCredential",
+ PASSWORDSPRIVATE_REMOVECOMPROMISEDCREDENTIAL)
+
+ protected:
+ ~PasswordsPrivateRemoveCompromisedCredentialFunction() override;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
+class PasswordsPrivateStartPasswordCheckFunction : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.startPasswordCheck",
+ PASSWORDSPRIVATE_STARTPASSWORDCHECK)
+
+ protected:
+ ~PasswordsPrivateStartPasswordCheckFunction() override;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+
+ private:
+ void OnStarted(password_manager::BulkLeakCheckService::State state);
+};
+
+class PasswordsPrivateStopPasswordCheckFunction : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.stopPasswordCheck",
+ PASSWORDSPRIVATE_STOPPASSWORDCHECK)
+
+ protected:
+ ~PasswordsPrivateStopPasswordCheckFunction() override;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+};
+
+class PasswordsPrivateGetPasswordCheckStatusFunction
+ : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("passwordsPrivate.getPasswordCheckStatus",
+ PASSWORDSPRIVATE_GETPASSWORDCHECKSTATUS)
+
+ protected:
+ ~PasswordsPrivateGetPasswordCheckStatusFunction() override;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
};
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
index 94758ce1b54..947070eb2f8 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_apitest.cc
@@ -4,6 +4,8 @@
#include <stddef.h>
+#include <algorithm>
+#include <memory>
#include <sstream>
#include "base/bind.h"
@@ -13,247 +15,104 @@
#include "base/numerics/safe_conversions.h"
#include "base/observer_list.h"
#include "base/optional.h"
+#include "base/stl_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_piece_forward.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h"
+#include "chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/extensions/api/passwords_private.h"
#include "chrome/test/base/testing_profile.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/test/test_utils.h"
#include "extensions/common/switches.h"
+#include "ui/base/l10n/time_format.h"
namespace extensions {
namespace {
-static const size_t kNumMocks = 3;
-static const int kNumCharactersInPassword = 10;
-static const char kPlaintextPassword[] = "plaintext";
-
-api::passwords_private::PasswordUiEntry CreateEntry(int id) {
- api::passwords_private::PasswordUiEntry entry;
- entry.urls.shown = "test" + std::to_string(id) + ".com";
- entry.urls.origin = "http://" + entry.urls.shown + "/login";
- entry.urls.link = entry.urls.origin;
- entry.username = "testName" + std::to_string(id);
- entry.num_characters_in_password = kNumCharactersInPassword;
- entry.id = id;
- return entry;
-}
-
-api::passwords_private::ExceptionEntry CreateException(int id) {
- api::passwords_private::ExceptionEntry exception;
- exception.urls.shown = "exception" + std::to_string(id) + ".com";
- exception.urls.origin = "http://" + exception.urls.shown + "/login";
- exception.urls.link = exception.urls.origin;
- exception.id = id;
- return exception;
-}
-
-// A test PasswordsPrivateDelegate implementation which uses mock data.
-// TestDelegate starts out with kNumMocks mocks of each type (saved password
-// and password exception) and removes one mock each time RemoveSavedPassword()
-// or RemovePasswordException() is called.
-class TestDelegate : public PasswordsPrivateDelegate {
+class PasswordsPrivateApiTest : public ExtensionApiTest {
public:
- TestDelegate() : profile_(nullptr) {
- // Create mock data.
- for (size_t i = 0; i < kNumMocks; i++) {
- current_entries_.push_back(CreateEntry(i));
- current_exceptions_.push_back(CreateException(i));
- }
- }
- ~TestDelegate() override {}
-
- void GetSavedPasswordsList(UiEntriesCallback callback) override {
- std::move(callback).Run(current_entries_);
- }
-
- void GetPasswordExceptionsList(
- const ExceptionEntriesCallback& callback) override {
- callback.Run(current_exceptions_);
- }
-
- void ChangeSavedPassword(int id,
- base::string16 username,
- base::Optional<base::string16> password) override {
- if (size_t{id} >= current_entries_.size())
- return;
-
- // PasswordUiEntry does not contain a password. Thus we are only updating
- // the username and the length of the password.
- current_entries_[id].username = base::UTF16ToUTF8(username);
- if (password)
- current_entries_[id].num_characters_in_password = password->size();
- SendSavedPasswordsList();
- }
-
- void RemoveSavedPassword(int id) override {
- if (current_entries_.empty())
- return;
+ PasswordsPrivateApiTest() = default;
+ ~PasswordsPrivateApiTest() override = default;
- // Since this is just mock data, remove the first entry regardless of
- // the data contained.
- last_deleted_entry_ = std::move(current_entries_.front());
- current_entries_.erase(current_entries_.begin());
- SendSavedPasswordsList();
- }
-
- void RemovePasswordException(int id) override {
- // Since this is just mock data, remove the first entry regardless of
- // the data contained.
- last_deleted_exception_ = std::move(current_exceptions_.front());
- current_exceptions_.erase(current_exceptions_.begin());
- SendPasswordExceptionsList();
- }
-
- // Simplified version of undo logic, only use for testing.
- void UndoRemoveSavedPasswordOrException() override {
- if (last_deleted_entry_) {
- current_entries_.insert(current_entries_.begin(),
- std::move(*last_deleted_entry_));
- last_deleted_entry_ = base::nullopt;
- SendSavedPasswordsList();
- } else if (last_deleted_exception_) {
- current_exceptions_.insert(current_exceptions_.begin(),
- std::move(*last_deleted_exception_));
- last_deleted_exception_ = base::nullopt;
- SendPasswordExceptionsList();
- }
- }
-
- void RequestShowPassword(int id,
- PlaintextPasswordCallback callback,
- content::WebContents* web_contents) override {
- // Return a mocked password value.
- std::move(callback).Run(base::ASCIIToUTF16(kPlaintextPassword));
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ ExtensionApiTest::SetUpCommandLine(command_line);
}
- void SetProfile(Profile* profile) { profile_ = profile; }
-
- void ImportPasswords(content::WebContents* web_contents) override {
- // The testing of password importing itself should be handled via
- // |PasswordManagerPorter|.
- importPasswordsTriggered = true;
- }
+ void SetUp() override { ExtensionApiTest::SetUp(); }
- void ExportPasswords(base::OnceCallback<void(const std::string&)> callback,
- content::WebContents* web_contents) override {
- // The testing of password exporting itself should be handled via
- // |PasswordManagerPorter|.
- exportPasswordsTriggered = true;
- std::move(callback).Run(std::string());
+ void SetUpOnMainThread() override {
+ ExtensionApiTest::SetUpOnMainThread();
+ s_test_delegate_ = static_cast<TestPasswordsPrivateDelegate*>(
+ PasswordsPrivateDelegateFactory::GetInstance()->SetTestingFactoryAndUse(
+ profile(),
+ base::BindRepeating([](content::BrowserContext* context) {
+ return std::unique_ptr<KeyedService>(
+ new TestPasswordsPrivateDelegate());
+ })));
+ s_test_delegate_->SetProfile(profile());
+ content::RunAllPendingInMessageLoop();
}
- void CancelExportPasswords() override {
- cancelExportPasswordsTriggered = true;
+ protected:
+ bool RunPasswordsSubtest(const std::string& subtest) {
+ return RunExtensionSubtest("passwords_private", "main.html?" + subtest,
+ kFlagNone, kFlagLoadAsComponent);
}
- api::passwords_private::ExportProgressStatus GetExportProgressStatus()
- override {
- // The testing of password exporting itself should be handled via
- // |PasswordManagerPorter|.
- return api::passwords_private::ExportProgressStatus::
- EXPORT_PROGRESS_STATUS_IN_PROGRESS;
+ bool importPasswordsWasTriggered() {
+ return s_test_delegate_->ImportPasswordsTriggered();
}
- // Flags for detecting whether import/export operations have been invoked.
- bool importPasswordsTriggered = false;
- bool exportPasswordsTriggered = false;
- bool cancelExportPasswordsTriggered = false;
-
- private:
- void SendSavedPasswordsList() {
- PasswordsPrivateEventRouter* router =
- PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
- if (router)
- router->OnSavedPasswordsListChanged(current_entries_);
+ bool exportPasswordsWasTriggered() {
+ return s_test_delegate_->ExportPasswordsTriggered();
}
- void SendPasswordExceptionsList() {
- PasswordsPrivateEventRouter* router =
- PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
- if (router)
- router->OnPasswordExceptionsListChanged(current_exceptions_);
+ bool cancelExportPasswordsWasTriggered() {
+ return s_test_delegate_->CancelExportPasswordsTriggered();
}
- // The current list of entries/exceptions. Cached here so that when new
- // observers are added, this delegate can send the current lists without
- // having to request them from |password_manager_presenter_| again.
- std::vector<api::passwords_private::PasswordUiEntry> current_entries_;
- std::vector<api::passwords_private::ExceptionEntry> current_exceptions_;
- // Simplified version of a undo manager that only allows undoing and redoing
- // the very last deletion.
- base::Optional<api::passwords_private::PasswordUiEntry> last_deleted_entry_;
- base::Optional<api::passwords_private::ExceptionEntry>
- last_deleted_exception_;
- Profile* profile_;
-};
-
-class PasswordsPrivateApiTest : public ExtensionApiTest {
- public:
- PasswordsPrivateApiTest() {
- if (!s_test_delegate_) {
- s_test_delegate_ = new TestDelegate();
- }
+ bool start_password_check_triggered() {
+ return s_test_delegate_->StartPasswordCheckTriggered();
}
- ~PasswordsPrivateApiTest() override {}
- static std::unique_ptr<KeyedService> GetPasswordsPrivateDelegate(
- content::BrowserContext* profile) {
- CHECK(s_test_delegate_);
- return base::WrapUnique(s_test_delegate_);
+ bool stop_password_check_triggered() {
+ return s_test_delegate_->StopPasswordCheckTriggered();
}
- void SetUpCommandLine(base::CommandLine* command_line) override {
- ExtensionApiTest::SetUpCommandLine(command_line);
+ void set_start_password_check_state(
+ password_manager::BulkLeakCheckService::State state) {
+ s_test_delegate_->SetStartPasswordCheckState(state);
}
- void SetUp() override {
- ExtensionApiTest::SetUp();
+ bool IsOptedInForAccountStorage() {
+ return s_test_delegate_->IsOptedInForAccountStorage();
}
- void SetUpOnMainThread() override {
- ExtensionApiTest::SetUpOnMainThread();
- PasswordsPrivateDelegateFactory::GetInstance()->SetTestingFactory(
- profile(), base::BindRepeating(
- &PasswordsPrivateApiTest::GetPasswordsPrivateDelegate));
- s_test_delegate_->SetProfile(profile());
- content::RunAllPendingInMessageLoop();
+ void SetOptedInForAccountStorage(bool opted_in) {
+ s_test_delegate_->SetAccountStorageOptIn(opted_in, nullptr);
}
- protected:
- bool RunPasswordsSubtest(const std::string& subtest) {
- return RunExtensionSubtest("passwords_private",
- "main.html?" + subtest,
- kFlagLoadAsComponent);
- }
+ void ResetPlaintextPassword() { s_test_delegate_->ResetPlaintextPassword(); }
- bool importPasswordsWasTriggered() {
- return s_test_delegate_->importPasswordsTriggered;
- }
-
- bool exportPasswordsWasTriggered() {
- return s_test_delegate_->exportPasswordsTriggered;
- }
-
- bool cancelExportPasswordsWasTriggered() {
- return s_test_delegate_->cancelExportPasswordsTriggered;
+ void AddCompromisedCredential(int id) {
+ s_test_delegate_->AddCompromisedCredential(id);
}
private:
- static TestDelegate* s_test_delegate_;
+ TestPasswordsPrivateDelegate* s_test_delegate_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateApiTest);
};
-// static
-TestDelegate* PasswordsPrivateApiTest::s_test_delegate_ = nullptr;
-
} // namespace
IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, ChangeSavedPassword) {
@@ -276,6 +135,11 @@ IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, RequestPlaintextPassword) {
EXPECT_TRUE(RunPasswordsSubtest("requestPlaintextPassword")) << message_;
}
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, RequestPlaintextPasswordFails) {
+ ResetPlaintextPassword();
+ EXPECT_TRUE(RunPasswordsSubtest("requestPlaintextPasswordFails")) << message_;
+}
+
IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, GetSavedPasswordList) {
EXPECT_TRUE(RunPasswordsSubtest("getSavedPasswordList")) << message_;
}
@@ -306,4 +170,92 @@ IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, RequestExportProgressStatus) {
EXPECT_TRUE(RunPasswordsSubtest("requestExportProgressStatus")) << message_;
}
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, IsNotOptedInForAccountStorage) {
+ EXPECT_TRUE(RunPasswordsSubtest("isNotOptedInForAccountStorage")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, IsOptedInForAccountStorage) {
+ SetOptedInForAccountStorage(true);
+ EXPECT_TRUE(RunPasswordsSubtest("isOptedInForAccountStorage")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, GetCompromisedCredentials) {
+ EXPECT_TRUE(RunPasswordsSubtest("getCompromisedCredentials")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
+ GetPlaintextCompromisedPassword) {
+ EXPECT_TRUE(RunPasswordsSubtest("getPlaintextCompromisedPassword"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
+ GetPlaintextCompromisedPasswordFails) {
+ ResetPlaintextPassword();
+ EXPECT_TRUE(RunPasswordsSubtest("getPlaintextCompromisedPasswordFails"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
+ ChangeCompromisedCredentialFails) {
+ EXPECT_TRUE(RunPasswordsSubtest("changeCompromisedCredentialFails"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
+ ChangeCompromisedCredentialSucceeds) {
+ AddCompromisedCredential(0);
+ EXPECT_TRUE(RunPasswordsSubtest("changeCompromisedCredentialSucceeds"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, OptInForAccountStorage) {
+ SetOptedInForAccountStorage(false);
+ EXPECT_TRUE(RunPasswordsSubtest("optInForAccountStorage")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, OptOutForAccountStorage) {
+ SetOptedInForAccountStorage(true);
+ EXPECT_TRUE(RunPasswordsSubtest("optOutForAccountStorage")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
+ RemoveCompromisedCredentialFails) {
+ EXPECT_TRUE(RunPasswordsSubtest("removeCompromisedCredentialFails"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest,
+ RemoveCompromisedCredentialSucceeds) {
+ AddCompromisedCredential(0);
+ EXPECT_TRUE(RunPasswordsSubtest("removeCompromisedCredentialSucceeds"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, StartPasswordCheck) {
+ set_start_password_check_state(
+ password_manager::BulkLeakCheckService::State::kRunning);
+ EXPECT_FALSE(start_password_check_triggered());
+ EXPECT_TRUE(RunPasswordsSubtest("startPasswordCheck")) << message_;
+ EXPECT_TRUE(start_password_check_triggered());
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, StartPasswordCheckFailed) {
+ set_start_password_check_state(
+ password_manager::BulkLeakCheckService::State::kIdle);
+ EXPECT_FALSE(start_password_check_triggered());
+ EXPECT_TRUE(RunPasswordsSubtest("startPasswordCheckFailed")) << message_;
+ EXPECT_TRUE(start_password_check_triggered());
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, StopPasswordCheck) {
+ EXPECT_FALSE(stop_password_check_triggered());
+ EXPECT_TRUE(RunPasswordsSubtest("stopPasswordCheck")) << message_;
+ EXPECT_TRUE(stop_password_check_triggered());
+}
+
+IN_PROC_BROWSER_TEST_F(PasswordsPrivateApiTest, GetPasswordCheckStatus) {
+ EXPECT_TRUE(RunPasswordsSubtest("getPasswordCheckStatus")) << message_;
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
index 5c4bb1067a0..b1c9d8c20f1 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h
@@ -14,10 +14,12 @@
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
+#include "base/strings/string_piece_forward.h"
#include "chrome/browser/ui/passwords/settings/password_manager_presenter.h"
#include "chrome/browser/ui/passwords/settings/password_ui_view.h"
#include "chrome/common/extensions/api/passwords_private.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "components/password_manager/core/browser/bulk_leak_check_service.h"
#include "components/password_manager/core/browser/ui/export_progress_status.h"
#include "extensions/browser/extension_function.h"
@@ -35,7 +37,13 @@ class PasswordsPrivateDelegate : public KeyedService {
using PlaintextPasswordCallback =
base::OnceCallback<void(base::Optional<base::string16>)>;
- ~PasswordsPrivateDelegate() override {}
+ using StartPasswordCheckCallback =
+ base::OnceCallback<void(password_manager::BulkLeakCheckService::State)>;
+
+ using PlaintextCompromisedPasswordCallback = base::OnceCallback<void(
+ base::Optional<api::passwords_private::CompromisedCredential>)>;
+
+ ~PasswordsPrivateDelegate() override = default;
// Gets the saved passwords list.
using UiEntries = std::vector<api::passwords_private::PasswordUiEntry>;
@@ -45,9 +53,8 @@ class PasswordsPrivateDelegate : public KeyedService {
// Gets the password exceptions list.
using ExceptionEntries = std::vector<api::passwords_private::ExceptionEntry>;
using ExceptionEntriesCallback =
- base::Callback<void(const ExceptionEntries&)>;
- virtual void GetPasswordExceptionsList(
- const ExceptionEntriesCallback& callback) = 0;
+ base::OnceCallback<void(const ExceptionEntries&)>;
+ virtual void GetPasswordExceptionsList(ExceptionEntriesCallback callback) = 0;
// Changes the username and password corresponding to |id|.
// |id|: The id for the password entry being updated.
@@ -74,13 +81,16 @@ class PasswordsPrivateDelegate : public KeyedService {
// Requests the plain text password for entry corresponding to the |id|
// generated for each entry of the password list.
// |id| the id created when going over the list of saved passwords.
+ // |reason| The reason why the plaintext password is requested.
// |callback| The callback that gets invoked with the saved password if it
// could be obtained successfully, or base::nullopt otherwise.
// |web_contents| The web content object used as the UI; will be used to show
// an OS-level authentication dialog if necessary.
- virtual void RequestShowPassword(int id,
- PlaintextPasswordCallback callback,
- content::WebContents* web_contents) = 0;
+ virtual void RequestPlaintextPassword(
+ int id,
+ api::passwords_private::PlaintextReason reason,
+ PlaintextPasswordCallback callback,
+ content::WebContents* web_contents) = 0;
// Trigger the password import procedure, allowing the user to select a file
// containing passwords to import.
@@ -99,6 +109,53 @@ class PasswordsPrivateDelegate : public KeyedService {
// Get the most recent progress status.
virtual api::passwords_private::ExportProgressStatus
GetExportProgressStatus() = 0;
+
+ // Whether the current signed-in user (aka unconsented primary account) has
+ // opted in to use the Google account storage for passwords (as opposed to
+ // local/profile storage).
+ virtual bool IsOptedInForAccountStorage() = 0;
+
+ // Sets whether the user is opted in to use the Google account storage for
+ // passwords. If |opt_in| is true and the user is not currently opted in,
+ // will trigger a reauth flow.
+ virtual void SetAccountStorageOptIn(bool opt_in,
+ content::WebContents* web_contents) = 0;
+
+ // Obtains information about compromised credentials. This includes the last
+ // time a check was run, as well as all compromised credentials that are
+ // present in the password store.
+ virtual std::vector<api::passwords_private::CompromisedCredential>
+ GetCompromisedCredentials() = 0;
+
+ // Requests the plaintext password for |credential| due to |reason|. If
+ // successful, |callback| gets invoked with the same |credential|, whose
+ // |password| field will be set.
+ virtual void GetPlaintextCompromisedPassword(
+ api::passwords_private::CompromisedCredential credential,
+ api::passwords_private::PlaintextReason reason,
+ content::WebContents* web_contents,
+ PlaintextCompromisedPasswordCallback callback) = 0;
+
+ // Attempts to change the stored password of |credential| to |new_password|.
+ // Returns whether the change succeeded.
+ virtual bool ChangeCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential,
+ base::StringPiece new_password) = 0;
+
+ // Attempts to remove |credential| from the password store. Returns whether
+ // the remove succeeded.
+ virtual bool RemoveCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential) = 0;
+
+ // Requests to start a check for compromised passwords. Invokes |callback|
+ // once a check is running or the request was stopped via StopPasswordCheck().
+ virtual void StartPasswordCheck(StartPasswordCheckCallback callback) = 0;
+ // Stops a check for compromised passwords.
+ virtual void StopPasswordCheck() = 0;
+
+ // Returns the current status of the password check.
+ virtual api::passwords_private::PasswordCheckStatus
+ GetPasswordCheckStatus() = 0;
};
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.cc
index ea89dc6e418..7308ce4a473 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.cc
@@ -6,6 +6,8 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h"
+#include "chrome/browser/password_manager/bulk_leak_check_service_factory.h"
+#include "chrome/browser/password_manager/password_store_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "extensions/browser/extension_system_provider.h"
@@ -25,30 +27,23 @@ PasswordsPrivateDelegate* PasswordsPrivateDelegateFactory::GetForBrowserContext(
// static
PasswordsPrivateDelegateFactory*
PasswordsPrivateDelegateFactory::GetInstance() {
- return base::Singleton<PasswordsPrivateDelegateFactory>::get();
+ static base::NoDestructor<PasswordsPrivateDelegateFactory> instance;
+ return instance.get();
}
PasswordsPrivateDelegateFactory::PasswordsPrivateDelegateFactory()
: BrowserContextKeyedServiceFactory(
"PasswordsPrivateDelegate",
BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(BulkLeakCheckServiceFactory::GetInstance());
+ DependsOn(PasswordStoreFactory::GetInstance());
}
-PasswordsPrivateDelegateFactory::~PasswordsPrivateDelegateFactory() {
-}
+PasswordsPrivateDelegateFactory::~PasswordsPrivateDelegateFactory() = default;
KeyedService* PasswordsPrivateDelegateFactory::BuildServiceInstanceFor(
content::BrowserContext* profile) const {
return new PasswordsPrivateDelegateImpl(static_cast<Profile*>(profile));
}
-bool PasswordsPrivateDelegateFactory::
- ServiceIsCreatedWithBrowserContext() const {
- return false;
-}
-
-bool PasswordsPrivateDelegateFactory::ServiceIsNULLWhileTesting() const {
- return false;
-}
-
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h
index e28c3bf3d56..428863cd748 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h
@@ -5,8 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_PASSWORDS_PRIVATE_DELEGATE_FACTORY_H_
#define CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_PASSWORDS_PRIVATE_DELEGATE_FACTORY_H_
-#include "base/macros.h"
-#include "base/memory/singleton.h"
+#include "base/no_destructor.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace context {
@@ -27,18 +26,13 @@ class PasswordsPrivateDelegateFactory
static PasswordsPrivateDelegateFactory* GetInstance();
private:
- friend struct base::DefaultSingletonTraits<PasswordsPrivateDelegateFactory>;
-
+ friend class base::NoDestructor<PasswordsPrivateDelegateFactory>;
PasswordsPrivateDelegateFactory();
~PasswordsPrivateDelegateFactory() override;
// BrowserContextKeyedServiceFactory implementation.
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* profile) const override;
- bool ServiceIsCreatedWithBrowserContext() const override;
- bool ServiceIsNULLWhileTesting() const override;
-
- DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateDelegateFactory);
};
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
index 7931d22b63e..a00fc1ed6b6 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.cc
@@ -14,17 +14,24 @@
#include "build/build_config.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h"
+#include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
#include "chrome/common/extensions/api/passwords_private.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
#include "components/password_manager/core/browser/password_list_sorter.h"
+#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/browser/password_ui_utils.h"
+#include "components/password_manager/core/browser/ui/plaintext_reason.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/prefs/pref_service.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
#include "content/public/browser/web_contents.h"
+#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(OS_WIN)
@@ -49,10 +56,9 @@ const char kExportInProgress[] = "in-progress";
const char kReauthenticationFailed[] = "reauth-failed";
#if defined(OS_CHROMEOS)
-constexpr static base::TimeDelta kShowPasswordAuthTokenLifetime =
- base::TimeDelta::FromSeconds(
- PasswordAccessAuthenticator::kAuthValidityPeriodSeconds);
-constexpr static base::TimeDelta kExportPasswordsAuthTokenLifetime =
+constexpr base::TimeDelta kShowPasswordAuthTokenLifetime =
+ password_manager::PasswordAccessAuthenticator::kAuthValidityPeriod;
+constexpr base::TimeDelta kExportPasswordsAuthTokenLifetime =
base::TimeDelta::FromSeconds(5);
#endif
@@ -83,6 +89,40 @@ extensions::api::passwords_private::ExportProgressStatus ConvertStatus(
EXPORT_PROGRESS_STATUS_NONE;
}
+password_manager::ReauthPurpose GetReauthPurpose(
+ extensions::api::passwords_private::PlaintextReason reason) {
+ switch (reason) {
+ case extensions::api::passwords_private::PLAINTEXT_REASON_VIEW:
+ return password_manager::ReauthPurpose::VIEW_PASSWORD;
+ case extensions::api::passwords_private::PLAINTEXT_REASON_COPY:
+ return password_manager::ReauthPurpose::COPY_PASSWORD;
+ case extensions::api::passwords_private::PLAINTEXT_REASON_EDIT:
+ return password_manager::ReauthPurpose::EDIT_PASSWORD;
+ case extensions::api::passwords_private::PLAINTEXT_REASON_NONE:
+ break;
+ }
+
+ NOTREACHED();
+ return password_manager::ReauthPurpose::VIEW_PASSWORD;
+}
+
+password_manager::PlaintextReason ConvertPlaintextReason(
+ extensions::api::passwords_private::PlaintextReason reason) {
+ switch (reason) {
+ case extensions::api::passwords_private::PLAINTEXT_REASON_VIEW:
+ return password_manager::PlaintextReason::kView;
+ case extensions::api::passwords_private::PLAINTEXT_REASON_COPY:
+ return password_manager::PlaintextReason::kCopy;
+ case extensions::api::passwords_private::PLAINTEXT_REASON_EDIT:
+ return password_manager::PlaintextReason::kEdit;
+ case extensions::api::passwords_private::PLAINTEXT_REASON_NONE:
+ break;
+ }
+
+ NOTREACHED();
+ return password_manager::PlaintextReason::kView;
+}
+
} // namespace
namespace extensions {
@@ -99,6 +139,18 @@ PasswordsPrivateDelegateImpl::PasswordsPrivateDelegateImpl(Profile* profile)
password_access_authenticator_(
base::BindRepeating(&PasswordsPrivateDelegateImpl::OsReauthCall,
base::Unretained(this))),
+ account_storage_opt_in_reauthenticator_(
+ base::BindRepeating(&PasswordsPrivateDelegateImpl::InvokeGoogleReauth,
+ base::Unretained(this))),
+ password_account_storage_opt_in_watcher_(
+ std::make_unique<
+ password_manager::PasswordAccountStorageOptInWatcher>(
+ IdentityManagerFactory::GetForProfile(profile_),
+ profile_->GetPrefs(),
+ base::BindRepeating(&PasswordsPrivateDelegateImpl::
+ OnAccountStorageOptInStateChanged,
+ base::Unretained(this)))),
+ password_check_delegate_(profile),
current_entries_initialized_(false),
current_exceptions_initialized_(false),
is_initialized_(false),
@@ -132,18 +184,18 @@ void PasswordsPrivateDelegateImpl::SendPasswordExceptionsList() {
}
void PasswordsPrivateDelegateImpl::GetPasswordExceptionsList(
- const ExceptionEntriesCallback& callback) {
+ ExceptionEntriesCallback callback) {
if (current_exceptions_initialized_)
- callback.Run(current_exceptions_);
+ std::move(callback).Run(current_exceptions_);
else
- get_password_exception_list_callbacks_.push_back(callback);
+ get_password_exception_list_callbacks_.push_back(std::move(callback));
}
void PasswordsPrivateDelegateImpl::ChangeSavedPassword(
int id,
base::string16 new_username,
base::Optional<base::string16> new_password) {
- const std::string* sort_key = password_id_generator_.TryGetSortKey(id);
+ const std::string* sort_key = password_id_generator_.TryGetKey(id);
DCHECK(sort_key);
password_manager_presenter_->ChangeSavedPassword(
*sort_key, std::move(new_username), std::move(new_password));
@@ -156,7 +208,7 @@ void PasswordsPrivateDelegateImpl::RemoveSavedPassword(int id) {
}
void PasswordsPrivateDelegateImpl::RemoveSavedPasswordInternal(int id) {
- const std::string* sort_key = password_id_generator_.TryGetSortKey(id);
+ const std::string* sort_key = password_id_generator_.TryGetKey(id);
if (sort_key)
password_manager_presenter_->RemoveSavedPassword(*sort_key);
}
@@ -168,7 +220,7 @@ void PasswordsPrivateDelegateImpl::RemovePasswordException(int id) {
}
void PasswordsPrivateDelegateImpl::RemovePasswordExceptionInternal(int id) {
- const std::string* sort_key = exception_id_generator_.TryGetSortKey(id);
+ const std::string* sort_key = exception_id_generator_.TryGetKey(id);
if (sort_key)
password_manager_presenter_->RemovePasswordException(*sort_key);
}
@@ -184,8 +236,9 @@ void PasswordsPrivateDelegateImpl::
password_manager_presenter_->UndoRemoveSavedPasswordOrException();
}
-void PasswordsPrivateDelegateImpl::RequestShowPassword(
+void PasswordsPrivateDelegateImpl::RequestPlaintextPassword(
int id,
+ api::passwords_private::PlaintextReason reason,
PlaintextPasswordCallback callback,
content::WebContents* web_contents) {
// Save |web_contents| so that it can be used later when OsReauthCall() is
@@ -195,20 +248,38 @@ void PasswordsPrivateDelegateImpl::RequestShowPassword(
// reauth-handling code.
web_contents_ = web_contents;
if (!password_access_authenticator_.EnsureUserIsAuthenticated(
- password_manager::ReauthPurpose::VIEW_PASSWORD)) {
+ GetReauthPurpose(reason))) {
std::move(callback).Run(base::nullopt);
return;
}
// Request the password. When it is retrieved, ShowPassword() will be called.
- const std::string* sort_key = password_id_generator_.TryGetSortKey(id);
+ const std::string* sort_key = password_id_generator_.TryGetKey(id);
if (!sort_key) {
std::move(callback).Run(base::nullopt);
return;
}
- password_manager_presenter_->RequestShowPassword(*sort_key,
- std::move(callback));
+ if (reason == api::passwords_private::PLAINTEXT_REASON_COPY) {
+ // In case of copy we don't need to give password back to UI. callback
+ // will receive either empty string in case of success or null otherwise.
+ // Copying occurs here so javascript doesn't need plaintext password.
+ callback = base::BindOnce(
+ [](PlaintextPasswordCallback callback,
+ base::Optional<base::string16> password) {
+ if (!password) {
+ std::move(callback).Run(base::nullopt);
+ return;
+ }
+ ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste)
+ .WriteText(*password);
+ std::move(callback).Run(base::string16());
+ },
+ std::move(callback));
+ }
+
+ password_manager_presenter_->RequestPlaintextPassword(
+ *sort_key, ConvertPlaintextReason(reason), std::move(callback));
}
bool PasswordsPrivateDelegateImpl::OsReauthCall(
@@ -243,6 +314,21 @@ bool PasswordsPrivateDelegateImpl::OsReauthCall(
#endif
}
+void PasswordsPrivateDelegateImpl::InvokeGoogleReauth(
+ content::WebContents* web_contents,
+ PasswordsPrivateDelegateImpl::GoogleReauthCallback callback) {
+ if (auto* client =
+ ChromePasswordManagerClient::FromWebContents(web_contents)) {
+ client->TriggerReauthForAccount(
+ IdentityManagerFactory::GetForProfile(profile_)->GetPrimaryAccountId(
+ signin::ConsentLevel::kNotRequired),
+ std::move(callback));
+ return;
+ }
+ std::move(callback).Run(
+ password_manager::PasswordManagerClient::ReauthSucceeded(false));
+}
+
Profile* PasswordsPrivateDelegateImpl::GetProfile() {
return profile_;
}
@@ -258,7 +344,6 @@ void PasswordsPrivateDelegateImpl::SetPasswordList(
entry.username = base::UTF16ToUTF8(form->username_value);
entry.id = password_id_generator_.GenerateId(
password_manager::CreateSortKey(*form));
- entry.num_characters_in_password = form->password_value.length();
if (!form->federation_origin.opaque()) {
entry.federation_text.reset(new std::string(l10n_util::GetStringFUTF8(
@@ -307,8 +392,8 @@ void PasswordsPrivateDelegateImpl::SetPasswordExceptionList(
current_exceptions_initialized_ = true;
InitializeIfNecessary();
- for (const auto& callback : get_password_exception_list_callbacks_)
- callback.Run(current_exceptions_);
+ for (auto& callback : get_password_exception_list_callbacks_)
+ std::move(callback).Run(current_exceptions_);
get_password_exception_list_callbacks_.clear();
}
@@ -347,6 +432,88 @@ PasswordsPrivateDelegateImpl::GetExportProgressStatus() {
return ConvertStatus(password_manager_porter_->GetExportProgressStatus());
}
+bool PasswordsPrivateDelegateImpl::IsOptedInForAccountStorage() {
+ return password_manager_util::IsOptedInForAccountStorage(
+ profile_->GetPrefs(), ProfileSyncServiceFactory::GetForProfile(profile_));
+}
+
+void PasswordsPrivateDelegateImpl::SetAccountStorageOptIn(
+ bool opt_in,
+ content::WebContents* web_contents) {
+ if (opt_in == IsOptedInForAccountStorage())
+ return;
+ if (!opt_in) {
+ password_manager_util::SetAccountStorageOptIn(
+ profile_->GetPrefs(),
+ ProfileSyncServiceFactory::GetForProfile(profile_), false);
+ return;
+ }
+ account_storage_opt_in_reauthenticator_.Run(
+ web_contents,
+ base::BindOnce(
+ &PasswordsPrivateDelegateImpl::SetAccountStorageOptInCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void PasswordsPrivateDelegateImpl::SetAccountStorageOptInCallback(
+ password_manager::PasswordManagerClient::ReauthSucceeded reauth_succeeded) {
+ if (reauth_succeeded) {
+ password_manager_util::SetAccountStorageOptIn(
+ profile_->GetPrefs(),
+ ProfileSyncServiceFactory::GetForProfile(profile_), true);
+ }
+}
+
+std::vector<api::passwords_private::CompromisedCredential>
+PasswordsPrivateDelegateImpl::GetCompromisedCredentials() {
+ return password_check_delegate_.GetCompromisedCredentials();
+}
+
+void PasswordsPrivateDelegateImpl::GetPlaintextCompromisedPassword(
+ api::passwords_private::CompromisedCredential credential,
+ api::passwords_private::PlaintextReason reason,
+ content::WebContents* web_contents,
+ PlaintextCompromisedPasswordCallback callback) {
+ // TODO(crbug.com/495290): Pass the native window directly to the
+ // reauth-handling code.
+ web_contents_ = web_contents;
+ if (!password_access_authenticator_.EnsureUserIsAuthenticated(
+ GetReauthPurpose(reason))) {
+ std::move(callback).Run(base::nullopt);
+ return;
+ }
+
+ std::move(callback).Run(
+ password_check_delegate_.GetPlaintextCompromisedPassword(
+ std::move(credential)));
+}
+
+bool PasswordsPrivateDelegateImpl::ChangeCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential,
+ base::StringPiece new_password) {
+ return password_check_delegate_.ChangeCompromisedCredential(credential,
+ new_password);
+}
+
+bool PasswordsPrivateDelegateImpl::RemoveCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential) {
+ return password_check_delegate_.RemoveCompromisedCredential(credential);
+}
+
+void PasswordsPrivateDelegateImpl::StartPasswordCheck(
+ StartPasswordCheckCallback callback) {
+ password_check_delegate_.StartPasswordCheck(std::move(callback));
+}
+
+void PasswordsPrivateDelegateImpl::StopPasswordCheck() {
+ password_check_delegate_.StopPasswordCheck();
+}
+
+api::passwords_private::PasswordCheckStatus
+PasswordsPrivateDelegateImpl::GetPasswordCheckStatus() {
+ return password_check_delegate_.GetPasswordCheckStatus();
+}
+
void PasswordsPrivateDelegateImpl::OnPasswordsExportProgress(
password_manager::ExportProgressStatus status,
const std::string& folder_name) {
@@ -357,22 +524,25 @@ void PasswordsPrivateDelegateImpl::OnPasswordsExportProgress(
}
}
+void PasswordsPrivateDelegateImpl::OnAccountStorageOptInStateChanged() {
+ PasswordsPrivateEventRouter* router =
+ PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
+ if (router) {
+ router->OnAccountStorageOptInStateChanged(IsOptedInForAccountStorage());
+ }
+}
+
void PasswordsPrivateDelegateImpl::Shutdown() {
- password_manager_presenter_.reset();
+ password_account_storage_opt_in_watcher_.reset();
password_manager_porter_.reset();
+ password_manager_presenter_.reset();
}
-SortKeyIdGenerator&
+IdGenerator<std::string>&
PasswordsPrivateDelegateImpl::GetPasswordIdGeneratorForTesting() {
return password_id_generator_;
}
-void PasswordsPrivateDelegateImpl::SetOsReauthCallForTesting(
- PasswordAccessAuthenticator::ReauthCallback os_reauth_call) {
- password_access_authenticator_.SetOsReauthCallForTesting(
- std::move(os_reauth_call));
-}
-
void PasswordsPrivateDelegateImpl::ExecuteFunction(
const base::Closure& callback) {
if (is_initialized_) {
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
index 03d191b747e..6bab4451e81 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h
@@ -13,18 +13,22 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
+#include "chrome/browser/extensions/api/passwords_private/password_check_delegate.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_utils.h"
-#include "chrome/browser/password_manager/reauth_purpose.h"
-#include "chrome/browser/ui/passwords/settings/password_access_authenticator.h"
#include "chrome/browser/ui/passwords/settings/password_manager_porter.h"
#include "chrome/browser/ui/passwords/settings/password_manager_presenter.h"
#include "chrome/browser/ui/passwords/settings/password_ui_view.h"
#include "chrome/common/extensions/api/passwords_private.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "components/password_manager/core/browser/password_access_authenticator.h"
+#include "components/password_manager/core/browser/password_account_storage_opt_in_watcher.h"
+#include "components/password_manager/core/browser/password_manager_client.h"
+#include "components/password_manager/core/browser/reauth_purpose.h"
#include "components/password_manager/core/browser/ui/export_progress_status.h"
#include "extensions/browser/extension_function.h"
@@ -38,15 +42,14 @@ namespace extensions {
// Concrete PasswordsPrivateDelegate implementation.
class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
- public PasswordUIView {
+ public PasswordUIView {
public:
explicit PasswordsPrivateDelegateImpl(Profile* profile);
~PasswordsPrivateDelegateImpl() override;
// PasswordsPrivateDelegate implementation.
void GetSavedPasswordsList(UiEntriesCallback callback) override;
- void GetPasswordExceptionsList(
- const ExceptionEntriesCallback& callback) override;
+ void GetPasswordExceptionsList(ExceptionEntriesCallback callback) override;
void ChangeSavedPassword(
int id,
base::string16 new_username,
@@ -54,15 +57,34 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
void RemoveSavedPassword(int id) override;
void RemovePasswordException(int id) override;
void UndoRemoveSavedPasswordOrException() override;
- void RequestShowPassword(int id,
- PlaintextPasswordCallback callback,
- content::WebContents* web_contents) override;
+ void RequestPlaintextPassword(int id,
+ api::passwords_private::PlaintextReason reason,
+ PlaintextPasswordCallback callback,
+ content::WebContents* web_contents) override;
void ImportPasswords(content::WebContents* web_contents) override;
void ExportPasswords(base::OnceCallback<void(const std::string&)> accepted,
content::WebContents* web_contents) override;
void CancelExportPasswords() override;
api::passwords_private::ExportProgressStatus GetExportProgressStatus()
override;
+ bool IsOptedInForAccountStorage() override;
+ void SetAccountStorageOptIn(bool opt_in,
+ content::WebContents* web_contents) override;
+ std::vector<api::passwords_private::CompromisedCredential>
+ GetCompromisedCredentials() override;
+ void GetPlaintextCompromisedPassword(
+ api::passwords_private::CompromisedCredential credential,
+ api::passwords_private::PlaintextReason reason,
+ content::WebContents* web_contents,
+ PlaintextCompromisedPasswordCallback callback) override;
+ bool ChangeCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential,
+ base::StringPiece new_password) override;
+ bool RemoveCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential) override;
+ void StartPasswordCheck(StartPasswordCheckCallback callback) override;
+ void StopPasswordCheck() override;
+ api::passwords_private::PasswordCheckStatus GetPasswordCheckStatus() override;
// PasswordUIView implementation.
Profile* GetProfile() override;
@@ -73,19 +95,34 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
const std::vector<std::unique_ptr<autofill::PasswordForm>>&
password_exception_list) override;
- // Callback for when the password list has been written to the destination.
- void OnPasswordsExportProgress(password_manager::ExportProgressStatus status,
- const std::string& folder_name);
-
// KeyedService overrides:
void Shutdown() override;
- SortKeyIdGenerator& GetPasswordIdGeneratorForTesting();
+ IdGenerator<std::string>& GetPasswordIdGeneratorForTesting();
+ // TODO(crbug.com/1049141): Move the strong alias out of PasswordManagerClient
+ // to avoid leaking implementation details here.
+ using GoogleReauthCallback = base::OnceCallback<void(
+ password_manager::PasswordManagerClient::ReauthSucceeded)>;
+ using GoogleAccountAuthenticator =
+ base::RepeatingCallback<void(content::WebContents*,
+ GoogleReauthCallback)>;
+
+#if defined(UNIT_TEST)
// Use this in tests to mock the OS-level reauthentication.
- void SetOsReauthCallForTesting(
- base::RepeatingCallback<bool(password_manager::ReauthPurpose)>
- os_reauth_call);
+ void set_os_reauth_call(
+ password_manager::PasswordAccessAuthenticator::ReauthCallback
+ os_reauth_call) {
+ password_access_authenticator_.set_os_reauth_call(
+ std::move(os_reauth_call));
+ }
+ // Use this in tests to mock the Google account reauthentication.
+ void set_account_storage_opt_in_reauthenticator(
+ GoogleAccountAuthenticator account_storage_opt_in_reauthenticator) {
+ account_storage_opt_in_reauthenticator_ =
+ std::move(account_storage_opt_in_reauthenticator);
+ }
+#endif // defined(UNIT_TEST)
private:
// Called after the lists are fetched. Once both lists have been set, the
@@ -104,10 +141,26 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
void RemovePasswordExceptionInternal(int id);
void UndoRemoveSavedPasswordOrExceptionInternal();
+ // Callback for when the password list has been written to the destination.
+ void OnPasswordsExportProgress(password_manager::ExportProgressStatus status,
+ const std::string& folder_name);
+
+ void OnAccountStorageOptInStateChanged();
+
+ // Callback for the reauth flow that is triggered upon the user opting in to
+ // account password storage. Will opt in the user if the reauth succeeded.
+ void SetAccountStorageOptInCallback(
+ password_manager::PasswordManagerClient::ReauthSucceeded
+ reauth_succeeded);
+
// Triggers an OS-dependent UI to present OS account login challenge and
// returns true if the user passed that challenge.
bool OsReauthCall(password_manager::ReauthPurpose purpose);
+ // Triggers a Google account reauthentication UI.
+ void InvokeGoogleReauth(content::WebContents* web_contents,
+ GoogleReauthCallback callback);
+
// Not owned by this class.
Profile* profile_;
@@ -117,7 +170,14 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
// Used to control the export and import flows.
std::unique_ptr<PasswordManagerPorter> password_manager_porter_;
- PasswordAccessAuthenticator password_access_authenticator_;
+ password_manager::PasswordAccessAuthenticator password_access_authenticator_;
+
+ GoogleAccountAuthenticator account_storage_opt_in_reauthenticator_;
+
+ std::unique_ptr<password_manager::PasswordAccountStorageOptInWatcher>
+ password_account_storage_opt_in_watcher_;
+
+ PasswordCheckDelegate password_check_delegate_;
// The current list of entries/exceptions. Cached here so that when new
// observers are added, this delegate can send the current lists without
@@ -127,8 +187,8 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
// Generators that map between sort keys used by |password_manager_presenter_|
// and ids used by the JavaScript front end.
- SortKeyIdGenerator password_id_generator_;
- SortKeyIdGenerator exception_id_generator_;
+ IdGenerator<std::string> password_id_generator_;
+ IdGenerator<std::string> exception_id_generator_;
// Whether SetPasswordList and SetPasswordExceptionList have been called, and
// whether this class has been initialized, meaning both have been called.
@@ -148,6 +208,8 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
// NativeWindow for the window where the API was called.
content::WebContents* web_contents_;
+ base::WeakPtrFactory<PasswordsPrivateDelegateImpl> weak_ptr_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateDelegateImpl);
};
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
index 274e5ac9496..4fe560946a2 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
@@ -11,63 +11,67 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind_test_util.h"
+#include "base/test/gmock_move_support.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/mock_callback.h"
+#include "base/test/scoped_feature_list.h"
#include "base/values.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h"
#include "chrome/browser/password_manager/password_store_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/common/extensions/api/passwords_private.h"
#include "chrome/test/base/testing_profile.h"
#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/compromised_credentials_table.h"
#include "components/password_manager/core/browser/password_list_sorter.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
#include "components/password_manager/core/browser/password_manager_test_utils.h"
+#include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/reauth_purpose.h"
#include "components/password_manager/core/browser/test_password_store.h"
+#include "components/password_manager/core/common/password_manager_features.h"
+#include "components/sync/driver/test_sync_service.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/test_event_router.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/clipboard/test/test_clipboard.h"
+using MockReauthCallback = base::MockCallback<
+ password_manager::PasswordAccessAuthenticator::ReauthCallback>;
using PasswordFormList = std::vector<std::unique_ptr<autofill::PasswordForm>>;
+using password_manager::ReauthPurpose;
+using password_manager::TestPasswordStore;
+using ::testing::Eq;
using ::testing::Ne;
+using ::testing::Return;
using ::testing::StrictMock;
-
namespace extensions {
namespace {
-template <typename T>
-base::OnceCallback<void(T)> GetCallbackArgument(T* arg) {
- return base::BindOnce([](T* arg, T value) { *arg = std::move(value); },
- base::Unretained(arg));
-}
-
-template <typename T>
-class CallbackTracker {
- public:
- CallbackTracker()
- : callback_(base::BindRepeating(&CallbackTracker::Callback,
- base::Unretained(this))) {}
-
- using TypedCallback = base::RepeatingCallback<void(const T&)>;
-
- const TypedCallback& callback() const { return callback_; }
-
- size_t call_count() const { return call_count_; }
-
- private:
- void Callback(const T& args) {
- EXPECT_FALSE(args.empty());
- ++call_count_;
- }
-
- size_t call_count_ = 0;
+constexpr char kHistogramName[] = "PasswordManager.AccessPasswordInSettings";
- TypedCallback callback_;
+using MockPlaintextPasswordCallback =
+ base::MockCallback<PasswordsPrivateDelegate::PlaintextPasswordCallback>;
- DISALLOW_COPY_AND_ASSIGN(CallbackTracker);
-};
+scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore(
+ Profile* profile) {
+ return base::WrapRefCounted(static_cast<TestPasswordStore*>(
+ PasswordStoreFactory::GetInstance()
+ ->SetTestingFactoryAndUse(
+ profile,
+ base::BindRepeating(&password_manager::BuildPasswordStore<
+ content::BrowserContext, TestPasswordStore>))
+ .get()));
+}
class PasswordEventObserver
: public extensions::TestEventRouter::EventObserver {
@@ -109,15 +113,6 @@ void PasswordEventObserver::OnBroadcastEvent(const extensions::Event& event) {
event_args_ = event.event_args->Clone();
}
-enum class ReauthResult { PASS, FAIL };
-
-bool FakeOsReauthCall(bool* reauth_called,
- ReauthResult result,
- password_manager::ReauthPurpose purpose) {
- *reauth_called = true;
- return result == ReauthResult::PASS;
-}
-
std::unique_ptr<KeyedService> BuildPasswordsPrivateEventRouter(
content::BrowserContext* context) {
return std::unique_ptr<KeyedService>(
@@ -126,12 +121,23 @@ std::unique_ptr<KeyedService> BuildPasswordsPrivateEventRouter(
autofill::PasswordForm CreateSampleForm() {
autofill::PasswordForm form;
+ form.signon_realm = "http://abc1.com";
form.origin = GURL("http://abc1.com");
form.username_value = base::ASCIIToUTF16("test@gmail.com");
form.password_value = base::ASCIIToUTF16("test");
return form;
}
+std::unique_ptr<KeyedService> BuildTestSyncService(content::BrowserContext*) {
+ auto sync_service = std::make_unique<syncer::TestSyncService>();
+ CoreAccountInfo fake_info;
+ fake_info.account_id = CoreAccountId("id");
+ fake_info.gaia = "gaia";
+ fake_info.email = "foo@bar.com";
+ sync_service->SetAuthenticatedAccountInfo(fake_info);
+ return sync_service;
+}
+
} // namespace
class PasswordsPrivateDelegateImplTest : public testing::Test {
@@ -146,32 +152,39 @@ class PasswordsPrivateDelegateImplTest : public testing::Test {
// PasswordsPrivateEventRouter.
void SetUpRouters();
+ void SetGoogleReauthResponse(PasswordsPrivateDelegateImpl* delegate,
+ bool should_succeed);
+
+ base::HistogramTester& histogram_tester() { return histogram_tester_; }
+
protected:
content::BrowserTaskEnvironment task_environment_;
TestingProfile profile_;
extensions::TestEventRouter* event_router_ = nullptr;
+ scoped_refptr<TestPasswordStore> store_ =
+ CreateAndUseTestPasswordStore(&profile_);
+ ui::TestClipboard* test_clipboard_ =
+ ui::TestClipboard::CreateForCurrentThread();
+ base::MockCallback<PasswordsPrivateDelegateImpl::GoogleAccountAuthenticator>
+ mock_google_authenticator_;
private:
+ base::HistogramTester histogram_tester_;
DISALLOW_COPY_AND_ASSIGN(PasswordsPrivateDelegateImplTest);
};
-PasswordsPrivateDelegateImplTest::PasswordsPrivateDelegateImplTest() = default;
+PasswordsPrivateDelegateImplTest::PasswordsPrivateDelegateImplTest() {
+ SetUpRouters();
+}
-PasswordsPrivateDelegateImplTest::~PasswordsPrivateDelegateImplTest() = default;
+PasswordsPrivateDelegateImplTest::~PasswordsPrivateDelegateImplTest() {
+ ui::Clipboard::DestroyClipboardForCurrentThread();
+}
void PasswordsPrivateDelegateImplTest::SetUpPasswordStore(
std::vector<autofill::PasswordForm> forms) {
- scoped_refptr<password_manager::TestPasswordStore> password_store(
- static_cast<password_manager::TestPasswordStore*>(
- PasswordStoreFactory::GetInstance()
- ->SetTestingFactoryAndUse(
- &profile_,
- base::BindRepeating(&password_manager::BuildPasswordStore<
- content::BrowserContext,
- password_manager::TestPasswordStore>))
- .get()));
for (const autofill::PasswordForm& form : forms) {
- password_store->AddLogin(form);
+ store_->AddLogin(form);
}
// Spin the loop to allow PasswordStore tasks being processed.
base::RunLoop().RunUntilIdle();
@@ -186,38 +199,55 @@ void PasswordsPrivateDelegateImplTest::SetUpRouters() {
&profile_, base::BindRepeating(&BuildPasswordsPrivateEventRouter));
}
-TEST_F(PasswordsPrivateDelegateImplTest, GetSavedPasswordsList) {
- CallbackTracker<PasswordsPrivateDelegate::UiEntries> tracker;
+void PasswordsPrivateDelegateImplTest::SetGoogleReauthResponse(
+ PasswordsPrivateDelegateImpl* delegate,
+ bool should_succeed) {
+ ON_CALL(mock_google_authenticator_, Run)
+ .WillByDefault(
+ [should_succeed](
+ content::WebContents*,
+ PasswordsPrivateDelegateImpl::GoogleReauthCallback callback) {
+ std::move(callback).Run(
+ password_manager::PasswordManagerClient::ReauthSucceeded(
+ should_succeed));
+ });
+ delegate->set_account_storage_opt_in_reauthenticator(
+ mock_google_authenticator_.Get());
+}
+TEST_F(PasswordsPrivateDelegateImplTest, GetSavedPasswordsList) {
PasswordsPrivateDelegateImpl delegate(&profile_);
- delegate.GetSavedPasswordsList(tracker.callback());
- EXPECT_EQ(0u, tracker.call_count());
+ base::MockCallback<PasswordsPrivateDelegate::UiEntriesCallback> callback;
+ EXPECT_CALL(callback, Run).Times(0);
+ delegate.GetSavedPasswordsList(callback.Get());
PasswordFormList list;
list.push_back(std::make_unique<autofill::PasswordForm>());
+
+ EXPECT_CALL(callback, Run);
delegate.SetPasswordList(list);
- EXPECT_EQ(1u, tracker.call_count());
- delegate.GetSavedPasswordsList(tracker.callback());
- EXPECT_EQ(2u, tracker.call_count());
+ EXPECT_CALL(callback, Run);
+ delegate.GetSavedPasswordsList(callback.Get());
}
TEST_F(PasswordsPrivateDelegateImplTest, GetPasswordExceptionsList) {
- CallbackTracker<PasswordsPrivateDelegate::ExceptionEntries> tracker;
-
PasswordsPrivateDelegateImpl delegate(&profile_);
- delegate.GetPasswordExceptionsList(tracker.callback());
- EXPECT_EQ(0u, tracker.call_count());
+ base::MockCallback<PasswordsPrivateDelegate::ExceptionEntriesCallback>
+ callback;
+ EXPECT_CALL(callback, Run).Times(0);
+ delegate.GetPasswordExceptionsList(callback.Get());
PasswordFormList list;
list.push_back(std::make_unique<autofill::PasswordForm>());
+
+ EXPECT_CALL(callback, Run);
delegate.SetPasswordExceptionList(list);
- EXPECT_EQ(1u, tracker.call_count());
- delegate.GetPasswordExceptionsList(tracker.callback());
- EXPECT_EQ(2u, tracker.call_count());
+ EXPECT_CALL(callback, Run);
+ delegate.GetPasswordExceptionsList(callback.Get());
}
TEST_F(PasswordsPrivateDelegateImplTest, ChangeSavedPassword) {
@@ -238,8 +268,6 @@ TEST_F(PasswordsPrivateDelegateImplTest, ChangeSavedPassword) {
ASSERT_EQ(1u, password_list.size());
EXPECT_EQ(sample_form.username_value,
base::UTF8ToUTF16(password_list[0].username));
- EXPECT_EQ(sample_form.password_value.size(),
- size_t{password_list[0].num_characters_in_password});
}));
EXPECT_TRUE(got_passwords);
@@ -260,12 +288,110 @@ TEST_F(PasswordsPrivateDelegateImplTest, ChangeSavedPassword) {
ASSERT_EQ(1u, password_list.size());
EXPECT_EQ(base::ASCIIToUTF16("new_user"),
base::UTF8ToUTF16(password_list[0].username));
- EXPECT_EQ(base::ASCIIToUTF16("new_pass").size(),
- size_t{password_list[0].num_characters_in_password});
}));
EXPECT_TRUE(got_passwords);
}
+// Checking callback result of RequestPlaintextPassword with reason Copy.
+// By implementation for Copy, callback will receive empty string.
+TEST_F(PasswordsPrivateDelegateImplTest, TestCopyPasswordCallbackResult) {
+ autofill::PasswordForm form = CreateSampleForm();
+ SetUpPasswordStore({form});
+
+ PasswordsPrivateDelegateImpl delegate(&profile_);
+ base::RunLoop().RunUntilIdle();
+
+ MockReauthCallback callback;
+ delegate.set_os_reauth_call(callback.Get());
+
+ EXPECT_CALL(callback, Run(ReauthPurpose::COPY_PASSWORD))
+ .WillOnce(Return(true));
+
+ MockPlaintextPasswordCallback password_callback;
+ EXPECT_CALL(password_callback, Run(Eq(base::string16())));
+ delegate.RequestPlaintextPassword(
+ 0, api::passwords_private::PLAINTEXT_REASON_COPY, password_callback.Get(),
+ nullptr);
+
+ base::string16 result;
+ test_clipboard_->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+ EXPECT_EQ(form.password_value, result);
+
+ histogram_tester().ExpectUniqueSample(
+ kHistogramName, password_manager::metrics_util::ACCESS_PASSWORD_COPIED,
+ 1);
+}
+
+TEST_F(PasswordsPrivateDelegateImplTest, TestShouldOptInIfReauthSucceeds) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ password_manager::features::kEnablePasswordsAccountStorage);
+
+ PasswordsPrivateDelegateImpl delegate(&profile_);
+
+ SetGoogleReauthResponse(&delegate, true);
+
+ auto* test_sync_service = static_cast<syncer::SyncService*>(
+ ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+ &profile_, base::BindRepeating(&BuildTestSyncService)));
+
+ password_manager_util::SetAccountStorageOptIn(profile_.GetPrefs(),
+ test_sync_service, false);
+ delegate.SetAccountStorageOptIn(true, nullptr);
+
+ EXPECT_TRUE(password_manager_util::IsOptedInForAccountStorage(
+ profile_.GetPrefs(), test_sync_service));
+}
+
+TEST_F(PasswordsPrivateDelegateImplTest, TestShouldOptOut) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ password_manager::features::kEnablePasswordsAccountStorage);
+
+ PasswordsPrivateDelegateImpl delegate(&profile_);
+
+ auto* test_sync_service = static_cast<syncer::SyncService*>(
+ ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+ &profile_, base::BindRepeating(&BuildTestSyncService)));
+
+ password_manager_util::SetAccountStorageOptIn(profile_.GetPrefs(),
+ test_sync_service, true);
+ delegate.SetAccountStorageOptIn(false, nullptr);
+
+ EXPECT_CALL(mock_google_authenticator_, Run).Times(0);
+ EXPECT_FALSE(password_manager_util::IsOptedInForAccountStorage(
+ profile_.GetPrefs(), test_sync_service));
+}
+
+TEST_F(PasswordsPrivateDelegateImplTest, TestCopyPasswordCallbackResultFail) {
+ SetUpPasswordStore({CreateSampleForm()});
+
+ PasswordsPrivateDelegateImpl delegate(&profile_);
+ base::RunLoop().RunUntilIdle();
+
+ MockReauthCallback callback;
+ delegate.set_os_reauth_call(callback.Get());
+
+ EXPECT_CALL(callback, Run(ReauthPurpose::COPY_PASSWORD))
+ .WillOnce(Return(false));
+
+ base::Time before_call = test_clipboard_->GetLastModifiedTime();
+
+ MockPlaintextPasswordCallback password_callback;
+ EXPECT_CALL(password_callback, Run(Eq(base::nullopt)));
+ delegate.RequestPlaintextPassword(
+ 0, api::passwords_private::PLAINTEXT_REASON_COPY, password_callback.Get(),
+ nullptr);
+ // Clipboard should not be modifiend in case Reauth failed
+ base::string16 result;
+ test_clipboard_->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+ EXPECT_EQ(base::string16(), result);
+ EXPECT_EQ(before_call, test_clipboard_->GetLastModifiedTime());
+
+ // Since Reauth had failed password was not copied and metric wasn't recorded
+ histogram_tester().ExpectTotalCount(kHistogramName, 0);
+}
+
TEST_F(PasswordsPrivateDelegateImplTest, TestPassedReauthOnView) {
SetUpPasswordStore({CreateSampleForm()});
@@ -274,16 +400,21 @@ TEST_F(PasswordsPrivateDelegateImplTest, TestPassedReauthOnView) {
// |delegate| to be completed.
base::RunLoop().RunUntilIdle();
- bool reauth_called = false;
- delegate.SetOsReauthCallForTesting(base::BindRepeating(
- &FakeOsReauthCall, &reauth_called, ReauthResult::PASS));
+ MockReauthCallback callback;
+ delegate.set_os_reauth_call(callback.Get());
+
+ EXPECT_CALL(callback, Run(ReauthPurpose::VIEW_PASSWORD))
+ .WillOnce(Return(true));
- base::Optional<base::string16> plaintext_password;
- delegate.RequestShowPassword(0, GetCallbackArgument(&plaintext_password),
- nullptr);
- EXPECT_TRUE(reauth_called);
- EXPECT_TRUE(plaintext_password.has_value());
- EXPECT_EQ(base::ASCIIToUTF16("test"), *plaintext_password);
+ MockPlaintextPasswordCallback password_callback;
+ EXPECT_CALL(password_callback, Run(Eq(base::ASCIIToUTF16("test"))));
+ delegate.RequestPlaintextPassword(
+ 0, api::passwords_private::PLAINTEXT_REASON_VIEW, password_callback.Get(),
+ nullptr);
+
+ histogram_tester().ExpectUniqueSample(
+ kHistogramName, password_manager::metrics_util::ACCESS_PASSWORD_VIEWED,
+ 1);
}
TEST_F(PasswordsPrivateDelegateImplTest, TestFailedReauthOnView) {
@@ -294,15 +425,20 @@ TEST_F(PasswordsPrivateDelegateImplTest, TestFailedReauthOnView) {
// |delegate| to be completed.
base::RunLoop().RunUntilIdle();
- bool reauth_called = false;
- delegate.SetOsReauthCallForTesting(base::BindRepeating(
- &FakeOsReauthCall, &reauth_called, ReauthResult::FAIL));
+ MockReauthCallback callback;
+ delegate.set_os_reauth_call(callback.Get());
+
+ EXPECT_CALL(callback, Run(ReauthPurpose::VIEW_PASSWORD))
+ .WillOnce(Return(false));
+
+ MockPlaintextPasswordCallback password_callback;
+ EXPECT_CALL(password_callback, Run(Eq(base::nullopt)));
+ delegate.RequestPlaintextPassword(
+ 0, api::passwords_private::PLAINTEXT_REASON_VIEW, password_callback.Get(),
+ nullptr);
- base::Optional<base::string16> plaintext_password;
- delegate.RequestShowPassword(0, GetCallbackArgument(&plaintext_password),
- nullptr);
- EXPECT_TRUE(reauth_called);
- EXPECT_FALSE(plaintext_password.has_value());
+ // Since Reauth had failed password was not viewed and metric wasn't recorded
+ histogram_tester().ExpectTotalCount(kHistogramName, 0);
}
TEST_F(PasswordsPrivateDelegateImplTest, TestReauthOnExport) {
@@ -315,19 +451,17 @@ TEST_F(PasswordsPrivateDelegateImplTest, TestReauthOnExport) {
// |delegate| to be completed.
base::RunLoop().RunUntilIdle();
- bool reauth_called = false;
- delegate.SetOsReauthCallForTesting(base::BindRepeating(
- &FakeOsReauthCall, &reauth_called, ReauthResult::PASS));
+ MockReauthCallback callback;
+ delegate.set_os_reauth_call(callback.Get());
EXPECT_CALL(mock_accepted, Run(std::string())).Times(2);
+ EXPECT_CALL(callback, Run(ReauthPurpose::EXPORT)).WillOnce(Return(true));
delegate.ExportPasswords(mock_accepted.Get(), nullptr);
- EXPECT_TRUE(reauth_called);
// Export should ignore previous reauthentication results.
- reauth_called = false;
+ EXPECT_CALL(callback, Run(ReauthPurpose::EXPORT)).WillOnce(Return(true));
delegate.ExportPasswords(mock_accepted.Get(), nullptr);
- EXPECT_TRUE(reauth_called);
}
TEST_F(PasswordsPrivateDelegateImplTest, TestReauthFailedOnExport) {
@@ -342,12 +476,74 @@ TEST_F(PasswordsPrivateDelegateImplTest, TestReauthFailedOnExport) {
EXPECT_CALL(mock_accepted, Run(std::string("reauth-failed")));
- bool reauth_called = false;
- delegate.SetOsReauthCallForTesting(base::BindRepeating(
- &FakeOsReauthCall, &reauth_called, ReauthResult::FAIL));
+ MockReauthCallback callback;
+ delegate.set_os_reauth_call(callback.Get());
+ EXPECT_CALL(callback, Run(ReauthPurpose::EXPORT)).WillOnce(Return(false));
delegate.ExportPasswords(mock_accepted.Get(), nullptr);
- EXPECT_TRUE(reauth_called);
+}
+
+// Verifies that PasswordsPrivateDelegateImpl::GetPlaintextCompromisedPassword
+// fails if the re-auth fails.
+TEST_F(PasswordsPrivateDelegateImplTest,
+ TestReauthOnGetPlaintextCompromisedPasswordFails) {
+ PasswordsPrivateDelegateImpl delegate(&profile_);
+
+ MockReauthCallback reauth_callback;
+ delegate.set_os_reauth_call(reauth_callback.Get());
+
+ base::MockCallback<
+ PasswordsPrivateDelegate::PlaintextCompromisedPasswordCallback>
+ credential_callback;
+
+ EXPECT_CALL(reauth_callback, Run(ReauthPurpose::VIEW_PASSWORD))
+ .WillOnce(Return(false));
+ EXPECT_CALL(credential_callback, Run(Eq(base::nullopt)));
+
+ delegate.GetPlaintextCompromisedPassword(
+ api::passwords_private::CompromisedCredential(),
+ api::passwords_private::PLAINTEXT_REASON_VIEW, nullptr,
+ credential_callback.Get());
+}
+
+// Verifies that PasswordsPrivateDelegateImpl::GetPlaintextCompromisedPassword
+// succeeds if the re-auth succeeds and there is a matching compromised
+// credential in the store.
+TEST_F(PasswordsPrivateDelegateImplTest,
+ TestReauthOnGetPlaintextCompromisedPassword) {
+ PasswordsPrivateDelegateImpl delegate(&profile_);
+
+ autofill::PasswordForm form = CreateSampleForm();
+ password_manager::CompromisedCredentials compromised_credentials;
+ compromised_credentials.signon_realm = form.signon_realm;
+ compromised_credentials.username = form.username_value;
+ store_->AddLogin(form);
+ store_->AddCompromisedCredentials(compromised_credentials);
+ base::RunLoop().RunUntilIdle();
+
+ api::passwords_private::CompromisedCredential credential =
+ std::move(delegate.GetCompromisedCredentials().at(0));
+
+ MockReauthCallback reauth_callback;
+ delegate.set_os_reauth_call(reauth_callback.Get());
+
+ base::MockCallback<
+ PasswordsPrivateDelegate::PlaintextCompromisedPasswordCallback>
+ credential_callback;
+
+ base::Optional<api::passwords_private::CompromisedCredential> opt_credential;
+ EXPECT_CALL(reauth_callback, Run(ReauthPurpose::VIEW_PASSWORD))
+ .WillOnce(Return(true));
+ EXPECT_CALL(credential_callback, Run).WillOnce(MoveArg(&opt_credential));
+
+ delegate.GetPlaintextCompromisedPassword(
+ std::move(credential), api::passwords_private::PLAINTEXT_REASON_VIEW,
+ nullptr, credential_callback.Get());
+
+ ASSERT_TRUE(opt_credential.has_value());
+ EXPECT_EQ(form.signon_realm, opt_credential->signon_realm);
+ EXPECT_EQ(form.username_value, base::UTF8ToUTF16(opt_credential->username));
+ EXPECT_EQ(form.password_value, base::UTF8ToUTF16(*opt_credential->password));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
index d46ef24ed8f..1a0ee0ff01d 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.cc
@@ -17,14 +17,14 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/passwords_private.h"
#include "content/public/browser/browser_context.h"
+#include "extensions/browser/extension_event_histogram_value.h"
#include "url/gurl.h"
namespace extensions {
PasswordsPrivateEventRouter::PasswordsPrivateEventRouter(
content::BrowserContext* context)
- : context_(context),
- event_router_(nullptr) {
+ : context_(context), event_router_(nullptr) {
event_router_ = EventRouter::Get(context_);
}
@@ -86,6 +86,36 @@ void PasswordsPrivateEventRouter::OnPasswordsExportProgress(
event_router_->BroadcastEvent(std::move(extension_event));
}
+void PasswordsPrivateEventRouter::OnAccountStorageOptInStateChanged(
+ bool opted_in) {
+ auto extension_event = std::make_unique<Event>(
+ events::PASSWORDS_PRIVATE_ON_ACCOUNT_STORAGE_OPT_IN_STATE_CHANGED,
+ api::passwords_private::OnAccountStorageOptInStateChanged::kEventName,
+ api::passwords_private::OnAccountStorageOptInStateChanged::Create(
+ opted_in));
+ event_router_->BroadcastEvent(std::move(extension_event));
+}
+
+void PasswordsPrivateEventRouter::OnCompromisedCredentialsChanged(
+ std::vector<api::passwords_private::CompromisedCredential>
+ compromised_credentials) {
+ auto extension_event = std::make_unique<Event>(
+ events::PASSWORDS_PRIVATE_ON_COMPROMISED_CREDENTIALS_INFO_CHANGED,
+ api::passwords_private::OnCompromisedCredentialsChanged::kEventName,
+ api::passwords_private::OnCompromisedCredentialsChanged::Create(
+ compromised_credentials));
+ event_router_->BroadcastEvent(std::move(extension_event));
+}
+
+void PasswordsPrivateEventRouter::OnPasswordCheckStatusChanged(
+ const api::passwords_private::PasswordCheckStatus& status) {
+ auto extension_event = std::make_unique<Event>(
+ events::PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED,
+ api::passwords_private::OnPasswordCheckStatusChanged::kEventName,
+ api::passwords_private::OnPasswordCheckStatusChanged::Create(status));
+ event_router_->BroadcastEvent(std::move(extension_event));
+}
+
PasswordsPrivateEventRouter* PasswordsPrivateEventRouter::Create(
content::BrowserContext* context) {
return new PasswordsPrivateEventRouter(context);
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h
index d4de02e6798..26616470670 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h
@@ -53,6 +53,20 @@ class PasswordsPrivateEventRouter : public KeyedService {
api::passwords_private::ExportProgressStatus status,
const std::string& folder_name);
+ // Notifies listeners about a (possible) change to the opt-in state for the
+ // account-scoped password storage.
+ void OnAccountStorageOptInStateChanged(bool opted_in);
+
+ // Notifies listeners about a change to the information about compromised
+ // credentials.
+ void OnCompromisedCredentialsChanged(
+ std::vector<api::passwords_private::CompromisedCredential>
+ compromised_credentials);
+
+ // Notifies listeners about a change to the status of the password check.
+ void OnPasswordCheckStatusChanged(
+ const api::passwords_private::PasswordCheckStatus& status);
+
protected:
explicit PasswordsPrivateEventRouter(content::BrowserContext* context);
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc
index 1c84db6ff5c..d360af9b18e 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.cc
@@ -23,28 +23,4 @@ api::passwords_private::UrlCollection CreateUrlCollectionFromForm(
return urls;
}
-SortKeyIdGenerator::SortKeyIdGenerator() = default;
-
-SortKeyIdGenerator::~SortKeyIdGenerator() = default;
-
-int SortKeyIdGenerator::GenerateId(const std::string& sort_key) {
- auto result = sort_key_cache_.emplace(sort_key, next_id_);
- if (result.second) {
- // In case we haven't seen |sort_key| before, add a pointer to the inserted
- // key and the corresponding id to the |id_cache_|. This insertion should
- // always succeed.
- auto iter =
- id_cache_.emplace_hint(id_cache_.end(), next_id_, &result.first->first);
- DCHECK_EQ(&result.first->first, iter->second);
- ++next_id_;
- }
-
- return result.first->second;
-}
-
-const std::string* SortKeyIdGenerator::TryGetSortKey(int id) const {
- auto it = id_cache_.find(id);
- return it != id_cache_.end() ? it->second : nullptr;
-}
-
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h
index 7f6e814bc68..72bf657a445 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_PASSWORDS_PRIVATE_UTILS_H_
#define CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_PASSWORDS_PRIVATE_UTILS_H_
+#include <functional>
#include <map>
#include <string>
@@ -23,34 +24,52 @@ namespace extensions {
api::passwords_private::UrlCollection CreateUrlCollectionFromForm(
const autofill::PasswordForm& form);
-// This class serves as an identifier for strings created by CreateSortKey() in
-// the password_manager namespace. It is similar to base::IDMap, but also allows
-// to get the id for an already inserted element.
-// TODO(https://crbug.com/778146): This class should be an implementation detail
-// of PasswordManagerPresenter. Move this class there once Android uses a
-// similar logic.
-class SortKeyIdGenerator {
+// This class is an id generator for an arbitrary key type. It is used by both
+// PasswordManagerPresenter and PasswordCheckDelegate to create ids send to the
+// UI. It is similar to base::IDMap, but has the following important
+// differences:
+// - IdGenerator owns a copy of the key data, so that clients don't need to
+// worry about dangling pointers.
+// - Repeated calls to GenerateId with the same |key| are no-ops, and return the
+// same ids.
+template <typename KeyT,
+ typename IdT = int32_t,
+ typename KeyCompare = std::less<>>
+class IdGenerator {
public:
- SortKeyIdGenerator();
- ~SortKeyIdGenerator();
-
- // This method generates an id corresponding to |sort_key|. Additionally it
+ // This method generates an id corresponding to |key|. Additionally it
// remembers ids generated in the past, so that this method is idempotent.
// Furthermore, it is guaranteed that different ids are returned for different
- // |sort_key| arguments. This implies GenerateId(a) == GenerateId(b) if and
- // only if a == b.
- int GenerateId(const std::string& sort_key);
+ // |key| arguments. This implies GenerateId(a) == GenerateId(b) if and only if
+ // a == b.
+ IdT GenerateId(const KeyT& key) {
+ auto result = key_cache_.emplace(key, next_id_);
+ if (result.second) {
+ // In case we haven't seen |key| before, add a pointer to the inserted key
+ // and the corresponding id to the |id_cache_|. This insertion should
+ // always succeed.
+ auto iter = id_cache_.emplace_hint(id_cache_.end(), next_id_,
+ &result.first->first);
+ DCHECK_EQ(&result.first->first, iter->second);
+ ++next_id_;
+ }
+
+ return result.first->second;
+ }
- // This method tries to return the sort key corresponding to |id|. In case
- // |id| was not generated by GenerateId() before, this method returns nullptr.
- // Otherwise it returns a pointer s to a sort key, such that |id| ==
- // GenerateId(*s).
- const std::string* TryGetSortKey(int id) const;
+ // This method tries to return the key corresponding to |id|. In case |id| was
+ // not generated by GenerateId() before, this method returns nullptr.
+ // Otherwise it returns a pointer p to a key, such that |id| ==
+ // GenerateId(*p).
+ const KeyT* TryGetKey(IdT id) const {
+ auto it = id_cache_.find(id);
+ return it != id_cache_.end() ? it->second : nullptr;
+ }
private:
- std::map<std::string, int> sort_key_cache_;
- base::flat_map<int, const std::string*> id_cache_;
- int next_id_ = 0;
+ std::map<KeyT, IdT, KeyCompare> key_cache_;
+ base::flat_map<IdT, const KeyT*> id_cache_;
+ IdT next_id_ = 0;
};
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc
index 00517525a37..574cac203aa 100644
--- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_utils_unittest.cc
@@ -63,19 +63,19 @@ TEST(CreateUrlCollectionFromFormTest, UrlsFromAndroidFormWithAppName) {
android_urls.link);
}
-TEST(SortKeyIdGeneratorTest, GenerateIds) {
+TEST(IdGeneratorTest, GenerateIds) {
using ::testing::Pointee;
using ::testing::Eq;
- SortKeyIdGenerator id_generator;
+ IdGenerator<std::string> id_generator;
int foo_id = id_generator.GenerateId("foo");
// Check idempotence.
EXPECT_EQ(foo_id, id_generator.GenerateId("foo"));
- // Check TryGetSortKey(id) == s iff id == GenerateId(*s).
- EXPECT_THAT(id_generator.TryGetSortKey(foo_id), Pointee(Eq("foo")));
- EXPECT_EQ(nullptr, id_generator.TryGetSortKey(foo_id + 1));
+ // Check TryGetKey(id) == s iff id == GenerateId(*s).
+ EXPECT_THAT(id_generator.TryGetKey(foo_id), Pointee(Eq("foo")));
+ EXPECT_EQ(nullptr, id_generator.TryGetKey(foo_id + 1));
// Check that different sort keys result in different ids.
int bar_id = id_generator.GenerateId("bar");
@@ -83,8 +83,8 @@ TEST(SortKeyIdGeneratorTest, GenerateIds) {
EXPECT_NE(foo_id, bar_id);
EXPECT_NE(bar_id, baz_id);
- EXPECT_THAT(id_generator.TryGetSortKey(bar_id), Pointee(Eq("bar")));
- EXPECT_THAT(id_generator.TryGetSortKey(baz_id), Pointee(Eq("baz")));
+ EXPECT_THAT(id_generator.TryGetKey(bar_id), Pointee(Eq("bar")));
+ EXPECT_THAT(id_generator.TryGetKey(baz_id), Pointee(Eq("baz")));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc b/chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
new file mode 100644
index 00000000000..6f0005f6cf9
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.cc
@@ -0,0 +1,265 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h"
+
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h"
+#include "ui/base/l10n/time_format.h"
+
+namespace extensions {
+
+namespace {
+
+using ui::TimeFormat;
+
+constexpr size_t kNumMocks = 3;
+
+api::passwords_private::PasswordUiEntry CreateEntry(int id) {
+ api::passwords_private::PasswordUiEntry entry;
+ entry.urls.shown = "test" + base::NumberToString(id) + ".com";
+ entry.urls.origin = "http://" + entry.urls.shown + "/login";
+ entry.urls.link = entry.urls.origin;
+ entry.username = "testName" + base::NumberToString(id);
+ entry.id = id;
+ return entry;
+}
+
+api::passwords_private::ExceptionEntry CreateException(int id) {
+ api::passwords_private::ExceptionEntry exception;
+ exception.urls.shown = "exception" + base::NumberToString(id) + ".com";
+ exception.urls.origin = "http://" + exception.urls.shown + "/login";
+ exception.urls.link = exception.urls.origin;
+ exception.id = id;
+ return exception;
+}
+} // namespace
+
+TestPasswordsPrivateDelegate::TestPasswordsPrivateDelegate()
+ : profile_(nullptr) {
+ // Create mock data.
+ for (size_t i = 0; i < kNumMocks; i++) {
+ current_entries_.push_back(CreateEntry(i));
+ current_exceptions_.push_back(CreateException(i));
+ }
+}
+TestPasswordsPrivateDelegate::~TestPasswordsPrivateDelegate() = default;
+
+void TestPasswordsPrivateDelegate::GetSavedPasswordsList(
+ UiEntriesCallback callback) {
+ std::move(callback).Run(current_entries_);
+}
+
+void TestPasswordsPrivateDelegate::GetPasswordExceptionsList(
+ ExceptionEntriesCallback callback) {
+ std::move(callback).Run(current_exceptions_);
+}
+
+void TestPasswordsPrivateDelegate::ChangeSavedPassword(
+ int id,
+ base::string16 username,
+ base::Optional<base::string16> password) {
+ if (static_cast<size_t>(id) >= current_entries_.size())
+ return;
+
+ // PasswordUiEntry does not contain a password. Thus we are only updating
+ // the username and the length of the password.
+ current_entries_[id].username = base::UTF16ToUTF8(username);
+ SendSavedPasswordsList();
+}
+
+void TestPasswordsPrivateDelegate::RemoveSavedPassword(int id) {
+ if (current_entries_.empty())
+ return;
+
+ // Since this is just mock data, remove the first entry regardless of
+ // the data contained.
+ last_deleted_entry_ = std::move(current_entries_.front());
+ current_entries_.erase(current_entries_.begin());
+ SendSavedPasswordsList();
+}
+
+void TestPasswordsPrivateDelegate::RemovePasswordException(int id) {
+ // Since this is just mock data, remove the first entry regardless of
+ // the data contained.
+ last_deleted_exception_ = std::move(current_exceptions_.front());
+ current_exceptions_.erase(current_exceptions_.begin());
+ SendPasswordExceptionsList();
+}
+
+// Simplified version of undo logic, only use for testing.
+void TestPasswordsPrivateDelegate::UndoRemoveSavedPasswordOrException() {
+ if (last_deleted_entry_) {
+ current_entries_.insert(current_entries_.begin(),
+ std::move(*last_deleted_entry_));
+ last_deleted_entry_ = base::nullopt;
+ SendSavedPasswordsList();
+ } else if (last_deleted_exception_) {
+ current_exceptions_.insert(current_exceptions_.begin(),
+ std::move(*last_deleted_exception_));
+ last_deleted_exception_ = base::nullopt;
+ SendPasswordExceptionsList();
+ }
+}
+
+void TestPasswordsPrivateDelegate::RequestPlaintextPassword(
+ int id,
+ api::passwords_private::PlaintextReason reason,
+ PlaintextPasswordCallback callback,
+ content::WebContents* web_contents) {
+ // Return a mocked password value.
+ std::move(callback).Run(plaintext_password_);
+}
+
+void TestPasswordsPrivateDelegate::ImportPasswords(
+ content::WebContents* web_contents) {
+ // The testing of password importing itself should be handled via
+ // |PasswordManagerPorter|.
+ import_passwords_triggered_ = true;
+}
+
+void TestPasswordsPrivateDelegate::ExportPasswords(
+ base::OnceCallback<void(const std::string&)> callback,
+ content::WebContents* web_contents) {
+ // The testing of password exporting itself should be handled via
+ // |PasswordManagerPorter|.
+ export_passwords_triggered_ = true;
+ std::move(callback).Run(std::string());
+}
+
+void TestPasswordsPrivateDelegate::CancelExportPasswords() {
+ cancel_export_passwords_triggered_ = true;
+}
+
+api::passwords_private::ExportProgressStatus
+TestPasswordsPrivateDelegate::GetExportProgressStatus() {
+ // The testing of password exporting itself should be handled via
+ // |PasswordManagerPorter|.
+ return api::passwords_private::ExportProgressStatus::
+ EXPORT_PROGRESS_STATUS_IN_PROGRESS;
+}
+
+bool TestPasswordsPrivateDelegate::IsOptedInForAccountStorage() {
+ return is_opted_in_for_account_storage_;
+}
+
+void TestPasswordsPrivateDelegate::SetAccountStorageOptIn(
+ bool opt_in,
+ content::WebContents* web_contents) {
+ is_opted_in_for_account_storage_ = opt_in;
+}
+
+std::vector<api::passwords_private::CompromisedCredential>
+TestPasswordsPrivateDelegate::GetCompromisedCredentials() {
+ api::passwords_private::CompromisedCredential credential;
+ credential.username = "alice";
+ credential.formatted_origin = "example.com";
+ credential.detailed_origin = "https://example.com";
+ credential.is_android_credential = false;
+ credential.change_password_url =
+ std::make_unique<std::string>("https://example.com/change-password");
+ credential.compromise_type = api::passwords_private::COMPROMISE_TYPE_LEAKED;
+ credential.compromise_time = 1583236800000; // Mar 03 2020 12:00:00 UTC
+ credential.elapsed_time_since_compromise = base::UTF16ToUTF8(
+ TimeFormat::Simple(TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_LONG,
+ base::TimeDelta::FromDays(3)));
+
+ std::vector<api::passwords_private::CompromisedCredential> credentials;
+ credentials.push_back(std::move(credential));
+ return credentials;
+}
+
+void TestPasswordsPrivateDelegate::GetPlaintextCompromisedPassword(
+ api::passwords_private::CompromisedCredential credential,
+ api::passwords_private::PlaintextReason reason,
+ content::WebContents* web_contents,
+ PlaintextCompromisedPasswordCallback callback) {
+ // Return a mocked password value.
+ if (!plaintext_password_) {
+ std::move(callback).Run(base::nullopt);
+ return;
+ }
+
+ credential.password =
+ std::make_unique<std::string>(base::UTF16ToUTF8(*plaintext_password_));
+ std::move(callback).Run(std::move(credential));
+}
+
+// Fake implementation of ChangeCompromisedCredential. This succeeds if the
+// delegate knows of a compromised credential with the same id.
+bool TestPasswordsPrivateDelegate::ChangeCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential,
+ base::StringPiece new_password) {
+ return std::any_of(compromised_credentials_.begin(),
+ compromised_credentials_.end(),
+ [&credential](const auto& compromised_credential) {
+ return compromised_credential.id == credential.id;
+ });
+}
+
+// Fake implementation of RemoveCompromisedCredential. This succeeds if the
+// delegate knows of a compromised credential with the same id.
+bool TestPasswordsPrivateDelegate::RemoveCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential) {
+ return base::EraseIf(compromised_credentials_,
+ [&credential](const auto& compromised_credential) {
+ return compromised_credential.id == credential.id;
+ }) != 0;
+}
+
+void TestPasswordsPrivateDelegate::StartPasswordCheck(
+ StartPasswordCheckCallback callback) {
+ start_password_check_triggered_ = true;
+ std::move(callback).Run(start_password_check_state_);
+}
+
+void TestPasswordsPrivateDelegate::StopPasswordCheck() {
+ stop_password_check_triggered_ = true;
+}
+
+api::passwords_private::PasswordCheckStatus
+TestPasswordsPrivateDelegate::GetPasswordCheckStatus() {
+ api::passwords_private::PasswordCheckStatus status;
+ status.state = api::passwords_private::PASSWORD_CHECK_STATE_RUNNING;
+ status.already_processed = std::make_unique<int>(5);
+ status.remaining_in_queue = std::make_unique<int>(10);
+ status.elapsed_time_since_last_check =
+ std::make_unique<std::string>(base::UTF16ToUTF8(TimeFormat::Simple(
+ TimeFormat::FORMAT_ELAPSED, TimeFormat::LENGTH_SHORT,
+ base::TimeDelta::FromMinutes(5))));
+ return status;
+}
+
+void TestPasswordsPrivateDelegate::SetProfile(Profile* profile) {
+ profile_ = profile;
+}
+
+void TestPasswordsPrivateDelegate::SetOptedInForAccountStorage(bool opted_in) {
+ is_opted_in_for_account_storage_ = opted_in;
+}
+
+void TestPasswordsPrivateDelegate::AddCompromisedCredential(int id) {
+ api::passwords_private::CompromisedCredential cred;
+ cred.id = id;
+ compromised_credentials_.push_back(std::move(cred));
+}
+
+void TestPasswordsPrivateDelegate::SendSavedPasswordsList() {
+ PasswordsPrivateEventRouter* router =
+ PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
+ if (router)
+ router->OnSavedPasswordsListChanged(current_entries_);
+}
+
+void TestPasswordsPrivateDelegate::SendPasswordExceptionsList() {
+ PasswordsPrivateEventRouter* router =
+ PasswordsPrivateEventRouterFactory::GetForProfile(profile_);
+ if (router)
+ router->OnPasswordExceptionsListChanged(current_exceptions_);
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h b/chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h
new file mode 100644
index 00000000000..639c9092fc4
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h
@@ -0,0 +1,124 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_TEST_PASSWORDS_PRIVATE_DELEGATE_H_
+#define CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_TEST_PASSWORDS_PRIVATE_DELEGATE_H_
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
+#include "chrome/browser/profiles/profile.h"
+
+namespace extensions {
+// A test PasswordsPrivateDelegate implementation which uses mock data.
+// TestDelegate starts out with kNumMocks mocks of each type (saved password
+// and password exception) and removes one mock each time RemoveSavedPassword()
+// or RemovePasswordException() is called.
+class TestPasswordsPrivateDelegate : public PasswordsPrivateDelegate {
+ public:
+ TestPasswordsPrivateDelegate();
+ ~TestPasswordsPrivateDelegate() override;
+
+ // PasswordsPrivateDelegate implementation.
+ void GetSavedPasswordsList(UiEntriesCallback callback) override;
+ void GetPasswordExceptionsList(ExceptionEntriesCallback callback) override;
+ void ChangeSavedPassword(int id,
+ base::string16 username,
+ base::Optional<base::string16> password) override;
+ void RemoveSavedPassword(int id) override;
+ void RemovePasswordException(int id) override;
+ // Simplified version of undo logic, only use for testing.
+ void UndoRemoveSavedPasswordOrException() override;
+ void RequestPlaintextPassword(int id,
+ api::passwords_private::PlaintextReason reason,
+ PlaintextPasswordCallback callback,
+ content::WebContents* web_contents) override;
+ void ImportPasswords(content::WebContents* web_contents) override;
+ void ExportPasswords(base::OnceCallback<void(const std::string&)> callback,
+ content::WebContents* web_contents) override;
+ void CancelExportPasswords() override;
+ api::passwords_private::ExportProgressStatus GetExportProgressStatus()
+ override;
+ bool IsOptedInForAccountStorage() override;
+ void SetAccountStorageOptIn(bool opt_in,
+ content::WebContents* web_contents) override;
+ std::vector<api::passwords_private::CompromisedCredential>
+ GetCompromisedCredentials() override;
+ void GetPlaintextCompromisedPassword(
+ api::passwords_private::CompromisedCredential credential,
+ api::passwords_private::PlaintextReason reason,
+ content::WebContents* web_contents,
+ PlaintextCompromisedPasswordCallback callback) override;
+ // Fake implementation of ChangeCompromisedCredential. This succeeds if the
+ // delegate knows of a compromised credential with the same id.
+ bool ChangeCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential,
+ base::StringPiece new_password) override;
+ // Fake implementation of RemoveCompromisedCredential. This succeeds if the
+ // delegate knows of a compromised credential with the same id.
+ bool RemoveCompromisedCredential(
+ const api::passwords_private::CompromisedCredential& credential) override;
+ void StartPasswordCheck(StartPasswordCheckCallback callback) override;
+ void StopPasswordCheck() override;
+ api::passwords_private::PasswordCheckStatus GetPasswordCheckStatus() override;
+
+ void SetProfile(Profile* profile);
+ void SetOptedInForAccountStorage(bool opted_in);
+ void AddCompromisedCredential(int id);
+
+ void ClearSavedPasswordsList() { current_entries_.clear(); }
+ void ResetPlaintextPassword() { plaintext_password_.reset(); }
+ bool ImportPasswordsTriggered() const { return import_passwords_triggered_; }
+ bool ExportPasswordsTriggered() const { return export_passwords_triggered_; }
+ bool CancelExportPasswordsTriggered() const {
+ return cancel_export_passwords_triggered_;
+ }
+ bool StartPasswordCheckTriggered() const {
+ return start_password_check_triggered_;
+ }
+ bool StopPasswordCheckTriggered() const {
+ return stop_password_check_triggered_;
+ }
+ void SetStartPasswordCheckState(
+ password_manager::BulkLeakCheckService::State state) {
+ start_password_check_state_ = state;
+ }
+
+ private:
+ void SendSavedPasswordsList();
+ void SendPasswordExceptionsList();
+
+ // The current list of entries/exceptions. Cached here so that when new
+ // observers are added, this delegate can send the current lists without
+ // having to request them from |password_manager_presenter_| again.
+ std::vector<api::passwords_private::PasswordUiEntry> current_entries_;
+ std::vector<api::passwords_private::ExceptionEntry> current_exceptions_;
+ // Simplified version of a undo manager that only allows undoing and redoing
+ // the very last deletion.
+ base::Optional<api::passwords_private::PasswordUiEntry> last_deleted_entry_;
+ base::Optional<api::passwords_private::ExceptionEntry>
+ last_deleted_exception_;
+ base::Optional<base::string16> plaintext_password_ =
+ base::ASCIIToUTF16("plaintext");
+
+ // List of compromised credentials.
+ std::vector<api::passwords_private::CompromisedCredential>
+ compromised_credentials_;
+ Profile* profile_ = nullptr;
+
+ bool is_opted_in_for_account_storage_ = false;
+
+ // Flags for detecting whether import/export operations have been invoked.
+ bool import_passwords_triggered_ = false;
+ bool export_passwords_triggered_ = false;
+ bool cancel_export_passwords_triggered_ = false;
+
+ // Flags for detecting whether password check operations have been invoked.
+ bool start_password_check_triggered_ = false;
+ bool stop_password_check_triggered_ = false;
+ password_manager::BulkLeakCheckService::State start_password_check_state_ =
+ password_manager::BulkLeakCheckService::State::kRunning;
+};
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_PASSWORDS_PRIVATE_TEST_PASSWORDS_PRIVATE_DELEGATE_H_
diff --git a/chromium/chrome/browser/extensions/api/permissions/permissions_api.cc b/chromium/chrome/browser/extensions/api/permissions/permissions_api.cc
index 7065b38d303..26e2ef7a60c 100644
--- a/chromium/chrome/browser/extensions/api/permissions/permissions_api.cc
+++ b/chromium/chrome/browser/extensions/api/permissions/permissions_api.cc
@@ -35,8 +35,6 @@ const char kCantRemoveRequiredPermissionsError[] =
"You cannot remove required permissions.";
const char kNotInManifestPermissionsError[] =
"Only permissions specified in the manifest may be requested.";
-const char kCannotBeOptionalError[] =
- "The optional permissions API does not support '*'.";
const char kUserGestureRequiredError[] =
"This function must be called during a user gesture";
@@ -77,9 +75,6 @@ ExtensionFunction::ResponseAction PermissionsContainsFunction::Run() {
// |unpack_result| if there are any unlisted.
unpack_result->unlisted_apis.empty() &&
unpack_result->unlisted_hosts.is_empty() &&
- // Unsupported optional permissions can never be granted, so we know if
- // there are any specified, the extension doesn't actively have them.
- unpack_result->unsupported_optional_apis.empty() &&
// Restricted file scheme patterns cannot be active on the extension,
// since it doesn't have file access in that case.
unpack_result->restricted_file_scheme_patterns.is_empty() &&
@@ -136,12 +131,6 @@ ExtensionFunction::ResponseAction PermissionsRemoveFunction::Run() {
return RespondNow(Error(kNotInManifestPermissionsError));
}
- if (!unpack_result->unsupported_optional_apis.empty()) {
- return RespondNow(
- Error(kCannotBeOptionalError,
- (*unpack_result->unsupported_optional_apis.begin())->name()));
- }
-
// Make sure we only remove optional permissions, and not required
// permissions. Sadly, for some reason we support having a permission be both
// optional and required (and should assume its required), so we need both of
@@ -236,12 +225,6 @@ ExtensionFunction::ResponseAction PermissionsRequestFunction::Run() {
return RespondNow(Error(kNotInManifestPermissionsError));
}
- if (!unpack_result->unsupported_optional_apis.empty()) {
- return RespondNow(
- Error(kCannotBeOptionalError,
- (*unpack_result->unsupported_optional_apis.begin())->name()));
- }
-
if (!unpack_result->restricted_file_scheme_patterns.is_empty()) {
return RespondNow(Error(
"Extension must have file access enabled to request '*'.",
diff --git a/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc b/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
index 0b6e2cfcf0f..bb3f8668c89 100644
--- a/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
@@ -123,10 +123,10 @@ bool UnpackAPIPermissions(const std::vector<std::string>& permissions_input,
continue;
}
- if (!api_permission->info()->supports_optional()) {
- result->unsupported_optional_apis.insert(api_permission->Clone());
- continue;
- }
+ // Permissions that don't support being optional are filtered out during
+ // manifest parsing, so between that and filtering out APIs that aren't in
+ // the optional set, all of these should support being optional.
+ DCHECK(api_permission->info()->supports_optional());
result->optional_apis.insert(api_permission->Clone());
}
diff --git a/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.h b/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.h
index 34ad7649843..669c442bf4f 100644
--- a/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.h
+++ b/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers.h
@@ -42,9 +42,6 @@ struct UnpackPermissionSetResult {
// API permissions that are in the extension's "optional" permission set.
APIPermissionSet optional_apis;
- // API permissions that are in the extension's "optional" permission set,
- // but don't support the optional permissions API.
- APIPermissionSet unsupported_optional_apis;
// Explicit hosts that are in the extension's "optional" permission set.
URLPatternSet optional_explicit_hosts;
diff --git a/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc b/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
index 9d9bbd62be2..33b40869f15 100644
--- a/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/permissions/permissions_api_helpers_unittest.cc
@@ -309,30 +309,6 @@ TEST(ExtensionPermissionsAPIHelpers, Unpack_APISeparation) {
EXPECT_TRUE(unpack_result->unlisted_apis.count(kUnlisted1));
}
-// Tests that an error is thrown for permissions that cannot be optional, when
-// requested as an optional permission.
-TEST(ExtensionPermissionsAPIHelpers, Unpack_UnsupportedAPIPermission) {
- APIPermissionSet optional_apis;
- optional_apis.insert(APIPermission::kWallpaper);
- EXPECT_FALSE((*optional_apis.begin())->info()->supports_optional());
- PermissionSet optional_permissions(std::move(optional_apis),
- ManifestPermissionSet(), URLPatternSet(),
- URLPatternSet());
-
- Permissions permissions_object;
- permissions_object.permissions = std::make_unique<std::vector<std::string>>(
- std::vector<std::string>({"wallpaper"}));
-
- std::string error;
- std::unique_ptr<UnpackPermissionSetResult> unpack_result =
- UnpackPermissionSet(permissions_object, PermissionSet(),
- optional_permissions, true, &error);
- ASSERT_TRUE(unpack_result) << error;
- EXPECT_EQ(1u, unpack_result->unsupported_optional_apis.size());
- EXPECT_TRUE(unpack_result->unsupported_optional_apis.count(
- APIPermission::kWallpaper));
-}
-
// Tests that unpacking works correctly with wildcard schemes (which are
// interesting, because they only match http | https, and not all schemes).
TEST(ExtensionPermissionsAPIHelpers, Unpack_WildcardSchemes) {
diff --git a/chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc b/chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc
index 15317c485d4..ab8175a2b7e 100644
--- a/chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/permissions/permissions_apitest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/extensions/api/permissions/permissions_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_management_test_util.h"
@@ -68,13 +69,28 @@ IN_PROC_BROWSER_TEST_F(PermissionsApiTest, ExperimentalPermissionsFail) {
<< message_;
}
-IN_PROC_BROWSER_TEST_F(PermissionsApiTest, FaviconPermission) {
+// TODO(crbug/1065399): Flaky on ChromeOS and Linux non-dbg builds.
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(NDEBUG)
+#define MAYBE_FaviconPermission DISABLED_FaviconPermission
+#else
+#define MAYBE_FaviconPermission FaviconPermission
+#endif
+IN_PROC_BROWSER_TEST_F(PermissionsApiTest, MAYBE_FaviconPermission) {
+ base::HistogramTester tester;
ASSERT_TRUE(RunExtensionTest("permissions/favicon")) << message_;
+ tester.ExpectBucketCount("Extensions.FaviconResourceRequested",
+ Manifest::TYPE_EXTENSION, 1);
}
// Test functions and APIs that are always allowed (even if you ask for no
// permissions).
-IN_PROC_BROWSER_TEST_F(PermissionsApiTest, AlwaysAllowed) {
+// Flaky on MacOS (see crbug/1064929).
+#if defined(OS_MACOSX)
+#define MAYBE_AlwaysAllowed DISABLED_AlwaysAllowed
+#else
+#define MAYBE_AlwaysAllowed AlwaysAllowed
+#endif
+IN_PROC_BROWSER_TEST_F(PermissionsApiTest, MAYBE_AlwaysAllowed) {
ASSERT_TRUE(RunExtensionTest("permissions/always_allowed")) << message_;
}
@@ -201,7 +217,7 @@ IN_PROC_BROWSER_TEST_F(PermissionsApiTest, FileLoad) {
}
EXPECT_TRUE(RunExtensionTestWithFlagsAndArg(
"permissions/file_load", temp_dir.GetPath().MaybeAsASCII().c_str(),
- kFlagEnableFileAccess))
+ kFlagEnableFileAccess, kFlagNone))
<< message_;
{
base::ScopedAllowBlockingForTesting allow_blocking;
diff --git a/chromium/chrome/browser/extensions/api/platform_keys/OWNERS b/chromium/chrome/browser/extensions/api/platform_keys/OWNERS
index 325f7c3fcd6..6835e98ab3e 100644
--- a/chromium/chrome/browser/extensions/api/platform_keys/OWNERS
+++ b/chromium/chrome/browser/extensions/api/platform_keys/OWNERS
@@ -1 +1,3 @@
emaxx@chromium.org
+
+# COMPONENT: Enterprise
diff --git a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
index 08b30719bdd..be4e536005b 100644
--- a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
+++ b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
@@ -12,9 +12,9 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/values.h"
-#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
+#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h"
+#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service_factory.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
-#include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h"
#include "chrome/browser/extensions/api/platform_keys/verify_trust_api.h"
#include "chrome/common/extensions/api/platform_keys_internal.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
@@ -75,9 +75,7 @@ const struct NameValuePair {
const char* const name;
const int value;
} kCertStatusErrors[] = {
-#define CERT_STATUS_FLAG(name, value) \
- { #name, value } \
- ,
+#define CERT_STATUS_FLAG(name, value) {#name, value},
#include "net/cert/cert_status_flags_list.h"
#undef CERT_STATUS_FLAG
};
@@ -120,8 +118,7 @@ std::string PlatformKeysTokenIdToApiId(
} // namespace platform_keys
PlatformKeysInternalGetPublicKeyFunction::
- ~PlatformKeysInternalGetPublicKeyFunction() {
-}
+ ~PlatformKeysInternalGetPublicKeyFunction() {}
ExtensionFunction::ResponseAction
PlatformKeysInternalGetPublicKeyFunction::Run() {
@@ -170,8 +167,7 @@ PlatformKeysInternalGetPublicKeyFunction::Run() {
}
PlatformKeysInternalSelectClientCertificatesFunction::
- ~PlatformKeysInternalSelectClientCertificatesFunction() {
-}
+ ~PlatformKeysInternalSelectClientCertificatesFunction() {}
ExtensionFunction::ResponseAction
PlatformKeysInternalSelectClientCertificatesFunction::Run() {
@@ -179,8 +175,8 @@ PlatformKeysInternalSelectClientCertificatesFunction::Run() {
api_pki::SelectClientCertificates::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- chromeos::PlatformKeysService* service =
- chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
+ chromeos::ExtensionPlatformKeysService* service =
+ chromeos::ExtensionPlatformKeysServiceFactory::GetForBrowserContext(
browser_context());
DCHECK(service);
@@ -289,8 +285,7 @@ void PlatformKeysInternalSelectClientCertificatesFunction::
api_pki::SelectClientCertificates::Results::Create(result_matches)));
}
-PlatformKeysInternalSignFunction::~PlatformKeysInternalSignFunction() {
-}
+PlatformKeysInternalSignFunction::~PlatformKeysInternalSignFunction() {}
ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() {
std::unique_ptr<api_pki::Sign::Params> params(
@@ -303,12 +298,16 @@ ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() {
return RespondNow(Error(platform_keys::kErrorInvalidToken));
}
- chromeos::PlatformKeysService* service =
- chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
+ chromeos::ExtensionPlatformKeysService* service =
+ chromeos::ExtensionPlatformKeysServiceFactory::GetForBrowserContext(
browser_context());
DCHECK(service);
if (params->hash_algorithm_name == "none") {
+ // Signing without digesting is only supported for RSASSA-PKCS1-v1_5.
+ if (params->algorithm_name != "RSASSA-PKCS1-v1_5")
+ return RespondNow(Error(kErrorAlgorithmNotSupported));
+
service->SignRSAPKCS1Raw(
platform_keys_token_id,
std::string(params->data.begin(), params->data.end()),
@@ -328,11 +327,21 @@ ExtensionFunction::ResponseAction PlatformKeysInternalSignFunction::Run() {
} else {
return RespondNow(Error(kErrorAlgorithmNotSupported));
}
- service->SignRSAPKCS1Digest(
+
+ chromeos::platform_keys::KeyType key_type;
+ if (params->algorithm_name == "RSASSA-PKCS1-v1_5") {
+ key_type = chromeos::platform_keys::KeyType::kRsassaPkcs1V15;
+ } else if (params->algorithm_name == "ECDSA") {
+ key_type = chromeos::platform_keys::KeyType::kEcdsa;
+ } else {
+ return RespondNow(Error(kErrorAlgorithmNotSupported));
+ }
+
+ service->SignDigest(
platform_keys_token_id,
std::string(params->data.begin(), params->data.end()),
std::string(params->public_key.begin(), params->public_key.end()),
- hash_algorithm, extension_id(),
+ key_type, hash_algorithm, extension_id(),
base::Bind(&PlatformKeysInternalSignFunction::OnSigned, this));
}
@@ -352,8 +361,7 @@ void PlatformKeysInternalSignFunction::OnSigned(
}
PlatformKeysVerifyTLSServerCertificateFunction::
- ~PlatformKeysVerifyTLSServerCertificateFunction() {
-}
+ ~PlatformKeysVerifyTLSServerCertificateFunction() {}
ExtensionFunction::ResponseAction
PlatformKeysVerifyTLSServerCertificateFunction::Run() {
diff --git a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
index 2ae65f5c0f0..c90bee00d95 100644
--- a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
+++ b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc
@@ -13,8 +13,8 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
-#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
-#include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h"
+#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service.h"
+#include "chrome/browser/chromeos/platform_keys/extension_platform_keys_service_factory.h"
#include "chrome/browser/extensions/api/platform_keys/platform_keys_test_base.h"
#include "chrome/browser/net/nss_context.h"
#include "chrome/browser/policy/profile_policy_connector.h"
@@ -105,8 +105,8 @@ class PlatformKeysTest : public PlatformKeysTestBase {
mock_policy_provider()->UpdateChromePolicy(policy);
}
- chromeos::PlatformKeysService* GetPlatformKeysService() {
- return chromeos::PlatformKeysServiceFactory::GetForBrowserContext(
+ chromeos::ExtensionPlatformKeysService* GetExtensionPlatformKeysService() {
+ return chromeos::ExtensionPlatformKeysServiceFactory::GetForBrowserContext(
profile());
}
@@ -223,7 +223,7 @@ class PlatformKeysTest : public PlatformKeysTestBase {
};
class TestSelectDelegate
- : public chromeos::PlatformKeysService::SelectDelegate {
+ : public chromeos::ExtensionPlatformKeysService::SelectDelegate {
public:
// On each Select call, selects the next entry in |certs_to_select| from back
// to front. Once the first entry is reached, that one will be selected
@@ -332,7 +332,7 @@ IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest, Basic) {
certs.push_back(client_cert2_);
certs.push_back(client_cert1_);
- GetPlatformKeysService()->SetSelectDelegate(
+ GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(certs));
ASSERT_TRUE(RunExtensionTest("basicTests")) << message_;
@@ -348,7 +348,7 @@ IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest, Permissions) {
net::CertificateList certs;
certs.push_back(client_cert1_);
- GetPlatformKeysService()->SetSelectDelegate(
+ GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(certs));
ASSERT_TRUE(RunExtensionTest("permissionTests")) << message_;
@@ -379,7 +379,7 @@ IN_PROC_BROWSER_TEST_P(ManagedWithoutPermissionPlatformKeysTest,
UserPermissionsBlocked) {
// To verify that the user is not prompted for any certificate selection,
// set up a delegate that fails on any invocation.
- GetPlatformKeysService()->SetSelectDelegate(
+ GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(net::CertificateList()));
ASSERT_TRUE(RunExtensionTest("managedProfile")) << message_;
@@ -397,7 +397,7 @@ IN_PROC_BROWSER_TEST_P(ManagedWithoutPermissionPlatformKeysTest,
// To verify that the user is not prompted for any certificate selection,
// set up a delegate that fails on any invocation.
- GetPlatformKeysService()->SetSelectDelegate(
+ GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(net::CertificateList()));
ASSERT_TRUE(RunExtensionTest("corporateKeyWithoutPermissionTests"))
@@ -432,7 +432,7 @@ IN_PROC_BROWSER_TEST_P(ManagedWithPermissionPlatformKeysTest,
net::CertificateList certs;
certs.push_back(client_cert1_);
- GetPlatformKeysService()->SetSelectDelegate(
+ GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(certs));
ASSERT_TRUE(RunExtensionTest("corporateKeyWithPermissionTests")) << message_;
@@ -456,7 +456,7 @@ IN_PROC_BROWSER_TEST_P(ManagedWithPermissionPlatformKeysTest,
if (user_status() == UserStatus::MANAGED_AFFILIATED_DOMAIN)
certs.push_back(nullptr);
- GetPlatformKeysService()->SetSelectDelegate(
+ GetExtensionPlatformKeysService()->SetSelectDelegate(
std::make_unique<TestSelectDelegate>(certs));
ASSERT_TRUE(RunExtensionTest("policyDoesGrantAccessToNonCorporateKey"))
diff --git a/chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc b/chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc
index 3fa500422e4..6f382e521ba 100644
--- a/chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc
+++ b/chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc
@@ -6,6 +6,7 @@
#include <algorithm>
#include <memory>
+#include <utility>
#include "base/bind.h"
#include "base/lazy_instance.h"
@@ -115,7 +116,7 @@ void VerifyTrustAPI::Verify(std::unique_ptr<Params> params,
base::PostTask(
FROM_HERE, {content::BrowserThread::IO},
base::BindOnce(&IOPart::Verify, base::Unretained(io_part_.get()),
- base::Passed(&params), extension_id, finish_callback));
+ std::move(params), extension_id, finish_callback));
}
void VerifyTrustAPI::OnExtensionUnloaded(
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_api.cc b/chromium/chrome/browser/extensions/api/preference/preference_api.cc
index f961cdda093..1d45aa27f99 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_api.cc
+++ b/chromium/chrome/browser/extensions/api/preference/preference_api.cc
@@ -25,12 +25,14 @@
#include "chrome/browser/net/prediction_options.h"
#include "chrome/common/pref_names.h"
#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
+#include "components/embedder_support/pref_names.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/proxy_config/proxy_config_pref_names.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/spellcheck/browser/pref_names.h"
#include "components/translate/core/browser/translate_pref_names.h"
#include "extensions/browser/extension_pref_value_map.h"
@@ -41,6 +43,7 @@
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/error_utils.h"
+#include "extensions/common/extension_id.h"
#include "extensions/common/permissions/api_permission.h"
#include "extensions/common/permissions/permissions_data.h"
#include "media/media_buildflags.h"
@@ -88,8 +91,9 @@ const PrefMappingEntry kPrefMapping[] = {
{"data_usage_reporting.enabled",
data_reduction_proxy::prefs::kDataUsageReportingEnabled,
APIPermission::kDataReductionProxy, APIPermission::kDataReductionProxy},
- {"alternateErrorPagesEnabled", prefs::kAlternateErrorPagesEnabled,
- APIPermission::kPrivacy, APIPermission::kPrivacy},
+ {"alternateErrorPagesEnabled",
+ embedder_support::kAlternateErrorPagesEnabled, APIPermission::kPrivacy,
+ APIPermission::kPrivacy},
{"autofillEnabled", autofill::prefs::kAutofillEnabledDeprecated,
APIPermission::kPrivacy, APIPermission::kPrivacy},
{"autofillAddressEnabled", autofill::prefs::kAutofillProfileEnabled,
@@ -145,6 +149,15 @@ const PrefMappingEntry kPrefMapping[] = {
{"autoclick", ash::prefs::kAccessibilityAutoclickEnabled,
APIPermission::kAccessibilityFeaturesRead,
APIPermission::kAccessibilityFeaturesModify},
+ {"caretHighlight", ash::prefs::kAccessibilityCaretHighlightEnabled,
+ APIPermission::kAccessibilityFeaturesRead,
+ APIPermission::kAccessibilityFeaturesModify},
+ {"cursorHighlight", ash::prefs::kAccessibilityCursorHighlightEnabled,
+ APIPermission::kAccessibilityFeaturesRead,
+ APIPermission::kAccessibilityFeaturesModify},
+ {"focusHighlight", ash::prefs::kAccessibilityFocusHighlightEnabled,
+ APIPermission::kAccessibilityFeaturesRead,
+ APIPermission::kAccessibilityFeaturesModify},
{"highContrast", ash::prefs::kAccessibilityHighContrastEnabled,
APIPermission::kAccessibilityFeaturesRead,
APIPermission::kAccessibilityFeaturesModify},
@@ -163,6 +176,9 @@ const PrefMappingEntry kPrefMapping[] = {
{"stickyKeys", ash::prefs::kAccessibilityStickyKeysEnabled,
APIPermission::kAccessibilityFeaturesRead,
APIPermission::kAccessibilityFeaturesModify},
+ {"switchAccess", ash::prefs::kAccessibilitySwitchAccessEnabled,
+ APIPermission::kAccessibilityFeaturesRead,
+ APIPermission::kAccessibilityFeaturesModify},
{"virtualKeyboard", ash::prefs::kAccessibilityVirtualKeyboardEnabled,
APIPermission::kAccessibilityFeaturesRead,
APIPermission::kAccessibilityFeaturesModify},
@@ -790,6 +806,35 @@ ExtensionFunction::ResponseAction SetPreferenceFunction::Run() {
base::Value(browser_pref_value->GetBool()));
}
+ // Whenever an extension takes control of the |kSafeBrowsingEnabled|
+ // preference, it must also set |kSafeBrowsingEnhanced| to false.
+ // See crbug.com/1064722 for more background.
+ //
+ // TODO(crbug.com/1064722): Consider extending
+ // chrome.privacy.services.safeBrowsingEnabled to a three-state enum.
+ if (prefs::kSafeBrowsingEnabled == browser_pref) {
+ preference_api->SetExtensionControlledPref(extension_id(),
+ prefs::kSafeBrowsingEnhanced,
+ scope, base::Value(false));
+ }
+
+ // Whenever an extension takes control of the |kBlockThirdPartyCookies|
+ // preference, we must also set |kCookieControlsMode|.
+ // See crbug.com/1065392 for more background.
+ //
+ // kCookieControlsMode offers an additional setting to only block third-party
+ // cookies in incognito mode that can't be selected by extensions.
+ // Instead they can use the preference api in incognito mode directly if they
+ // are permitted to run there.
+ if (browser_pref == prefs::kBlockThirdPartyCookies) {
+ preference_api->SetExtensionControlledPref(
+ extension_id(), prefs::kCookieControlsMode, scope,
+ base::Value(static_cast<int>(
+ browser_pref_value->GetBool()
+ ? content_settings::CookieControlsMode::kOn
+ : content_settings::CookieControlsMode::kOff)));
+ }
+
preference_api->SetExtensionControlledPref(
extension_id(), browser_pref, scope,
base::Value::FromUniquePtrValue(std::move(browser_pref_value)));
@@ -840,8 +885,30 @@ ExtensionFunction::ResponseAction ClearPreferenceFunction::Run() {
Error(extensions::preference_api_constants::kPermissionErrorMessage,
pref_key));
+ // Whenever an extension clears the |kBlockThirdPartyCookies| preference,
+ // it must also clear |kCookieControlsMode|.
+ // See crbug.com/1065392 for more background.
+ if (browser_pref == prefs::kBlockThirdPartyCookies) {
+ PreferenceAPI::Get(browser_context())
+ ->RemoveExtensionControlledPref(extension_id(),
+ prefs::kCookieControlsMode, scope);
+ }
+
PreferenceAPI::Get(browser_context())
->RemoveExtensionControlledPref(extension_id(), browser_pref, scope);
+
+ // Whenever an extension clears the |kSafeBrowsingEnabled| preference,
+ // it must also clear |kSafeBrowsingEnhanced|. See crbug.com/1064722 for
+ // more background.
+ //
+ // TODO(crbug.com/1064722): Consider extending
+ // chrome.privacy.services.safeBrowsingEnabled to a three-state enum.
+ if (prefs::kSafeBrowsingEnabled == browser_pref) {
+ PreferenceAPI::Get(browser_context())
+ ->RemoveExtensionControlledPref(extension_id(),
+ prefs::kSafeBrowsingEnhanced, scope);
+ }
+
return RespondNow(NoArguments());
}
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_api.h b/chromium/chrome/browser/extensions/api/preference/preference_api.h
index fbb632013c7..010826176af 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_api.h
+++ b/chromium/chrome/browser/extensions/api/preference/preference_api.h
@@ -12,12 +12,12 @@
#include "base/memory/ref_counted.h"
#include "base/scoped_observer.h"
#include "chrome/browser/extensions/api/content_settings/content_settings_store.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_observer.h"
#include "components/prefs/pref_change_registrar.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_prefs_scope.h"
class ExtensionPrefValueMap;
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc b/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc
index a347e5d47b0..69144a56811 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -21,12 +21,15 @@
#include "chrome/common/pref_names.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/content_settings/core/common/features.h"
#include "components/content_settings/core/common/pref_names.h"
+#include "components/embedder_support/pref_names.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/prefs/pref_service.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/translate/core/browser/translate_pref_names.h"
#include "content/public/browser/notification_service.h"
#include "extensions/browser/extension_registry.h"
@@ -46,7 +49,8 @@ class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
prefs::kBlockThirdPartyCookies);
ASSERT_TRUE(pref);
EXPECT_TRUE(pref->IsExtensionControlled());
- EXPECT_TRUE(prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled));
+ EXPECT_TRUE(
+ prefs->GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
EXPECT_TRUE(prefs->GetBoolean(autofill::prefs::kAutofillEnabledDeprecated));
EXPECT_TRUE(prefs->GetBoolean(autofill::prefs::kAutofillCreditCardEnabled));
EXPECT_TRUE(prefs->GetBoolean(autofill::prefs::kAutofillProfileEnabled));
@@ -68,7 +72,8 @@ class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
prefs::kBlockThirdPartyCookies);
ASSERT_TRUE(pref);
EXPECT_FALSE(pref->IsExtensionControlled());
- EXPECT_FALSE(prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled));
+ EXPECT_FALSE(
+ prefs->GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
EXPECT_FALSE(
prefs->GetBoolean(autofill::prefs::kAutofillEnabledDeprecated));
EXPECT_FALSE(
@@ -86,6 +91,30 @@ class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
EXPECT_FALSE(prefs->GetBoolean(prefs::kSearchSuggestEnabled));
}
+ // Verifies whether the boolean |preference| has the |expected_value| and is
+ // |expected_controlled| by an extension.
+
+ void VerifyPrefValueAndControlledState(const std::string& preference,
+ const base::Value& expected_value,
+ bool expected_controlled) {
+ SCOPED_TRACE(preference);
+
+ PrefService* prefs = profile_->GetPrefs();
+ const PrefService::Preference* pref = prefs->FindPreference(preference);
+ ASSERT_TRUE(pref);
+ const base::Value* actual_value = pref->GetValue();
+ EXPECT_EQ(expected_value.type(), actual_value->type());
+
+ EXPECT_EQ(expected_value, *actual_value);
+ EXPECT_EQ(expected_controlled, pref->IsExtensionControlled());
+ }
+
+ void SetUp() override {
+ extensions::ExtensionApiTest::SetUp();
+ feature_list.InitAndEnableFeature(
+ content_settings::kImprovedCookieControls);
+ }
+
void SetUpOnMainThread() override {
extensions::ExtensionApiTest::SetUpOnMainThread();
@@ -111,6 +140,7 @@ class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
extensions::ExtensionApiTest::TearDownOnMainThread();
}
+ base::test::ScopedFeatureList feature_list;
Profile* profile_;
std::unique_ptr<ScopedKeepAlive> keep_alive_;
};
@@ -123,7 +153,7 @@ class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
#endif
IN_PROC_BROWSER_TEST_F(ExtensionPreferenceApiTest, MAYBE_Standard) {
PrefService* prefs = profile_->GetPrefs();
- prefs->SetBoolean(prefs::kAlternateErrorPagesEnabled, false);
+ prefs->SetBoolean(embedder_support::kAlternateErrorPagesEnabled, false);
prefs->SetBoolean(autofill::prefs::kAutofillEnabledDeprecated, false);
prefs->SetBoolean(autofill::prefs::kAutofillCreditCardEnabled, false);
prefs->SetBoolean(autofill::prefs::kAutofillProfileEnabled, false);
@@ -405,3 +435,141 @@ IN_PROC_BROWSER_TEST_F(ExtensionPreferenceApiTest, DataReductionProxy) {
EXPECT_TRUE(RunExtensionTest("preference/data_reduction_proxy")) <<
message_;
}
+
+// Tests the behavior of the Safe Browsing API as described in
+// crbug.com/1064722.
+IN_PROC_BROWSER_TEST_F(ExtensionPreferenceApiTest, SafeBrowsing_SetTrue) {
+ ExtensionTestMessageListener listener_true("set to true",
+ /* will_reply */ true);
+ ExtensionTestMessageListener listener_clear("cleared", /* will_reply */ true);
+ ExtensionTestMessageListener listener_false("set to false",
+ /* will_reply */ true);
+ ExtensionTestMessageListener listener_done("done", /* will_reply */ false);
+
+ const base::FilePath extension_path =
+ test_data_dir_.AppendASCII("preference").AppendASCII("safe_browsing");
+ const extensions::Extension* extension = LoadExtension(extension_path);
+ ASSERT_TRUE(extension);
+
+ // Step 1. of the test sets the API to TRUE.
+ // Both preferences are now controlled by extension. |kSafeBrowsingEnabled| is
+ // set to TRUE, while |kSafeBrowsingEnhanced| is always FALSE.
+ ASSERT_TRUE(listener_true.WaitUntilSatisfied());
+ VerifyPrefValueAndControlledState(prefs::kSafeBrowsingEnabled,
+ base::Value(true),
+ /* expected_controlled */ true);
+ VerifyPrefValueAndControlledState(prefs::kSafeBrowsingEnhanced,
+ base::Value(false),
+ /* expected_controlled */ true);
+ listener_true.Reply("ok");
+
+ // Step 2. of the test clears the value.
+ // Neither preference is now controlled by extension, and they take on their
+ // default values - TRUE and FALSE, respectively.
+ ASSERT_TRUE(listener_clear.WaitUntilSatisfied());
+ VerifyPrefValueAndControlledState(prefs::kSafeBrowsingEnabled,
+ base::Value(true),
+ /* expected_controlled */ false);
+ VerifyPrefValueAndControlledState(prefs::kSafeBrowsingEnhanced,
+ base::Value(false),
+ /* expected_controlled */ false);
+ listener_clear.Reply("ok");
+
+ // Step 3. of the test sets the API to FALSE.
+ // Both preferences are now controlled by extension. |kSafeBrowsingEnabled| is
+ // set to FALSE, and |kSafeBrowsingEnhanced| is also FALSE.
+ ASSERT_TRUE(listener_false.WaitUntilSatisfied());
+ VerifyPrefValueAndControlledState(prefs::kSafeBrowsingEnabled,
+ base::Value(false),
+ /* expected_controlled */ true);
+ VerifyPrefValueAndControlledState(prefs::kSafeBrowsingEnhanced,
+ base::Value(false),
+ /* expected_controlled */ true);
+ listener_false.Reply("ok");
+
+ // Step 4. of the test uninstalls the extension.
+ // Neither preference is now controlled by extension, and they take on their
+ // default values - TRUE and FALSE, respectively.
+ ASSERT_TRUE(listener_done.WaitUntilSatisfied());
+ UninstallExtension(extension->id());
+ VerifyPrefValueAndControlledState(prefs::kSafeBrowsingEnabled,
+ base::Value(true),
+ /* expected_controlled */ false);
+ VerifyPrefValueAndControlledState(prefs::kSafeBrowsingEnhanced,
+ base::Value(false),
+ /* expected_controlled */ false);
+}
+
+// Tests the behavior of the ThirdPartyCookies preference API.
+// kCookieControlsMode should be enforced to kOn/kOff if kBlockThirdPartyCookies
+// is set to true/false by an extension.
+IN_PROC_BROWSER_TEST_F(ExtensionPreferenceApiTest, ThirdPartyCookiesAllowed) {
+ ExtensionTestMessageListener listener_true("set to true",
+ /* will_reply */ true);
+ ExtensionTestMessageListener listener_clear("cleared", /* will_reply */ true);
+ ExtensionTestMessageListener listener_false("set to false",
+ /* will_reply */ true);
+ ExtensionTestMessageListener listener_done("done", /* will_reply */ false);
+
+ // Verify initial state.
+ VerifyPrefValueAndControlledState(prefs::kBlockThirdPartyCookies,
+ base::Value(false),
+ /* expected_controlled */ false);
+ VerifyPrefValueAndControlledState(
+ prefs::kCookieControlsMode,
+ base::Value(static_cast<int>(
+ content_settings::CookieControlsMode::kIncognitoOnly)),
+ /* expected_controlled */ false);
+
+ const base::FilePath extension_path =
+ test_data_dir_.AppendASCII("preference")
+ .AppendASCII("third_party_cookies_allowed");
+ const extensions::Extension* extension = LoadExtension(extension_path);
+ ASSERT_TRUE(extension);
+
+ // Step 1. of the test sets the API to TRUE.
+ ASSERT_TRUE(listener_true.WaitUntilSatisfied());
+ VerifyPrefValueAndControlledState(prefs::kBlockThirdPartyCookies,
+ base::Value(false),
+ /* expected_controlled */ true);
+ VerifyPrefValueAndControlledState(
+ prefs::kCookieControlsMode,
+ base::Value(static_cast<int>(content_settings::CookieControlsMode::kOff)),
+ /* expected_controlled */ true);
+ listener_true.Reply("ok");
+
+ // Step 2. of the test clears the value.
+ ASSERT_TRUE(listener_clear.WaitUntilSatisfied());
+ VerifyPrefValueAndControlledState(prefs::kBlockThirdPartyCookies,
+ base::Value(false),
+ /* expected_controlled */ false);
+ VerifyPrefValueAndControlledState(
+ prefs::kCookieControlsMode,
+ base::Value(static_cast<int>(
+ content_settings::CookieControlsMode::kIncognitoOnly)),
+ /* expected_controlled */ false);
+ listener_clear.Reply("ok");
+
+ // Step 3. of the test sets the API to FALSE.
+ ASSERT_TRUE(listener_false.WaitUntilSatisfied());
+ VerifyPrefValueAndControlledState(prefs::kBlockThirdPartyCookies,
+ base::Value(true),
+ /* expected_controlled */ true);
+ VerifyPrefValueAndControlledState(
+ prefs::kCookieControlsMode,
+ base::Value(static_cast<int>(content_settings::CookieControlsMode::kOn)),
+ /* expected_controlled */ true);
+ listener_false.Reply("ok");
+
+ // Step 4. of the test uninstalls the extension.
+ ASSERT_TRUE(listener_done.WaitUntilSatisfied());
+ UninstallExtension(extension->id());
+ VerifyPrefValueAndControlledState(prefs::kBlockThirdPartyCookies,
+ base::Value(false),
+ /* expected_controlled */ false);
+ VerifyPrefValueAndControlledState(
+ prefs::kCookieControlsMode,
+ base::Value(static_cast<int>(
+ content_settings::CookieControlsMode::kIncognitoOnly)),
+ /* expected_controlled */ false);
+}
diff --git a/chromium/chrome/browser/extensions/api/processes/processes_api.cc b/chromium/chrome/browser/extensions/api/processes/processes_api.cc
index a56649cbead..bd0417665c3 100644
--- a/chromium/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chromium/chrome/browser/extensions/api/processes/processes_api.cc
@@ -87,12 +87,15 @@ api::processes::ProcessType GetProcessType(
case task_manager::Task::PLUGIN:
return api::processes::PROCESS_TYPE_PLUGIN;
- case task_manager::Task::WORKER:
- return api::processes::PROCESS_TYPE_WORKER;
-
case task_manager::Task::NACL:
return api::processes::PROCESS_TYPE_NACL;
+ // TODO(https://crbug.com/1048715): Assign a different process type for each
+ // worker type.
+ case task_manager::Task::DEDICATED_WORKER:
+ case task_manager::Task::SHARED_WORKER:
+ return api::processes::PROCESS_TYPE_WORKER;
+
case task_manager::Task::SERVICE_WORKER:
return api::processes::PROCESS_TYPE_SERVICE_WORKER;
@@ -149,24 +152,24 @@ void FillProcessData(
if (!include_optional)
return;
- out_process->cpu.reset(
- new double(task_manager->GetPlatformIndependentCPUUsage(id)));
- out_process->network.reset(new double(static_cast<double>(
- task_manager->GetProcessTotalNetworkUsage(id))));
+ const double cpu_usage = task_manager->GetPlatformIndependentCPUUsage(id);
+ if (!std::isnan(cpu_usage))
+ out_process->cpu = std::make_unique<double>(cpu_usage);
+
+ const int64_t network_usage = task_manager->GetProcessTotalNetworkUsage(id);
+ if (network_usage != -1)
+ out_process->network = std::make_unique<double>(network_usage);
int64_t v8_allocated = 0;
int64_t v8_used = 0;
if (task_manager->GetV8Memory(id, &v8_allocated, &v8_used)) {
- out_process->js_memory_allocated.reset(new double(static_cast<double>(
- v8_allocated)));
- out_process->js_memory_used.reset(new double(static_cast<double>(v8_used)));
+ out_process->js_memory_allocated = std::make_unique<double>(v8_allocated);
+ out_process->js_memory_used = std::make_unique<double>(v8_used);
}
const int64_t sqlite_bytes = task_manager->GetSqliteMemoryUsed(id);
- if (sqlite_bytes != -1) {
- out_process->sqlite_memory.reset(new double(static_cast<double>(
- sqlite_bytes)));
- }
+ if (sqlite_bytes != -1)
+ out_process->sqlite_memory = std::make_unique<double>(sqlite_bytes);
blink::WebCacheResourceTypeStats cache_stats;
if (task_manager->GetWebCacheStats(id, &cache_stats)) {
@@ -511,9 +514,9 @@ ExtensionFunction::ResponseAction ProcessesTerminateFunction::Run() {
// IO thread.
base::PostTaskAndReplyWithResult(
FROM_HERE, {content::BrowserThread::IO},
- base::Bind(&ProcessesTerminateFunction::GetProcessHandleOnIO, this,
- child_process_host_id_),
- base::Bind(&ProcessesTerminateFunction::OnProcessHandleOnUI, this));
+ base::BindOnce(&ProcessesTerminateFunction::GetProcessHandleOnIO, this,
+ child_process_host_id_),
+ base::BindOnce(&ProcessesTerminateFunction::OnProcessHandleOnUI, this));
// Promise to respond later.
return RespondLater();
diff --git a/chromium/chrome/browser/extensions/api/resources_private/resources_private_api.cc b/chromium/chrome/browser/extensions/api/resources_private/resources_private_api.cc
index 3f4c2698942..24faa7952af 100644
--- a/chromium/chrome/browser/extensions/api/resources_private/resources_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/resources_private/resources_private_api.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/api/resources_private/resources_private_api.h"
+#include <memory>
#include <string>
#include <utility>
@@ -13,6 +14,7 @@
#include "chrome/common/extensions/api/resources_private.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
+#include "components/zoom/page_zoom_constants.h"
#include "pdf/buildflags.h"
#include "printing/buildflags/buildflags.h"
#include "ui/base/l10n/l10n_util.h"
@@ -41,6 +43,7 @@ void AddStringsForIdentity(base::DictionaryValue* dict) {
}
void AddStringsForPdf(base::DictionaryValue* dict) {
+#if BUILDFLAG(ENABLE_PDF)
static constexpr webui::LocalizedString kPdfResources[] = {
{"passwordDialogTitle", IDS_PDF_PASSWORD_DIALOG_TITLE},
{"passwordPrompt", IDS_PDF_NEED_PASSWORD},
@@ -57,6 +60,8 @@ void AddStringsForPdf(base::DictionaryValue* dict) {
{"tooltipPrint", IDS_PDF_TOOLTIP_PRINT},
{"tooltipFitToPage", IDS_PDF_TOOLTIP_FIT_PAGE},
{"tooltipFitToWidth", IDS_PDF_TOOLTIP_FIT_WIDTH},
+ {"tooltipTwoUpViewEnable", IDS_PDF_TOOLTIP_TWO_UP_VIEW_ENABLE},
+ {"tooltipTwoUpViewDisable", IDS_PDF_TOOLTIP_TWO_UP_VIEW_DISABLE},
{"tooltipZoomIn", IDS_PDF_TOOLTIP_ZOOM_IN},
{"tooltipZoomOut", IDS_PDF_TOOLTIP_ZOOM_OUT},
#if defined(OS_CHROMEOS)
@@ -114,6 +119,9 @@ void AddStringsForPdf(base::DictionaryValue* dict) {
};
for (const auto& resource : kPdfResources)
dict->SetString(resource.name, l10n_util::GetStringUTF16(resource.id));
+
+ dict->SetString("presetZoomFactors", zoom::GetPresetZoomFactorsAsJSON());
+#endif // BUILDFLAG(ENABLE_PDF)
}
void AddAdditionalDataForPdf(base::DictionaryValue* dict) {
@@ -124,6 +132,9 @@ void AddAdditionalDataForPdf(base::DictionaryValue* dict) {
dict->SetKey("pdfAnnotationsEnabled",
base::Value(base::FeatureList::IsEnabled(
chrome_pdf::features::kPDFAnnotations)));
+ dict->SetKey("pdfTwoUpViewEnabled",
+ base::Value(base::FeatureList::IsEnabled(
+ chrome_pdf::features::kPDFTwoUpView)));
bool enable_printing = true;
#if defined(OS_CHROMEOS)
diff --git a/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc b/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
index 35898e2e8f3..dbafaf34b2c 100644
--- a/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc
@@ -309,6 +309,8 @@ bool ChromeRuntimeAPIDelegate::GetPlatformInfo(PlatformInfo* info) {
const char* arch = update_client::UpdateQueryParams::GetArch();
if (strcmp(arch, "arm") == 0) {
info->arch = extensions::api::runtime::PLATFORM_ARCH_ARM;
+ } else if (strcmp(arch, "arm64") == 0) {
+ info->arch = extensions::api::runtime::PLATFORM_ARCH_ARM64;
} else if (strcmp(arch, "x86") == 0) {
info->arch = extensions::api::runtime::PLATFORM_ARCH_X86_32;
} else if (strcmp(arch, "x64") == 0) {
@@ -325,6 +327,9 @@ bool ChromeRuntimeAPIDelegate::GetPlatformInfo(PlatformInfo* info) {
const char* nacl_arch = update_client::UpdateQueryParams::GetNaclArch();
if (strcmp(nacl_arch, "arm") == 0) {
info->nacl_arch = extensions::api::runtime::PLATFORM_NACL_ARCH_ARM;
+ } else if (strcmp(nacl_arch, "arm64") == 0) {
+ // Use ARM for ARM64 NaCl, as ARM64 NaCl is not available.
+ info->nacl_arch = extensions::api::runtime::PLATFORM_NACL_ARCH_ARM;
} else if (strcmp(nacl_arch, "x86-32") == 0) {
info->nacl_arch = extensions::api::runtime::PLATFORM_NACL_ARCH_X86_32;
} else if (strcmp(nacl_arch, "x86-64") == 0) {
diff --git a/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc b/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc
index 369e089d1cc..b63180157fd 100644
--- a/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate_unittest.cc
@@ -118,7 +118,8 @@ class DownloaderTestDelegate : public ExtensionDownloaderTestDelegate {
base::Unretained(delegate), id,
ExtensionDownloaderDelegate::Error::NO_UPDATE_AVAILABLE,
ExtensionDownloaderDelegate::PingResult(),
- fetch_data->request_ids()));
+ fetch_data->request_ids(),
+ ExtensionDownloaderDelegate::FailureData()));
continue;
}
auto update = updates_.find(id);
diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api_unittest.cc
index fdbd0c31876..dcb7e10cb8f 100644
--- a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_api_unittest.cc
@@ -17,14 +17,14 @@
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
+#include "chrome/browser/sessions/session_tab_helper_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/test_browser_window.h"
#include "chrome/test/base/testing_browser_process.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/navigation_entry.h"
-#include "content/public/test/browser_side_navigation_test_utils.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/web_contents_tester.h"
#include "net/url_request/url_request_context_getter.h"
@@ -87,7 +87,6 @@ class SafeBrowsingPrivateApiUnitTest : public ExtensionServiceTestBase {
void SafeBrowsingPrivateApiUnitTest::SetUp() {
ExtensionServiceTestBase::SetUp();
InitializeEmptyExtensionService();
- content::BrowserSideNavigationSetUp();
browser_window_ = std::make_unique<TestBrowserWindow>();
Browser::CreateParams params(profile(), true);
@@ -108,7 +107,6 @@ void SafeBrowsingPrivateApiUnitTest::TearDown() {
while (!browser()->tab_strip_model()->empty())
browser()->tab_strip_model()->DetachWebContentsAt(0);
browser_window_.reset();
- content::BrowserSideNavigationTearDown();
// Make sure the NetworkContext owned by SafeBrowsingService is destructed
// before the NetworkService object..
@@ -134,8 +132,8 @@ TEST_F(SafeBrowsingPrivateApiUnitTest, GetReferrerChain) {
content::WebContents* raw_web_contents = web_contents.get();
ASSERT_TRUE(raw_web_contents);
- SessionTabHelper::CreateForWebContents(raw_web_contents);
- int tab_id = SessionTabHelper::IdForTab(raw_web_contents).id();
+ CreateSessionServiceTabHelper(raw_web_contents);
+ int tab_id = sessions::SessionTabHelper::IdForTab(raw_web_contents).id();
browser()->tab_strip_model()->AppendWebContents(std::move(web_contents),
true);
@@ -156,8 +154,8 @@ TEST_F(SafeBrowsingPrivateApiUnitTest, GetReferrerChainForNonSafeBrowsingUser) {
content::WebContents* raw_web_contents = web_contents.get();
ASSERT_TRUE(raw_web_contents);
- SessionTabHelper::CreateForWebContents(raw_web_contents);
- int tab_id = SessionTabHelper::IdForTab(raw_web_contents).id();
+ CreateSessionServiceTabHelper(raw_web_contents);
+ int tab_id = sessions::SessionTabHelper::IdForTab(raw_web_contents).id();
browser()->tab_strip_model()->AppendWebContents(std::move(web_contents),
true);
diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc
index ff2386afdd5..06b5e42aee5 100644
--- a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h"
+#include "base/bind_helpers.h"
#include "build/build_config.h"
#include <utility>
@@ -17,6 +18,8 @@
#include "base/time/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
+#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service_factory.h"
+#include "components/safe_browsing/content/web_ui/safe_browsing_ui.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/browser_process_platform_part_chromeos.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
@@ -27,7 +30,6 @@
#include "chrome/browser/policy/chrome_browser_cloud_management_controller.h"
#endif
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
-#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
@@ -43,8 +45,8 @@
#include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h"
#include "components/policy/core/common/cloud/realtime_reporting_job_configuration.h"
#include "components/prefs/pref_service.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
-#include "components/safe_browsing/proto/webprotect.pb.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/proto/webprotect.pb.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#if defined(OS_CHROMEOS)
#include "components/user_manager/user.h"
@@ -71,7 +73,7 @@ const char kChromeBrowserCloudManagementClientDescription[] =
namespace extensions {
const base::Feature SafeBrowsingPrivateEventRouter::kRealtimeReportingFeature{
- "SafeBrowsingRealtimeReporting", base::FEATURE_DISABLED_BY_DEFAULT};
+ "SafeBrowsingRealtimeReporting", base::FEATURE_ENABLED_BY_DEFAULT};
// Key names used with when building the dictionary to pass to the real-time
// reporting API.
@@ -88,8 +90,23 @@ const char SafeBrowsingPrivateEventRouter::kKeyReason[] = "reason";
const char SafeBrowsingPrivateEventRouter::kKeyNetErrorCode[] = "netErrorCode";
const char SafeBrowsingPrivateEventRouter::kKeyClickedThrough[] =
"clickedThrough";
-const char SafeBrowsingPrivateEventRouter::kKeyTriggeredRules[] =
- "triggeredRules";
+const char SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleId[] = "ruleId";
+const char SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleName[] = "ruleName";
+const char SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleResourceName[] =
+ "ruleResourceName";
+const char SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleSeverity[] =
+ "severity";
+const char SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleAction[] = "action";
+const char SafeBrowsingPrivateEventRouter::kKeyMatchedDetectors[] =
+ "matchedDetectors";
+const char SafeBrowsingPrivateEventRouter::kKeyMatchedDetectorId[] =
+ "detectorId";
+const char SafeBrowsingPrivateEventRouter::kKeyMatchedDetectorName[] =
+ "displayName";
+const char SafeBrowsingPrivateEventRouter::kKeyMatchedDetectorType[] =
+ "detectorType";
+const char SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleInfo[] =
+ "triggeredRuleInfo";
const char SafeBrowsingPrivateEventRouter::kKeyThreatType[] = "threatType";
const char SafeBrowsingPrivateEventRouter::kKeyContentType[] = "contentType";
const char SafeBrowsingPrivateEventRouter::kKeyContentSize[] = "contentSize";
@@ -426,18 +443,83 @@ void SafeBrowsingPrivateEventRouter::OnSensitiveDataEvent(
if (content_size >= 0)
event.SetIntKey(kKeyContentSize, content_size);
event.SetStringKey(kKeyTrigger, trigger);
+ event.SetBoolKey(kKeyClickedThrough, false);
- base::ListValue triggered_rules;
- for (auto rule : verdict.triggered_rules()) {
- triggered_rules.AppendString(rule.rule_name());
+ base::ListValue triggered_rule_info;
+ for (const auto& rule : verdict.triggered_rules()) {
+ base::Value triggered_rule(base::Value::Type::DICTIONARY);
+ triggered_rule.SetIntKey(kKeyTriggeredRuleId, rule.rule_id());
+ triggered_rule.SetStringKey(kKeyTriggeredRuleName,
+ rule.rule_name());
+ triggered_rule.SetStringKey(kKeyTriggeredRuleResourceName,
+ rule.rule_resource_name());
+ triggered_rule.SetStringKey(kKeyTriggeredRuleSeverity,
+ rule.rule_severity());
+ triggered_rule.SetIntKey(kKeyTriggeredRuleAction, rule.action());
+
+ base::ListValue matched_detectors;
+ for (const auto& detector : rule.matched_detectors()) {
+ base::Value matched_detector(base::Value::Type::DICTIONARY);
+ matched_detector.SetStringKey(kKeyMatchedDetectorId,
+ detector.detector_id());
+ matched_detector.SetStringKey(kKeyMatchedDetectorName,
+ detector.display_name());
+ matched_detector.SetStringKey(kKeyMatchedDetectorType,
+ detector.detector_type());
+
+ matched_detectors.Append(std::move(matched_detector));
+ }
+ triggered_rule.SetKey(kKeyMatchedDetectors,
+ std::move(matched_detectors));
+
+ triggered_rule_info.Append(std::move(triggered_rule));
}
- event.SetKey(kKeyTriggeredRules, std::move(triggered_rules));
+ event.SetKey(kKeyTriggeredRuleInfo, std::move(triggered_rule_info));
+
return event;
},
verdict, url.spec(), file_name, download_digest_sha256,
GetProfileUserName(), mime_type, trigger, content_size));
}
+void SafeBrowsingPrivateEventRouter::OnSensitiveDataWarningBypassed(
+ const GURL& url,
+ const std::string& file_name,
+ const std::string& download_digest_sha256,
+ const std::string& mime_type,
+ const std::string& trigger,
+ const int64_t content_size) {
+ if (!IsRealtimeReportingEnabled())
+ return;
+
+ ReportRealtimeEvent(
+ kKeySensitiveDataEvent,
+ base::BindOnce(
+ [](const std::string& url, const std::string& file_name,
+ const std::string& download_digest_sha256,
+ const std::string& profile_user_name, const std::string& mime_type,
+ const std::string& trigger, const int64_t content_size) {
+ // Create a real-time event dictionary from the arguments and
+ // report it.
+ base::Value event(base::Value::Type::DICTIONARY);
+ event.SetStringKey(kKeyUrl, url);
+ event.SetStringKey(kKeyFileName, file_name);
+ event.SetStringKey(kKeyDownloadDigestSha256,
+ download_digest_sha256);
+ event.SetStringKey(kKeyProfileUserName, profile_user_name);
+ event.SetStringKey(kKeyContentType, mime_type);
+ // |content_size| can be set to -1 to indicate an unknown size, in
+ // which case the field is not set.
+ if (content_size >= 0)
+ event.SetIntKey(kKeyContentSize, content_size);
+ event.SetStringKey(kKeyTrigger, trigger);
+ event.SetBoolKey(kKeyClickedThrough, true);
+ return event;
+ },
+ url.spec(), file_name, download_digest_sha256, GetProfileUserName(),
+ mime_type, trigger, content_size));
+}
+
void SafeBrowsingPrivateEventRouter::OnUnscannedFileEvent(
const GURL& url,
const std::string& file_name,
@@ -577,6 +659,12 @@ void SafeBrowsingPrivateEventRouter::SetCloudPolicyClientForTesting(
client_ = client;
}
+void SafeBrowsingPrivateEventRouter::SetBinaryUploadServiceForTesting(
+ safe_browsing::BinaryUploadService* binary_upload_service) {
+ DCHECK_EQ(nullptr, binary_upload_service_);
+ binary_upload_service_ = binary_upload_service;
+}
+
void SafeBrowsingPrivateEventRouter::InitRealtimeReportingClient() {
// If already initialized, do nothing.
if (client_) {
@@ -611,7 +699,7 @@ void SafeBrowsingPrivateEventRouter::InitRealtimeReportingClient() {
if (g_browser_process) {
binary_upload_service_ =
- g_browser_process->safe_browsing_service()->GetBinaryUploadService(
+ safe_browsing::BinaryUploadServiceFactory::GetForProfile(
Profile::FromBrowserContext(context_));
IfAuthorized(base::BindOnce(
&SafeBrowsingPrivateEventRouter::InitRealtimeReportingClientCallback,
@@ -637,6 +725,9 @@ void SafeBrowsingPrivateEventRouter::InitRealtimeReportingClientCallback(
auto* user = GetChromeOSUser();
if (user) {
auto* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(user);
+ // If primary user profile is not finalized, use the current profile.
+ if (!profile)
+ profile = Profile::FromBrowserContext(context_);
DCHECK(profile);
if (user->IsActiveDirectoryUser()) {
// TODO(crbug.com/1012048): Handle AD, likely through crbug.com/1012170.
@@ -759,6 +850,10 @@ void SafeBrowsingPrivateEventRouter::ReportRealtimeEventCallback(
wrapper.SetStringKey("time", now_str);
wrapper.SetKey(name, std::move(event_builder).Run());
+ // Show the report on chrome://safe-browsing, if appropriate.
+ safe_browsing::WebUIInfoSingleton::GetInstance()->AddToReportingEvents(
+ wrapper);
+
base::Value event_list(base::Value::Type::LIST);
event_list.Append(std::move(wrapper));
@@ -794,14 +889,10 @@ bool SafeBrowsingPrivateEventRouter::IsRealtimeReportingAvailable() {
->IsEnterpriseManaged())
return false;
- // The Chrome OS user must be afiliated with the device.
+ // The Chrome OS user must be affiliated with the device.
+ // This also implies that the user is managed.
auto* user = GetChromeOSUser();
- if (!user || !user->IsAffiliated())
- return false;
-
- // And that user must be managed.
- auto* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(user);
- return profile && profile->GetProfilePolicyConnector()->IsManaged();
+ return user && user->IsAffiliated();
#else
return policy::ChromeBrowserCloudManagementController::IsEnabled();
#endif
diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h
index edf11925be6..63b94a104e2 100644
--- a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h
+++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h
@@ -69,7 +69,16 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
static const char kKeyReason[];
static const char kKeyNetErrorCode[];
static const char kKeyClickedThrough[];
- static const char kKeyTriggeredRules[];
+ static const char kKeyTriggeredRuleId[];
+ static const char kKeyTriggeredRuleName[];
+ static const char kKeyTriggeredRuleResourceName[];
+ static const char kKeyTriggeredRuleSeverity[];
+ static const char kKeyTriggeredRuleAction[];
+ static const char kKeyMatchedDetectors[];
+ static const char kKeyMatchedDetectorId[];
+ static const char kKeyMatchedDetectorName[];
+ static const char kKeyMatchedDetectorType[];
+ static const char kKeyTriggeredRuleInfo[];
static const char kKeyThreatType[];
static const char kKeyContentType[];
static const char kKeyContentSize[];
@@ -136,6 +145,14 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
const std::string& trigger,
const int64_t content_size);
+ // Notifies listeners that scanning for sensitive data detected a violation.
+ void OnSensitiveDataWarningBypassed(const GURL& url,
+ const std::string& file_name,
+ const std::string& download_digest_sha256,
+ const std::string& mime_type,
+ const std::string& trigger,
+ const int64_t content_size);
+
// Notifies listeners that deep scanning failed, for the given |reason|.
void OnUnscannedFileEvent(const GURL& url,
const std::string& file_name,
@@ -177,6 +194,9 @@ class SafeBrowsingPrivateEventRouter : public KeyedService {
void SetCloudPolicyClientForTesting(policy::CloudPolicyClient* client);
+ void SetBinaryUploadServiceForTesting(
+ safe_browsing::BinaryUploadService* binary_upload_service);
+
protected:
// Callback to report safe browsing event through real-time reporting channel,
// if the browser is authorized to do so. Declared as protected to be called
diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
index 4eb80fad57b..3b5e213a364 100644
--- a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
@@ -21,12 +21,23 @@
#include "chrome/test/base/testing_profile_manager.h"
#include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
#include "components/policy/core/common/cloud/realtime_reporting_job_configuration.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/proto/webprotect.pb.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/test_event_router.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
+#include "chromeos/tpm/stub_install_attributes.h"
+#include "components/account_id/account_id.h"
+#include "components/user_manager/scoped_user_manager.h"
+#include "components/user_manager/user.h"
+#endif
+
using ::testing::_;
using ::testing::Mock;
using ::testing::SaveArg;
@@ -163,6 +174,44 @@ class SafeBrowsingPrivateEventRouterTest : public testing::Test {
"sha256_of_bypass_exe", "BYPASSED_WARNING", "exe", 890);
}
+ void TriggerOnSensitiveDataEvent() {
+ safe_browsing::DlpDeepScanningVerdict verdict;
+ verdict.set_status(safe_browsing::DlpDeepScanningVerdict::SUCCESS);
+ safe_browsing::DlpDeepScanningVerdict::TriggeredRule* rule =
+ verdict.add_triggered_rules();
+ rule->set_action(
+ safe_browsing::DlpDeepScanningVerdict::TriggeredRule::BLOCK);
+ rule->set_rule_name("fake rule");
+ rule->set_rule_id(12345);
+ rule->set_rule_resource_name("fake resource name");
+ rule->set_rule_severity("fake severity");
+
+ safe_browsing::DlpDeepScanningVerdict::MatchedDetector* detector =
+ rule->add_matched_detectors();
+ detector->set_detector_id("fake id");
+ detector->set_display_name("fake name");
+ detector->set_detector_type("fake type");
+
+ detector = rule->add_matched_detectors();
+ detector->set_detector_id("fake id2");
+ detector->set_display_name("fake name2");
+ detector->set_detector_type("fake type2");
+
+ SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile_)
+ ->OnSensitiveDataEvent(verdict,
+ GURL("https://evil.com/sensitive_data.txt"),
+ "sensitive_data.txt", "sha256_of_data",
+ "text/plain", "FILE_UPLOAD", 12345);
+ }
+
+ void TriggerOnUnscannedFileEvent() {
+ SafeBrowsingPrivateEventRouterFactory::GetForProfile(profile_)
+ ->OnUnscannedFileEvent(GURL("https://evil.com/sensitive_data.txt"),
+ "sensitive_data.txt", "sha256_of_data",
+ "text/plain", "FILE_DOWNLOAD",
+ "filePasswordProtected", 12345);
+ }
+
void SetReportingPolicy(bool enabled) {
TestingBrowserProcess::GetGlobal()->local_state()->SetBoolean(
prefs::kUnsafeEventsReportingEnabled, enabled);
@@ -207,7 +256,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnReuseDetected) {
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _))
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _))
.WillOnce(CaptureArg(&report));
TriggerOnPolicySpecifiedPasswordReuseDetectedEvent();
@@ -223,7 +272,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnReuseDetected) {
report.FindKey(policy::RealtimeReportingJobConfiguration::kEventListKey);
ASSERT_NE(nullptr, event_list);
EXPECT_EQ(base::Value::Type::LIST, event_list->type());
- base::Value::ListStorage& mutable_list = event_list->GetList();
+ base::Value::ListView mutable_list = event_list->GetList();
ASSERT_EQ(1, (int)mutable_list.size());
base::Value wrapper = std::move(mutable_list[0]);
EXPECT_EQ(base::Value::Type::DICTIONARY, wrapper.type());
@@ -243,7 +292,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnPasswordChanged) {
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _))
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _))
.WillOnce(CaptureArg(&report));
TriggerOnPolicySpecifiedPasswordChangedEvent();
@@ -258,7 +307,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnPasswordChanged) {
report.FindKey(policy::RealtimeReportingJobConfiguration::kEventListKey);
ASSERT_NE(nullptr, event_list);
EXPECT_EQ(base::Value::Type::LIST, event_list->type());
- base::Value::ListStorage& mutable_list = event_list->GetList();
+ base::Value::ListView mutable_list = event_list->GetList();
ASSERT_EQ(1, (int)mutable_list.size());
base::Value wrapper = std::move(mutable_list[0]);
EXPECT_EQ(base::Value::Type::DICTIONARY, wrapper.type());
@@ -276,7 +325,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnDangerousDownloadOpened) {
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _))
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _))
.WillOnce(CaptureArg(&report));
TriggerOnDangerousDownloadOpenedEvent();
@@ -297,7 +346,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnDangerousDownloadOpened) {
report.FindKey(policy::RealtimeReportingJobConfiguration::kEventListKey);
ASSERT_NE(nullptr, event_list);
EXPECT_EQ(base::Value::Type::LIST, event_list->type());
- base::Value::ListStorage& mutable_list = event_list->GetList();
+ base::Value::ListView mutable_list = event_list->GetList();
ASSERT_EQ(1, (int)mutable_list.size());
base::Value wrapper = std::move(mutable_list[0]);
EXPECT_EQ(base::Value::Type::DICTIONARY, wrapper.type());
@@ -323,7 +372,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _))
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _))
.WillOnce(CaptureArg(&report));
TriggerOnSecurityInterstitialProceededEvent();
@@ -341,7 +390,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
report.FindKey(policy::RealtimeReportingJobConfiguration::kEventListKey);
ASSERT_NE(nullptr, event_list);
EXPECT_EQ(base::Value::Type::LIST, event_list->type());
- base::Value::ListStorage& mutable_list = event_list->GetList();
+ base::Value::ListView mutable_list = event_list->GetList();
ASSERT_EQ(1, (int)mutable_list.size());
base::Value wrapper = std::move(mutable_list[0]);
EXPECT_EQ(base::Value::Type::DICTIONARY, wrapper.type());
@@ -363,7 +412,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnSecurityInterstitialShown) {
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _))
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _))
.WillOnce(CaptureArg(&report));
TriggerOnSecurityInterstitialShownEvent();
@@ -381,7 +430,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnSecurityInterstitialShown) {
report.FindKey(policy::RealtimeReportingJobConfiguration::kEventListKey);
ASSERT_NE(nullptr, event_list);
EXPECT_EQ(base::Value::Type::LIST, event_list->type());
- base::Value::ListStorage& mutable_list = event_list->GetList();
+ base::Value::ListView mutable_list = event_list->GetList();
ASSERT_EQ(1, (int)mutable_list.size());
base::Value wrapper = std::move(mutable_list[0]);
EXPECT_EQ(base::Value::Type::DICTIONARY, wrapper.type());
@@ -403,7 +452,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnDangerousDownloadWarning) {
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _))
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _))
.WillOnce(CaptureArg(&report));
TriggerOnDangerousDownloadWarningEvent();
@@ -415,7 +464,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnDangerousDownloadWarning) {
report.FindKey(policy::RealtimeReportingJobConfiguration::kEventListKey);
ASSERT_NE(nullptr, event_list);
EXPECT_EQ(base::Value::Type::LIST, event_list->type());
- base::Value::ListStorage& mutable_list = event_list->GetList();
+ base::Value::ListView mutable_list = event_list->GetList();
ASSERT_EQ(1, (int)mutable_list.size());
base::Value wrapper = std::move(mutable_list[0]);
EXPECT_EQ(base::Value::Type::DICTIONARY, wrapper.type());
@@ -442,7 +491,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _))
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _))
.WillOnce(CaptureArg(&report));
TriggerOnDangerousDownloadWarningEventBypass();
@@ -454,7 +503,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
report.FindKey(policy::RealtimeReportingJobConfiguration::kEventListKey);
ASSERT_NE(nullptr, event_list);
EXPECT_EQ(base::Value::Type::LIST, event_list->type());
- base::Value::ListStorage& mutable_list = event_list->GetList();
+ base::Value::ListView mutable_list = event_list->GetList();
ASSERT_EQ(1, (int)mutable_list.size());
base::Value wrapper = std::move(mutable_list[0]);
EXPECT_EQ(base::Value::Type::DICTIONARY, wrapper.type());
@@ -479,7 +528,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, PolicyControlOnToOffIsDynamic) {
api::safe_browsing_private::OnSecurityInterstitialShown::kEventName);
event_router_->AddEventObserver(&event_observer);
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(1);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(1);
TriggerOnSecurityInterstitialShownEvent();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, event_observer.PassEventArgs().GetList().size());
@@ -487,7 +536,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, PolicyControlOnToOffIsDynamic) {
// Now turn off policy. This time no report should be generated.
SetReportingPolicy(false);
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(0);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(0);
TriggerOnSecurityInterstitialShownEvent();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, event_observer.PassEventArgs().GetList().size());
@@ -506,7 +555,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, PolicyControlOffToOnIsDynamic) {
// Now turn on policy.
SetReportingPolicy(true);
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(1);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(1);
TriggerOnSecurityInterstitialShownEvent();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, event_observer.PassEventArgs().GetList().size());
@@ -521,7 +570,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestUnauthorizedOnReuseDetected) {
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(0);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(0);
TriggerOnPolicySpecifiedPasswordReuseDetectedEvent();
base::RunLoop().RunUntilIdle();
@@ -537,7 +586,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest, TestUnauthorizedOnPasswordChanged) {
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(0);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(0);
TriggerOnPolicySpecifiedPasswordChangedEvent();
base::RunLoop().RunUntilIdle();
@@ -554,7 +603,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(0);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(0);
TriggerOnDangerousDownloadOpenedEvent();
base::RunLoop().RunUntilIdle();
@@ -571,7 +620,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(0);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(0);
TriggerOnSecurityInterstitialProceededEvent();
base::RunLoop().RunUntilIdle();
@@ -588,7 +637,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(0);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(0);
TriggerOnSecurityInterstitialShownEvent();
base::RunLoop().RunUntilIdle();
@@ -605,7 +654,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(0);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(0);
TriggerOnDangerousDownloadWarningEvent();
base::RunLoop().RunUntilIdle();
@@ -622,7 +671,7 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
event_router_->AddEventObserver(&event_observer);
base::Value report;
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(0);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(0);
TriggerOnDangerousDownloadWarningEventBypass();
base::RunLoop().RunUntilIdle();
@@ -631,6 +680,118 @@ TEST_F(SafeBrowsingPrivateEventRouterTest,
EXPECT_EQ(base::Value::Type::NONE, report.type());
}
+TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnSensitiveDataEvent) {
+ SetUpRouters(/*realtime_reporting_enable=*/true, /*authorized=*/true);
+
+ base::Value report;
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _))
+ .WillOnce(CaptureArg(&report));
+
+ TriggerOnSensitiveDataEvent();
+ base::RunLoop().RunUntilIdle();
+
+ Mock::VerifyAndClearExpectations(client_.get());
+ EXPECT_EQ(base::Value::Type::DICTIONARY, report.type());
+ base::Value* event_list =
+ report.FindKey(policy::RealtimeReportingJobConfiguration::kEventListKey);
+ ASSERT_NE(nullptr, event_list);
+ EXPECT_EQ(base::Value::Type::LIST, event_list->type());
+ base::Value::ListView mutable_list = event_list->GetList();
+ ASSERT_EQ(1, (int)mutable_list.size());
+ base::Value wrapper = std::move(mutable_list[0]);
+ EXPECT_EQ(base::Value::Type::DICTIONARY, wrapper.type());
+ base::Value* event =
+ wrapper.FindKey(SafeBrowsingPrivateEventRouter::kKeySensitiveDataEvent);
+ ASSERT_NE(nullptr, event);
+
+ EXPECT_EQ(12345, *event->FindIntKey(
+ SafeBrowsingPrivateEventRouter::kKeyContentSize));
+ EXPECT_EQ("text/plain", *event->FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyContentType));
+ EXPECT_EQ("sha256_of_data",
+ *event->FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyDownloadDigestSha256));
+ EXPECT_EQ(
+ "sensitive_data.txt",
+ *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyFileName));
+ EXPECT_EQ("FILE_UPLOAD",
+ *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyTrigger));
+
+ base::Value* triggered_rule_info =
+ event->FindKey(SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleInfo);
+ ASSERT_NE(nullptr, triggered_rule_info);
+ ASSERT_EQ(1u, triggered_rule_info->GetList().size());
+ base::Value triggered_rule = std::move(triggered_rule_info->GetList()[0]);
+ EXPECT_EQ(12345, triggered_rule.FindIntKey(
+ SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleId));
+ EXPECT_EQ(3, triggered_rule.FindIntKey(
+ SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleAction));
+ EXPECT_EQ("fake rule",
+ *triggered_rule.FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleName));
+ EXPECT_EQ("fake resource name",
+ *triggered_rule.FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleResourceName));
+ EXPECT_EQ("fake severity",
+ *triggered_rule.FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyTriggeredRuleSeverity));
+
+ base::Value* matched_detectors = triggered_rule.FindKey(
+ SafeBrowsingPrivateEventRouter::kKeyMatchedDetectors);
+ ASSERT_NE(nullptr, matched_detectors);
+ ASSERT_EQ(2u, matched_detectors->GetList().size());
+ base::Value detector = std::move(matched_detectors->GetList()[0]);
+ EXPECT_EQ("fake id",
+ *detector.FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyMatchedDetectorId));
+ EXPECT_EQ("fake type",
+ *detector.FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyMatchedDetectorType));
+ EXPECT_EQ("fake name",
+ *detector.FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyMatchedDetectorName));
+}
+
+TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnUnscannedFileEvent) {
+ SetUpRouters(/*realtime_reporting_enable=*/true, /*authorized=*/true);
+
+ base::Value report;
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _))
+ .WillOnce(CaptureArg(&report));
+
+ TriggerOnUnscannedFileEvent();
+ base::RunLoop().RunUntilIdle();
+
+ Mock::VerifyAndClearExpectations(client_.get());
+ EXPECT_EQ(base::Value::Type::DICTIONARY, report.type());
+ base::Value* event_list =
+ report.FindKey(policy::RealtimeReportingJobConfiguration::kEventListKey);
+ ASSERT_NE(nullptr, event_list);
+ EXPECT_EQ(base::Value::Type::LIST, event_list->type());
+ base::Value::ListView mutable_list = event_list->GetList();
+ ASSERT_EQ(1, (int)mutable_list.size());
+ base::Value wrapper = std::move(mutable_list[0]);
+ EXPECT_EQ(base::Value::Type::DICTIONARY, wrapper.type());
+ base::Value* event =
+ wrapper.FindKey(SafeBrowsingPrivateEventRouter::kKeyUnscannedFileEvent);
+ ASSERT_NE(nullptr, event);
+
+ EXPECT_EQ(12345, *event->FindIntKey(
+ SafeBrowsingPrivateEventRouter::kKeyContentSize));
+ EXPECT_EQ("text/plain", *event->FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyContentType));
+ EXPECT_EQ("sha256_of_data",
+ *event->FindStringKey(
+ SafeBrowsingPrivateEventRouter::kKeyDownloadDigestSha256));
+ EXPECT_EQ(
+ "sensitive_data.txt",
+ *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyFileName));
+ EXPECT_EQ("FILE_DOWNLOAD",
+ *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyTrigger));
+ EXPECT_EQ("filePasswordProtected",
+ *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyReason));
+}
+
// Tests to make sure the feature flag and policy control real-time reporting
// as expected. The parameter for these tests is a tuple of bools:
//
@@ -666,12 +827,28 @@ class SafeBrowsingIsRealtimeReportingEnabledTest
TestingBrowserProcess::GetGlobal()->local_state()->SetBoolean(
prefs::kUnsafeEventsReportingEnabled, is_policy_enabled_);
+
+#if defined(OS_CHROMEOS)
+ auto user_manager = std::make_unique<chromeos::FakeChromeUserManager>();
+ const AccountId account_id(
+ AccountId::FromUserEmail(profile_->GetProfileUserName()));
+ const user_manager::User* user = user_manager->AddUserWithAffiliation(
+ account_id, /*is_affiliated=*/is_manageable_);
+ chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user,
+ profile_);
+ user_manager->UserLoggedIn(account_id, user->username_hash(),
+ /*browser_restart=*/false,
+ /*is_child=*/false);
+ scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
+ std::move(user_manager));
+ profile_->ScopedCrosSettingsTestHelper()
+ ->InstallAttributes()
+ ->SetCloudManaged("domain.com", "device_id");
+#endif
}
bool should_init() {
-#if defined(OS_CHROMEOS)
- return false;
-#elif BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !defined(OS_CHROMEOS)
return is_feature_flag_enabled_;
#else
return is_feature_flag_enabled_ && is_manageable_;
@@ -684,6 +861,11 @@ class SafeBrowsingIsRealtimeReportingEnabledTest
const bool is_manageable_;
const bool is_policy_enabled_;
const bool is_authorized_;
+
+#if defined(OS_CHROMEOS)
+ private:
+ std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
+#endif
};
TEST_P(SafeBrowsingIsRealtimeReportingEnabledTest,
@@ -702,9 +884,7 @@ TEST_P(SafeBrowsingIsRealtimeReportingEnabledTest, CheckRealtimeReport) {
api::safe_browsing_private::OnPolicySpecifiedPasswordChanged::kEventName);
event_router_->AddEventObserver(&event_observer);
-#if defined(OS_CHROMEOS)
- bool should_report = false;
-#elif BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING) && !defined(OS_CHROMEOS)
bool should_report =
is_feature_flag_enabled_ && is_policy_enabled_ && is_authorized_;
#else
@@ -713,13 +893,13 @@ TEST_P(SafeBrowsingIsRealtimeReportingEnabledTest, CheckRealtimeReport) {
#endif
if (should_report) {
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(1);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(1);
} else if (client_) {
// Because the test will crate a |client_| object when the policy is
// set, even if the feature flag or other conditions indicate that
// reports should not be sent, it is possible that the pointer is not
// null. In this case, make sure UploadRealtimeReport() is not called.
- EXPECT_CALL(*client_, UploadRealtimeReport(_, _)).Times(0);
+ EXPECT_CALL(*client_, UploadRealtimeReport_(_, _)).Times(0);
}
TriggerOnPolicySpecifiedPasswordChangedEvent();
diff --git a/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc b/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc
index 7d2d33e5188..f130eced5de 100644
--- a/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc
+++ b/chromium/chrome/browser/extensions/api/sessions/sessions_api.cc
@@ -242,6 +242,11 @@ SessionsGetDevicesFunction::CreateWindowModel(
const std::string& session_tag) {
DCHECK(!window.tabs.empty());
+ // Ignore app popup window for now because we do not have a corresponding
+ // api::windows::WindowType value.
+ if (window.type == sessions::SessionWindow::TYPE_APP_POPUP)
+ return nullptr;
+
// Prune tabs that are not syncable or are NewTabPage. Then, sort the tabs
// from most recent to least recent.
std::vector<const sessions::SessionTab*> tabs_in_window;
@@ -286,6 +291,8 @@ SessionsGetDevicesFunction::CreateWindowModel(
case sessions::SessionWindow::TYPE_DEVTOOLS:
type = api::windows::WINDOW_TYPE_DEVTOOLS;
break;
+ case sessions::SessionWindow::TYPE_APP_POPUP:
+ NOTREACHED();
}
api::windows::WindowState state = api::windows::WINDOW_STATE_NONE;
diff --git a/chromium/chrome/browser/extensions/api/sessions/sessions_api.h b/chromium/chrome/browser/extensions/api/sessions/sessions_api.h
index 6d177c1ce6e..2841e654bac 100644
--- a/chromium/chrome/browser/extensions/api/sessions/sessions_api.h
+++ b/chromium/chrome/browser/extensions/api/sessions/sessions_api.h
@@ -8,7 +8,6 @@
#include <string>
#include "base/macros.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/common/extensions/api/sessions.h"
#include "chrome/common/extensions/api/tabs.h"
#include "chrome/common/extensions/api/windows.h"
@@ -16,7 +15,9 @@
#include "components/sessions/core/tab_restore_service_observer.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_function.h"
+class Browser;
class Profile;
namespace sync_sessions {
diff --git a/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc b/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc
index 533703ccb9f..a32ab213704 100644
--- a/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc
@@ -234,19 +234,19 @@ void ExtensionSessionsTest::CreateSessionModels() {
// sessions (anything older than 14 days), so we cannot use
// MockModelTypeWorker's convenience functions, which internally use very
// old timestamps.
- auto header_entity_data = std::make_unique<syncer::EntityData>();
- header_entity_data->client_tag_hash =
+ syncer::EntityData header_entity_data;
+ header_entity_data.client_tag_hash =
TagHashFromSpecifics(header_entity.session());
- header_entity_data->id =
- "FakeId:" + header_entity_data->client_tag_hash.value();
- header_entity_data->specifics = header_entity;
- header_entity_data->creation_time =
+ header_entity_data.id =
+ "FakeId:" + header_entity_data.client_tag_hash.value();
+ header_entity_data.specifics = header_entity;
+ header_entity_data.creation_time =
time_now - base::TimeDelta::FromSeconds(index);
- header_entity_data->modification_time = header_entity_data->creation_time;
+ header_entity_data.modification_time = header_entity_data.creation_time;
- auto header_update = std::make_unique<syncer::UpdateResponseData>();
- header_update->entity = std::move(header_entity_data);
- header_update->response_version = 1;
+ syncer::UpdateResponseData header_update;
+ header_update.entity = std::move(header_entity_data);
+ header_update.response_version = 1;
syncer::UpdateResponseDataList updates;
updates.push_back(std::move(header_update));
worker.UpdateFromServer(std::move(updates));
diff --git a/chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc b/chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
index ed9c0d567e0..3fc49945ee2 100644
--- a/chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
@@ -101,8 +101,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, OverrideStartupPagesSettings) {
SessionStartupPref::SetStartupPref(prefs, startup_pref);
const extensions::Extension* extension = LoadExtensionWithInstallParam(
- test_data_dir_.AppendASCII("settings_override"),
- kFlagEnableFileAccess,
+ test_data_dir_.AppendASCII("settings_override"), kFlagEnableFileAccess,
"10");
ASSERT_TRUE(extension);
startup_pref = SessionStartupPref::GetStartupPref(prefs);
diff --git a/chromium/chrome/browser/extensions/api/settings_private/OWNERS b/chromium/chrome/browser/extensions/api/settings_private/OWNERS
index 5f9293fd57e..14a91b03c35 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/OWNERS
+++ b/chromium/chrome/browser/extensions/api/settings_private/OWNERS
@@ -1,5 +1,5 @@
-dbeam@chromium.org
michaelpg@chromium.org
-stevenjb@chromium.org
+
+file://chrome/browser/resources/settings/OWNERS
# COMPONENT: UI>Settings
diff --git a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
index 3337e8e5d40..99993cc1055 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -11,7 +11,6 @@
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/extensions/api/settings_private/generated_prefs.h"
#include "chrome/browser/extensions/api/settings_private/generated_prefs_factory.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/extensions/settings_api_helpers.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile.h"
@@ -21,14 +20,16 @@
#include "components/browsing_data/core/pref_names.h"
#include "components/component_updater/pref_names.h"
#include "components/content_settings/core/common/pref_names.h"
+#include "components/dom_distiller/core/pref_names.h"
#include "components/drive/drive_pref_names.h"
+#include "components/embedder_support/pref_names.h"
#include "components/language/core/browser/pref_names.h"
#include "components/omnibox/browser/omnibox_pref_names.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/payments/core/payment_prefs.h"
#include "components/prefs/pref_service.h"
#include "components/proxy_config/proxy_config_pref_names.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/search_engines/default_search_manager.h"
#include "components/spellcheck/browser/pref_names.h"
#include "components/translate/core/browser/translate_pref_names.h"
@@ -43,11 +44,13 @@
#include "extensions/common/extension.h"
#if defined(OS_CHROMEOS)
+#include "ash/public/cpp/ambient/ambient_prefs.h"
#include "ash/public/cpp/ash_pref_names.h" // nogncheck
#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
#include "chrome/browser/chromeos/guest_os/guest_os_pref_names.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
+#include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
@@ -145,7 +148,7 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
s_whitelist = new PrefsUtil::TypedPrefMap();
// Miscellaneous
- (*s_whitelist)[::prefs::kAlternateErrorPagesEnabled] =
+ (*s_whitelist)[::embedder_support::kAlternateErrorPagesEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[autofill::prefs::kAutofillProfileEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
@@ -197,6 +200,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
(*s_whitelist)[::prefs::kConfirmToQuitEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
#endif
+ (*s_whitelist)[dom_distiller::prefs::kOfferReaderMode] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
// On startup.
(*s_whitelist)[::prefs::kRestoreOnStartup] =
@@ -241,12 +246,20 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
// Privacy page
(*s_whitelist)[::prefs::kSigninAllowedOnNextStartup] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[::prefs::kDnsOverHttpsMode] =
+ settings_api::PrefType::PREF_TYPE_STRING;
+ (*s_whitelist)[::prefs::kDnsOverHttpsTemplates] =
+ settings_api::PrefType::PREF_TYPE_STRING;
- // Sync and personalization page.
+ // Security page
(*s_whitelist)[::prefs::kSafeBrowsingEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[::prefs::kSafeBrowsingEnhanced] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kSafeBrowsingScoutReportingEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+
+ // Sync and personalization page.
(*s_whitelist)[::prefs::kSearchSuggestEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)
@@ -282,6 +295,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
// Site Settings prefs.
(*s_whitelist)[::prefs::kBlockThirdPartyCookies] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[::prefs::kCookieControlsMode] =
+ settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)[::prefs::kPluginsAlwaysOpenPdfExternally] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kEnableDRM] =
@@ -336,6 +351,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_api::PrefType::PREF_TYPE_STRING;
(*s_whitelist)[::prefs::kAccessibilityCaptionsBackgroundOpacity] =
settings_api::PrefType::PREF_TYPE_NUMBER;
+ (*s_whitelist)[::prefs::kLiveCaptionEnabled] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
#if defined(OS_CHROMEOS)
// Accounts / Users / People.
@@ -415,6 +432,9 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
(*s_whitelist)[ash::prefs::kAccessibilitySwitchAccessAutoScanSpeedMs] =
settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)
+ [ash::prefs::kAccessibilityTabletModeShelfNavigationButtonsEnabled] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)
[ash::prefs::kAccessibilitySwitchAccessAutoScanKeyboardSpeedMs] =
settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)[ash::prefs::kAccessibilityVirtualKeyboardEnabled] =
@@ -435,17 +455,35 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
// Guest OS
(*s_whitelist)[crostini::prefs::kCrostiniEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[crostini::prefs::kCrostiniMicSharing] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[crostini::prefs::kCrostiniMicSharingAtLastLaunch] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[crostini::prefs::kCrostiniSharedUsbDevices] =
settings_api::PrefType::PREF_TYPE_LIST;
(*s_whitelist)[crostini::prefs::kCrostiniContainers] =
settings_api::PrefType::PREF_TYPE_LIST;
+ (*s_whitelist)[crostini::prefs::kCrostiniPortForwarding] =
+ settings_api::PrefType::PREF_TYPE_LIST;
(*s_whitelist)[guest_os::prefs::kGuestOSPathsSharedToVms] =
settings_api::PrefType::PREF_TYPE_DICTIONARY;
+ // Plugin Vm
+ (*s_whitelist)[plugin_vm::prefs::kPluginVmImageExists] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[plugin_vm::prefs::kPluginVmPrintersAllowed] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+
// Android Apps.
(*s_whitelist)[arc::prefs::kArcEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ // Ambient Mode.
+ (*s_whitelist)[ash::ambient::prefs::kAmbientModeEnabled] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[ash::ambient::prefs::kAmbientModeTopicSource] =
+ settings_api::PrefType::PREF_TYPE_NUMBER;
+
// Google Assistant.
(*s_whitelist)[chromeos::assistant::prefs::kAssistantConsentStatus] =
settings_api::PrefType::PREF_TYPE_NUMBER;
@@ -549,20 +587,28 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
// Device settings.
(*s_whitelist)[::prefs::kTapToClickEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[::prefs::kNaturalScroll] =
+ (*s_whitelist)[ash::prefs::kNaturalScroll] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kTouchpadSensitivity] =
settings_api::PrefType::PREF_TYPE_NUMBER;
+ (*s_whitelist)[::prefs::kTouchpadScrollSensitivity] =
+ settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)[::prefs::kPrimaryMouseButtonRight] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[::prefs::kMouseReverseScroll] =
+ (*s_whitelist)[ash::prefs::kMouseReverseScroll] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kMouseAcceleration] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[::prefs::kMouseScrollAcceleration] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kTouchpadAcceleration] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[::prefs::kTouchpadScrollAcceleration] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kMouseSensitivity] =
settings_api::PrefType::PREF_TYPE_NUMBER;
+ (*s_whitelist)[::prefs::kMouseScrollSensitivity] =
+ settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)[::prefs::kLanguageRemapSearchKeyTo] =
settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)[::prefs::kLanguageRemapControlKeyTo] =
diff --git a/chromium/chrome/browser/extensions/api/settings_private/settings_private_api.cc b/chromium/chrome/browser/extensions/api/settings_private/settings_private_api.cc
index 821ed539375..d01d93603d6 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/settings_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/settings_private_api.cc
@@ -10,7 +10,6 @@
#include "base/values.h"
#include "chrome/browser/extensions/api/settings_private/settings_private_delegate.h"
#include "chrome/browser/extensions/api/settings_private/settings_private_delegate_factory.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h"
#include "chrome/common/extensions/api/settings_private.h"
diff --git a/chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc b/chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc
index df85ee8f848..5eda7d995da 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop_current.h"
#include "base/run_loop.h"
#include "base/values.h"
@@ -53,7 +54,7 @@ class SettingsPrivateApiTest : public ExtensionApiTest {
protected:
bool RunSettingsSubtest(const std::string& subtest) {
return RunExtensionSubtest("settings_private", "main.html?" + subtest,
- kFlagLoadAsComponent);
+ kFlagNone, kFlagLoadAsComponent);
}
void SetPrefPolicy(const std::string& key, policy::PolicyLevel level) {
diff --git a/chromium/chrome/browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc b/chromium/chrome/browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc
index e6460b930f1..d875a5d6930 100644
--- a/chromium/chrome/browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/signed_in_devices/id_mapping_helper_unittest.cc
@@ -11,11 +11,26 @@
#include "base/time/time.h"
#include "base/values.h"
#include "components/sync_device_info/device_info.h"
+#include "components/sync_device_info/device_info_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using syncer::DeviceInfo;
+namespace {
+std::unique_ptr<DeviceInfo> CreateDevice(const std::string& guid,
+ const std::string& name,
+ const std::string& device_id) {
+ return std::make_unique<DeviceInfo>(
+ guid, name, "chrome_version", "user_agent",
+ sync_pb::SyncEnums_DeviceType_TYPE_LINUX, device_id,
+ base::SysInfo::HardwareInfo(), base::Time(),
+ syncer::DeviceInfoUtil::GetPulseInterval(),
+ /*send_tab_to_self_receiving_enabled=*/true,
+ /*sharing_info=*/base::nullopt);
+}
+} // namespace
+
namespace extensions {
bool VerifyDictionary(const std::string& path,
const std::string& expected_value,
@@ -31,19 +46,10 @@ bool VerifyDictionary(const std::string& path,
TEST(IdMappingHelperTest, SetIdsForDevices) {
std::vector<std::unique_ptr<DeviceInfo>> devices;
- devices.push_back(std::make_unique<DeviceInfo>(
- base::GenerateGUID(), "abc Device", "XYZ v1", "XYZ SyncAgent v1",
- sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id1",
- base::SysInfo::HardwareInfo(), base::Time(),
- /*send_tab_to_self_receiving_enabled=*/true,
- /*sharing_info=*/base::nullopt));
-
- devices.push_back(std::make_unique<DeviceInfo>(
- base::GenerateGUID(), "def Device", "XYZ v1", "XYZ SyncAgent v1",
- sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id2",
- base::SysInfo::HardwareInfo(), base::Time(),
- /*send_tab_to_self_receiving_enabled=*/true,
- /*sharing_info=*/base::nullopt));
+ devices.push_back(
+ CreateDevice(base::GenerateGUID(), "abc Device", "device_id1"));
+ devices.push_back(
+ CreateDevice(base::GenerateGUID(), "def Device", "device_id2"));
base::DictionaryValue dictionary;
@@ -58,12 +64,8 @@ TEST(IdMappingHelperTest, SetIdsForDevices) {
EXPECT_NE(public_id1, public_id2);
// Now add a third device.
- devices.push_back(std::make_unique<DeviceInfo>(
- base::GenerateGUID(), "ghi Device", "XYZ v1", "XYZ SyncAgent v1",
- sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id3",
- base::SysInfo::HardwareInfo(), base::Time(),
- /*send_tab_to_self_receiving_enabled=*/true,
- /*sharing_info=*/base::nullopt));
+ devices.push_back(
+ CreateDevice(base::GenerateGUID(), "ghi Device", "device_id3"));
CreateMappingForUnmappedDevices(devices, &dictionary);
diff --git a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h
index c46442ec14b..f303e521243 100644
--- a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h
+++ b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api.h
@@ -9,7 +9,7 @@
#include <string>
#include <vector>
-#include "chrome/browser/extensions/chrome_extension_function.h"
+#include "extensions/browser/extension_function.h"
class Profile;
diff --git a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc
index 0ebd0738031..61eeb37b7d3 100644
--- a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc
@@ -18,6 +18,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/device_info_sync_service_factory.h"
#include "components/sync_device_info/device_info.h"
+#include "components/sync_device_info/device_info_util.h"
#include "components/sync_device_info/fake_device_info_sync_service.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/common/extension.h"
@@ -27,6 +28,19 @@ using syncer::DeviceInfo;
using syncer::FakeDeviceInfoSyncService;
using syncer::FakeDeviceInfoTracker;
+namespace {
+std::unique_ptr<DeviceInfo> CreateDevice(const std::string& guid,
+ const std::string& name) {
+ return std::make_unique<DeviceInfo>(
+ guid, name, "chrome_version", "user_agent",
+ sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id",
+ base::SysInfo::HardwareInfo(), base::Time(),
+ syncer::DeviceInfoUtil::GetPulseInterval(),
+ /*send_tab_to_self_receiving_enabled=*/true,
+ /*sharing_info=*/base::nullopt);
+}
+} // namespace
+
namespace extensions {
TEST(SignedInDevicesAPITest, GetSignedInDevices) {
@@ -40,22 +54,13 @@ TEST(SignedInDevicesAPITest, GetSignedInDevices) {
scoped_refptr<Extension> extension_test =
extension_prefs.AddExtension(extension_name);
- DeviceInfo device_info1(base::GenerateGUID(), "abc Device", "XYZ v1",
- "XYZ SyncAgent v1",
- sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id",
- base::SysInfo::HardwareInfo(), base::Time(),
- /*send_tab_to_self_receiving_enabled=*/true,
- /*sharing_info=*/base::nullopt);
+ std::unique_ptr<DeviceInfo> device_info1 =
+ CreateDevice(base::GenerateGUID(), "abc Device");
+ std::unique_ptr<DeviceInfo> device_info2 =
+ CreateDevice(base::GenerateGUID(), "def Device");
- DeviceInfo device_info2(base::GenerateGUID(), "def Device", "XYZ v2",
- "XYZ SyncAgent v2",
- sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id",
- base::SysInfo::HardwareInfo(), base::Time(),
- /*send_tab_to_self_receiving_enabled=*/true,
- /*sharing_info=*/base::nullopt);
-
- device_tracker.Add(&device_info1);
- device_tracker.Add(&device_info2);
+ device_tracker.Add(device_info1.get());
+ device_tracker.Add(device_info2.get());
std::vector<std::unique_ptr<DeviceInfo>> output1 = GetAllSignedInDevices(
extension_test->id(), &device_tracker, extension_prefs.prefs());
@@ -69,14 +74,10 @@ TEST(SignedInDevicesAPITest, GetSignedInDevices) {
// Add a third device and make sure the first 2 ids are retained and a new
// id is generated for the third device.
- DeviceInfo device_info3(base::GenerateGUID(), "def Device", "jkl v2",
- "XYZ SyncAgent v2",
- sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id",
- base::SysInfo::HardwareInfo(), base::Time(),
- /*send_tab_to_self_receiving_enabled=*/true,
- /*sharing_info=*/base::nullopt);
+ std::unique_ptr<DeviceInfo> device_info3 =
+ CreateDevice(base::GenerateGUID(), "jkl Device");
- device_tracker.Add(&device_info3);
+ device_tracker.Add(device_info3.get());
std::vector<std::unique_ptr<DeviceInfo>> output2 = GetAllSignedInDevices(
extension_test->id(), &device_tracker, extension_prefs.prefs());
@@ -136,31 +137,22 @@ TEST_F(ExtensionSignedInDevicesTest, GetAll) {
DeviceInfoSyncServiceFactory::GetForProfile(profile())
->GetDeviceInfoTracker());
- DeviceInfo device_info1(base::GenerateGUID(), "abc Device", "XYZ v1",
- "XYZ SyncAgent v1",
- sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id",
- base::SysInfo::HardwareInfo(), base::Time(),
- /*send_tab_to_self_receiving_enabled=*/true,
- /*sharing_info=*/base::nullopt);
-
- DeviceInfo device_info2(base::GenerateGUID(), "def Device", "XYZ v2",
- "XYZ SyncAgent v2",
- sync_pb::SyncEnums_DeviceType_TYPE_LINUX, "device_id",
- base::SysInfo::HardwareInfo(), base::Time(),
- /*send_tab_to_self_receiving_enabled=*/true,
- /*sharing_info=*/base::nullopt);
+ std::unique_ptr<DeviceInfo> device_info1 =
+ CreateDevice(base::GenerateGUID(), "abc Device");
+ std::unique_ptr<DeviceInfo> device_info2 =
+ CreateDevice(base::GenerateGUID(), "def Device");
- device_tracker->Add(&device_info1);
- device_tracker->Add(&device_info2);
+ device_tracker->Add(device_info1.get());
+ device_tracker->Add(device_info2.get());
std::unique_ptr<base::ListValue> result(
RunFunctionAndReturnList(new SignedInDevicesGetFunction(), "[null]"));
// Ensure dictionary matches device info.
VerifyDictionaryWithDeviceInfo(GetDictionaryFromList(0, result.get()),
- &device_info1);
+ device_info1.get());
VerifyDictionaryWithDeviceInfo(GetDictionaryFromList(1, result.get()),
- &device_info2);
+ device_info2.get());
// Ensure public ids are set and unique.
std::string public_id1 = GetPublicId(GetDictionaryFromList(0, result.get()));
diff --git a/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc b/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
index 49d784a90d7..c64bdc40e29 100644
--- a/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
@@ -127,7 +127,7 @@ class TCPSocketUnitTest : public TCPSocketUnitTestBase,
net::MockClientSocketFactory mock_client_socket_factory_;
};
-INSTANTIATE_TEST_SUITE_P(/* no prefix */,
+INSTANTIATE_TEST_SUITE_P(All,
TCPSocketUnitTest,
testing::Values(net::SYNCHRONOUS, net::ASYNC));
@@ -560,7 +560,7 @@ class TCPSocketSettingsTest : public TCPSocketUnitTestBase,
TestSocketFactory client_socket_factory_;
};
-INSTANTIATE_TEST_SUITE_P(/* no prefix */,
+INSTANTIATE_TEST_SUITE_P(All,
TCPSocketSettingsTest,
testing::Bool());
diff --git a/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc b/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
index 580a81c0d96..9ff019adcd8 100644
--- a/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
@@ -271,7 +271,7 @@ TEST_F(TLSSocketTest, UpgradeToTLSWithCustomOptionsTLS13) {
EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
}
-INSTANTIATE_TEST_SUITE_P(/* no prefix */,
+INSTANTIATE_TEST_SUITE_P(All,
TLSSocketTest,
testing::Values(net::SYNCHRONOUS, net::ASYNC));
diff --git a/chromium/chrome/browser/extensions/api/storage/managed_value_store_cache.cc b/chromium/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
index 13344e45ef8..c6b4d057806 100644
--- a/chromium/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
+++ b/chromium/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
@@ -115,9 +115,8 @@ ManagedValueStoreCache::ExtensionTracker::ExtensionTracker(
extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
// Load schemas when the extension system is ready. It might be ready now.
ExtensionSystem::Get(profile_)->ready().Post(
- FROM_HERE,
- base::Bind(&ExtensionTracker::OnExtensionsReady,
- weak_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&ExtensionTracker::OnExtensionsReady,
+ weak_factory_.GetWeakPtr()));
}
void ManagedValueStoreCache::ExtensionTracker::OnExtensionWillBeInstalled(
diff --git a/chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc b/chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
index 26678d70605..1a1c21ede6e 100644
--- a/chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/storage/settings_sync_unittest.cc
@@ -15,6 +15,7 @@
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/storage/settings_sync_util.h"
+#include "chrome/browser/extensions/api/storage/sync_storage_backend.h"
#include "chrome/browser/extensions/api/storage/sync_value_store_cache.h"
#include "chrome/browser/extensions/api/storage/syncable_settings_storage.h"
#include "chrome/test/base/testing_profile.h"
@@ -198,6 +199,12 @@ class ExtensionSettingsSyncTest : public testing::Test {
EventRouterFactory::GetInstance()->SetTestingFactory(
profile_.get(), base::BindRepeating(&BuildEventRouter));
+
+ // Hold a pointer to SyncValueStoreCache in the main thread, such that
+ // GetSyncableService() can be called from the backend sequence.
+ sync_cache_ = static_cast<SyncValueStoreCache*>(
+ frontend_->GetValueStoreCache(settings_namespace::SYNC));
+ ASSERT_NE(sync_cache_, nullptr);
}
void TearDown() override {
@@ -218,17 +225,21 @@ class ExtensionSettingsSyncTest : public testing::Test {
}
// Gets the syncer::SyncableService for the given sync type.
- syncer::SyncableService* GetSyncableService(syncer::ModelType model_type) {
- SyncValueStoreCache* sync_cache = static_cast<SyncValueStoreCache*>(
- frontend_->GetValueStoreCache(settings_namespace::SYNC));
- return sync_cache->GetSyncableService(model_type);
+ SyncStorageBackend* GetSyncableService(syncer::ModelType model_type) {
+ // SyncValueStoreCache::GetSyncableService internally enforces |model_type|
+ // to be APP_SETTINGS or EXTENSION_SETTINGS, and the dynamic type of the
+ // returned service is always SyncStorageBackend, so it can be downcast.
+ DCHECK(model_type == syncer::APP_SETTINGS ||
+ model_type == syncer::EXTENSION_SETTINGS);
+ return static_cast<SyncStorageBackend*>(
+ sync_cache_->GetSyncableService(model_type));
}
// Gets all the sync data from the SyncableService for a sync type as a map
// from extension id to its sync data.
SettingSyncDataMultimap GetAllSyncData(syncer::ModelType model_type) {
syncer::SyncDataList as_list =
- GetSyncableService(model_type)->GetAllSyncData(model_type);
+ GetSyncableService(model_type)->GetAllSyncDataForTesting(model_type);
SettingSyncDataMultimap as_map;
for (auto it = as_list.begin(); it != as_list.end(); ++it) {
std::unique_ptr<SettingSyncData> sync_data(new SettingSyncData(*it));
@@ -272,6 +283,7 @@ class ExtensionSettingsSyncTest : public testing::Test {
std::unique_ptr<MockSyncChangeProcessor> sync_processor_;
std::unique_ptr<syncer::SyncChangeProcessorWrapperForTest>
sync_processor_wrapper_;
+ SyncValueStoreCache* sync_cache_;
};
// Get a semblance of coverage for both EXTENSION_SETTINGS and APP_SETTINGS
@@ -1014,7 +1026,7 @@ TEST_F(ExtensionSettingsSyncTest, FailingGetAllSyncDataDoesntStopSync) {
GetExisting("bad")->set_status_code(ValueStore::CORRUPTION);
{
syncer::SyncDataList all_sync_data =
- GetSyncableService(model_type)->GetAllSyncData(model_type);
+ GetSyncableService(model_type)->GetAllSyncDataForTesting(model_type);
EXPECT_EQ(1u, all_sync_data.size());
EXPECT_EQ("good/foo", syncer::SyncDataLocal(all_sync_data[0]).GetTag());
}
diff --git a/chromium/chrome/browser/extensions/api/storage/sync_storage_backend.cc b/chromium/chrome/browser/extensions/api/storage/sync_storage_backend.cc
index 6e1cd48a154..d25a5140f04 100644
--- a/chromium/chrome/browser/extensions/api/storage/sync_storage_backend.cc
+++ b/chromium/chrome/browser/extensions/api/storage/sync_storage_backend.cc
@@ -146,8 +146,8 @@ void SyncStorageBackend::WaitUntilReadyToSync(base::OnceClosure done) {
std::move(done).Run();
}
-syncer::SyncDataList SyncStorageBackend::GetAllSyncData(syncer::ModelType type)
- const {
+syncer::SyncDataList SyncStorageBackend::GetAllSyncDataForTesting(
+ syncer::ModelType type) const {
DCHECK(IsOnBackendSequence());
// For all extensions, get all their settings. This has the effect
// of bringing in the entire state of extension settings in memory; sad.
diff --git a/chromium/chrome/browser/extensions/api/storage/sync_storage_backend.h b/chromium/chrome/browser/extensions/api/storage/sync_storage_backend.h
index f57cedb5f56..db9c01d4f48 100644
--- a/chromium/chrome/browser/extensions/api/storage/sync_storage_backend.h
+++ b/chromium/chrome/browser/extensions/api/storage/sync_storage_backend.h
@@ -49,7 +49,7 @@ class SyncStorageBackend : public syncer::SyncableService {
// syncer::SyncableService implementation.
void WaitUntilReadyToSync(base::OnceClosure done) override;
- syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
+ syncer::SyncDataList GetAllSyncDataForTesting(syncer::ModelType type) const;
syncer::SyncMergeResult MergeDataAndStartSyncing(
syncer::ModelType type,
const syncer::SyncDataList& initial_sync_data,
diff --git a/chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc b/chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc
index 3841b7adf65..bb4af725af9 100644
--- a/chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/streams_private/streams_private_api.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/prerender/prerender_contents.h"
+#include "components/sessions/core/session_id.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
@@ -66,7 +67,19 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
// will take ownership of the stream.
GURL handler_url(Extension::GetBaseURLFromExtensionId(extension_id).spec() +
handler->handler_url());
- int tab_id = ExtensionTabUtil::GetTabId(web_contents);
+
+ // If this is an inner contents, then (a) it's a guest view and doesn't have a
+ // tab id anyway, or (b) it's a portal. In the portal case, providing a
+ // distinct tab id breaks the pdf viewer / extension APIs. For now we just
+ // indicate that a portal contents has no tab id. Unfortunately, this will
+ // still be broken in subtle ways once the portal is activated (e.g. some
+ // forms of zooming won't work).
+ // TODO(1042323): Present a coherent representation of a tab id for portal
+ // contents.
+ int tab_id = web_contents->GetOuterWebContents()
+ ? SessionID::InvalidValue().id()
+ : ExtensionTabUtil::GetTabId(web_contents);
+
std::unique_ptr<StreamContainer> stream_container(
new StreamContainer(tab_id, embedded, handler_url, extension_id,
std::move(transferrable_loader), original_url));
diff --git a/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc b/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc
index 6d8f4bc0eb0..37f7cf90fc3 100644
--- a/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc
+++ b/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_manager.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_action.h"
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
index 0fdb361b5a2..0b5e53f00fa 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
@@ -22,12 +22,12 @@
#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -247,7 +247,7 @@ ExtensionFunction::ResponseAction TabCaptureCaptureFunction::Run() {
// Make sure either we have been granted permission to capture through an
// extension icon click or our extension is whitelisted.
if (!extension()->permissions_data()->HasAPIPermissionForTab(
- SessionTabHelper::IdForTab(target_contents).id(),
+ sessions::SessionTabHelper::IdForTab(target_contents).id(),
APIPermission::kTabCaptureForTab) &&
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kWhitelistedExtensionID) != extension_id &&
@@ -434,7 +434,7 @@ ExtensionFunction::ResponseAction TabCaptureGetMediaStreamIdFunction::Run() {
// Make sure either we have been granted permission to capture through an
// extension icon click or our extension is whitelisted.
if (!extension()->permissions_data()->HasAPIPermissionForTab(
- SessionTabHelper::IdForTab(target_contents).id(),
+ sessions::SessionTabHelper::IdForTab(target_contents).id(),
APIPermission::kTabCaptureForTab) &&
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kWhitelistedExtensionID) != extension_id) {
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.h b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.h
index 15c0827eec9..699090ba7df 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.h
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.h
@@ -9,8 +9,8 @@
#define CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_TAB_CAPTURE_API_H_
#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/common/extensions/api/tab_capture.h"
+#include "extensions/browser/extension_function.h"
namespace extensions {
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
index e2734050f96..b43a43f1405 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc
@@ -177,7 +177,9 @@ IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_MaxOffscreenTabs) {
}
// Tests that tab capture video frames can be received in a VIDEO element.
-IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest, EndToEndWithoutRemoting) {
+// Flaky on all platforms. See https://crbug.com/1040894
+IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest,
+ DISABLED_EndToEndWithoutRemoting) {
if (IsTooIntensiveForThisPlatform()) {
LOG(WARNING) << "Skipping this CPU-intensive test on this platform/build.";
return;
@@ -197,7 +199,8 @@ IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest, EndToEndWithoutRemoting) {
// received in a VIDEO element. More allowance is provided for color deviation
// because of the additional layers of video processing performed within
// WebRTC.
-IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest, EndToEndThroughWebRTC) {
+// Flaky on all platforms. See https://crbug.com/1040894
+IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest, DISABLED_EndToEndThroughWebRTC) {
if (IsTooIntensiveForThisPlatform()) {
LOG(WARNING) << "Skipping this CPU-intensive test on this platform/build.";
return;
@@ -389,9 +392,8 @@ IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, DISABLED_GrantForChromePages) {
// Tests that a tab in incognito mode can be captured.
IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_CaptureInSplitIncognitoMode) {
AddExtensionToCommandLineWhitelist();
- ASSERT_TRUE(RunExtensionSubtest("tab_capture",
- "start_tab_capture.html",
- kFlagEnableIncognito | kFlagUseIncognito))
+ ASSERT_TRUE(RunExtensionSubtest("tab_capture", "start_tab_capture.html",
+ kFlagEnableIncognito, kFlagUseIncognito))
<< message_;
}
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
index f14b467269c..ffde54ce493 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc
@@ -277,6 +277,10 @@ class TabCapturePerformanceTest : public TabCapturePerformanceTestBase,
} // namespace
IN_PROC_BROWSER_TEST_P(TabCapturePerformanceTest, Performance) {
+ if (!is_full_performance_run()) {
+ // TODO(crbug.com/1042457): Flaky failures across multiple CQ builders.
+ return;
+ }
// Load the extension and test page, and tell the extension to start tab
// capture.
LoadExtension(GetApiTestDataDir()
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
index 82a0c898096..f69202e9d88 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
@@ -10,8 +10,8 @@
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/values.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_streams_registry.h"
#include "content/public/browser/render_frame_host.h"
@@ -85,7 +85,7 @@ class TabCaptureRegistry::LiveRequest : public content::WebContentsObserver {
}
void GetCaptureInfo(tab_capture::CaptureInfo* info) const {
- info->tab_id = SessionTabHelper::IdForTab(web_contents()).id();
+ info->tab_id = sessions::SessionTabHelper::IdForTab(web_contents()).id();
info->status = capture_state_;
info->fullscreen = is_fullscreened_;
}
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
index e520e8ac977..44268dd99c3 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -41,7 +41,6 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h"
#include "chrome/browser/resource_coordinator/tab_manager.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/translate/chrome_translate_client.h"
#include "chrome/browser/ui/apps/chrome_app_delegate.h"
#include "chrome/browser/ui/browser.h"
@@ -63,6 +62,7 @@
#include "chrome/common/url_constants.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "components/translate/core/browser/language_state.h"
#include "components/translate/core/common/language_detection_details.h"
#include "components/zoom/zoom_controller.h"
@@ -485,6 +485,9 @@ ExtensionFunction::ResponseAction WindowsCreateFunction::Run() {
if (ExtensionTabUtil::IsKillURL(url))
return RespondNow(Error(tabs_constants::kNoCrashBrowserError));
urls.push_back(url);
+
+ // Log if this navigation looks like it is to a devtools URL.
+ ExtensionTabUtil::LogPossibleDevtoolsSchemeNavigation(url);
}
}
@@ -547,9 +550,8 @@ ExtensionFunction::ResponseAction WindowsCreateFunction::Run() {
// Initialize default window bounds according to window type.
ui::WindowShowState ignored_show_state = ui::SHOW_STATE_DEFAULT;
- WindowSizer::GetBrowserWindowBoundsAndShowState(std::string(), gfx::Rect(),
- nullptr, &window_bounds,
- &ignored_show_state);
+ WindowSizer::GetBrowserWindowBoundsAndShowState(
+ gfx::Rect(), nullptr, &window_bounds, &ignored_show_state);
// Any part of the bounds can optionally be set by the caller.
if (create_data->left)
@@ -877,7 +879,6 @@ ExtensionFunction::ResponseAction TabsQueryFunction::Run() {
EXTENSION_FUNCTION_VALIDATE(params.get());
bool loading_status_set = params->query_info.status != tabs::TAB_STATUS_NONE;
- bool loading = params->query_info.status == tabs::TAB_STATUS_LOADING;
URLPatternSet url_patterns;
if (params->query_info.url.get()) {
@@ -1034,8 +1035,11 @@ ExtensionFunction::ResponseAction TabsQueryFunction::Run() {
}
}
- if (loading_status_set && loading != web_contents->IsLoading())
+ if (loading_status_set &&
+ params->query_info.status !=
+ ExtensionTabUtil::GetLoadingStatus(web_contents)) {
continue;
+ }
result->Append(CreateTabObjectHelper(web_contents, extension(),
source_context_type(), tab_strip, i)
@@ -1225,7 +1229,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
contents = browser->tab_strip_model()->GetActiveWebContents();
if (!contents)
return RespondNow(Error(tabs_constants::kNoSelectedTabError));
- tab_id = SessionTabHelper::IdForTab(contents).id();
+ tab_id = sessions::SessionTabHelper::IdForTab(contents).id();
} else {
tab_id = *params->tab_id;
}
@@ -1347,6 +1351,9 @@ bool TabsUpdateFunction::UpdateURL(const std::string& url_string,
return false;
}
+ // Log if this navigation looks like it is to a devtools URL.
+ ExtensionTabUtil::LogPossibleDevtoolsSchemeNavigation(url);
+
const bool is_javascript_scheme = url.SchemeIs(url::kJavaScriptScheme);
UMA_HISTOGRAM_BOOLEAN("Extensions.ApiTabUpdateJavascript",
is_javascript_scheme);
@@ -1672,7 +1679,7 @@ WebContents* TabsCaptureVisibleTabFunction::GetWebContentsForID(
if (!extension()->permissions_data()->CanCaptureVisiblePage(
contents->GetLastCommittedURL(),
- SessionTabHelper::IdForTab(contents).id(), error,
+ sessions::SessionTabHelper::IdForTab(contents).id(), error,
extensions::CaptureRequirement::kActiveTabOrAllUrls)) {
return nullptr;
}
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
index c4eadfb2170..ca2c1186813 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc
@@ -13,12 +13,12 @@
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_service_test_base.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
+#include "chrome/browser/sessions/session_tab_helper_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/test_browser_window.h"
+#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/navigation_entry.h"
-#include "content/public/test/browser_side_navigation_test_utils.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/web_contents_tester.h"
#include "extensions/browser/api_test_utils.h"
@@ -108,7 +108,6 @@ void TabsApiUnitTest::SetUp() {
ExtensionServiceTestBase::SetUp();
InitializeEmptyExtensionService();
- content::BrowserSideNavigationSetUp();
browser_window_.reset(new TestBrowserWindow());
Browser::CreateParams params(profile(), true);
@@ -122,7 +121,6 @@ void TabsApiUnitTest::SetUp() {
void TabsApiUnitTest::TearDown() {
browser_.reset();
browser_window_.reset();
- content::BrowserSideNavigationTearDown();
ExtensionServiceTestBase::TearDown();
}
@@ -298,8 +296,8 @@ TEST_F(TabsApiUnitTest, PDFExtensionNavigation) {
EXPECT_EQ(kGoogle, raw_web_contents->GetLastCommittedURL());
EXPECT_EQ(kGoogle, raw_web_contents->GetVisibleURL());
- SessionTabHelper::CreateForWebContents(raw_web_contents);
- int tab_id = SessionTabHelper::IdForTab(raw_web_contents).id();
+ CreateSessionServiceTabHelper(raw_web_contents);
+ int tab_id = sessions::SessionTabHelper::IdForTab(raw_web_contents).id();
browser()->tab_strip_model()->AppendWebContents(std::move(web_contents),
true);
@@ -367,8 +365,8 @@ TEST_F(TabsApiUnitTest, TabsUpdateJavaScriptUrlNotAllowed) {
content::WebContentsTester* web_contents_tester =
content::WebContentsTester::For(raw_contents);
web_contents_tester->NavigateAndCommit(GURL("http://www.example.com"));
- SessionTabHelper::CreateForWebContents(raw_contents);
- int tab_id = SessionTabHelper::IdForTab(raw_contents).id();
+ CreateSessionServiceTabHelper(raw_contents);
+ int tab_id = sessions::SessionTabHelper::IdForTab(raw_contents).id();
static constexpr char kFormatArgs[] = R"([%d, {"url": "%s"}])";
const std::string args = base::StringPrintf(
@@ -404,8 +402,9 @@ TEST_F(TabsApiUnitTest, TabsGoForwardAndBack) {
content::WebContents* raw_web_contents = web_contents.get();
ASSERT_TRUE(raw_web_contents);
- SessionTabHelper::CreateForWebContents(raw_web_contents);
- const int tab_id = SessionTabHelper::IdForTab(raw_web_contents).id();
+ CreateSessionServiceTabHelper(raw_web_contents);
+ const int tab_id =
+ sessions::SessionTabHelper::IdForTab(raw_web_contents).id();
browser()->tab_strip_model()->AppendWebContents(std::move(web_contents),
true);
// Go back with chrome.tabs.goBack.
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc
index 12b43d03904..a2d7cd800f1 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_constants.cc
@@ -63,8 +63,6 @@ const char kShowStateValueMinimized[] = "minimized";
const char kShowStateValueMaximized[] = "maximized";
const char kShowStateValueFullscreen[] = "fullscreen";
const char kShowStateValueLockedFullscreen[] = "locked-fullscreen";
-const char kStatusValueComplete[] = "complete";
-const char kStatusValueLoading[] = "loading";
const char kWindowTypeValueNormal[] = "normal";
const char kWindowTypeValuePopup[] = "popup";
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_constants.h b/chromium/chrome/browser/extensions/api/tabs/tabs_constants.h
index 14b4f865265..12261d10c0f 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_constants.h
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_constants.h
@@ -70,8 +70,6 @@ extern const char kShowStateValueMinimized[];
extern const char kShowStateValueMaximized[];
extern const char kShowStateValueFullscreen[];
extern const char kShowStateValueLockedFullscreen[];
-extern const char kStatusValueComplete[];
-extern const char kStatusValueLoading[];
extern const char kWindowTypeValueNormal[];
extern const char kWindowTypeValuePopup[];
extern const char kWindowTypeValueApp[];
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
index bc7b34ca36b..fd2ff75a3af 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
@@ -163,15 +163,17 @@ void TabsEventRouter::TabEntry::WebContentsDestroyed() {
}
TabsEventRouter::TabsEventRouter(Profile* profile)
- : profile_(profile), browser_tab_strip_tracker_(this, this, this) {
+ : profile_(profile), browser_tab_strip_tracker_(this, this) {
DCHECK(!profile->IsOffTheRecord());
+ BrowserList::AddObserver(this);
browser_tab_strip_tracker_.Init();
tab_manager_scoped_observer_.Add(g_browser_process->GetTabManager());
}
TabsEventRouter::~TabsEventRouter() {
+ BrowserList::RemoveObserver(this);
}
bool TabsEventRouter::ShouldTrackBrowser(Browser* browser) {
@@ -233,7 +235,7 @@ void TabsEventRouter::OnTabStripModelChanged(
if (selection.active_tab_changed()) {
DispatchActiveTabChanged(selection.old_contents, selection.new_contents,
- selection.new_model.active(), selection.reason);
+ selection.new_model.active());
}
if (selection.selection_changed()) {
@@ -302,7 +304,13 @@ void TabsEventRouter::OnDiscardedStateChange(
::mojom::LifecycleUnitDiscardReason reason,
bool is_discarded) {
std::set<std::string> changed_property_names;
+ // If the "discarded" property changes, so does the "status" property:
+ // - a discarded tab has status "unloaded", and will transition to "loading"
+ // on un-discarding; and,
+ // - a tab can only be discarded if its status is "complete" or "loading", in
+ // which case it will transition to "unloaded".
changed_property_names.insert(tabs_constants::kDiscardedKey);
+ changed_property_names.insert(tabs_constants::kStatusKey);
DispatchTabUpdatedEvent(contents, std::move(changed_property_names));
}
@@ -398,8 +406,7 @@ void TabsEventRouter::DispatchTabDetachedAt(WebContents* contents,
void TabsEventRouter::DispatchActiveTabChanged(WebContents* old_contents,
WebContents* new_contents,
- int index,
- int reason) {
+ int index) {
auto args = std::make_unique<base::ListValue>();
int tab_id = ExtensionTabUtil::GetTabId(new_contents);
args->AppendInteger(tab_id);
@@ -414,24 +421,21 @@ void TabsEventRouter::DispatchActiveTabChanged(WebContents* old_contents,
// deprecated events take two arguments: tabId, {windowId}.
Profile* profile =
Profile::FromBrowserContext(new_contents->GetBrowserContext());
- EventRouter::UserGestureState gesture =
- reason & CHANGE_REASON_USER_GESTURE
- ? EventRouter::USER_GESTURE_ENABLED
- : EventRouter::USER_GESTURE_NOT_ENABLED;
+
DispatchEvent(profile, events::TABS_ON_SELECTION_CHANGED,
api::tabs::OnSelectionChanged::kEventName,
- args->CreateDeepCopy(), gesture);
+ args->CreateDeepCopy(), EventRouter::USER_GESTURE_UNKNOWN);
DispatchEvent(profile, events::TABS_ON_ACTIVE_CHANGED,
api::tabs::OnActiveChanged::kEventName, std::move(args),
- gesture);
+ EventRouter::USER_GESTURE_UNKNOWN);
// The onActivated event takes one argument: {windowId, tabId}.
auto on_activated_args = std::make_unique<base::ListValue>();
object_args->Set(tabs_constants::kTabIdKey, std::make_unique<Value>(tab_id));
on_activated_args->Append(std::move(object_args));
- DispatchEvent(profile, events::TABS_ON_ACTIVATED,
- api::tabs::OnActivated::kEventName,
- std::move(on_activated_args), gesture);
+ DispatchEvent(
+ profile, events::TABS_ON_ACTIVATED, api::tabs::OnActivated::kEventName,
+ std::move(on_activated_args), EventRouter::USER_GESTURE_UNKNOWN);
}
void TabsEventRouter::DispatchTabSelectionChanged(
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h
index e7335a902ae..50c5a1d31e4 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h
@@ -95,8 +95,7 @@ class TabsEventRouter : public TabStripModelObserver,
bool was_active);
void DispatchActiveTabChanged(content::WebContents* old_contents,
content::WebContents* new_contents,
- int index,
- int reason);
+ int index);
void DispatchTabSelectionChanged(TabStripModel* tab_strip_model,
const ui::ListSelectionModel& old_model);
void DispatchTabMoved(content::WebContents* contents,
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
index 77050a952f3..a4451241d59 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_interactive_test.cc
@@ -134,10 +134,12 @@ class NonPersistentExtensionTabsTest
// TODO(crbug.com/984350): Expand the test to verify that setSelfAsOpener
// param is ignored from Service Worker extension scripts.
IN_PROC_BROWSER_TEST_P(NonPersistentExtensionTabsTest, TabCurrentWindow) {
- ASSERT_TRUE(RunExtensionTestWithFlags(
- "tabs/current_window", GetParam() == ContextType::kServiceWorker
- ? kFlagRunAsServiceWorkerBasedExtension
- : kFlagNone))
+ ASSERT_TRUE(
+ RunExtensionTestWithFlags("tabs/current_window",
+ GetParam() == ContextType::kServiceWorker
+ ? kFlagRunAsServiceWorkerBasedExtension
+ : kFlagNone,
+ kFlagNone))
<< message_;
}
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc
index 3301202197e..0e27b87db5c 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc
@@ -343,7 +343,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, GetAllWindows) {
CloseAppWindow(app_window);
}
-IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, GetAllWindowsAllTypes) {
+// Flaky. https://crbug.com/1035620
+IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DISABLED_GetAllWindowsAllTypes) {
const size_t NUM_WINDOWS = 5;
std::set<int> window_ids;
std::set<int> result_ids;
@@ -911,8 +912,9 @@ IN_PROC_BROWSER_TEST_F(ExtensionWindowLastFocusedTest,
DevToolsWindowTesting::CloseDevToolsWindowSync(devtools);
}
+// Flaky. https://crbug.com/1035622
IN_PROC_BROWSER_TEST_F(ExtensionWindowLastFocusedTest,
- NoDevtoolsAndAppWindows) {
+ DISABLED_NoDevtoolsAndAppWindows) {
DevToolsWindow* devtools = DevToolsWindowTesting::OpenDevToolsWindowSync(
browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
{
@@ -1414,7 +1416,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DiscardWithId) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL(url::kAboutBlankURL),
WindowOpenDisposition::NEW_BACKGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
content::WebContents* web_contents =
browser()->tab_strip_model()->GetWebContentsAt(1);
@@ -1458,7 +1460,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DiscardWithInvalidId) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL(url::kAboutBlankURL),
WindowOpenDisposition::NEW_BACKGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Set up the function with an extension.
scoped_refptr<const Extension> extension = ExtensionBuilder("Test").Build();
@@ -1491,7 +1493,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DiscardWithoutId) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL(url::kAboutBlankURL),
WindowOpenDisposition::NEW_BACKGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
content::WebContents* web_contents =
browser()->tab_strip_model()->GetWebContentsAt(1);
@@ -1813,7 +1815,7 @@ content::WebContents* ExtensionTabsZoomTest::OpenUrlAndWaitForLoad(
const GURL& url) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
return browser()->tab_strip_model()->GetActiveWebContents();
}
@@ -2074,7 +2076,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, TemporaryAddressSpoof) {
second_web_contents, GURL("http://www.facebook.com:83"));
ui_test_utils::NavigateToURLWithDisposition(
browser(), url, WindowOpenDisposition::CURRENT_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
bool load_success =
pdf_extension_test_util::EnsurePDFHasLoaded(second_web_contents);
diff --git a/chromium/chrome/browser/extensions/api/tabs/windows_util.cc b/chromium/chrome/browser/extensions/api/tabs/windows_util.cc
index ae70d408258..7b84b7f8413 100644
--- a/chromium/chrome/browser/extensions/api/tabs/windows_util.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/windows_util.cc
@@ -9,7 +9,6 @@
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/window_controller.h"
diff --git a/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.cc b/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.cc
index 9debf108e62..56168cbd8ea 100644
--- a/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.cc
+++ b/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.cc
@@ -12,10 +12,13 @@
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
-#include "base/task/task_traits.h"
#include "base/time/time.h"
#include "chromeos/dbus/util/version_loader.h"
#include "components/version_info/version_info.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+
+using crostini::mojom::InstallerState;
namespace extensions {
@@ -24,35 +27,24 @@ namespace {
const char kCursorHide[] = "\x1b[?25l";
const char kCursorShow[] = "\x1b[?25h";
const char kColor0Normal[] = "\x1b[0m"; // Default.
-const char kColor1Red[] = "\x1b[31m";
-const char kColor2Green[] = "\x1b[32m";
-const char kColor4Blue[] = "\x1b[34m";
+const char kColor1RedBright[] = "\x1b[1;31m";
+const char kColor2GreenBright[] = "\x1b[1;32m";
+const char kColor3Yellow[] = "\x1b[33m";
const char kColor5Purple[] = "\x1b[35m";
-const char kProgressStart[] = "\x1b[7m"; // Invert color.
-const char kProgressEnd[] = "\x1b[27m"; // Revert color.
+const char kEraseInLine[] = "\x1b[K";
const char kSpinner[] = "|/-\\";
-const int kTimestampLength = 25;
-const int kMaxProgress = 9;
-const base::NoDestructor<std::vector<std::string>> kSuccessEmoji(
- {"😀", "😉", "🤩", "🤪", "😎", "🥳", "👍"});
-const base::NoDestructor<std::vector<std::string>> kErrorEmoji({"🤕", "😠",
- "😧", "😢", "😞"});
+const int kMaxStage = 9;
+
+std::string MoveForward(int i) {
+ return base::StringPrintf("\x1b[%dC", i);
+}
+
} // namespace
CrostiniStartupStatus::CrostiniStartupStatus(
base::RepeatingCallback<void(const std::string&)> print,
- bool verbose,
- base::OnceClosure callback)
- : print_(std::move(print)),
- verbose_(verbose),
- callback_(std::move(callback)) {
- Print(kCursorHide);
- if (verbose_) {
- PrintWithTimestamp("Chrome OS " + version_info::GetVersionNumber() + " " +
- chromeos::version_loader::GetVersion(
- chromeos::version_loader::VERSION_FULL) +
- "\r\n");
- }
+ bool verbose)
+ : print_(std::move(print)), verbose_(verbose) {
}
CrostiniStartupStatus::~CrostiniStartupStatus() = default;
@@ -60,162 +52,105 @@ CrostiniStartupStatus::~CrostiniStartupStatus() = default;
void CrostiniStartupStatus::OnCrostiniRestarted(
crostini::CrostiniResult result) {
if (result != crostini::CrostiniResult::SUCCESS) {
- LOG(ERROR) << "Error starting crostini for terminal: "
- << static_cast<int>(result);
- PrintWithTimestamp(base::StringPrintf(
- "Error starting penguin container: %d %s\r\n", result,
- (*kErrorEmoji)[rand() % kErrorEmoji->size()].c_str()));
+ PrintAfterStage(
+ kColor1RedBright,
+ base::StringPrintf("Error starting penguin container: %d\r\n", result));
} else {
if (verbose_) {
- PrintWithTimestamp(base::StringPrintf(
- "Ready %s\r\n",
- (*kSuccessEmoji)[rand() % kSuccessEmoji->size()].c_str()));
+ stage_index_ = kMaxStage + 1; // done.
+ PrintStage(kColor2GreenBright, "done\r\n");
}
- Print(kCursorShow);
}
- std::move(callback_).Run();
- delete this;
+ Print(
+ base::StringPrintf("\r%s%s%s", kEraseInLine, kColor0Normal, kCursorShow));
}
-void CrostiniStartupStatus::ShowStatusLineAtInterval() {
+void CrostiniStartupStatus::ShowProgressAtInterval() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // Wait one interval before showing progress.
+ if (spinner_index_ > 0) {
+ PrintProgress();
+ }
++spinner_index_;
- PrintStatusLine();
base::PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&CrostiniStartupStatus::ShowStatusLineAtInterval,
+ FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&CrostiniStartupStatus::ShowProgressAtInterval,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(300));
}
void CrostiniStartupStatus::OnStageStarted(InstallerState stage) {
stage_ = stage;
- progress_index_++;
+ if (stage_index_ < kMaxStage) {
+ ++stage_index_;
+ }
if (!verbose_) {
return;
}
static base::NoDestructor<base::flat_map<InstallerState, std::string>>
kStartStrings({
- {InstallerState::kStart, "Starting... 🤔"},
+ {InstallerState::kStart, "Initializing"},
{InstallerState::kInstallImageLoader,
- "Checking cros-termina component..."},
- {InstallerState::kStartConcierge, "Starting VM controller..."},
- {InstallerState::kCreateDiskImage, "Creating termina VM image..."},
- {InstallerState::kStartTerminaVm, "Starting termina VM..."},
- {InstallerState::kCreateContainer, "Creating penguin container..."},
- {InstallerState::kSetupContainer,
- "Checking penguin container setup..."},
- {InstallerState::kStartContainer, "Starting penguin container..."},
+ "Checking cros-termina component installed"},
+ {InstallerState::kStartConcierge, "Starting VM controller"},
+ {InstallerState::kCreateDiskImage,
+ "Checking termina VM image installed"},
+ {InstallerState::kStartTerminaVm, "Starting termina VM"},
+ {InstallerState::kCreateContainer,
+ "Checking penguin container installed"},
+ {InstallerState::kSetupContainer, "Checking penguin container setup"},
+ {InstallerState::kStartContainer, "Starting penguin container"},
{InstallerState::kFetchSshKeys,
- "Fetching penguin container ssh keys..."},
- {InstallerState::kMountContainer,
- "Mounting penguin container sshfs..."},
+ "Fetching penguin container ssh keys"},
+ {InstallerState::kMountContainer, "Mounting penguin container sshfs"},
});
- const std::string& start_string = (*kStartStrings)[stage];
- cursor_position_ = kTimestampLength + start_string.length();
- PrintWithTimestamp(start_string + "\r\n");
- PrintStatusLine();
-}
-
-void CrostiniStartupStatus::OnComponentLoaded(crostini::CrostiniResult result) {
- PrintCrostiniResult(result);
-}
-
-void CrostiniStartupStatus::OnConciergeStarted(bool success) {
- PrintSuccess(success);
-}
-
-void CrostiniStartupStatus::OnDiskImageCreated(
- bool success,
- vm_tools::concierge::DiskImageStatus status,
- int64_t disk_size_available) {
- PrintSuccess(success);
-}
-
-void CrostiniStartupStatus::OnVmStarted(bool success) {
- PrintSuccess(success);
+ const std::string& stage_string = (*kStartStrings)[stage];
+ PrintStage(kColor3Yellow, stage_string);
}
void CrostiniStartupStatus::OnContainerDownloading(int32_t download_percent) {
if (download_percent % 8 == 0) {
- PrintResult(".");
+ PrintAfterStage(kColor3Yellow, ".");
}
}
-void CrostiniStartupStatus::OnContainerCreated(
- crostini::CrostiniResult result) {
- PrintCrostiniResult(result);
-}
-
-void CrostiniStartupStatus::OnContainerSetup(bool success) {
- PrintSuccess(success);
-}
-
-void CrostiniStartupStatus::OnContainerStarted(
- crostini::CrostiniResult result) {
- PrintCrostiniResult(result);
-}
-
-void CrostiniStartupStatus::OnSshKeysFetched(bool success) {
- PrintSuccess(success);
-}
-
-void CrostiniStartupStatus::OnContainerMounted(bool success) {
- PrintSuccess(success);
-}
-
-void CrostiniStartupStatus::PrintStatusLine() {
- std::string progress(progress_index_, ' ');
- std::string dots(std::max(kMaxProgress - progress_index_, 0), '.');
- Print(base::StringPrintf("[%s%s%s%s%s%s] %s%c%s\r", kProgressStart,
- progress.c_str(), kProgressEnd, kColor5Purple,
- dots.c_str(), kColor0Normal, kColor4Blue,
- kSpinner[spinner_index_ & 0x3], kColor0Normal));
-}
-
void CrostiniStartupStatus::Print(const std::string& output) {
print_.Run(output);
}
-void CrostiniStartupStatus::PrintWithTimestamp(const std::string& output) {
- base::Time::Exploded exploded;
- base::Time::Now().LocalExplode(&exploded);
- Print(base::StringPrintf("%04d-%02d-%02d %02d:%02d:%02d.%03d %s",
- exploded.year, exploded.month, exploded.day_of_month,
- exploded.hour, exploded.minute, exploded.second,
- exploded.millisecond, output.c_str()));
-}
-
-void CrostiniStartupStatus::PrintResult(const std::string& output) {
- if (!verbose_) {
+void CrostiniStartupStatus::InitializeProgress() {
+ if (progress_initialized_) {
return;
}
-
- std::string cursor_move = "\x1b[A"; // cursor up.
- for (int i = 0; i < cursor_position_; ++i) {
- cursor_move += "\x1b[C"; // cursor forward.
- }
- Print(cursor_move + output + "\r\n");
- cursor_position_ += output.length();
- PrintStatusLine();
-}
-
-void CrostiniStartupStatus::PrintCrostiniResult(
- crostini::CrostiniResult result) {
- if (result == crostini::CrostiniResult::SUCCESS) {
- PrintSuccess(true);
- } else {
- PrintResult(base::StringPrintf("%serror=%d%s ❌", kColor1Red, result,
- kColor0Normal));
- }
-}
-
-void CrostiniStartupStatus::PrintSuccess(bool success) {
- if (success) {
- PrintResult(
- base::StringPrintf("%sdone%s ✔️", kColor2Green, kColor0Normal));
- } else {
- PrintResult(base::StringPrintf("%serror%s ❌", kColor1Red, kColor0Normal));
- }
+ progress_initialized_ = true;
+ Print(base::StringPrintf("%s%s[%s] ", kCursorHide, kColor5Purple,
+ std::string(kMaxStage, ' ').c_str()));
+}
+
+void CrostiniStartupStatus::PrintProgress() {
+ InitializeProgress();
+ Print(base::StringPrintf("\r%s%s%c", MoveForward(stage_index_).c_str(),
+ kColor5Purple, kSpinner[spinner_index_ & 0x3]));
+}
+
+void CrostiniStartupStatus::PrintStage(const char* color,
+ const std::string& output) {
+ DCHECK_GE(stage_index_, 1);
+ InitializeProgress();
+ std::string progress(stage_index_ - 1, '=');
+ Print(base::StringPrintf("\r%s[%s%s%s%s%s ", kColor5Purple, progress.c_str(),
+ MoveForward(3 + (kMaxStage - stage_index_)).c_str(),
+ kEraseInLine, color, output.c_str()));
+ end_of_line_index_ = 4 + kMaxStage + output.size();
+}
+
+void CrostiniStartupStatus::PrintAfterStage(const char* color,
+ const std::string& output) {
+ InitializeProgress();
+ Print(base::StringPrintf("\r%s%s%s", MoveForward(end_of_line_index_).c_str(),
+ color, output.c_str()));
+ end_of_line_index_ += output.size();
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.h b/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.h
index 75475ebd4d2..9191f235010 100644
--- a/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.h
+++ b/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status.h
@@ -9,11 +9,9 @@
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
-#include "chrome/browser/chromeos/crostini/crostini_installer_types.mojom.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_simple_types.h"
-
-using crostini::mojom::InstallerState;
+#include "chrome/browser/chromeos/crostini/crostini_types.mojom.h"
namespace extensions {
@@ -22,14 +20,13 @@ class CrostiniStartupStatus
: public crostini::CrostiniManager::RestartObserver {
public:
CrostiniStartupStatus(base::RepeatingCallback<void(const std::string&)> print,
- bool verbose,
- base::OnceClosure callback);
+ bool verbose);
~CrostiniStartupStatus() override;
- // Updates the status line every 300ms.
- void ShowStatusLineAtInterval();
+ // Updates the progress spinner every 300ms.
+ void ShowProgressAtInterval();
- // Deletes this object when called.
+ // Called when startup is complete.
void OnCrostiniRestarted(crostini::CrostiniResult result);
private:
@@ -37,37 +34,23 @@ class CrostiniStartupStatus
FRIEND_TEST_ALL_PREFIXES(CrostiniStartupStatusTest, TestVerbose);
// crostini::CrostiniManager::RestartObserver
- void OnStageStarted(InstallerState stage) override;
- void OnComponentLoaded(crostini::CrostiniResult result) override;
- void OnConciergeStarted(bool success) override;
- void OnDiskImageCreated(bool success,
- vm_tools::concierge::DiskImageStatus status,
- int64_t disk_size_available) override;
- void OnVmStarted(bool success) override;
+ void OnStageStarted(crostini::mojom::InstallerState stage) override;
void OnContainerDownloading(int32_t download_percent) override;
- void OnContainerCreated(crostini::CrostiniResult result) override;
- void OnContainerSetup(bool success) override;
- void OnContainerStarted(crostini::CrostiniResult result) override;
- void OnSshKeysFetched(bool success) override;
- void OnContainerMounted(bool success) override;
- void PrintStatusLine();
void Print(const std::string& output);
- void PrintWithTimestamp(const std::string& output);
- // Moves cursor up and to the right to previous line before status line before
- // printing output.
- void PrintResult(const std::string& output);
- void PrintCrostiniResult(crostini::CrostiniResult result);
- void PrintSuccess(bool success);
+ void InitializeProgress();
+ void PrintProgress();
+ void PrintStage(const char* color, const std::string& output);
+ void PrintAfterStage(const char* color, const std::string& output);
base::RepeatingCallback<void(const std::string& output)> print_;
const bool verbose_;
- base::OnceClosure callback_;
+ bool progress_initialized_ = false;
int spinner_index_ = 0;
- int progress_index_ = 0;
- // Position of cursor on line above status line.
- int cursor_position_ = 0;
- InstallerState stage_ = InstallerState::kStart;
+ int stage_index_ = 0;
+ int end_of_line_index_ = 0;
+ crostini::mojom::InstallerState stage_ =
+ crostini::mojom::InstallerState::kStart;
base::WeakPtrFactory<CrostiniStartupStatus> weak_factory_{this};
};
diff --git a/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status_unittest.cc b/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status_unittest.cc
index 4e930e73ac9..c4307e82a6f 100644
--- a/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/terminal/crostini_startup_status_unittest.cc
@@ -11,6 +11,8 @@
#include "chrome/browser/chromeos/crostini/crostini_simple_types.h"
#include "testing/gtest/include/gtest/gtest.h"
+using crostini::mojom::InstallerState;
+
namespace extensions {
class CrostiniStartupStatusTest : public testing::Test {
@@ -25,9 +27,7 @@ class CrostiniStartupStatusTest : public testing::Test {
return new CrostiniStartupStatus(
base::BindRepeating(&CrostiniStartupStatusTest::Print,
base::Unretained(this)),
- verbose,
- base::BindOnce(&CrostiniStartupStatusTest::Done,
- base::Unretained(this)));
+ verbose);
}
void SetUp() override {}
@@ -40,45 +40,36 @@ TEST_F(CrostiniStartupStatusTest, TestNotVerbose) {
auto* startup_status = NewStartupStatus(false);
startup_status->OnStageStarted(InstallerState::kStart);
startup_status->OnStageStarted(InstallerState::kInstallImageLoader);
- startup_status->OnComponentLoaded(crostini::CrostiniResult::SUCCESS);
startup_status->OnCrostiniRestarted(crostini::CrostiniResult::SUCCESS);
- EXPECT_TRUE(done_);
-
- // Hides cursor, shows cursor.
- EXPECT_EQ(output_.size(), 2u);
- EXPECT_EQ(output_[0], "\x1b[?25l");
- EXPECT_EQ(output_[1], "\x1b[?25h");
+ EXPECT_EQ(output_.size(), 1u);
+ // CR, delete line, default color, show cursor.
+ EXPECT_EQ(output_[0], "\r\x1b[K\x1b[0m\x1b[?25h");
}
TEST_F(CrostiniStartupStatusTest, TestVerbose) {
auto* startup_status = NewStartupStatus(true);
startup_status->OnStageStarted(InstallerState::kStart);
startup_status->OnStageStarted(InstallerState::kInstallImageLoader);
- startup_status->OnComponentLoaded(crostini::CrostiniResult::SUCCESS);
startup_status->OnCrostiniRestarted(crostini::CrostiniResult::SUCCESS);
- EXPECT_TRUE(done_);
-
- // Hides cursor, version, start, status, component, status, done, status,
- // ready, shows cursor.
- EXPECT_EQ(output_.size(), 10u);
- EXPECT_EQ(output_[0], "\x1b[?25l");
- EXPECT_EQ(output_[1].find("Chrome OS "), 24u);
- EXPECT_EQ(output_[2].substr(24), "Starting... 🤔\r\n");
- EXPECT_EQ(output_[3],
- "[\x1b[7m \x1b[27m\x1b[35m........\x1b[0m] \x1b[34m|\x1b[0m\r");
- EXPECT_EQ(output_[4].substr(24), "Checking cros-termina component...\r\n");
- EXPECT_EQ(output_[5],
- "[\x1b[7m \x1b[27m\x1b[35m.......\x1b[0m] \x1b[34m|\x1b[0m\r");
- std::string expected = "\x1b[A";
- for (int i = 0; i < 59; ++i)
- expected += "\x1b[C";
- expected += "\x1b[32mdone\x1b[0m \xE2\x9C\x94\xEF\xb8\x8F\r\n";
- EXPECT_EQ(output_[6], expected);
- EXPECT_EQ(output_[7],
- "[\x1b[7m \x1b[27m\x1b[35m.......\x1b[0m] \x1b[34m|\x1b[0m\r");
- EXPECT_EQ(output_[8].find("Ready"), 24u);
- EXPECT_EQ(output_[9], "\x1b[?25h");
+
+ EXPECT_EQ(output_.size(), 5u);
+ // Hide cursor, init progress.
+ EXPECT_EQ(output_[0], "\x1b[?25l\x1b[35m[ ] ");
+
+ // CR, purple, forward 11, yellow, stage.
+ EXPECT_EQ(output_[1], "\r\x1b[35m[\x1b[11C\x1b[K\x1b[33mInitializing ");
+
+ // CR, purple, progress, forward 10, erase, yellow, stage.
+ EXPECT_EQ(output_[2],
+ "\r\x1b[35m[=\x1b[10C\x1b[K\x1b[33mChecking cros-termina component "
+ "installed ");
+
+ // CR, purple, progress, forward 2, erase, green, done, symbol, CRLF.
+ EXPECT_EQ(output_[3], "\r\x1b[35m[=========\x1b[2C\x1b[K\x1b[1;32mdone\r\n ");
+
+ // CR, delete line, default color, show cursor;
+ EXPECT_EQ(output_[4], "\r\x1b[K\x1b[0m\x1b[?25h");
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc
index c09b80b9f33..46d738f35ee 100644
--- a/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -9,15 +9,21 @@
#include <utility>
#include <vector>
+#include "ash/public/cpp/ash_pref_names.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/memory/scoped_refptr.h"
+#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "base/values.h"
+#include "chrome/browser/chromeos/crostini/crostini_features.h"
+#include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
+#include "chrome/browser/chromeos/crostini/crostini_terminal.h"
+#include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/extensions/api/terminal/crostini_startup_status.h"
#include "chrome/browser/extensions/api/terminal/terminal_extension_helper.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -43,6 +49,8 @@ namespace OnTerminalResize =
extensions::api::terminal_private::OnTerminalResize;
namespace OpenTerminalProcess =
extensions::api::terminal_private::OpenTerminalProcess;
+namespace OpenVmshellProcess =
+ extensions::api::terminal_private::OpenVmshellProcess;
namespace CloseTerminalProcess =
extensions::api::terminal_private::CloseTerminalProcess;
namespace SendInput = extensions::api::terminal_private::SendInput;
@@ -119,18 +127,16 @@ int GetTabOrWindowSessionId(content::BrowserContext* browser_context,
return window ? window->session_id().id() : -1;
}
-void SettingsChanged(Profile* profile) {
- const base::DictionaryValue* value = profile->GetPrefs()->GetDictionary(
- crostini::prefs::kCrostiniTerminalSettings);
-
+void PreferenceChanged(Profile* profile,
+ const std::string& pref_name,
+ extensions::events::HistogramValue histogram,
+ const char* eventName) {
auto args = std::make_unique<base::ListValue>();
- args->Append(value->CreateDeepCopy());
-
+ args->Append(profile->GetPrefs()->Get(pref_name)->CreateDeepCopy());
extensions::EventRouter* event_router = extensions::EventRouter::Get(profile);
if (event_router) {
- auto event = std::make_unique<extensions::Event>(
- extensions::events::TERMINAL_PRIVATE_ON_SETTINGS_CHANGED,
- terminal_private::OnSettingsChanged::kEventName, std::move(args));
+ auto event = std::make_unique<extensions::Event>(histogram, eventName,
+ std::move(args));
event_router->BroadcastEvent(std::move(event));
}
}
@@ -144,8 +150,20 @@ TerminalPrivateAPI::TerminalPrivateAPI(content::BrowserContext* context)
pref_change_registrar_(std::make_unique<PrefChangeRegistrar>()) {
Profile* profile = Profile::FromBrowserContext(context);
pref_change_registrar_->Init(profile->GetPrefs());
- pref_change_registrar_->Add(crostini::prefs::kCrostiniTerminalSettings,
- base::BindRepeating(&SettingsChanged, profile));
+ pref_change_registrar_->Add(
+ crostini::prefs::kCrostiniTerminalSettings,
+ base::BindRepeating(
+ &PreferenceChanged, profile,
+ crostini::prefs::kCrostiniTerminalSettings,
+ extensions::events::TERMINAL_PRIVATE_ON_SETTINGS_CHANGED,
+ terminal_private::OnSettingsChanged::kEventName));
+ pref_change_registrar_->Add(
+ ash::prefs::kAccessibilitySpokenFeedbackEnabled,
+ base::BindRepeating(
+ &PreferenceChanged, profile,
+ ash::prefs::kAccessibilitySpokenFeedbackEnabled,
+ extensions::events::TERMINAL_PRIVATE_ON_A11Y_STATUS_CHANGED,
+ terminal_private::OnA11yStatusChanged::kEventName));
}
TerminalPrivateAPI::~TerminalPrivateAPI() = default;
@@ -168,6 +186,13 @@ TerminalPrivateOpenTerminalProcessFunction::Run() {
OpenTerminalProcess::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
+ return OpenProcess(params->process_name, std::move(params->args));
+}
+
+ExtensionFunction::ResponseAction
+TerminalPrivateOpenTerminalProcessFunction::OpenProcess(
+ const std::string& process_name,
+ std::unique_ptr<std::vector<std::string>> args) {
const std::string& user_id_hash =
extensions::ExtensionsBrowserClient::Get()->GetUserIdHashFromContext(
browser_context());
@@ -195,7 +220,7 @@ TerminalPrivateOpenTerminalProcessFunction::Run() {
OpenProcess(user_id_hash, tab_id,
{command_line->GetSwitchValueASCII(switches::kCroshCommand)});
- } else if (params->process_name == kCroshName) {
+ } else if (process_name == kCroshName) {
// command=crosh: use '/usr/bin/crosh' on a device, 'cat' otherwise.
if (base::SysInfo::IsRunningOnChromeOS()) {
OpenProcess(user_id_hash, tab_id, {kCroshCommand});
@@ -203,14 +228,19 @@ TerminalPrivateOpenTerminalProcessFunction::Run() {
OpenProcess(user_id_hash, tab_id, {kStubbedCroshCommand});
}
- } else if (params->process_name == kVmShellName) {
+ } else if (process_name == kVmShellName) {
+ // Ensure crostini is allowed before starting terminal.
+ Profile* profile = Profile::FromBrowserContext(browser_context());
+ if (!crostini::CrostiniFeatures::Get()->IsAllowed(profile))
+ return RespondNow(Error("vmshell not allowed"));
+
// command=vmshell: ensure --owner_id, --vm_name, and --target_container are
// set and the specified vm/container is running.
base::CommandLine vmshell_cmd({kVmShellCommand});
- std::vector<std::string> args = {kVmShellCommand};
- if (params->args)
- args.insert(args.end(), params->args->begin(), params->args->end());
- base::CommandLine params_args(args);
+ if (!args)
+ args = std::make_unique<std::vector<std::string>>();
+ args->insert(args->begin(), kVmShellCommand);
+ base::CommandLine params_args(*args);
std::string owner_id =
GetSwitch(&params_args, &vmshell_cmd, kSwitchOwnerId, user_id_hash);
std::string vm_name = GetSwitch(&params_args, &vmshell_cmd, kSwitchVmName,
@@ -220,34 +250,58 @@ TerminalPrivateOpenTerminalProcessFunction::Run() {
crostini::kCrostiniDefaultContainerName);
std::string startup_id = params_args.GetSwitchValueASCII(kSwitchStartupId);
- auto open_process =
- base::BindOnce(&TerminalPrivateOpenTerminalProcessFunction::OpenProcess,
- this, user_id_hash, tab_id, vmshell_cmd.argv());
- auto* mgr = crostini::CrostiniManager::GetForProfile(
- Profile::FromBrowserContext(browser_context()));
+ auto* mgr = crostini::CrostiniManager::GetForProfile(profile);
bool verbose =
!mgr->GetContainerInfo(crostini::kCrostiniDefaultVmName,
crostini::kCrostiniDefaultContainerName)
.has_value();
- auto* observer = new CrostiniStartupStatus(
+ auto observer = std::make_unique<CrostiniStartupStatus>(
base::BindRepeating(&NotifyProcessOutput, browser_context(), tab_id,
startup_id,
api::terminal_private::ToString(
api::terminal_private::OUTPUT_TYPE_STDOUT)),
- verbose, std::move(open_process));
- observer->ShowStatusLineAtInterval();
+ verbose);
+ // Save copy of pointer for RestartObserver before moving object.
+ CrostiniStartupStatus* observer_ptr = observer.get();
+ observer->ShowProgressAtInterval();
mgr->RestartCrostini(
vm_name, container_name,
- base::BindOnce(&CrostiniStartupStatus::OnCrostiniRestarted,
- base::Unretained(observer)),
- observer);
+ base::BindOnce(
+ &TerminalPrivateOpenTerminalProcessFunction::OnCrostiniRestarted,
+ this, std::move(observer), user_id_hash, tab_id,
+ vmshell_cmd.argv()),
+ observer_ptr);
} else {
// command=[unrecognized].
- return RespondNow(Error("Invalid process name: " + params->process_name));
+ return RespondNow(Error("Invalid process name: " + process_name));
}
return RespondLater();
}
+void TerminalPrivateOpenTerminalProcessFunction::OnCrostiniRestarted(
+ std::unique_ptr<CrostiniStartupStatus> startup_status,
+ const std::string& user_id_hash,
+ int tab_id,
+ const std::vector<std::string>& arguments,
+ crostini::CrostiniResult result) {
+ if (crostini::MaybeShowCrostiniDialogBeforeLaunch(
+ Profile::FromBrowserContext(browser_context()), result)) {
+ const std::string msg = "Waiting for component update dialog response";
+ LOG(ERROR) << msg;
+ Respond(Error(msg));
+ return;
+ }
+ startup_status->OnCrostiniRestarted(result);
+ if (result == crostini::CrostiniResult::SUCCESS) {
+ OpenProcess(user_id_hash, tab_id, arguments);
+ } else {
+ const std::string msg =
+ base::StringPrintf("Error starting crostini for terminal: %d", result);
+ LOG(ERROR) << msg;
+ Respond(Error(msg));
+ }
+}
+
void TerminalPrivateOpenTerminalProcessFunction::OpenProcess(
const std::string& user_id_hash,
int tab_id,
@@ -273,7 +327,6 @@ void TerminalPrivateOpenTerminalProcessFunction::OpenOnRegistryTaskRunner(
chromeos::ProcessProxyRegistry* registry =
chromeos::ProcessProxyRegistry::Get();
const base::CommandLine cmdline{arguments};
-
std::string terminal_id;
bool success = registry->OpenProcess(cmdline, user_id_hash, output_callback,
&terminal_id);
@@ -282,6 +335,19 @@ void TerminalPrivateOpenTerminalProcessFunction::OpenOnRegistryTaskRunner(
base::BindOnce(callback, success, terminal_id));
}
+TerminalPrivateOpenVmshellProcessFunction::
+ ~TerminalPrivateOpenVmshellProcessFunction() = default;
+
+ExtensionFunction::ResponseAction
+TerminalPrivateOpenVmshellProcessFunction::Run() {
+ std::unique_ptr<OpenVmshellProcess::Params> params(
+ OpenVmshellProcess::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ // Only opens 'vmshell'.
+ return OpenProcess(kVmShellName, std::move(params->args));
+}
+
TerminalPrivateSendInputFunction::~TerminalPrivateSendInputFunction() = default;
void TerminalPrivateOpenTerminalProcessFunction::RespondOnUIThread(
@@ -459,6 +525,8 @@ TerminalPrivateGetSettingsFunction::~TerminalPrivateGetSettingsFunction() =
default;
ExtensionFunction::ResponseAction TerminalPrivateGetSettingsFunction::Run() {
+ crostini::RecordTerminalSettingsChangesUMAs(
+ Profile::FromBrowserContext(browser_context()));
PrefService* service =
Profile::FromBrowserContext(browser_context())->GetPrefs();
const base::DictionaryValue* value =
@@ -481,4 +549,15 @@ ExtensionFunction::ResponseAction TerminalPrivateSetSettingsFunction::Run() {
return RespondNow(NoArguments());
}
+TerminalPrivateGetA11yStatusFunction::~TerminalPrivateGetA11yStatusFunction() =
+ default;
+
+ExtensionFunction::ResponseAction TerminalPrivateGetA11yStatusFunction::Run() {
+ return RespondNow(
+ OneArgument(Profile::FromBrowserContext(browser_context())
+ ->GetPrefs()
+ ->Get(ash::prefs::kAccessibilitySpokenFeedbackEnabled)
+ ->CreateDeepCopy()));
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.h b/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.h
index a5345c329de..2f1961d86a5 100644
--- a/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.h
+++ b/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.h
@@ -5,9 +5,11 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_TERMINAL_TERMINAL_PRIVATE_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_TERMINAL_TERMINAL_PRIVATE_API_H_
+#include <memory>
#include <string>
#include <vector>
+#include "chrome/browser/chromeos/crostini/crostini_simple_types.h"
#include "chrome/browser/profiles/profile.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/extension_function.h"
@@ -17,6 +19,8 @@ class PrefChangeRegistrar;
namespace extensions {
+class CrostiniStartupStatus;
+
class TerminalPrivateAPI : public BrowserContextKeyedAPI {
public:
explicit TerminalPrivateAPI(content::BrowserContext* context);
@@ -49,7 +53,20 @@ class TerminalPrivateOpenTerminalProcessFunction : public ExtensionFunction {
ExtensionFunction::ResponseAction Run() override;
+ // Open the specified |process_name| with supplied |args|.
+ ExtensionFunction::ResponseAction OpenProcess(
+ const std::string& process_name,
+ std::unique_ptr<std::vector<std::string>> args);
+
private:
+ // Callback for when starting crostini is complete.
+ void OnCrostiniRestarted(
+ std::unique_ptr<CrostiniStartupStatus> startup_status,
+ const std::string& user_id_hash,
+ int tab_id,
+ const std::vector<std::string>& arguments,
+ crostini::CrostiniResult result);
+
using ProcessOutputCallback =
base::Callback<void(const std::string& terminal_id,
const std::string& output_type,
@@ -67,6 +84,19 @@ class TerminalPrivateOpenTerminalProcessFunction : public ExtensionFunction {
void RespondOnUIThread(bool success, const std::string& terminal_id);
};
+// Opens new vmshell process. Returns the new terminal id.
+class TerminalPrivateOpenVmshellProcessFunction
+ : public TerminalPrivateOpenTerminalProcessFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("terminalPrivate.openVmshellProcess",
+ TERMINALPRIVATE_OPENVMSHELLPROCESS)
+
+ protected:
+ ~TerminalPrivateOpenVmshellProcessFunction() override;
+
+ ExtensionFunction::ResponseAction Run() override;
+};
+
// Send input to the terminal process specified by the terminal ID, which is set
// as an argument.
class TerminalPrivateSendInputFunction : public ExtensionFunction {
@@ -171,6 +201,17 @@ class TerminalPrivateSetSettingsFunction : public ExtensionFunction {
ExtensionFunction::ResponseAction Run() override;
};
+class TerminalPrivateGetA11yStatusFunction : public ExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("terminalPrivate.getA11yStatus",
+ TERMINALPRIVATE_GETA11YSTATUS)
+
+ protected:
+ ~TerminalPrivateGetA11yStatusFunction() override;
+
+ ExtensionFunction::ResponseAction Run() override;
+};
+
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_TERMINAL_TERMINAL_PRIVATE_API_H_
diff --git a/chromium/chrome/browser/extensions/api/terminal/terminal_private_browsertest.cc b/chromium/chrome/browser/extensions/api/terminal/terminal_private_browsertest.cc
new file mode 100644
index 00000000000..81de7f37d48
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/terminal/terminal_private_browsertest.cc
@@ -0,0 +1,68 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/chromeos/crostini/fake_crostini_features.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/browser_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace extensions {
+
+class TerminalPrivateBrowserTest : public InProcessBrowserTest {
+ public:
+ TerminalPrivateBrowserTest() {
+ scoped_feature_list_.InitAndEnableFeature(features::kTerminalSystemApp);
+ }
+
+ protected:
+ void ExpectJsResult(const std::string& script, const std::string& expected) {
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ content::EvalJsResult eval_result =
+ EvalJs(web_contents, script, content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+ /*world_id=*/1);
+ EXPECT_EQ(eval_result.value.GetString(), expected);
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ DISALLOW_COPY_AND_ASSIGN(TerminalPrivateBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(TerminalPrivateBrowserTest, OpenTerminalProcessChecks) {
+ ui_test_utils::NavigateToURL(
+ browser(), GURL("chrome-untrusted://terminal/html/terminal.html"));
+
+ const std::string script = R"(new Promise((resolve) => {
+ chrome.terminalPrivate.openVmshellProcess([], () => {
+ const lastError = chrome.runtime.lastError;
+ resolve(lastError ? lastError.message : "success");
+ })}))";
+
+ // 'vmshell not allowed' when crostini is not allowed.
+ crostini::FakeCrostiniFeatures crostini_features;
+ crostini_features.set_allowed(false);
+ ExpectJsResult(script, "vmshell not allowed");
+
+ // 'Error starting crostini for terminal: 22' when crostini is allowed.
+ // This is the specific error we expect to see in a test environment
+ // (LOAD_COMPONENT_FAILED), but the point of the test is to see that we get
+ // past the vmshell allowed checks.
+ crostini_features.set_allowed(true);
+ ExpectJsResult(script, "Waiting for component update dialog response");
+
+ // openTerminalProcess not defined.
+ ExpectJsResult("typeof chrome.terminalPrivate.openTerminalProcess",
+ "undefined");
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.cc b/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.cc
index c94337d34a8..65817e7d145 100644
--- a/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.cc
+++ b/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.cc
@@ -28,7 +28,7 @@ ExtensionFunction::ResponseAction TopSitesGetFunction::Run() {
return RespondNow(Error(kUnknownErrorDoNotUse));
ts->GetMostVisitedURLs(
- base::Bind(&TopSitesGetFunction::OnMostVisitedURLsAvailable, this));
+ base::BindOnce(&TopSitesGetFunction::OnMostVisitedURLsAvailable, this));
// GetMostVisitedURLs() will invoke the callback synchronously if the URLs are
// already populated.
diff --git a/chromium/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc b/chromium/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
index 1c278c1b36a..ff0e2d0879a 100644
--- a/chromium/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/top_sites/top_sites_apitest.cc
@@ -39,7 +39,7 @@ class TopSitesExtensionTest : public InProcessBrowserTest {
// This may return async or sync. If sync, top_sites_inited_ will be true
// before we get to the conditional below. Otherwise, we'll run a nested
// message loop until the async callback.
- top_sites->GetMostVisitedURLs(base::Bind(
+ top_sites->GetMostVisitedURLs(base::BindOnce(
&TopSitesExtensionTest::OnTopSitesAvailable, base::Unretained(this)));
if (!top_sites_inited_) {
diff --git a/chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index 060590f6dcc..86e7906c504 100644
--- a/chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -25,14 +25,12 @@
#include "chrome/common/url_constants.h"
#include "chromeos/constants/chromeos_features.h"
#include "components/user_manager/user_manager.h"
+#include "content/public/browser/audio_service.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/system_connector.h"
#include "extensions/browser/event_router.h"
#include "extensions/common/api/virtual_keyboard.h"
#include "extensions/common/api/virtual_keyboard_private.h"
#include "media/audio/audio_system.h"
-#include "services/audio/public/cpp/audio_system_factory.h"
-#include "services/service_manager/public/cpp/connector.h"
#include "ui/aura/event_injector.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/constants.h"
@@ -172,10 +170,8 @@ ChromeVirtualKeyboardDelegate::~ChromeVirtualKeyboardDelegate() {}
void ChromeVirtualKeyboardDelegate::GetKeyboardConfig(
OnKeyboardSettingsCallback on_settings_callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (!audio_system_) {
- audio_system_ =
- audio::CreateAudioSystem(content::GetSystemConnector()->Clone());
- }
+ if (!audio_system_)
+ audio_system_ = content::CreateAudioSystemForAudioService();
audio_system_->HasInputDevices(
base::BindOnce(&ChromeVirtualKeyboardDelegate::OnHasInputDevices,
weak_this_, std::move(on_settings_callback)));
@@ -308,7 +304,7 @@ bool ChromeVirtualKeyboardDelegate::SetDraggableArea(
const api::virtual_keyboard_private::Bounds& rect) {
auto* keyboard_client = ChromeKeyboardControllerClient::Get();
// Since controller will be destroyed when system switch from VK to
- // physical keyboard, return true to avoid unneccessary exception.
+ // physical keyboard, return true to avoid unnecessary exception.
if (!keyboard_client->is_keyboard_enabled())
return true;
@@ -386,24 +382,26 @@ void ChromeVirtualKeyboardDelegate::OnHasInputDevices(
"handwritinggesture",
base::FeatureList::IsEnabled(features::kHandwritingGesture)));
features->AppendString(GenerateFeatureFlag(
- "usemojodecoder", base::FeatureList::IsEnabled(
- chromeos::features::kImeDecoderWithSandbox)));
+ "floatingkeyboarddefault",
+ base::FeatureList::IsEnabled(
+ chromeos::features::kVirtualKeyboardFloatingDefault)));
features->AppendString(GenerateFeatureFlag(
- "hmminputlogic",
- base::FeatureList::IsEnabled(chromeos::features::kImeInputLogicHmm)));
+ "imemozcproto",
+ base::FeatureList::IsEnabled(chromeos::features::kImeMozcProto)));
+ // 3 flags below are used to enable IME new APIs on each decoder.
features->AppendString(GenerateFeatureFlag(
"fstinputlogic",
base::FeatureList::IsEnabled(chromeos::features::kImeInputLogicFst)));
features->AppendString(GenerateFeatureFlag(
- "fstnonenglish",
- base::FeatureList::IsEnabled(chromeos::features::kImeInputLogicFst)));
- features->AppendString(GenerateFeatureFlag(
- "floatingkeyboarddefault",
- base::FeatureList::IsEnabled(
- chromeos::features::kVirtualKeyboardFloatingDefault)));
+ "hmminputlogic",
+ base::FeatureList::IsEnabled(chromeos::features::kImeInputLogicHmm)));
features->AppendString(GenerateFeatureFlag(
"mozcinputlogic",
base::FeatureList::IsEnabled(chromeos::features::kImeInputLogicMozc)));
+ // Flag used to enable decoder Mojo APIs instead of NaCl APIs.
+ features->AppendString(GenerateFeatureFlag(
+ "usemojodecoder", base::FeatureList::IsEnabled(
+ chromeos::features::kImeDecoderWithSandbox)));
features->AppendString(GenerateFeatureFlag(
"borderedkey", base::FeatureList::IsEnabled(
chromeos::features::kVirtualKeyboardBorderedKey)));
@@ -411,6 +409,12 @@ void ChromeVirtualKeyboardDelegate::OnHasInputDevices(
"resizablefloatingkeyboard",
base::FeatureList::IsEnabled(
chromeos::features::kVirtualKeyboardFloatingResizable)));
+ features->AppendString(GenerateFeatureFlag(
+ "assistiveAutoCorrect",
+ base::FeatureList::IsEnabled(chromeos::features::kAssistAutoCorrect)));
+ features->AppendString(GenerateFeatureFlag(
+ "nativerulebased", base::FeatureList::IsEnabled(
+ chromeos::features::kNativeRuleBasedTyping)));
results->Set("features", std::move(features));
diff --git a/chromium/chrome/browser/extensions/api/vpn_provider/OWNERS b/chromium/chrome/browser/extensions/api/vpn_provider/OWNERS
index a913a05204b..e1cacf4d8ab 100644
--- a/chromium/chrome/browser/extensions/api/vpn_provider/OWNERS
+++ b/chromium/chrome/browser/extensions/api/vpn_provider/OWNERS
@@ -1,2 +1,4 @@
bartfab@chromium.org
emaxx@chromium.org
+
+# COMPONENT: Enterprise
diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
index 4c7a4ed1b8d..edd6f2da449 100644
--- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
+++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -73,7 +73,7 @@ void WebNavigationEventRouter::PendingWebContents::WebContentsDestroyed() {
}
WebNavigationEventRouter::WebNavigationEventRouter(Profile* profile)
- : profile_(profile), browser_tab_strip_tracker_(this, this, nullptr) {
+ : profile_(profile), browser_tab_strip_tracker_(this, this) {
browser_tab_strip_tracker_.Init();
}
@@ -311,10 +311,9 @@ void WebNavigationTabObserver::DidFinishLoad(
void WebNavigationTabObserver::DidFailLoad(
content::RenderFrameHost* render_frame_host,
const GURL& validated_url,
- int error_code,
- const base::string16& error_description) {
+ int error_code) {
// When showing replacement content, we might get load signals for frames
- // that weren't reguarly loaded.
+ // that weren't regularly loaded.
if (!navigation_state_.IsValidFrame(render_frame_host))
return;
diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
index 2bfcc079c5c..497cab0dc73 100644
--- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
+++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
@@ -15,7 +15,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "chrome/browser/extensions/api/web_navigation/frame_navigation_state.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_tab_strip_tracker.h"
#include "chrome/browser/ui/browser_tab_strip_tracker_delegate.h"
@@ -24,6 +23,7 @@
#include "content/public/browser/web_contents_user_data.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_function.h"
#include "url/gurl.h"
namespace extensions {
@@ -56,8 +56,7 @@ class WebNavigationTabObserver
const GURL& validated_url) override;
void DidFailLoad(content::RenderFrameHost* render_frame_host,
const GURL& validated_url,
- int error_code,
- const base::string16& error_description) override;
+ int error_code) override;
void DidOpenRequestedURL(content::WebContents* new_contents,
content::RenderFrameHost* source_render_frame_host,
const GURL& url,
diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index 9ae3e1dd655..93cc46fb3e7 100644
--- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -30,14 +30,13 @@
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/context_menu_params.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/context_menu_params.h"
-#include "content/public/common/resource_type.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
@@ -51,9 +50,8 @@
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "third_party/blink/public/common/context_menu_data/media_type.h"
-#include "third_party/blink/public/platform/web_input_event.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
-using content::ResourceType;
using content::WebContents;
namespace extensions {
@@ -215,16 +213,9 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, Api) {
ASSERT_TRUE(RunExtensionTest("webnavigation/api")) << message_;
}
-// Flaky on Windows Linux and Chrome OS. See http://crbug.com/874782.
-#if defined(OS_WIN) || defined(OS_CHROMEOS) || defined(OS_LINUX)
-#define MAYBE_GetFrame DISABLED_GetFrame
-#else
-#define MAYBE_GetFrame GetFrame
-#endif
-IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_GetFrame) {
+IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, GetFrame) {
ASSERT_TRUE(RunExtensionTest("webnavigation/getFrame")) << message_;
}
-#undef MAYBE_GetFrame
IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ClientRedirect) {
ASSERT_TRUE(RunExtensionTest("webnavigation/clientRedirect"))
@@ -324,14 +315,7 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, SimpleLoad) {
ASSERT_TRUE(RunExtensionTest("webnavigation/simpleLoad")) << message_;
}
-// Flaky on Windows, Mac and Linux. See http://crbug.com/477480 (Windows) and
-// https://crbug.com/746407 (Mac, Linux).
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
-#define MAYBE_Failures DISABLED_Failures
-#else
-#define MAYBE_Failures Failures
-#endif
-IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_Failures) {
+IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, Failures) {
ASSERT_TRUE(RunExtensionTest("webnavigation/failures")) << message_;
}
diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 5b47f142c93..5783a667590 100644
--- a/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -4,6 +4,7 @@
#include <memory>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
@@ -12,6 +13,7 @@
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "base/run_loop.h"
+#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
#include "base/task/post_task.h"
@@ -80,6 +82,7 @@
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/simple_url_loader_test_helper.h"
#include "content/public/test/url_loader_interceptor.h"
+#include "content/public/test/url_loader_monitor.h"
#include "extensions/browser/api/web_request/web_request_api.h"
#include "extensions/browser/blocked_action_type.h"
#include "extensions/browser/extension_prefs.h"
@@ -94,6 +97,8 @@
#include "google_apis/gaia/gaia_switches.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/network_isolation_key.h"
+#include "net/cookies/site_for_cookies.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_util.h"
#include "net/test/embedded_test_server/default_handlers.h"
@@ -110,8 +115,9 @@
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/test/test_url_loader_client.h"
-#include "third_party/blink/public/platform/web_input_event.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
#include "ui/base/ui_base_features.h"
+#include "url/origin.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/profiles/profile_helper.h"
@@ -521,12 +527,21 @@ class ExtensionWebRequestApiAuthRequiredTest
: public ExtensionWebRequestApiTest,
public testing::WithParamInterface<ProfileMode> {
public:
- int GetFlags() {
+ int GetBrowserTestFlags() {
switch (GetParam()) {
case ProfileMode::kUserProfile:
return kFlagEnableFileAccess;
case ProfileMode::kIncognito:
- return kFlagEnableIncognito | kFlagUseIncognito | kFlagEnableFileAccess;
+ return kFlagEnableIncognito | kFlagEnableFileAccess;
+ }
+ }
+
+ int GetApiTestFlags() {
+ switch (GetParam()) {
+ case ProfileMode::kUserProfile:
+ return kFlagNone;
+ case ProfileMode::kIncognito:
+ return kFlagUseIncognito;
}
}
};
@@ -540,7 +555,8 @@ IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiAuthRequiredTest,
// Pass "debug" as a custom arg to debug test flakiness.
ASSERT_TRUE(RunExtensionSubtestWithArgAndFlags(
- "webrequest", "test_auth_required.html", "debug", GetFlags()))
+ "webrequest", "test_auth_required.html", "debug", GetBrowserTestFlags(),
+ GetApiTestFlags()))
<< message_;
}
@@ -554,7 +570,8 @@ IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiAuthRequiredTest,
// Pass "debug" as a custom arg to debug test flakiness.
ASSERT_TRUE(RunExtensionSubtestWithArgAndFlags(
- "webrequest", "test_auth_required_async.html", "debug", GetFlags()))
+ "webrequest", "test_auth_required_async.html", "debug",
+ GetBrowserTestFlags(), GetApiTestFlags()))
<< message_;
}
@@ -566,7 +583,8 @@ IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiAuthRequiredTest,
ASSERT_TRUE(StartEmbeddedTestServer());
ASSERT_TRUE(RunExtensionSubtestWithArgAndFlags(
- "webrequest", "test_auth_required_parallel.html", nullptr, GetFlags()))
+ "webrequest", "test_auth_required_parallel.html", nullptr,
+ GetBrowserTestFlags(), GetApiTestFlags()))
<< message_;
}
@@ -599,15 +617,9 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
<< message_;
}
-// Flaky on ChromeOS: https://crbug.com/1003661 and Linux:
-// https://crbug.com/1864717
-#if defined(OS_CHROMEOS) || defined(OS_LINUX)
-#define MAYBE_WebRequestExtraHeaders DISABLED_WebRequestExtraHeaders
-#else
-#define MAYBE_WebRequestExtraHeaders WebRequestExtraHeaders
-#endif
+// Flaky on all platforms: https://crbug.com/1003661
IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
- MAYBE_WebRequestExtraHeaders) {
+ DISABLED_WebRequestExtraHeaders) {
CancelLoginDialog login_dialog_helper;
ASSERT_TRUE(StartEmbeddedTestServer());
@@ -620,6 +632,8 @@ enum class ExtraHeadersRequirementMode {
kDisabled,
kEnabledWithCorsLegacyModeEnabledPolicy,
kEnabledWithCorsMitigationListPolicy,
+ kEnabledWithHiddenCorsLegacyModeEnabledPolicy,
+ kEnabledWithHiddenCorsMitigationListPolicy,
};
class ExtensionWebRequestApiPolicyTest
@@ -644,17 +658,41 @@ class ExtensionWebRequestApiPolicyTest
test_name_ += "?cors_mode=blink";
break;
case ExtraHeadersRequirementMode::kEnabledWithCorsLegacyModeEnabledPolicy:
- feature_list_.InitAndEnableFeature(network::features::kOutOfBlinkCors);
+ feature_list_.InitWithFeatures(
+ {network::features::kOutOfBlinkCors},
+ {features::kHideCorsLegacyModeEnabledPolicySupport});
UpdatePolicy(policy::key::kCorsLegacyModeEnabled,
std::make_unique<base::Value>(true));
test_name_ += "?cors_mode=blink";
break;
case ExtraHeadersRequirementMode::kEnabledWithCorsMitigationListPolicy:
- feature_list_.InitAndEnableFeature(network::features::kOutOfBlinkCors);
+ feature_list_.InitWithFeatures(
+ {network::features::kOutOfBlinkCors},
+ {features::kHideCorsMitigationListPolicySupport});
UpdatePolicy(policy::key::kCorsMitigationList,
std::make_unique<base::ListValue>());
test_name_ += "?cors_mode=network_service&with_force_extra_headers";
break;
+ case ExtraHeadersRequirementMode::
+ kEnabledWithHiddenCorsLegacyModeEnabledPolicy:
+ feature_list_.InitWithFeatures(
+ {features::kHideCorsLegacyModeEnabledPolicySupport,
+ network::features::kOutOfBlinkCors},
+ {});
+ UpdatePolicy(policy::key::kCorsLegacyModeEnabled,
+ std::make_unique<base::Value>(true));
+ test_name_ += "?cors_mode=network_service";
+ break;
+ case ExtraHeadersRequirementMode::
+ kEnabledWithHiddenCorsMitigationListPolicy:
+ feature_list_.InitWithFeatures(
+ {features::kHideCorsMitigationListPolicySupport,
+ network::features::kOutOfBlinkCors},
+ {});
+ UpdatePolicy(policy::key::kCorsMitigationList,
+ std::make_unique<base::ListValue>());
+ test_name_ += "?cors_mode=network_service";
+ break;
}
ExtensionWebRequestApiTest::SetUpInProcessBrowserTestFixture();
@@ -675,15 +713,8 @@ class ExtensionWebRequestApiPolicyTest
std::string test_name_ = "test_cors.html";
};
-// Flaky on Win10: http://crbug.com/1020185
-#if defined(OS_WIN)
-#define MAYBE_WebRequestCORSWithExtraHeaders \
- DISABLED_WebRequestCORSWithExtraHeaders
-#else
-#define MAYBE_WebRequestCORSWithExtraHeaders WebRequestCORSWithExtraHeaders
-#endif
IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiPolicyTest,
- MAYBE_WebRequestCORSWithExtraHeaders) {
+ WebRequestCORSWithExtraHeaders) {
ASSERT_TRUE(StartEmbeddedTestServer());
ASSERT_TRUE(RunExtensionSubtest("webrequest", test_name())) << message_;
}
@@ -710,6 +741,18 @@ INSTANTIATE_TEST_SUITE_P(
testing::Values(
ExtraHeadersRequirementMode::kEnabledWithCorsMitigationListPolicy));
+INSTANTIATE_TEST_SUITE_P(
+ EnabledWithHiddenCorsLegacyModeEnabledPolicy,
+ ExtensionWebRequestApiPolicyTest,
+ testing::Values(ExtraHeadersRequirementMode::
+ kEnabledWithHiddenCorsLegacyModeEnabledPolicy));
+
+INSTANTIATE_TEST_SUITE_P(
+ EnabledWithHiddenCorsMitigationListPolicy,
+ ExtensionWebRequestApiPolicyTest,
+ testing::Values(ExtraHeadersRequirementMode::
+ kEnabledWithHiddenCorsMitigationListPolicy));
+
IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestRedirects) {
ASSERT_TRUE(StartEmbeddedTestServer());
ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_redirects.html"))
@@ -1370,7 +1413,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
auto request = std::make_unique<network::ResourceRequest>();
request->url = url;
request->resource_type =
- static_cast<int>(content::ResourceType::kSubResource);
+ static_cast<int>(blink::mojom::ResourceType::kSubResource);
auto* url_loader_factory =
content::BrowserContext::GetDefaultStoragePartition(profile())
@@ -2188,7 +2231,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy,
// Wait until all remote Javascript files have been blocked / pulled down.
ui_test_utils::NavigateToURLWithDisposition(
browser(), extension_test_url, WindowOpenDisposition::CURRENT_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// Domain that hosts javascript file referenced by example_com.
const std::string example2_com = "example2.com";
@@ -2217,7 +2260,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy,
// Wait until all remote Javascript files have been pulled down.
ui_test_utils::NavigateToURLWithDisposition(
browser(), extension_test_url, WindowOpenDisposition::CURRENT_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// The server saw a request for the remote Javascript file.
EXPECT_TRUE(BrowsedTo(example2_com));
@@ -2254,7 +2297,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy,
ui_test_utils::NavigateToURLWithDisposition(
browser(), embedded_test_server()->GetURL(protected_domain, test_path),
WindowOpenDisposition::CURRENT_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// The server saw a request for the protected site.
EXPECT_TRUE(BrowsedTo(protected_domain));
@@ -2270,7 +2313,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy,
ui_test_utils::NavigateToURLWithDisposition(
browser(), embedded_test_server()->GetURL(unprotected_domain, test_path),
WindowOpenDisposition::CURRENT_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
// The server saw a request for the non-protected site.
EXPECT_TRUE(BrowsedTo(unprotected_domain));
@@ -2718,7 +2761,7 @@ class ServiceWorkerWebRequestApiTest : public testing::WithParamInterface<bool>,
}
};
-INSTANTIATE_TEST_SUITE_P(/* No prefix */,
+INSTANTIATE_TEST_SUITE_P(All,
ServiceWorkerWebRequestApiTest,
::testing::Bool());
@@ -2735,6 +2778,30 @@ IN_PROC_BROWSER_TEST_P(ServiceWorkerWebRequestApiTest,
RunServiceWorkerFetchTest("empty.js");
}
+IN_PROC_BROWSER_TEST_P(ServiceWorkerWebRequestApiTest,
+ ServiceWorkerFallbackAfterRedirect) {
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ InstallRequestHeaderModifyingExtension();
+
+ RegisterServiceWorker("/fetch_event_passthrough.js", "/echoheader");
+
+ // Make sure the request is intercepted with no redirect.
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/echoheader?foo"));
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ EXPECT_EQ("bar", EvalJs(web_contents, "document.body.textContent;"));
+
+ // Make sure the request is intercepted with a redirect.
+ GURL redirect_url = embedded_test_server()->GetURL(
+ "/server-redirect?" +
+ embedded_test_server()->GetURL("/echoheader?foo").spec());
+ ui_test_utils::NavigateToURL(browser(), redirect_url);
+ EXPECT_EQ("bar", EvalJs(web_contents, "document.body.textContent;"));
+}
+
// An extension should be able to modify the request header for service worker
// script by using WebRequest API.
IN_PROC_BROWSER_TEST_P(ServiceWorkerWebRequestApiTest, ServiceWorkerScript) {
@@ -2920,7 +2987,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, Initiator_SplitIncognito) {
will_reply);
const Extension* extension = LoadExtensionWithFlags(
test_data_dir_.AppendASCII("webrequest").AppendASCII("initiator_split"),
- ExtensionBrowserTest::kFlagEnableIncognito);
+ kFlagEnableIncognito);
ASSERT_TRUE(extension);
EXPECT_TRUE(ready_listener.WaitUntilSatisfied());
@@ -3067,6 +3134,55 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, AppCacheRequests) {
1);
}
+// Regression test for http://crbug.com/996940. Requests that redirected to an
+// appcache handled URL could have request ID collisions.
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, RedirectToAppCacheRequest) {
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(StartEmbeddedTestServer());
+
+ GURL main_url = embedded_test_server()->GetURL(
+ "/appcache/simple_page_with_manifest.html");
+
+ base::string16 expected_title = base::ASCIIToUTF16("AppCache updated");
+
+ // Load the main page first to make sure it is cached. After the first
+ // navigation, load the extension, then navigate again.
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
+ content::TitleWatcher title_watcher(
+ browser()->tab_strip_model()->GetActiveWebContents(), expected_title);
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ TestExtensionDir test_dir;
+ test_dir.WriteManifest(R"({
+ "name": "Web Request Appcache Redirect Test",
+ "manifest_version": 2,
+ "version": "0.1",
+ "background": { "scripts": ["background.js"] },
+ "permissions": ["<all_urls>", "webRequest"]
+ })");
+ test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), R"(
+ window.numErrors = 0;
+ chrome.webRequest.onErrorOccurred.addListener(function(details) {
+ window.numErrors++;
+ }, {urls: ['<all_urls>']});
+
+ chrome.test.sendMessage('ready');
+ )");
+
+ ExtensionTestMessageListener listener("ready", false);
+ const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+ ASSERT_TRUE(extension);
+ EXPECT_TRUE(listener.WaitUntilSatisfied());
+
+ // This navigation should go through appcache.
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(
+ browser(),
+ embedded_test_server()->GetURL("/server-redirect?" + main_url.spec())));
+
+ EXPECT_EQ(
+ GetCountFromBackgroundPage(extension, profile(), "window.numErrors"), 0);
+}
+
// Regression test for https://crbug.com/1019614.
IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, HSTSUpgradeAfterRedirect) {
net::EmbeddedTestServer https_test_server(
@@ -3119,4 +3235,138 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, HSTSUpgradeAfterRedirect) {
EXPECT_EQ(final_url, web_contents->GetLastCommittedURL());
}
+enum class RedirectType {
+ kOnBeforeRequest,
+ kOnHeadersReceived,
+};
+
+class RedirectInfoWebRequestApiTest
+ : public testing::WithParamInterface<RedirectType>,
+ public ExtensionApiTest {
+ public:
+ void SetUpOnMainThread() override {
+ ExtensionApiTest::SetUpOnMainThread();
+ host_resolver()->AddRule("*", "127.0.0.1");
+ embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ }
+
+ void InstallRequestRedirectingExtension(const std::string& resource_type) {
+ TestExtensionDir test_dir;
+ test_dir.WriteManifest(R"({
+ "name": "Simple Redirect",
+ "manifest_version": 2,
+ "version": "0.1",
+ "background": { "scripts": ["background.js"] },
+ "permissions": ["<all_urls>", "webRequest", "webRequestBlocking"]
+ })");
+ test_dir.WriteFile(
+ FILE_PATH_LITERAL("background.js"),
+ base::StringPrintf(R"(
+ chrome.webRequest.%s.addListener(function(details) {
+ if (details.type == '%s' &&
+ details.url.includes('hello.html')) {
+ var redirectUrl =
+ details.url.replace('original.test', 'redirected.test');
+ return {redirectUrl: redirectUrl};
+ }
+ }, {urls: ['*://original.test/*']}, ['blocking']);
+ chrome.test.sendMessage('ready');
+ )",
+ GetParam() == RedirectType::kOnBeforeRequest
+ ? "onBeforeRequest"
+ : "onHeadersReceived",
+ resource_type.c_str()));
+ ExtensionTestMessageListener listener("ready", false);
+ const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+ ASSERT_TRUE(extension);
+ EXPECT_TRUE(listener.WaitUntilSatisfied());
+ }
+
+ private:
+ TestExtensionDir test_dir_;
+};
+
+INSTANTIATE_TEST_SUITE_P(RedirectMode,
+ RedirectInfoWebRequestApiTest,
+ ::testing::Values(RedirectType::kOnBeforeRequest,
+ RedirectType::kOnHeadersReceived));
+
+// Test that a main frame request redirected by an extension has the correct
+// site_for_cookies and network_isolation_key parameters.
+IN_PROC_BROWSER_TEST_P(RedirectInfoWebRequestApiTest,
+ VerifyRedirectInfoMainFrame) {
+ InstallRequestRedirectingExtension("main_frame");
+
+ content::URLLoaderMonitor monitor;
+
+ // Navigate to the URL that should be redirected, and check that the extension
+ // redirects it.
+ GURL url = embedded_test_server()->GetURL("original.test", "/hello.html");
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(web_contents);
+ GURL redirected_url =
+ embedded_test_server()->GetURL("redirected.test", "/hello.html");
+ EXPECT_EQ(redirected_url, web_contents->GetLastCommittedURL());
+
+ // Check the parameters passed to the URLLoaderFactory.
+ base::Optional<network::ResourceRequest> resource_request =
+ monitor.GetRequestInfo(redirected_url);
+ ASSERT_TRUE(resource_request.has_value());
+ EXPECT_TRUE(resource_request->site_for_cookies.IsFirstParty(redirected_url));
+ ASSERT_TRUE(resource_request->trusted_params);
+ url::Origin redirected_origin = url::Origin::Create(redirected_url);
+ EXPECT_EQ(resource_request->trusted_params->network_isolation_key,
+ net::NetworkIsolationKey(redirected_origin, redirected_origin));
+}
+
+// Test that a sub frame request redirected by an extension has the correct
+// site_for_cookies and network_isolation_key parameters.
+IN_PROC_BROWSER_TEST_P(RedirectInfoWebRequestApiTest,
+ VerifyBeforeRequestRedirectInfoSubFrame) {
+ InstallRequestRedirectingExtension("sub_frame");
+
+ content::URLLoaderMonitor monitor;
+
+ // Navigate to page with an iframe that should be redirected, and check that
+ // the extension redirects it.
+ GURL original_iframed_url =
+ embedded_test_server()->GetURL("original.test", "/hello.html");
+ GURL page_with_iframe_url = embedded_test_server()->GetURL(
+ "somewhere-else.test",
+ net::test_server::GetFilePathWithReplacements(
+ "/page_with_iframe.html",
+ base::StringPairs{
+ {"title1.html", original_iframed_url.spec().c_str()}}));
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), page_with_iframe_url));
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(web_contents);
+ EXPECT_EQ(page_with_iframe_url, web_contents->GetLastCommittedURL());
+
+ // Since frames are returned in breadth first order, and there's only one
+ // iframe, the iframe should be the second frame in this vector.
+ std::vector<content::RenderFrameHost*> all_frames =
+ web_contents->GetAllFrames();
+ ASSERT_EQ(2u, all_frames.size());
+ GURL redirected_url =
+ embedded_test_server()->GetURL("redirected.test", "/hello.html");
+ ASSERT_EQ(redirected_url, all_frames[1]->GetLastCommittedURL());
+
+ // Check the parameters passed to the URLLoaderFactory.
+ base::Optional<network::ResourceRequest> resource_request =
+ monitor.GetRequestInfo(redirected_url);
+ ASSERT_TRUE(resource_request.has_value());
+ EXPECT_TRUE(
+ resource_request->site_for_cookies.IsFirstParty(page_with_iframe_url));
+ EXPECT_FALSE(resource_request->site_for_cookies.IsFirstParty(redirected_url));
+ ASSERT_TRUE(resource_request->trusted_params);
+ url::Origin top_level_origin = url::Origin::Create(page_with_iframe_url);
+ url::Origin redirected_origin = url::Origin::Create(redirected_url);
+ EXPECT_EQ(resource_request->trusted_params->network_isolation_key,
+ net::NetworkIsolationKey(top_level_origin, redirected_origin));
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_event_details_unittest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_event_details_unittest.cc
index 3739ff2aa03..6b57d40ab2c 100644
--- a/chromium/chrome/browser/extensions/api/web_request/web_request_event_details_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/web_request/web_request_event_details_unittest.cc
@@ -27,7 +27,6 @@ TEST(WebRequestEventDetailsTest, WhitelistedCopyForPublicSession) {
};
orig->render_process_id_ = 1;
- orig->render_frame_id_ = 2;
orig->extra_info_spec_ = 3;
orig->request_body_.reset(new base::DictionaryValue);
@@ -49,7 +48,6 @@ TEST(WebRequestEventDetailsTest, WhitelistedCopyForPublicSession) {
orig->CreatePublicSessionCopy();
EXPECT_EQ(orig->render_process_id_, copy->render_process_id_);
- EXPECT_EQ(orig->render_frame_id_, copy->render_frame_id_);
EXPECT_EQ(0, copy->extra_info_spec_);
EXPECT_EQ(nullptr, copy->request_body_);
diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
index d58a7afb20d..51f8e47f2d0 100644
--- a/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
@@ -112,7 +112,8 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, LocalNTPRequests) {
const GURL example_com("http://example.com");
auto create_request_params =
- [&example_com](const url::Origin& initiator, content::ResourceType type,
+ [&example_com](const url::Origin& initiator,
+ blink::mojom::ResourceType type,
extensions::WebRequestResourceType web_request_type,
bool is_navigation_request) {
WebRequestInfoInitParams info_params;
@@ -129,15 +130,15 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, LocalNTPRequests) {
url::Origin::Create(GURL(chrome::kChromeSearchLocalNtpUrl));
// Sub-resource browser initiated requests are hidden from extensions.
- WebRequestInfoInitParams info_params_1 =
- create_request_params(ntp_origin, content::ResourceType::kSubResource,
- extensions::WebRequestResourceType::OTHER, false);
+ WebRequestInfoInitParams info_params_1 = create_request_params(
+ ntp_origin, blink::mojom::ResourceType::kSubResource,
+ extensions::WebRequestResourceType::OTHER, false);
EXPECT_TRUE(WebRequestPermissions::HideRequest(
permission_helper_, WebRequestInfo(std::move(info_params_1))));
// Sub-frame navigations initiated from the local ntp should be hidden.
WebRequestInfoInitParams info_params_2 = create_request_params(
- ntp_origin, content::ResourceType::kSubFrame,
+ ntp_origin, blink::mojom::ResourceType::kSubFrame,
extensions::WebRequestResourceType::SUB_FRAME, true);
EXPECT_TRUE(WebRequestPermissions::HideRequest(
permission_helper_, WebRequestInfo(std::move(info_params_2))));
@@ -145,7 +146,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, LocalNTPRequests) {
// Sub-frame navigations initiated from a non-sensitive domain should not be
// hidden.
WebRequestInfoInitParams info_params_3 = create_request_params(
- url::Origin::Create(example_com), content::ResourceType::kSubFrame,
+ url::Origin::Create(example_com), blink::mojom::ResourceType::kSubFrame,
extensions::WebRequestResourceType::SUB_FRAME, true);
EXPECT_FALSE(WebRequestPermissions::HideRequest(
permission_helper_, WebRequestInfo(std::move(info_params_3))));
@@ -154,8 +155,8 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, LocalNTPRequests) {
TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest,
TestCanExtensionAccessURL_HostPermissions) {
const GURL url("http://example.com");
- const content::ResourceType kResourceType =
- content::ResourceType::kSubResource;
+ const blink::mojom::ResourceType kResourceType =
+ blink::mojom::ResourceType::kSubResource;
EXPECT_EQ(PermissionsData::PageAccess::kAllowed,
WebRequestPermissions::CanExtensionAccessURL(
@@ -235,7 +236,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest,
-1, // No tab id.
false, // crosses_incognito
WebRequestPermissions::REQUIRE_HOST_PERMISSION_FOR_URL_AND_INITIATOR,
- initiator, content::ResourceType::kSubFrame));
+ initiator, blink::mojom::ResourceType::kSubFrame));
EXPECT_EQ(
PermissionsData::PageAccess::kDenied,
diff --git a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
index 9d920b10a5c..79cd40ff29c 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
@@ -15,19 +15,17 @@
#include "base/task_runner_util.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/audio_service.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/system_connector.h"
#include "content/public/browser/web_contents.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/permissions/permissions_data.h"
#include "media/audio/audio_system.h"
-#include "services/audio/public/cpp/audio_system_factory.h"
-#include "services/service_manager/public/cpp/connector.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -125,7 +123,7 @@ std::string WebrtcAudioPrivateFunction::CalculateHMAC(
}
void WebrtcAudioPrivateFunction::InitDeviceIDSalt() {
- device_id_salt_ = GetProfile()->GetMediaDeviceIDSalt();
+ device_id_salt_ = browser_context()->GetMediaDeviceIDSalt();
}
std::string WebrtcAudioPrivateFunction::device_id_salt() const {
@@ -134,14 +132,12 @@ std::string WebrtcAudioPrivateFunction::device_id_salt() const {
media::AudioSystem* WebrtcAudioPrivateFunction::GetAudioSystem() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!audio_system_) {
- audio_system_ =
- audio::CreateAudioSystem(content::GetSystemConnector()->Clone());
- }
+ if (!audio_system_)
+ audio_system_ = content::CreateAudioSystemForAudioService();
return audio_system_.get();
}
-bool WebrtcAudioPrivateGetSinksFunction::RunAsync() {
+ExtensionFunction::ResponseAction WebrtcAudioPrivateGetSinksFunction::Run() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
InitDeviceIDSalt();
GetAudioSystem()->GetDeviceDescriptions(
@@ -149,7 +145,7 @@ bool WebrtcAudioPrivateGetSinksFunction::RunAsync() {
base::BindOnce(
&WebrtcAudioPrivateGetSinksFunction::ReceiveOutputDeviceDescriptions,
this));
- return true;
+ return RespondLater();
}
void WebrtcAudioPrivateGetSinksFunction::ReceiveOutputDeviceDescriptions(
@@ -163,8 +159,7 @@ void WebrtcAudioPrivateGetSinksFunction::ReceiveOutputDeviceDescriptions(
// TODO(joi): Add other parameters.
results->push_back(std::move(info));
}
- results_ = wap::GetSinks::Results::Create(*results);
- SendResponse(true);
+ Respond(ArgumentList(wap::GetSinks::Results::Create(*results)));
}
WebrtcAudioPrivateGetAssociatedSinkFunction::
@@ -173,7 +168,8 @@ WebrtcAudioPrivateGetAssociatedSinkFunction::
WebrtcAudioPrivateGetAssociatedSinkFunction::
~WebrtcAudioPrivateGetAssociatedSinkFunction() {}
-bool WebrtcAudioPrivateGetAssociatedSinkFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcAudioPrivateGetAssociatedSinkFunction::Run() {
params_ = wap::GetAssociatedSink::Params::Create(*args_);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
EXTENSION_FUNCTION_VALIDATE(params_.get());
@@ -183,7 +179,7 @@ bool WebrtcAudioPrivateGetAssociatedSinkFunction::RunAsync() {
true, base::BindOnce(&WebrtcAudioPrivateGetAssociatedSinkFunction::
ReceiveInputDeviceDescriptions,
this));
- return true;
+ return RespondLater();
}
void WebrtcAudioPrivateGetAssociatedSinkFunction::
@@ -228,13 +224,13 @@ void WebrtcAudioPrivateGetAssociatedSinkFunction::CalculateHMACAndReply(
void WebrtcAudioPrivateGetAssociatedSinkFunction::Reply(
const std::string& associated_sink_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ std::string sink_id;
if (associated_sink_id == media::AudioDeviceDescription::kDefaultDeviceId) {
DVLOG(2) << "Got default ID, replacing with empty ID.";
- results_ = wap::GetAssociatedSink::Results::Create("");
} else {
- results_ = wap::GetAssociatedSink::Results::Create(associated_sink_id);
+ sink_id = associated_sink_id;
}
- SendResponse(true);
+ Respond(OneArgument(std::make_unique<base::Value>(sink_id)));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h
index 303734c30a0..69ccc1128b3 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h
+++ b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h
@@ -12,11 +12,11 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/system/system_monitor.h"
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/common/extensions/api/webrtc_audio_private.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
+#include "extensions/browser/extension_function.h"
#include "media/audio/audio_device_description.h"
namespace media {
@@ -52,7 +52,7 @@ class WebrtcAudioPrivateEventService
// Common base for WebrtcAudioPrivate functions, that provides a
// couple of optionally-used common implementations.
-class WebrtcAudioPrivateFunction : public ChromeAsyncExtensionFunction {
+class WebrtcAudioPrivateFunction : public ExtensionFunction {
protected:
WebrtcAudioPrivateFunction();
~WebrtcAudioPrivateFunction() override;
@@ -88,7 +88,7 @@ class WebrtcAudioPrivateGetSinksFunction : public WebrtcAudioPrivateFunction {
DECLARE_EXTENSION_FUNCTION("webrtcAudioPrivate.getSinks",
WEBRTC_AUDIO_PRIVATE_GET_SINKS)
- bool RunAsync() override;
+ ResponseAction Run() override;
// Receives output device descriptions, calculates HMACs for them and sends
// the response.
@@ -109,7 +109,7 @@ class WebrtcAudioPrivateGetAssociatedSinkFunction
WEBRTC_AUDIO_PRIVATE_GET_ASSOCIATED_SINK)
// UI thread: Entry point, posts GetInputDeviceDescriptions() to IO thread.
- bool RunAsync() override;
+ ResponseAction Run() override;
// Receives the input device descriptions, looks up the raw source device ID
// basing on |params|, and requests the associated raw sink ID for it.
diff --git a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
index 50073312642..2a399b87e64 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
@@ -31,9 +31,9 @@
#include "chrome/common/buildflags.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/audio_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/media_device_id.h"
-#include "content/public/browser/system_connector.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/common/permissions/permission_set.h"
@@ -44,8 +44,6 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
-#include "services/audio/public/cpp/audio_system_factory.h"
-#include "services/service_manager/public/cpp/connector.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_WIN)
@@ -72,7 +70,7 @@ void GetAudioDeviceDescriptions(bool for_input,
AudioDeviceDescriptions* device_descriptions) {
base::RunLoop run_loop;
std::unique_ptr<media::AudioSystem> audio_system =
- audio::CreateAudioSystem(content::GetSystemConnector()->Clone());
+ content::CreateAudioSystemForAudioService();
audio_system->GetDeviceDescriptions(
for_input,
base::BindOnce(
diff --git a/chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.cc b/chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.cc
index cc33832c845..048aeda06c9 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.cc
@@ -33,7 +33,8 @@ WebrtcDesktopCapturePrivateChooseDesktopMediaFunction::
~WebrtcDesktopCapturePrivateChooseDesktopMediaFunction() {
}
-bool WebrtcDesktopCapturePrivateChooseDesktopMediaFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcDesktopCapturePrivateChooseDesktopMediaFunction::Run() {
using Params =
extensions::api::webrtc_desktop_capture_private::ChooseDesktopMedia
::Params;
@@ -53,16 +54,14 @@ bool WebrtcDesktopCapturePrivateChooseDesktopMediaFunction::RunAsync() {
params->request.guest_render_frame_id);
if (!rfh) {
- error_ = kTargetNotFoundError;
- return false;
+ return RespondNow(Error(kTargetNotFoundError));
}
GURL origin = rfh->GetLastCommittedURL().GetOrigin();
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kAllowHttpScreenCapture) &&
!content::IsOriginSecure(origin)) {
- error_ = kUrlNotSecure;
- return false;
+ return RespondNow(Error(kUrlNotSecure));
}
base::string16 target_name = base::UTF8ToUTF16(
content::IsOriginSecure(origin) ? net::GetHostAndOptionalPort(origin)
@@ -71,8 +70,7 @@ bool WebrtcDesktopCapturePrivateChooseDesktopMediaFunction::RunAsync() {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(rfh);
if (!web_contents) {
- error_ = kTargetNotFoundError;
- return false;
+ return RespondNow(Error(kTargetNotFoundError));
}
using Sources = std::vector<api::desktop_capture::DesktopCaptureSourceType>;
diff --git a/chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.h b/chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.h
index 1b41610fe5d..44adf1bb4c1 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.h
+++ b/chromium/chrome/browser/extensions/api/webrtc_desktop_capture_private/webrtc_desktop_capture_private_api.h
@@ -20,7 +20,7 @@ class WebrtcDesktopCapturePrivateChooseDesktopMediaFunction
~WebrtcDesktopCapturePrivateChooseDesktopMediaFunction() override;
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcDesktopCapturePrivateCancelChooseDesktopMediaFunction
diff --git a/chromium/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc b/chromium/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc
index d94e331c4af..34702924774 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_from_web_accessible_resource_browsertest.cc
@@ -5,61 +5,22 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "components/permissions/permission_request_manager.h"
+#include "components/permissions/test/permission_request_observer.h"
#include "extensions/test/result_catcher.h"
-#include "media/base/media_switches.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
namespace extensions {
-namespace {
-
-// Used to observe the creation of permission prompt without responding.
-class PermissionRequestObserver : public PermissionRequestManager::Observer {
- public:
- explicit PermissionRequestObserver(content::WebContents* web_contents)
- : request_manager_(
- PermissionRequestManager::FromWebContents(web_contents)),
- request_shown_(false) {
- request_manager_->AddObserver(this);
- }
- ~PermissionRequestObserver() override {
- // Safe to remove twice if it happens.
- request_manager_->RemoveObserver(this);
- }
-
- bool request_shown() const { return request_shown_; }
-
- private:
- // PermissionRequestManager::Observer
- void OnBubbleAdded() override {
- request_shown_ = true;
- request_manager_->RemoveObserver(this);
- }
-
- PermissionRequestManager* request_manager_;
- bool request_shown_;
-
- DISALLOW_COPY_AND_ASSIGN(PermissionRequestObserver);
-};
-
-} // namespace
-
class WebRtcFromWebAccessibleResourceTest : public ExtensionApiTest {
public:
WebRtcFromWebAccessibleResourceTest() {}
~WebRtcFromWebAccessibleResourceTest() override {}
// InProcessBrowserTest:
- void SetUpCommandLine(base::CommandLine* command_line) override {
- ExtensionApiTest::SetUpCommandLine(command_line);
-
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
- }
-
void SetUpOnMainThread() override {
ExtensionApiTest::SetUpOnMainThread();
host_resolver()->AddRule("a.com", "127.0.0.1");
@@ -96,11 +57,12 @@ IN_PROC_BROWSER_TEST_F(WebRtcFromWebAccessibleResourceTest,
GURL url = GetTestServerInsecureUrl("/extensions/test_file.html?succeed");
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
- PermissionRequestManager* request_manager =
- PermissionRequestManager::FromWebContents(web_contents);
+ permissions::PermissionRequestManager* request_manager =
+ permissions::PermissionRequestManager::FromWebContents(web_contents);
request_manager->set_auto_response_for_test(
- PermissionRequestManager::ACCEPT_ALL);
- PermissionRequestObserver permission_request_observer(web_contents);
+ permissions::PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestObserver permission_request_observer(
+ web_contents);
extensions::ResultCatcher catcher;
ui_test_utils::NavigateToURL(browser(), url);
@@ -119,11 +81,12 @@ IN_PROC_BROWSER_TEST_F(WebRtcFromWebAccessibleResourceTest,
GURL url = GetTestServerInsecureUrl("/extensions/test_file.html?fail");
content::WebContents* web_contents =
browser()->tab_strip_model()->GetActiveWebContents();
- PermissionRequestManager* request_manager =
- PermissionRequestManager::FromWebContents(web_contents);
+ permissions::PermissionRequestManager* request_manager =
+ permissions::PermissionRequestManager::FromWebContents(web_contents);
request_manager->set_auto_response_for_test(
- PermissionRequestManager::DENY_ALL);
- PermissionRequestObserver permission_request_observer(web_contents);
+ permissions::PermissionRequestManager::DENY_ALL);
+ permissions::PermissionRequestObserver permission_request_observer(
+ web_contents);
extensions::ResultCatcher catcher;
ui_test_utils::NavigateToURL(browser(), url);
diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
index bb110a5ba9b..9ad9aefa707 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
@@ -86,7 +86,8 @@ std::string HashIdWithOrigin(const std::string& security_origin,
// http://crbug.com/710371
content::RenderProcessHost* WebrtcLoggingPrivateFunction::RphFromRequest(
const api::webrtc_logging_private::RequestInfo& request,
- const std::string& security_origin) {
+ const std::string& security_origin,
+ std::string* error) {
// There are 2 ways these API functions can get called.
//
// 1. From a whitelisted component extension on behalf of a page with the
@@ -118,11 +119,11 @@ content::RenderProcessHost* WebrtcLoggingPrivateFunction::RphFromRequest(
GetSenderWebContents(),
base::BindRepeating(get_guest, &guests_found, &target_host));
if (!target_host) {
- SetError("No webview render process found");
+ *error = "No webview render process found";
return nullptr;
}
if (guests_found > 1) {
- SetError("Multiple webviews found");
+ *error = "Multiple webviews found";
return nullptr;
}
return target_host;
@@ -134,9 +135,9 @@ content::RenderProcessHost* WebrtcLoggingPrivateFunction::RphFromRequest(
content::RenderProcessHost* rph =
content::RenderProcessHost::FromID(*request.guest_process_id);
if (!rph) {
- SetError(
+ *error =
base::StringPrintf("Failed to get RPH fro guest proccess ID (%d).",
- *request.guest_process_id));
+ *request.guest_process_id);
}
return rph;
}
@@ -144,33 +145,34 @@ content::RenderProcessHost* WebrtcLoggingPrivateFunction::RphFromRequest(
// Otherwise, use the |tab_id|. If there's no |target_viewview|, no |tab_id|,
// and no |guest_process_id|, we can't look up the RenderProcessHost.
if (!request.tab_id.get()) {
- SetError("No webview, tab ID, or guest process ID specified.");
+ *error = "No webview, tab ID, or guest process ID specified.";
return nullptr;
}
int tab_id = *request.tab_id;
content::WebContents* contents = nullptr;
- if (!ExtensionTabUtil::GetTabById(tab_id, GetProfile(), true, &contents)) {
- SetError(extensions::ErrorUtils::FormatErrorMessage(
+ if (!ExtensionTabUtil::GetTabById(tab_id, browser_context(), true,
+ &contents)) {
+ *error = extensions::ErrorUtils::FormatErrorMessage(
extensions::tabs_constants::kTabNotFoundError,
- base::NumberToString(tab_id)));
+ base::NumberToString(tab_id));
return nullptr;
}
if (!contents) {
- SetError("Web contents for tab not found.");
+ *error = "Web contents for tab not found.";
return nullptr;
}
GURL expected_origin = contents->GetLastCommittedURL().GetOrigin();
if (expected_origin.spec() != security_origin) {
- SetError(base::StringPrintf(
+ *error = base::StringPrintf(
"Invalid security origin. Expected=%s, actual=%s",
- expected_origin.spec().c_str(), security_origin.c_str()));
+ expected_origin.spec().c_str(), security_origin.c_str());
return nullptr;
}
content::RenderProcessHost* rph = contents->GetMainFrame()->GetProcess();
if (!rph) {
- SetError("Failed to get RPH.");
+ *error = "Failed to get RPH.";
}
return rph;
}
@@ -178,10 +180,12 @@ content::RenderProcessHost* WebrtcLoggingPrivateFunction::RphFromRequest(
WebRtcLoggingController*
WebrtcLoggingPrivateFunction::LoggingControllerFromRequest(
const api::webrtc_logging_private::RequestInfo& request,
- const std::string& security_origin) {
- content::RenderProcessHost* host = RphFromRequest(request, security_origin);
+ const std::string& security_origin,
+ std::string* error) {
+ content::RenderProcessHost* host =
+ RphFromRequest(request, security_origin, error);
if (!host) {
- // SetError() will have been called by RphFromRequest().
+ DCHECK(!error->empty()) << "|error| must be set by RphFromRequest()";
return nullptr;
}
return WebRtcLoggingController::FromRenderProcessHost(host);
@@ -191,18 +195,21 @@ WebRtcLoggingController*
WebrtcLoggingPrivateFunctionWithGenericCallback::PrepareTask(
const api::webrtc_logging_private::RequestInfo& request,
const std::string& security_origin,
- WebRtcLoggingController::GenericDoneCallback* callback) {
+ WebRtcLoggingController::GenericDoneCallback* callback,
+ std::string* error) {
*callback = base::Bind(
&WebrtcLoggingPrivateFunctionWithGenericCallback::FireCallback, this);
- return LoggingControllerFromRequest(request, security_origin);
+ return LoggingControllerFromRequest(request, security_origin, error);
}
void WebrtcLoggingPrivateFunctionWithGenericCallback::FireCallback(
bool success, const std::string& error_message) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (!success)
- SetError(error_message);
- SendResponse(success);
+ if (success) {
+ Respond(NoArguments());
+ } else {
+ Respond(Error(error_message));
+ }
}
void WebrtcLoggingPrivateFunctionWithUploadCallback::FireCallback(
@@ -212,18 +219,16 @@ void WebrtcLoggingPrivateFunctionWithUploadCallback::FireCallback(
if (success) {
api::webrtc_logging_private::UploadResult result;
result.report_id = report_id;
- SetResult(result.ToValue());
+ Respond(OneArgument(result.ToValue()));
} else {
- SetError(error_message);
+ Respond(Error(error_message));
}
- SendResponse(success);
}
void WebrtcLoggingPrivateFunctionWithRecordingDoneCallback::FireErrorCallback(
const std::string& error_message) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- SetError(error_message);
- SendResponse(false);
+ Respond(Error(error_message));
}
void WebrtcLoggingPrivateFunctionWithRecordingDoneCallback::FireCallback(
@@ -235,107 +240,108 @@ void WebrtcLoggingPrivateFunctionWithRecordingDoneCallback::FireCallback(
result.prefix_path = prefix_path;
result.did_stop = did_stop;
result.did_manual_stop = did_manual_stop;
- SetResult(result.ToValue());
- SendResponse(true);
+ Respond(OneArgument(result.ToValue()));
}
-bool WebrtcLoggingPrivateSetMetaDataFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcLoggingPrivateSetMetaDataFunction::Run() {
std::unique_ptr<SetMetaData::Params> params(
SetMetaData::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingController::GenericDoneCallback callback;
+ std::string error;
WebRtcLoggingController* webrtc_logging_controller =
- PrepareTask(params->request, params->security_origin, &callback);
+ PrepareTask(params->request, params->security_origin, &callback, &error);
if (!webrtc_logging_controller)
- return false;
+ return RespondNow(Error(error));
std::unique_ptr<WebRtcLogMetaDataMap> meta_data(new WebRtcLogMetaDataMap());
for (const MetaDataEntry& entry : params->meta_data)
(*meta_data)[entry.key] = entry.value;
webrtc_logging_controller->SetMetaData(std::move(meta_data), callback);
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateStartFunction::RunAsync() {
+ExtensionFunction::ResponseAction WebrtcLoggingPrivateStartFunction::Run() {
std::unique_ptr<Start::Params> params(Start::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingController::GenericDoneCallback callback;
+ std::string error;
WebRtcLoggingController* webrtc_logging_controller =
- PrepareTask(params->request, params->security_origin, &callback);
+ PrepareTask(params->request, params->security_origin, &callback, &error);
if (!webrtc_logging_controller)
- return false;
+ return RespondNow(Error(error));
webrtc_logging_controller->StartLogging(callback);
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::Run() {
std::unique_ptr<SetUploadOnRenderClose::Params> params(
SetUploadOnRenderClose::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
+ std::string error;
WebRtcLoggingController* webrtc_logging_controller(
- LoggingControllerFromRequest(params->request, params->security_origin));
+ LoggingControllerFromRequest(params->request, params->security_origin,
+ &error));
if (!webrtc_logging_controller)
- return false;
+ return RespondNow(Error(error));
webrtc_logging_controller->set_upload_log_on_render_close(
params->should_upload);
- // Post a task since this is an asynchronous extension function.
- // TODO(devlin): This is unneccessary; this should just be a
- // ExtensionFunction. Fix this.
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(
- &WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::SendResponse,
- this, true));
- return true;
+ return RespondNow(NoArguments());
}
-bool WebrtcLoggingPrivateStopFunction::RunAsync() {
+ExtensionFunction::ResponseAction WebrtcLoggingPrivateStopFunction::Run() {
std::unique_ptr<Stop::Params> params(Stop::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingController::GenericDoneCallback callback;
+ std::string error;
WebRtcLoggingController* webrtc_logging_controller =
- PrepareTask(params->request, params->security_origin, &callback);
+ PrepareTask(params->request, params->security_origin, &callback, &error);
if (!webrtc_logging_controller)
- return false;
+ return RespondNow(Error(error));
webrtc_logging_controller->StopLogging(callback);
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateStoreFunction::RunAsync() {
+ExtensionFunction::ResponseAction WebrtcLoggingPrivateStoreFunction::Run() {
std::unique_ptr<Store::Params> params(Store::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingController::GenericDoneCallback callback;
+ std::string error;
WebRtcLoggingController* webrtc_logging_controller =
- PrepareTask(params->request, params->security_origin, &callback);
+ PrepareTask(params->request, params->security_origin, &callback, &error);
if (!webrtc_logging_controller)
- return false;
+ return RespondNow(Error(error));
const std::string local_log_id(HashIdWithOrigin(params->security_origin,
params->log_id));
webrtc_logging_controller->StoreLog(local_log_id, callback);
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateUploadStoredFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcLoggingPrivateUploadStoredFunction::Run() {
std::unique_ptr<UploadStored::Params> params(
UploadStored::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
- WebRtcLoggingController* logging_controller =
- LoggingControllerFromRequest(params->request, params->security_origin);
+ std::string error;
+ WebRtcLoggingController* logging_controller = LoggingControllerFromRequest(
+ params->request, params->security_origin, &error);
if (!logging_controller)
- return false;
+ return RespondNow(Error(error));
WebRtcLoggingController::UploadDoneCallback callback =
base::Bind(&WebrtcLoggingPrivateUploadStoredFunction::FireCallback, this);
@@ -344,47 +350,50 @@ bool WebrtcLoggingPrivateUploadStoredFunction::RunAsync() {
params->log_id));
logging_controller->UploadStoredLog(local_log_id, callback);
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateUploadFunction::RunAsync() {
+ExtensionFunction::ResponseAction WebrtcLoggingPrivateUploadFunction::Run() {
std::unique_ptr<Upload::Params> params(Upload::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
- WebRtcLoggingController* logging_controller =
- LoggingControllerFromRequest(params->request, params->security_origin);
+ std::string error;
+ WebRtcLoggingController* logging_controller = LoggingControllerFromRequest(
+ params->request, params->security_origin, &error);
if (!logging_controller)
- return false;
+ return RespondNow(Error(error));
WebRtcLoggingController::UploadDoneCallback callback =
base::Bind(&WebrtcLoggingPrivateUploadFunction::FireCallback, this);
logging_controller->UploadLog(callback);
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateDiscardFunction::RunAsync() {
+ExtensionFunction::ResponseAction WebrtcLoggingPrivateDiscardFunction::Run() {
std::unique_ptr<Discard::Params> params(Discard::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
WebRtcLoggingController::GenericDoneCallback callback;
+ std::string error;
WebRtcLoggingController* webrtc_logging_controller =
- PrepareTask(params->request, params->security_origin, &callback);
+ PrepareTask(params->request, params->security_origin, &callback, &error);
if (!webrtc_logging_controller)
- return false;
+ return RespondNow(Error(error));
webrtc_logging_controller->DiscardLog(callback);
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateStartRtpDumpFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcLoggingPrivateStartRtpDumpFunction::Run() {
std::unique_ptr<StartRtpDump::Params> params(
StartRtpDump::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
if (!params->incoming && !params->outgoing) {
FireCallback(false, "Either incoming or outgoing must be true.");
- return true;
+ return AlreadyResponded();
}
RtpDumpType type =
@@ -392,11 +401,11 @@ bool WebrtcLoggingPrivateStartRtpDumpFunction::RunAsync() {
? RTP_DUMP_BOTH
: (params->incoming ? RTP_DUMP_INCOMING : RTP_DUMP_OUTGOING);
+ std::string error;
content::RenderProcessHost* host =
- RphFromRequest(params->request, params->security_origin);
+ RphFromRequest(params->request, params->security_origin, &error);
if (!host) {
- // SetError() will have been called by RphFromRequest().
- return false;
+ return RespondNow(Error(error));
}
WebRtcLoggingController* webrtc_logging_controller =
@@ -406,17 +415,18 @@ bool WebrtcLoggingPrivateStartRtpDumpFunction::RunAsync() {
base::Bind(&WebrtcLoggingPrivateStartRtpDumpFunction::FireCallback, this);
webrtc_logging_controller->StartRtpDump(type, callback);
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateStopRtpDumpFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcLoggingPrivateStopRtpDumpFunction::Run() {
std::unique_ptr<StopRtpDump::Params> params(
StopRtpDump::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
if (!params->incoming && !params->outgoing) {
FireCallback(false, "Either incoming or outgoing must be true.");
- return true;
+ return AlreadyResponded();
}
RtpDumpType type =
@@ -424,11 +434,11 @@ bool WebrtcLoggingPrivateStopRtpDumpFunction::RunAsync() {
? RTP_DUMP_BOTH
: (params->incoming ? RTP_DUMP_INCOMING : RTP_DUMP_OUTGOING);
+ std::string error;
content::RenderProcessHost* host =
- RphFromRequest(params->request, params->security_origin);
+ RphFromRequest(params->request, params->security_origin, &error);
if (!host) {
- // SetError() will have been called by RphFromRequest().
- return false;
+ return RespondNow(Error(error));
}
WebRtcLoggingController* webrtc_logging_controller =
@@ -438,12 +448,13 @@ bool WebrtcLoggingPrivateStopRtpDumpFunction::RunAsync() {
base::Bind(&WebrtcLoggingPrivateStopRtpDumpFunction::FireCallback, this);
webrtc_logging_controller->StopRtpDump(type, callback);
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::Run() {
if (!CanEnableAudioDebugRecordingsFromExtension(extension())) {
- return false;
+ return RespondNow(Error(""));
}
std::unique_ptr<StartAudioDebugRecordings::Params> params(
@@ -452,14 +463,14 @@ bool WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::RunAsync() {
if (params->seconds < 0) {
FireErrorCallback("seconds must be greater than or equal to 0");
- return true;
+ return AlreadyResponded();
}
+ std::string error;
content::RenderProcessHost* host =
- RphFromRequest(params->request, params->security_origin);
+ RphFromRequest(params->request, params->security_origin, &error);
if (!host) {
- // SetError() will have been called by RphFromRequest().
- return false;
+ return RespondNow(Error(error));
}
scoped_refptr<AudioDebugRecordingsHandler> audio_debug_recordings_handler(
@@ -474,23 +485,24 @@ bool WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::RunAsync() {
base::Bind(&WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::
FireErrorCallback,
this));
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::Run() {
if (!CanEnableAudioDebugRecordingsFromExtension(extension())) {
- return false;
+ return RespondNow(Error(""));
}
std::unique_ptr<StopAudioDebugRecordings::Params> params(
StopAudioDebugRecordings::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
+ std::string error;
content::RenderProcessHost* host =
- RphFromRequest(params->request, params->security_origin);
+ RphFromRequest(params->request, params->security_origin, &error);
if (!host) {
- // SetError() will have been called by RphFromRequest().
- return false;
+ return RespondNow(Error(error));
}
scoped_refptr<AudioDebugRecordingsHandler> audio_debug_recordings_handler(
@@ -505,26 +517,26 @@ bool WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::RunAsync() {
base::Bind(&WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::
FireErrorCallback,
this));
- return true;
+ return RespondLater();
}
-bool WebrtcLoggingPrivateStartEventLoggingFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcLoggingPrivateStartEventLoggingFunction::Run() {
std::unique_ptr<StartEventLogging::Params> params(
StartEventLogging::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
+ std::string error;
content::RenderProcessHost* host =
- RphFromRequest(params->request, params->security_origin);
+ RphFromRequest(params->request, params->security_origin, &error);
if (!host) {
- // SetError() will have been called by RphFromRequest().
- return false;
+ return RespondNow(Error(error));
}
WebRtcLoggingController* webrtc_logging_controller =
WebRtcLoggingController::FromRenderProcessHost(host);
if (!webrtc_logging_controller) {
- SetError("WebRTC logging controller not found.");
- return false;
+ return RespondNow(Error("WebRTC logging controller not found."));
}
WebRtcLoggingController::StartEventLoggingCallback callback =
@@ -534,7 +546,7 @@ bool WebrtcLoggingPrivateStartEventLoggingFunction::RunAsync() {
webrtc_logging_controller->StartEventLogging(
params->session_id, params->max_log_size_bytes, params->output_period_ms,
params->web_app_id, callback);
- return true;
+ return RespondLater();
}
void WebrtcLoggingPrivateStartEventLoggingFunction::FireCallback(
@@ -547,16 +559,16 @@ void WebrtcLoggingPrivateStartEventLoggingFunction::FireCallback(
DCHECK(error_message.empty());
api::webrtc_logging_private::StartEventLoggingResult result;
result.log_id = log_id;
- SetResult(result.ToValue());
+ Respond(OneArgument(result.ToValue()));
} else {
DCHECK(log_id.empty());
DCHECK(!error_message.empty());
- SetError(error_message);
+ Respond(Error(error_message));
}
- SendResponse(success);
}
-bool WebrtcLoggingPrivateGetLogsDirectoryFunction::RunAsync() {
+ExtensionFunction::ResponseAction
+WebrtcLoggingPrivateGetLogsDirectoryFunction::Run() {
#if defined(OS_LINUX) || defined(OS_CHROMEOS)
// Unlike other WebrtcLoggingPrivate functions that take a RequestInfo object,
// this function shouldn't be called by a component extension on behalf of
@@ -570,7 +582,7 @@ bool WebrtcLoggingPrivateGetLogsDirectoryFunction::RunAsync() {
WebRtcLoggingController::FromRenderProcessHost(host);
if (!webrtc_logging_controller) {
FireErrorCallback("WebRTC logging controller not found.");
- return true;
+ return AlreadyResponded();
}
webrtc_logging_controller->GetLogsDirectory(
@@ -579,11 +591,9 @@ bool WebrtcLoggingPrivateGetLogsDirectoryFunction::RunAsync() {
base::Bind(
&WebrtcLoggingPrivateGetLogsDirectoryFunction::FireErrorCallback,
this));
- return true;
+ return RespondLater();
#else // defined(OS_LINUX) || defined(OS_CHROMEOS)
- SetError("Not supported on the current OS");
- SendResponse(false);
- return false;
+ return RespondNow(Error("Not supported on the current OS"));
#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
}
@@ -600,8 +610,7 @@ void WebrtcLoggingPrivateGetLogsDirectoryFunction::FireCallback(
void WebrtcLoggingPrivateGetLogsDirectoryFunction::FireErrorCallback(
const std::string& error_message) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- SetError(error_message);
- SendResponse(false);
+ Respond(Error(error_message));
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h
index 3ded513b39b..e371b984dd6 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h
+++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h
@@ -7,10 +7,10 @@
#include <string>
-#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/media/webrtc/audio_debug_recordings_handler.h"
#include "chrome/browser/media/webrtc/webrtc_logging_controller.h"
#include "chrome/common/extensions/api/webrtc_logging_private.h"
+#include "extensions/browser/extension_function.h"
#include "media/media_buildflags.h"
namespace content {
@@ -21,20 +21,22 @@ class RenderProcessHost;
namespace extensions {
-class WebrtcLoggingPrivateFunction : public ChromeAsyncExtensionFunction {
+class WebrtcLoggingPrivateFunction : public ExtensionFunction {
protected:
~WebrtcLoggingPrivateFunction() override {}
// Returns the RenderProcessHost associated with the given |request|
- // authorized by the |security_origin|. Returns null if unauthorized or
- // the RPH does not exist.
+ // authorized by the |security_origin|. Returns null and sets |*error| to an
+ // appropriate error if unauthorized or the RPH does not exist.
content::RenderProcessHost* RphFromRequest(
const api::webrtc_logging_private::RequestInfo& request,
- const std::string& security_origin);
+ const std::string& security_origin,
+ std::string* error);
WebRtcLoggingController* LoggingControllerFromRequest(
const api::webrtc_logging_private::RequestInfo& request,
- const std::string& security_origin);
+ const std::string& security_origin,
+ std::string* error);
};
class WebrtcLoggingPrivateFunctionWithGenericCallback
@@ -45,11 +47,13 @@ class WebrtcLoggingPrivateFunctionWithGenericCallback
// Finds the appropriate logging controller for performing the task and
// prepares a generic callback object for when the task is completed. If the
// logging controller can't be found for the given request+origin, the
- // returned ptr will be null.
+ // returned ptr will be null and |*error| will be set to an appropriate error
+ // message.
WebRtcLoggingController* PrepareTask(
const api::webrtc_logging_private::RequestInfo& request,
const std::string& security_origin,
- WebRtcLoggingController::GenericDoneCallback* callback);
+ WebRtcLoggingController::GenericDoneCallback* callback,
+ std::string* error);
// Must be called on UI thread.
void FireCallback(bool success, const std::string& error_message);
@@ -88,7 +92,7 @@ class WebrtcLoggingPrivateSetMetaDataFunction
~WebrtcLoggingPrivateSetMetaDataFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateStartFunction
@@ -102,7 +106,7 @@ class WebrtcLoggingPrivateStartFunction
~WebrtcLoggingPrivateStartFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateSetUploadOnRenderCloseFunction
@@ -116,7 +120,7 @@ class WebrtcLoggingPrivateSetUploadOnRenderCloseFunction
~WebrtcLoggingPrivateSetUploadOnRenderCloseFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateStopFunction
@@ -130,7 +134,7 @@ class WebrtcLoggingPrivateStopFunction
~WebrtcLoggingPrivateStopFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateStoreFunction
@@ -144,7 +148,7 @@ class WebrtcLoggingPrivateStoreFunction
~WebrtcLoggingPrivateStoreFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateUploadStoredFunction
@@ -158,7 +162,7 @@ class WebrtcLoggingPrivateUploadStoredFunction
~WebrtcLoggingPrivateUploadStoredFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateUploadFunction
@@ -172,7 +176,7 @@ class WebrtcLoggingPrivateUploadFunction
~WebrtcLoggingPrivateUploadFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateDiscardFunction
@@ -186,7 +190,7 @@ class WebrtcLoggingPrivateDiscardFunction
~WebrtcLoggingPrivateDiscardFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateStartRtpDumpFunction
@@ -200,7 +204,7 @@ class WebrtcLoggingPrivateStartRtpDumpFunction
~WebrtcLoggingPrivateStartRtpDumpFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateStopRtpDumpFunction
@@ -214,7 +218,7 @@ class WebrtcLoggingPrivateStopRtpDumpFunction
~WebrtcLoggingPrivateStopRtpDumpFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateStartAudioDebugRecordingsFunction
@@ -228,7 +232,7 @@ class WebrtcLoggingPrivateStartAudioDebugRecordingsFunction
~WebrtcLoggingPrivateStartAudioDebugRecordingsFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateStopAudioDebugRecordingsFunction
@@ -242,7 +246,7 @@ class WebrtcLoggingPrivateStopAudioDebugRecordingsFunction
~WebrtcLoggingPrivateStopAudioDebugRecordingsFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
};
class WebrtcLoggingPrivateStartEventLoggingFunction
@@ -256,7 +260,7 @@ class WebrtcLoggingPrivateStartEventLoggingFunction
~WebrtcLoggingPrivateStartEventLoggingFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
// If |success|, |log_id| must hold the ID. Otherwise, |error_message| must
// hold a non-empty error message.
@@ -277,7 +281,7 @@ class WebrtcLoggingPrivateGetLogsDirectoryFunction
~WebrtcLoggingPrivateGetLogsDirectoryFunction() override {}
// ExtensionFunction overrides.
- bool RunAsync() override;
+ ResponseAction Run() override;
// Must be called on UI thread.
void FireErrorCallback(const std::string& error_message);
diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
index f5cacaa1dfb..b8491df14db 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "base/strings/string_split.h"
diff --git a/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.cc b/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.cc
index e34e0df8a4c..60108f37b6b 100644
--- a/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.cc
+++ b/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.cc
@@ -12,6 +12,7 @@
#include "chrome/common/pref_names.h"
#include "components/crx_file/id_util.h"
#include "components/prefs/pref_service.h"
+#include "extensions/browser/extension_prefs.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/manifest_constants.h"
@@ -23,6 +24,11 @@ ExtensionInstallStatus GetWebstoreExtensionInstallStatus(
Profile* profile) {
DCHECK(crx_file::id_util::IdIsValid(extension_id));
+ if (ExtensionPrefs::Get(profile)->HasDisableReason(
+ extension_id, disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED)) {
+ return kCustodianApprovalRequired;
+ }
+
ExtensionRegistry* registry = ExtensionRegistry::Get(profile);
if (registry->enabled_extensions().Contains(extension_id))
return kEnabled;
diff --git a/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.h b/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.h
index 0e7285db48a..4e3101f9fc4 100644
--- a/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.h
+++ b/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status.h
@@ -27,7 +27,9 @@ enum ExtensionInstallStatus {
// Extension has been installed but it's terminated.
kTerminated,
// Extension is blacklisted.
- kBlacklisted
+ kBlacklisted,
+ // Extension requires custodian approval to enable.
+ kCustodianApprovalRequired
};
// Returns the Extension install status for an Chrome web store extension with
diff --git a/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc b/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc
index 706d2c3d802..ebac07208c4 100644
--- a/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/webstore_private/extension_install_status_unittest.cc
@@ -15,6 +15,8 @@
#include "chrome/common/pref_names.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "extensions/browser/disable_reason.h"
+#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/pref_names.h"
#include "extensions/common/extension_builder.h"
@@ -217,4 +219,15 @@ TEST_F(ExtensionInstallStatusTest, PendingExtenisonIsRejected) {
GetWebstoreExtensionInstallStatus(kExtensionId, profile()));
}
+// If an extension is disabled due to reason
+// DISABLE_CUSTODIAN_APPROVAL_REQUIRED, then GetWebstoreExtensionInstallStatus()
+// should return kCustodianApprovalRequired.
+TEST_F(ExtensionInstallStatusTest, ExtensionCustodianApprovalRequired) {
+ ExtensionPrefs::Get(profile())->AddDisableReason(
+ kExtensionId,
+ extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED);
+ EXPECT_EQ(ExtensionInstallStatus::kCustodianApprovalRequired,
+ GetWebstoreExtensionInstallStatus(kExtensionId, profile()));
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
index 59b5434b193..99b1e505dc6 100644
--- a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc
@@ -33,8 +33,10 @@
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/app_list/app_list_util.h"
+#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
+#include "chrome/grit/generated_resources.h"
#include "components/crx_file/id_util.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
@@ -42,6 +44,7 @@
#include "content/public/browser/gpu_feature_checker.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
+#include "extensions/browser/extension_dialog_auto_confirm.h"
#include "extensions/browser/extension_function_constants.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
@@ -49,12 +52,15 @@
#include "extensions/common/manifest_constants.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request.h"
+#include "ui/base/l10n/l10n_util.h"
#include "url/gurl.h"
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+// TODO(https://crbug.com/1060801): Here and elsewhere, possibly switch build
+// flag to #if defined(OS_CHROMEOS)
#include "chrome/browser/supervised_user/supervised_user_service.h"
#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
-#endif
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
using safe_browsing::SafeBrowsingNavigationObserverManager;
@@ -155,6 +161,16 @@ const char kIncognitoError[] =
const char kEphemeralAppLaunchingNotSupported[] =
"Ephemeral launching of apps is no longer supported.";
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+// Note that the following error doesn't mean an incorrect password was entered,
+// nor that the parent permisison request was canceled by the user, but rather
+// that the Parent permission request after credential entry and acceptance
+// failed due to either a network connection error or some unsatisfied invariant
+// that prevented the request from completing.
+const char kWebstoreParentPermissionFailedError[] =
+ "Parent permission request failed";
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
+
// The number of user gestures to trace back for the referrer chain.
const int kExtensionReferrerUserGestureLimit = 2;
@@ -206,10 +222,58 @@ ConvertExtensionInstallStatusForAPI(ExtensionInstallStatus status) {
case kBlacklisted:
return api::webstore_private::ExtensionInstallStatus::
EXTENSION_INSTALL_STATUS_BLACKLISTED;
+ case kCustodianApprovalRequired:
+ return api::webstore_private::ExtensionInstallStatus::
+ EXTENSION_INSTALL_STATUS_CUSTODIAN_APPROVAL_REQUIRED;
}
return api::webstore_private::EXTENSION_INSTALL_STATUS_NONE;
}
+// Requests extension by adding the id into the pending list in Profile Prefs if
+// available. Returns |kRequestPending| if the request has been added
+// successfully. Otherwise, returns the initial extension install status.
+ExtensionInstallStatus AddExtensionToPendingList(const ExtensionId& id,
+ Profile* profile) {
+ ExtensionInstallStatus status =
+ GetWebstoreExtensionInstallStatus(id, profile);
+ // We put the |id| into the pending request list if it can be requested.
+ // Ideally we should not get here if the status is not |kCanRequest|. However
+ // policy might be updated between the client calling |requestExtension| or
+ // |beginInstallWithManifest3| and us checking the status here. Handle
+ // approvals and rejections for this case by adding the |id| into the pending
+ // list. ExtensionRequestObserver will observe this update and show the
+ // notificaion immediately.
+ // Please note that only the |id| that can be requested will be uploaded to
+ // the server and ExtensionRequestObserver will also show notifications once
+ // it's approved or rejected.
+ // |id| will be removed from the pending list once the notification is
+ // confirmed or closed by the user.
+ if (status != kCanRequest && status != kInstallable &&
+ status != kBlockedByPolicy) {
+ return status;
+ }
+
+ DictionaryPrefUpdate pending_requests_update(
+ profile->GetPrefs(), prefs::kCloudExtensionRequestIds);
+ DCHECK(!pending_requests_update->FindKey(id));
+ base::Value request_data(base::Value::Type::DICTIONARY);
+ request_data.SetKey(extension_misc::kExtensionRequestTimestamp,
+ ::util::TimeToValue(base::Time::Now()));
+ pending_requests_update->SetKey(id, std::move(request_data));
+ // Query the new extension install status again. It should be changed from
+ // |kCanRequest| to |kRequestPending| if the id has been added into pending
+ // list successfully. Otherwise, it shouldn't be changed.
+ ExtensionInstallStatus new_status =
+ GetWebstoreExtensionInstallStatus(id, profile);
+#if DCHECK_IS_ON()
+ if (status == kCanRequest)
+ DCHECK_EQ(kRequestPending, new_status);
+ else
+ DCHECK_EQ(status, new_status);
+#endif // DCHECK_IS_ON()
+ return new_status;
+}
+
} // namespace
// static
@@ -226,11 +290,15 @@ WebstorePrivateApi::PopApprovalForTesting(Profile* profile,
}
WebstorePrivateBeginInstallWithManifest3Function::
- WebstorePrivateBeginInstallWithManifest3Function() : chrome_details_(this) {
-}
+ WebstorePrivateBeginInstallWithManifest3Function()
+ : chrome_details_(this) {}
WebstorePrivateBeginInstallWithManifest3Function::
- ~WebstorePrivateBeginInstallWithManifest3Function() {
+ ~WebstorePrivateBeginInstallWithManifest3Function() = default;
+
+base::string16 WebstorePrivateBeginInstallWithManifest3Function::
+ GetBlockedByPolicyErrorMessageForTesting() const {
+ return blocked_by_policy_error_message_;
}
ExtensionFunction::ResponseAction
@@ -323,7 +391,10 @@ void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseSuccess(
bool allow =
ExtensionSystem::Get(profile)->management_policy()->UserMayInstall(
dummy_extension_.get(), &policy_error);
- if (!allow) {
+ ExtensionInstallStatus install_status =
+ GetWebstoreExtensionInstallStatus(id, profile);
+ if (!allow && install_status != kCanRequest &&
+ install_status != kRequestPending) {
bool blocked_for_child = false;
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
// If the installation was blocked because the user is a child, we send a
@@ -339,14 +410,14 @@ void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseSuccess(
blocked_for_child = true;
}
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
- api::webstore_private::Result code =
- blocked_for_child
- ? api::webstore_private::RESULT_BLOCKED_FOR_CHILD_ACCOUNT
- : api::webstore_private::RESULT_BLOCKED_BY_POLICY;
- Respond(BuildResponse(code, base::UTF16ToUTF8(policy_error)));
- // Matches the AddRef in Run().
- Release();
- return;
+ if (blocked_for_child) {
+ Respond(
+ BuildResponse(api::webstore_private::RESULT_BLOCKED_FOR_CHILD_ACCOUNT,
+ base::UTF16ToUTF8(policy_error)));
+ // Matches the AddRef in Run().
+ Release();
+ return;
+ }
}
content::WebContents* web_contents = GetSenderWebContents();
@@ -358,14 +429,50 @@ void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseSuccess(
Release();
return;
}
+ if (install_status == kBlockedByPolicy) {
+ ShowBlockedByPolicyDialog(
+ dummy_extension_.get(), icon_, web_contents,
+ base::BindOnce(&WebstorePrivateBeginInstallWithManifest3Function::
+ OnBlockByPolicyPromptDone,
+ this));
+ return;
+ }
+
install_prompt_.reset(new ExtensionInstallPrompt(web_contents));
- install_prompt_->ShowDialog(
- base::Bind(&WebstorePrivateBeginInstallWithManifest3Function::
- OnInstallPromptDone,
- this),
- dummy_extension_.get(), &icon_,
- ExtensionInstallPrompt::GetDefaultShowDialogCallback());
- // Control flow finishes up in OnInstallPromptDone.
+ if (install_status == kCanRequest || install_status == kRequestPending) {
+ install_prompt_->ShowDialog(
+ base::BindRepeating(&WebstorePrivateBeginInstallWithManifest3Function::
+ OnRequestPromptDone,
+ this),
+ dummy_extension_.get(), &icon_,
+ std::make_unique<ExtensionInstallPrompt::Prompt>(
+ install_status == kCanRequest
+ ? ExtensionInstallPrompt::EXTENSION_REQUEST_PROMPT
+ : ExtensionInstallPrompt::EXTENSION_PENDING_REQUEST_PROMPT),
+ ExtensionInstallPrompt::GetDefaultShowDialogCallback());
+ } else {
+ auto prompt = std::make_unique<ExtensionInstallPrompt::Prompt>(
+ ExtensionInstallPrompt::INSTALL_PROMPT);
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+
+ if (!dummy_extension_->is_theme()) {
+ // We don't prompt for parent permission for themes, so no need
+ // to configure the install prompt to indicate that this is a child
+ // asking a parent for installation permission.
+ prompt->set_requires_parent_permission(profile->IsChild());
+ }
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
+
+ install_prompt_->ShowDialog(
+ base::BindRepeating(&WebstorePrivateBeginInstallWithManifest3Function::
+ OnInstallPromptDone,
+ this),
+ dummy_extension_.get(), &icon_, std::move(prompt),
+ ExtensionInstallPrompt::GetDefaultShowDialogCallback());
+ }
+ // Control flow finishes up in OnInstallPromptDone, OnRequestPromptDone or
+ // OnBlockByPolicyPromptDone.
}
void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseFailure(
@@ -381,14 +488,147 @@ void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseFailure(
Release();
}
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+
+void WebstorePrivateBeginInstallWithManifest3Function::OnParentPermissionDone(
+ ParentPermissionDialog::Result result) {
+ switch (result) {
+ case ParentPermissionDialog::Result::kParentPermissionReceived:
+ OnParentPermissionReceived();
+ break;
+ case ParentPermissionDialog::Result::kParentPermissionCanceled:
+ OnParentPermissionCanceled();
+ break;
+ case ParentPermissionDialog::Result::kParentPermissionFailed:
+ OnParentPermissionFailed();
+ break;
+ }
+}
+
+void WebstorePrivateBeginInstallWithManifest3Function::
+ OnParentPermissionReceived() {
+ SupervisedUserService* service =
+ SupervisedUserServiceFactory::GetForProfile(chrome_details_.GetProfile());
+ service->AddOrUpdateExtensionApproval(*dummy_extension_);
+
+ HandleInstallProceed();
+ Release(); // Matches the AddRef in Run().
+}
+
+void WebstorePrivateBeginInstallWithManifest3Function::
+ OnParentPermissionCanceled() {
+ if (test_webstore_installer_delegate) {
+ test_webstore_installer_delegate->OnExtensionInstallFailure(
+ dummy_extension_->id(), kWebstoreParentPermissionFailedError,
+ WebstoreInstaller::FailureReason::FAILURE_REASON_CANCELLED);
+ }
+
+ HandleInstallAbort(true /* user_initiated */);
+ Release(); // Matches the AddRef in Run().
+}
+
+void WebstorePrivateBeginInstallWithManifest3Function::
+ OnParentPermissionFailed() {
+ if (test_webstore_installer_delegate) {
+ test_webstore_installer_delegate->OnExtensionInstallFailure(
+ dummy_extension_->id(), kWebstoreParentPermissionFailedError,
+ WebstoreInstaller::FailureReason::FAILURE_REASON_OTHER);
+ }
+
+ Respond(BuildResponse(api::webstore_private::RESULT_UNKNOWN_ERROR,
+ kWebstoreParentPermissionFailedError));
+
+ Release(); // Matches the AddRef in Run().
+}
+
+bool WebstorePrivateBeginInstallWithManifest3Function::
+ PromptForParentApproval() {
+ Profile* profile = chrome_details_.GetProfile();
+ DCHECK(profile->IsChild());
+ content::WebContents* web_contents = GetSenderWebContents();
+ if (!web_contents) {
+ // The browser window has gone away.
+ Respond(BuildResponse(api::webstore_private::RESULT_USER_CANCELLED,
+ kWebstoreUserCancelledError));
+ return false;
+ }
+
+ ParentPermissionDialog::DoneCallback done_callback = base::BindOnce(
+ &WebstorePrivateBeginInstallWithManifest3Function::OnParentPermissionDone,
+ this);
+
+ parent_permission_dialog_ =
+ ParentPermissionDialog::CreateParentPermissionDialogForExtension(
+ profile, web_contents, web_contents->GetTopLevelNativeWindow(),
+ gfx::ImageSkia::CreateFrom1xBitmap(icon_), dummy_extension_.get(),
+ std::move(done_callback));
+ parent_permission_dialog_->ShowDialog();
+
+ return true;
+}
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
+
void WebstorePrivateBeginInstallWithManifest3Function::OnInstallPromptDone(
ExtensionInstallPrompt::Result result) {
- if (result == ExtensionInstallPrompt::Result::ACCEPTED) {
- HandleInstallProceed();
- } else {
- HandleInstallAbort(result == ExtensionInstallPrompt::Result::USER_CANCELED);
+ switch (result) {
+ case ExtensionInstallPrompt::Result::ACCEPTED:
+ case ExtensionInstallPrompt::Result::ACCEPTED_AND_OPTION_CHECKED: {
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+ // Handle parent permission for child accounts on ChromeOS.
+ Profile* profile = chrome_details_.GetProfile();
+ if (!dummy_extension_->is_theme() // Parent permission not required for
+ // theme installation
+ && g_browser_process->profile_manager()->IsValidProfile(profile) &&
+ profile->IsChild()) {
+ if (PromptForParentApproval()) {
+ // If are showing parent permission dialog, return instead of
+ // break, so that we don't release the ref below.
+ return;
+ } else {
+ // An error occurred, break so that we release the ref below.
+ break;
+ }
+ }
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
+ HandleInstallProceed();
+ break;
+ }
+ case ExtensionInstallPrompt::Result::USER_CANCELED:
+ case ExtensionInstallPrompt::Result::ABORTED: {
+ HandleInstallAbort(result ==
+ ExtensionInstallPrompt::Result::USER_CANCELED);
+ break;
+ }
+ }
+
+ // Matches the AddRef in Run().
+ Release();
+}
+
+void WebstorePrivateBeginInstallWithManifest3Function::OnRequestPromptDone(
+ ExtensionInstallPrompt::Result result) {
+ switch (result) {
+ case ExtensionInstallPrompt::Result::ACCEPTED:
+ AddExtensionToPendingList(details().id, chrome_details_.GetProfile());
+ break;
+ case ExtensionInstallPrompt::Result::USER_CANCELED:
+ case ExtensionInstallPrompt::Result::ABORTED:
+ break;
+ case ExtensionInstallPrompt::Result::ACCEPTED_AND_OPTION_CHECKED:
+ NOTREACHED();
}
+ Respond(BuildResponse(api::webstore_private::RESULT_USER_CANCELLED,
+ kWebstoreUserCancelledError));
+ // Matches the AddRef in Run().
+ Release();
+}
+void WebstorePrivateBeginInstallWithManifest3Function::
+ OnBlockByPolicyPromptDone() {
+ // TODO(crbug.com/1061205): Returns |blocked_by_policy| when CWS is ready for
+ // the new dialog change.
+ Respond(BuildResponse(api::webstore_private::RESULT_USER_CANCELLED,
+ kWebstoreUserCancelledError));
// Matches the AddRef in Run().
Release();
}
@@ -419,7 +659,6 @@ void WebstorePrivateBeginInstallWithManifest3Function::HandleInstallProceed() {
// specific histogram here.
ExtensionService::RecordPermissionMessagesHistogram(
dummy_extension_.get(), "WebStoreInstall");
-
Respond(BuildResponse(api::webstore_private::RESULT_SUCCESS, std::string()));
}
@@ -443,7 +682,8 @@ void WebstorePrivateBeginInstallWithManifest3Function::HandleInstallAbort(
ExtensionFunction::ResponseValue
WebstorePrivateBeginInstallWithManifest3Function::BuildResponse(
- api::webstore_private::Result result, const std::string& error) {
+ api::webstore_private::Result result,
+ const std::string& error) {
if (result != api::webstore_private::RESULT_SUCCESS)
return ErrorWithArguments(CreateResults(result), error);
@@ -459,11 +699,48 @@ WebstorePrivateBeginInstallWithManifest3Function::CreateResults(
return BeginInstallWithManifest3::Results::Create(result);
}
+void WebstorePrivateBeginInstallWithManifest3Function::
+ ShowBlockedByPolicyDialog(const Extension* extension,
+ const SkBitmap& icon,
+ content::WebContents* contents,
+ base::OnceClosure done_callback) {
+ DCHECK(extension);
+ DCHECK(contents);
+
+ Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
+
+ std::string message_from_admin =
+ extensions::ExtensionManagementFactory::GetForBrowserContext(profile)
+ ->BlockedInstallMessage(extension->id());
+ if (!message_from_admin.empty()) {
+ blocked_by_policy_error_message_ =
+ l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_MESSAGE_FROM_ADMIN,
+ base::UTF8ToUTF16(message_from_admin));
+ }
+
+ gfx::ImageSkia image =
+ (icon.empty()
+ ? (extension->is_app() ? extensions::util::GetDefaultAppIcon()
+ : extensions::util::GetDefaultExtensionIcon())
+ : gfx::ImageSkia::CreateFrom1xBitmap(icon));
+
+ if (extensions::ScopedTestDialogAutoConfirm::GetAutoConfirmValue() !=
+ extensions::ScopedTestDialogAutoConfirm::NONE) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ std::move(done_callback));
+ return;
+ }
+
+ chrome::ShowExtensionInstallBlockedDialog(
+ extension->name(), blocked_by_policy_error_message_, image, contents,
+ std::move(done_callback));
+}
+
WebstorePrivateCompleteInstallFunction::
WebstorePrivateCompleteInstallFunction() : chrome_details_(this) {}
WebstorePrivateCompleteInstallFunction::
- ~WebstorePrivateCompleteInstallFunction() {}
+ ~WebstorePrivateCompleteInstallFunction() = default;
ExtensionFunction::ResponseAction
WebstorePrivateCompleteInstallFunction::Run() {
@@ -600,8 +877,8 @@ ExtensionFunction::ResponseAction WebstorePrivateSetStoreLoginFunction::Run() {
WebstorePrivateGetWebGLStatusFunction::WebstorePrivateGetWebGLStatusFunction()
: feature_checker_(content::GpuFeatureChecker::Create(
gpu::GPU_FEATURE_TYPE_ACCELERATED_WEBGL,
- base::Bind(&WebstorePrivateGetWebGLStatusFunction::OnFeatureCheck,
- base::Unretained(this)))) {}
+ base::BindOnce(&WebstorePrivateGetWebGLStatusFunction::OnFeatureCheck,
+ base::Unretained(this)))) {}
WebstorePrivateGetWebGLStatusFunction::
~WebstorePrivateGetWebGLStatusFunction() {}
@@ -813,31 +1090,11 @@ WebstorePrivateRequestExtensionFunction::Run() {
Profile* profile = Profile::FromBrowserContext(browser_context());
ExtensionInstallStatus status =
- GetWebstoreExtensionInstallStatus(extension_id, profile);
- if (status == kCanRequest) {
- AddExtensionToPendingList(extension_id);
- // Query the new extension install status again. It should be changed from
- // kCanRequest to kRequestPending if the id has been added into pending list
- // successfully.
- status = GetWebstoreExtensionInstallStatus(extension_id, profile);
- DCHECK_EQ(kRequestPending, status);
- }
+ AddExtensionToPendingList(extension_id, profile);
api::webstore_private::ExtensionInstallStatus api_status =
ConvertExtensionInstallStatusForAPI(status);
return RespondNow(OneArgument(RequestExtension::Results::Create(api_status)));
}
-void WebstorePrivateRequestExtensionFunction::AddExtensionToPendingList(
- const ExtensionId& id) {
- DictionaryPrefUpdate pending_requests_update(
- Profile::FromBrowserContext(browser_context())->GetPrefs(),
- prefs::kCloudExtensionRequestIds);
- DCHECK(!pending_requests_update->FindKey(id));
- base::Value request_data(base::Value::Type::DICTIONARY);
- request_data.SetKey(extension_misc::kExtensionRequestTimestamp,
- ::util::TimeToValue(base::Time::Now()));
- pending_requests_update->SetKey(id, std::move(request_data));
-}
-
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
index 7e8cb607f8f..f1651c720d8 100644
--- a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
+++ b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h
@@ -8,17 +8,25 @@
#include <memory>
#include <string>
+#include "base/strings/string16.h"
#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h"
#include "chrome/browser/extensions/active_install_data.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "chrome/browser/extensions/extension_install_prompt.h"
#include "chrome/browser/extensions/webstore_install_helper.h"
#include "chrome/browser/extensions/webstore_installer.h"
+#include "chrome/common/buildflags.h"
#include "chrome/common/extensions/api/webstore_private.h"
#include "chrome/common/extensions/webstore_install_result.h"
#include "extensions/browser/extension_function.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+// TODO(https://crbug.com/1060801): Here and elsewhere, possibly switch build
+// flag to #if defined(OS_CHROMEOS)
+#include "chrome/browser/ui/supervised_user/parent_permission_dialog.h"
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
+
namespace content {
class GpuFeatureChecker;
}
@@ -51,6 +59,8 @@ class WebstorePrivateBeginInstallWithManifest3Function
WebstorePrivateBeginInstallWithManifest3Function();
+ base::string16 GetBlockedByPolicyErrorMessageForTesting() const;
+
private:
using Params = api::webstore_private::BeginInstallWithManifest3::Params;
@@ -68,7 +78,18 @@ class WebstorePrivateBeginInstallWithManifest3Function
InstallHelperResultCode result,
const std::string& error_message) override;
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+ void OnParentPermissionDone(ParentPermissionDialog::Result result);
+ void OnParentPermissionReceived();
+ void OnParentPermissionCanceled();
+ void OnParentPermissionFailed();
+ // Returns true if the parental approval prompt was shown, false if there was
+ // an error showing it.
+ bool PromptForParentApproval();
+#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
+ void OnRequestPromptDone(ExtensionInstallPrompt::Result result);
+ void OnBlockByPolicyPromptDone();
void HandleInstallProceed();
void HandleInstallAbort(bool user_initiated);
@@ -79,6 +100,15 @@ class WebstorePrivateBeginInstallWithManifest3Function
std::unique_ptr<base::ListValue> CreateResults(
api::webstore_private::Result result) const;
+ // Shows block dialog when |extension| is blcoked by policy on the Window that
+ // |contents| belongs to. |done_callback| will be invoked once the dialog is
+ // closed by user.
+ // Custom error message will be appended if it's set by the policy.
+ void ShowBlockedByPolicyDialog(const Extension* extension,
+ const SkBitmap& icon,
+ content::WebContents* contents,
+ base::OnceClosure done_callback);
+
const Params::Details& details() const { return params_->details; }
ChromeExtensionFunctionDetails chrome_details_;
@@ -94,6 +124,12 @@ class WebstorePrivateBeginInstallWithManifest3Function
// ExtensionInstallPrompt to prompt for confirmation of the install.
scoped_refptr<Extension> dummy_extension_;
+ base::string16 blocked_by_policy_error_message_;
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+ std::unique_ptr<ParentPermissionDialog> parent_permission_dialog_;
+#endif
+
std::unique_ptr<ExtensionInstallPrompt> install_prompt_;
};
@@ -346,8 +382,6 @@ class WebstorePrivateRequestExtensionFunction : public ExtensionFunction {
// Extensionfunction:
ExtensionFunction::ResponseAction Run() override;
- void AddExtensionToPendingList(const ExtensionId& id);
-
DISALLOW_COPY_AND_ASSIGN(WebstorePrivateRequestExtensionFunction);
};
diff --git a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
index 739cb25b12b..d7e32fe1d58 100644
--- a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
@@ -42,8 +42,21 @@
#include "ui/gl/gl_switches.h"
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+// TODO(https://crbug.com/1060801): Here and elsewhere, possibly switch build
+// flag to #if defined(OS_CHROMEOS)
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "chrome/browser/supervised_user/logged_in_user_mixin.h"
#include "chrome/browser/supervised_user/supervised_user_constants.h"
+#include "chrome/browser/supervised_user/supervised_user_features.h"
+#include "chrome/browser/supervised_user/supervised_user_service.h"
+#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
+#include "chrome/browser/ui/supervised_user/parent_permission_dialog.h"
+#include "chrome/browser/ui/views/parent_permission_dialog_view.h"
+#include "chrome/common/pref_names.h"
+#include "components/account_id/account_id.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "extensions/common/extension_builder.h"
#if defined(OS_CHROMEOS)
#include "chromeos/constants/chromeos_switches.h"
@@ -79,6 +92,7 @@ class WebstoreInstallListener : public WebstoreInstaller::Delegate {
received_failure_ = true;
id_ = id;
error_ = error;
+ last_failure_reason_ = reason;
if (waiting_) {
waiting_ = false;
@@ -94,12 +108,17 @@ class WebstoreInstallListener : public WebstoreInstaller::Delegate {
content::RunMessageLoop();
}
bool received_success() const { return received_success_; }
+ bool received_failure() const { return received_failure_; }
const std::string& id() const { return id_; }
+ WebstoreInstaller::FailureReason last_failure_reason() {
+ return last_failure_reason_;
+ }
private:
bool received_failure_;
bool received_success_;
bool waiting_;
+ WebstoreInstaller::FailureReason last_failure_reason_;
std::string id_;
std::string error_;
};
@@ -302,8 +321,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, IsInIncognitoMode) {
GURL page_url = GetTestServerURL("incognito.html");
- ASSERT_TRUE(
- RunPageTest(page_url.spec(), ExtensionApiTest::kFlagUseIncognito));
+ ASSERT_TRUE(RunPageTest(page_url.spec(), kFlagNone, kFlagUseIncognito));
}
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, IsNotInIncognitoMode) {
@@ -373,15 +391,21 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, EmptyCrx) {
}
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+static constexpr char kTestChildEmail[] = "test_child_user@google.com";
+static constexpr char kTestChildGaiaId[] = "8u8tuw09sufncmnaos";
+
class ExtensionWebstorePrivateApiTestChild
: public ExtensionWebstorePrivateApiTest {
public:
ExtensionWebstorePrivateApiTestChild()
: embedded_test_server_(std::make_unique<net::EmbeddedTestServer>()),
- logged_in_user_mixin_(&mixin_host_,
- chromeos::LoggedInUserMixin::LogInType::kChild,
- embedded_test_server_.get(),
- this) {
+ logged_in_user_mixin_(
+ &mixin_host_,
+ chromeos::LoggedInUserMixin::LogInType::kChild,
+ embedded_test_server_.get(),
+ this,
+ true /* should_launch_browser */,
+ AccountId::FromUserEmailGaiaId(kTestChildEmail, kTestChildGaiaId)) {
// Suppress regular user login to enable child user login.
set_chromeos_user_ = false;
}
@@ -423,10 +447,39 @@ class ExtensionWebstorePrivateApiTestChild
browser_main_parts);
}
+ void InitializeFamilyData() {
+ // Set up the child user's custodians (i.e. parents).
+ ASSERT_TRUE(browser());
+ PrefService* prefs = browser()->profile()->GetPrefs();
+ prefs->SetString(prefs::kSupervisedUserCustodianEmail,
+ "test_parent_0@google.com");
+ prefs->SetString(prefs::kSupervisedUserCustodianObfuscatedGaiaId,
+ "239029320");
+
+ prefs->SetString(prefs::kSupervisedUserSecondCustodianEmail,
+ "test_parent_1@google.com");
+ prefs->SetString(prefs::kSupervisedUserSecondCustodianObfuscatedGaiaId,
+ "85948533");
+
+ // Set up the identity test environment, which provides fake
+ // OAuth refresh tokens.
+ identity_test_env_ = std::make_unique<signin::IdentityTestEnvironment>();
+ identity_test_env_->MakeAccountAvailable(kTestChildEmail);
+ identity_test_env_->SetPrimaryAccount(kTestChildEmail);
+ identity_test_env_->SetRefreshTokenForPrimaryAccount();
+ identity_test_env_->SetAutomaticIssueOfAccessTokens(true);
+ }
+
void SetUpOnMainThread() override {
mixin_host_.SetUpOnMainThread();
+ logged_in_user_mixin_.LogInUser(true /* issue_any_scope_token */);
ExtensionWebstorePrivateApiTest::SetUpOnMainThread();
- logged_in_user_mixin_.LogInUser(true /*issue_any_scope_token*/);
+
+ InitializeFamilyData();
+ SupervisedUserService* service =
+ SupervisedUserServiceFactory::GetForProfile(profile());
+ service->SetSupervisedUserExtensionsMayRequestPermissionsPrefForTesting(
+ true);
}
void TearDownOnMainThread() override {
@@ -444,22 +497,154 @@ class ExtensionWebstorePrivateApiTestChild
ExtensionWebstorePrivateApiTest::TearDown();
}
+ chromeos::LoggedInUserMixin* GetLoggedInUserMixin() {
+ return &logged_in_user_mixin_;
+ }
+
+ void SetNextReAuthStatus(
+ const GaiaAuthConsumer::ReAuthProofTokenStatus next_status) {
+ GetLoggedInUserMixin()
+ ->GetFakeGaiaMixin()
+ ->fake_gaia()
+ ->SetNextReAuthStatus(next_status);
+ }
+
+ protected:
+ std::unique_ptr<signin::IdentityTestEnvironment> identity_test_env_;
+
private:
// Replicate what MixinBasedInProcessBrowserTest does since inheriting from
// that class is inconvenient here.
InProcessBrowserTestMixinHost mixin_host_;
// Create another embedded test server to avoid starting the same one twice.
std::unique_ptr<net::EmbeddedTestServer> embedded_test_server_;
-
chromeos::LoggedInUserMixin logged_in_user_mixin_;
};
-// Tests that extension installation is blocked for child accounts, and
-// attempting to do so produces a special error code.
-// Note: This will have to be updated when we enable child-initiated installs.
-IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestChild, InstallBlocked) {
- ASSERT_TRUE(browser());
- ASSERT_TRUE(RunInstallTest("begin_install_fail_child.html", "extension.crx"));
+class ExtensionWebstorePrivateApiTestChildInstallDisabled
+ : public ExtensionWebstorePrivateApiTestChild {
+ public:
+ ExtensionWebstorePrivateApiTestChildInstallDisabled() {
+ feature_list_.InitWithFeatures(
+ {}, {supervised_users::kSupervisedUserInitiatedExtensionInstall});
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+// Tests that extension installation is blocked for child accounts when
+// the feature flag is disabled.
+IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestChildInstallDisabled,
+ InstallBlocked) {
+ ASSERT_TRUE(RunInstallTest("install_blocked_child.html", "app.crx"));
+}
+
+static constexpr char kTestAppId[] = "iladmdjkfniedhfhcfoefgojhgaiaccc";
+static constexpr char kTestAppVersion[] = "0.1";
+
+// Test fixture for various cases of installation for child accounts
+// when the feature flag is enabled.
+class ExtensionWebstorePrivateApiTestChildInstallEnabled
+ : public ExtensionWebstorePrivateApiTestChild,
+ public TestParentPermissionDialogViewObserver {
+ public:
+ // The next dialog action to take.
+ enum class NextDialogAction {
+ kCancel,
+ kAccept,
+ };
+
+ ExtensionWebstorePrivateApiTestChildInstallEnabled()
+ : TestParentPermissionDialogViewObserver(this) {
+ feature_list_.InitWithFeatures(
+ {supervised_users::kSupervisedUserInitiatedExtensionInstall}, {});
+ }
+
+ // TestParentPermissionDialogViewObserver override:
+ void OnTestParentPermissionDialogViewCreated(
+ ParentPermissionDialogView* view) override {
+ view->SetRepromptAfterIncorrectCredential(false);
+ view->SetIdentityManagerForTesting(identity_test_env_->identity_manager());
+ // Everything is set up, so take the next action.
+ if (next_dialog_action_) {
+ switch (next_dialog_action_.value()) {
+ case NextDialogAction::kCancel:
+ view->CancelDialog();
+ break;
+ case NextDialogAction::kAccept:
+ view->AcceptDialog();
+ break;
+ }
+ }
+ }
+
+ void set_next_dialog_action(NextDialogAction action) {
+ next_dialog_action_ = action;
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+ base::Optional<NextDialogAction> next_dialog_action_;
+};
+
+// Tests install for a child when parent permission is granted.
+IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestChildInstallEnabled,
+ ParentPermissionGranted) {
+ WebstoreInstallListener listener;
+ WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
+ set_next_dialog_action(NextDialogAction::kAccept);
+
+ // Tell the Reauth API client to return a success for the next reauth
+ // request.
+ SetNextReAuthStatus(GaiaAuthConsumer::ReAuthProofTokenStatus::kSuccess);
+ ASSERT_TRUE(RunInstallTest("install_child.html", "app.crx"));
+ listener.Wait();
+ ASSERT_TRUE(listener.received_success());
+ ASSERT_EQ(kTestAppId, listener.id());
+
+ scoped_refptr<const Extension> extension =
+ extensions::ExtensionBuilder("test extension")
+ .SetID(kTestAppId)
+ .SetVersion(kTestAppVersion)
+ .Build();
+ SupervisedUserService* service =
+ SupervisedUserServiceFactory::GetForProfile(profile());
+ ASSERT_TRUE(service->IsExtensionAllowed(*extension));
+}
+
+// Tests no install occurs for a child when the parent permission
+// dialog is canceled.
+IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestChildInstallEnabled,
+ ParentPermissionCanceled) {
+ WebstoreInstallListener listener;
+ set_next_dialog_action(NextDialogAction::kCancel);
+ WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
+ ASSERT_TRUE(RunInstallTest("install_cancel_child.html", "app.crx"));
+ listener.Wait();
+ ASSERT_TRUE(listener.received_failure());
+ ASSERT_EQ(kTestAppId, listener.id());
+ ASSERT_EQ(listener.last_failure_reason(),
+ WebstoreInstaller::FailureReason::FAILURE_REASON_CANCELLED);
+ scoped_refptr<const Extension> extension =
+ extensions::ExtensionBuilder("test extension")
+ .SetID(kTestAppId)
+ .SetVersion(kTestAppVersion)
+ .Build();
+ SupervisedUserService* service =
+ SupervisedUserServiceFactory::GetForProfile(profile());
+ ASSERT_FALSE(service->IsExtensionAllowed(*extension));
+}
+
+// Tests that no parent permission is required for a child to install a theme.
+IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestChildInstallEnabled,
+ NoParentPermissionRequiredForTheme) {
+ WebstoreInstallListener listener;
+ WebstorePrivateApi::SetWebstoreInstallerDelegateForTesting(&listener);
+ ASSERT_TRUE(RunInstallTest("theme.html", "../../theme.crx"));
+ listener.Wait();
+ ASSERT_TRUE(listener.received_success());
+ ASSERT_EQ("idlfhncioikpdnlhnmcjogambnefbbfp", listener.id());
}
#endif // BUILDFLAG(ENABLE_SUPERVISED_USERS)
diff --git a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc
index 3c42a4188b8..2a8ec2b13aa 100644
--- a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_unittest.cc
@@ -6,15 +6,22 @@
#include <vector>
+#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/util/values/values_util.h"
#include "chrome/browser/extensions/extension_api_unittest.h"
-#include "chrome/browser/extensions/extension_function_test_utils.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/test/web_contents_tester.h"
+#include "extensions/browser/api_test_utils.h"
+#include "extensions/browser/extension_dialog_auto_confirm.h"
#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/pref_names.h"
#include "extensions/common/extension_builder.h"
namespace extensions {
@@ -22,11 +29,65 @@ namespace {
constexpr char kInvalidId[] = "Invalid id";
constexpr char kExtensionId[] = "abcdefghijklmnopabcdefghijklmnop";
constexpr int kFakeTime = 12345;
+constexpr char kExtensionManifest[] = R"({
+ \"name\" : \"Extension\",
+ \"manifest_version\": 3,
+ \"version\": \"0.1\"})";
+constexpr char kBlockAllExtensionSettings[] = R"({
+ "*": {
+ "installation_mode":"blocked",
+ "blocked_install_message":"This extension is blocked."
+ }
+})";
+constexpr char kBlockOneExtensionSettings[] = R"({
+ "abcdefghijklmnopabcdefghijklmnop": {
+ "installation_mode":"blocked"
+ }
+})";
+
+constexpr char kAllowedExtensionSettings[] = R"({
+ "abcdefghijklmnopabcdefghijklmnop" : {
+ "installation_mode": "allowed"
+ }
+})";
+
+constexpr char kBlockedExtensionSettings[] = R"({
+ "abcdefghijklmnopabcdefghijklmnop" : {
+ "installation_mode": "blocked"
+ }
+})";
+
+constexpr char kWebstoreUserCancelledError[] = "User cancelled install";
base::Time GetFaketime() {
return base::Time::FromJavaTime(kFakeTime);
}
+// Verifies that the extension request pending list in |profile| matches the
+// |expected_pending_requests|.
+void VerifyPendingList(
+ const std::map<ExtensionId, base::Time>& expected_pending_requests,
+ Profile* profile) {
+ const base::DictionaryValue* actual_pending_requests =
+ profile->GetPrefs()->GetDictionary(prefs::kCloudExtensionRequestIds);
+ ASSERT_EQ(expected_pending_requests.size(), actual_pending_requests->size());
+ for (const auto& expected_request : expected_pending_requests) {
+ EXPECT_EQ(::util::TimeToValue(expected_request.second),
+ *actual_pending_requests->FindKey(expected_request.first)
+ ->FindKey(extension_misc::kExtensionRequestTimestamp));
+ }
+}
+
+void SetExtensionSettings(const std::string& settings_string,
+ TestingProfile* profile) {
+ base::Optional<base::Value> settings =
+ base::JSONReader::Read(settings_string);
+ ASSERT_TRUE(settings.has_value());
+ profile->GetTestingPrefService()->SetManagedPref(
+ pref_names::kExtensionManagement,
+ base::Value::ToUniquePtrValue(std::move(*settings)));
+}
+
} // namespace
class WebstorePrivateExtensionInstallRequestBase : public ExtensionApiUnittest {
@@ -88,7 +149,7 @@ class WebstorePrivateRequestExtensionTest
profile()->GetTestingPrefService()->SetManagedPref(
prefs::kCloudExtensionRequestEnabled,
std::make_unique<base::Value>(true));
- VerifyPendingList({});
+ VerifyPendingList({}, profile());
}
void SetPendingList(const std::vector<ExtensionId>& ids) {
@@ -104,18 +165,6 @@ class WebstorePrivateRequestExtensionTest
prefs::kCloudExtensionRequestIds, std::move(id_values));
}
- void VerifyPendingList(
- const std::map<ExtensionId, base::Time>& expected_pending_requests) {
- const base::DictionaryValue* actual_pending_requests =
- profile()->GetPrefs()->GetDictionary(prefs::kCloudExtensionRequestIds);
- ASSERT_EQ(expected_pending_requests.size(),
- actual_pending_requests->size());
- for (const auto& expected_request : expected_pending_requests) {
- EXPECT_EQ(::util::TimeToValue(expected_request.second),
- *actual_pending_requests->FindKey(expected_request.first)
- ->FindKey(extension_misc::kExtensionRequestTimestamp));
- }
- }
};
TEST_F(WebstorePrivateRequestExtensionTest, InvalidExtensionId) {
@@ -124,7 +173,7 @@ TEST_F(WebstorePrivateRequestExtensionTest, InvalidExtensionId) {
EXPECT_EQ(kInvalidId,
RunFunctionAndReturnError(function.get(),
GenerateArgs("invalid-extension-id")));
- VerifyPendingList({});
+ VerifyPendingList({}, profile());
}
TEST_F(WebstorePrivateRequestExtensionTest, UnrequestableExtension) {
@@ -135,12 +184,35 @@ TEST_F(WebstorePrivateRequestExtensionTest, UnrequestableExtension) {
RunFunctionAndReturnValue(function.get(), GenerateArgs(kExtensionId));
VerifyResponse(ExtensionInstallStatus::EXTENSION_INSTALL_STATUS_ENABLED,
response.get());
- VerifyPendingList({});
+ VerifyPendingList({}, profile());
+}
+
+TEST_F(WebstorePrivateRequestExtensionTest, AlreadyApprovedExtension) {
+ SetExtensionSettings(kAllowedExtensionSettings, profile());
+ auto function =
+ base::MakeRefCounted<WebstorePrivateRequestExtensionFunction>();
+ std::unique_ptr<base::Value> response =
+ RunFunctionAndReturnValue(function.get(), GenerateArgs(kExtensionId));
+ VerifyResponse(ExtensionInstallStatus::EXTENSION_INSTALL_STATUS_INSTALLABLE,
+ response.get());
+ VerifyPendingList({{kExtensionId, base::Time::Now()}}, profile());
+}
+
+TEST_F(WebstorePrivateRequestExtensionTest, AlreadyRejectedExtension) {
+ SetExtensionSettings(kBlockedExtensionSettings, profile());
+ auto function =
+ base::MakeRefCounted<WebstorePrivateRequestExtensionFunction>();
+ std::unique_ptr<base::Value> response =
+ RunFunctionAndReturnValue(function.get(), GenerateArgs(kExtensionId));
+ VerifyResponse(
+ ExtensionInstallStatus::EXTENSION_INSTALL_STATUS_BLOCKED_BY_POLICY,
+ response.get());
+ VerifyPendingList({{kExtensionId, base::Time::Now()}}, profile());
}
TEST_F(WebstorePrivateRequestExtensionTest, AlreadyPendingExtension) {
SetPendingList({kExtensionId});
- VerifyPendingList({{kExtensionId, GetFaketime()}});
+ VerifyPendingList({{kExtensionId, GetFaketime()}}, profile());
auto function =
base::MakeRefCounted<WebstorePrivateRequestExtensionFunction>();
std::unique_ptr<base::Value> response =
@@ -148,7 +220,7 @@ TEST_F(WebstorePrivateRequestExtensionTest, AlreadyPendingExtension) {
VerifyResponse(
ExtensionInstallStatus::EXTENSION_INSTALL_STATUS_REQUEST_PENDING,
response.get());
- VerifyPendingList({{kExtensionId, GetFaketime()}});
+ VerifyPendingList({{kExtensionId, GetFaketime()}}, profile());
}
TEST_F(WebstorePrivateRequestExtensionTest, RequestExtension) {
@@ -159,7 +231,205 @@ TEST_F(WebstorePrivateRequestExtensionTest, RequestExtension) {
VerifyResponse(
ExtensionInstallStatus::EXTENSION_INSTALL_STATUS_REQUEST_PENDING,
response.get());
- VerifyPendingList({{kExtensionId, base::Time::Now()}});
+ VerifyPendingList({{kExtensionId, base::Time::Now()}}, profile());
+}
+
+class WebstorePrivateBeginInstallWithManifest3Test
+ : public ExtensionApiUnittest {
+ public:
+ WebstorePrivateBeginInstallWithManifest3Test()
+ : ExtensionApiUnittest(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
+
+ void SetUp() override {
+ ExtensionApiUnittest::SetUp();
+ TestExtensionSystem* test_extension_system =
+ static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()));
+ service_ = test_extension_system->CreateExtensionService(
+ base::CommandLine::ForCurrentProcess(), base::FilePath(), false);
+ }
+
+ void EnableExtensionRequest(bool enable) {
+ profile()->GetTestingPrefService()->SetManagedPref(
+ prefs::kCloudExtensionRequestEnabled,
+ std::make_unique<base::Value>(enable));
+ }
+
+ void SetExtensionSettings(const std::string& settings_string) {
+ base::Optional<base::Value> settings =
+ base::JSONReader::Read(settings_string);
+ ASSERT_TRUE(settings);
+ profile()->GetTestingPrefService()->SetManagedPref(
+ pref_names::kExtensionManagement,
+ base::Value::ToUniquePtrValue(std::move(*settings)));
+ }
+
+ std::string GenerateArgs(const char* id, const char* manifest) {
+ return base::StringPrintf(R"([{"id":"%s", "manifest":"%s"}])", id,
+ manifest);
+ }
+
+ void VerifyExtensionRequestFunctionResult(ExtensionFunction* function) {
+ const base::Value* result = nullptr;
+ ASSERT_TRUE(function->GetResultList() &&
+ function->GetResultList()->Get(0, &result));
+ EXPECT_EQ("user_cancelled", result->GetString());
+ EXPECT_EQ(kWebstoreUserCancelledError, function->GetError());
+ }
+
+ void VerifyBlockedByPolicyFunctionResult(
+ WebstorePrivateBeginInstallWithManifest3Function* function,
+ const base::string16& expected_blocked_message) {
+ const base::Value* result;
+ ASSERT_TRUE(function->GetResultList() &&
+ function->GetResultList()->Get(0, &result));
+ EXPECT_EQ("user_cancelled", result->GetString());
+ EXPECT_EQ(kWebstoreUserCancelledError, function->GetError());
+ EXPECT_EQ(expected_blocked_message,
+ function->GetBlockedByPolicyErrorMessageForTesting());
+ }
+
+ scoped_refptr<const Extension> CreateExtension(const ExtensionId& id) {
+ return ExtensionBuilder("extension").SetID(id).Build();
+ }
+
+ private:
+ ExtensionService* service_ = nullptr;
+};
+
+TEST_F(WebstorePrivateBeginInstallWithManifest3Test,
+ RequestExtensionWithConfirmThenShowPendingDialog) {
+ EnableExtensionRequest(true);
+ std::unique_ptr<content::WebContents> web_contents =
+ content::WebContentsTester::CreateTestWebContents(profile(), nullptr);
+
+ VerifyPendingList({}, profile());
+
+ // Confirm request dialog
+ auto function =
+ base::MakeRefCounted<WebstorePrivateBeginInstallWithManifest3Function>();
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ {
+ ScopedTestDialogAutoConfirm auto_confirm(
+ ScopedTestDialogAutoConfirm::ACCEPT);
+ api_test_utils::RunFunction(function.get(),
+ GenerateArgs(kExtensionId, kExtensionManifest),
+ profile());
+ }
+ VerifyExtensionRequestFunctionResult(function.get());
+ VerifyPendingList({{kExtensionId, base::Time::Now()}}, profile());
+
+ // Show pending request dialog which can only be canceled.
+ function =
+ base::MakeRefCounted<WebstorePrivateBeginInstallWithManifest3Function>();
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ {
+ ScopedTestDialogAutoConfirm auto_cancel(
+ ScopedTestDialogAutoConfirm::CANCEL);
+ api_test_utils::RunFunction(function.get(),
+ GenerateArgs(kExtensionId, kExtensionManifest),
+ profile());
+ }
+ VerifyExtensionRequestFunctionResult(function.get());
+ VerifyPendingList({{kExtensionId, base::Time::Now()}}, profile());
+}
+
+TEST_F(WebstorePrivateBeginInstallWithManifest3Test,
+ RequestExtensionWithCancel) {
+ EnableExtensionRequest(true);
+ VerifyPendingList({}, profile());
+
+ std::unique_ptr<content::WebContents> web_contents =
+ content::WebContentsTester::CreateTestWebContents(profile(), nullptr);
+ auto function =
+ base::MakeRefCounted<WebstorePrivateBeginInstallWithManifest3Function>();
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ ScopedTestDialogAutoConfirm auto_cancel(ScopedTestDialogAutoConfirm::CANCEL);
+
+ api_test_utils::RunFunction(function.get(),
+ GenerateArgs(kExtensionId, kExtensionManifest),
+ profile());
+ VerifyExtensionRequestFunctionResult(function.get());
+ VerifyPendingList({}, profile());
+}
+
+TEST_F(WebstorePrivateBeginInstallWithManifest3Test,
+ NormalInstallIfRequestExtensionIsDisabled) {
+ EnableExtensionRequest(true);
+ VerifyPendingList({}, profile());
+
+ std::unique_ptr<content::WebContents> web_contents =
+ content::WebContentsTester::CreateTestWebContents(profile(), nullptr);
+ auto function =
+ base::MakeRefCounted<WebstorePrivateBeginInstallWithManifest3Function>();
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ {
+ ScopedTestDialogAutoConfirm auto_confirm(
+ ScopedTestDialogAutoConfirm::ACCEPT);
+ api_test_utils::RunFunction(function.get(),
+ GenerateArgs(kExtensionId, kExtensionManifest),
+ profile());
+ }
+ VerifyPendingList({{kExtensionId, base::Time::Now()}}, profile());
+
+ // Show install prompt dialog if extension request feature is disabled.
+ EnableExtensionRequest(false);
+ function =
+ base::MakeRefCounted<WebstorePrivateBeginInstallWithManifest3Function>();
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ {
+ // Successfully confirm the install prompt and the API returns an empty
+ // string without error.
+ ScopedTestDialogAutoConfirm auto_cancel(
+ ScopedTestDialogAutoConfirm::ACCEPT);
+ std::unique_ptr<base::Value> response = RunFunctionAndReturnValue(
+ function.get(), GenerateArgs(kExtensionId, kExtensionManifest));
+ ASSERT_TRUE(response);
+ ASSERT_TRUE(response->is_string());
+ EXPECT_TRUE(response->GetString().empty());
+ }
+
+ // Pending list is not changed.
+ VerifyPendingList({{kExtensionId, base::Time::Now()}}, profile());
+}
+
+TEST_F(WebstorePrivateBeginInstallWithManifest3Test, BlockedByPolicy) {
+ SetExtensionSettings(kBlockAllExtensionSettings);
+
+ std::unique_ptr<content::WebContents> web_contents =
+ content::WebContentsTester::CreateTestWebContents(profile(), nullptr);
+ auto function =
+ base::MakeRefCounted<WebstorePrivateBeginInstallWithManifest3Function>();
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::ACCEPT);
+
+ api_test_utils::RunFunction(function.get(),
+ GenerateArgs(kExtensionId, kExtensionManifest),
+ profile());
+ VerifyBlockedByPolicyFunctionResult(
+ function.get(),
+ base::ASCIIToUTF16(
+ "From your administrator: This extension is blocked."));
+}
+
+TEST_F(WebstorePrivateBeginInstallWithManifest3Test,
+ BlockedByPolicyWithExtensionRequest) {
+ SetExtensionSettings(kBlockOneExtensionSettings);
+ EnableExtensionRequest(true);
+ VerifyPendingList({}, profile());
+
+ std::unique_ptr<content::WebContents> web_contents =
+ content::WebContentsTester::CreateTestWebContents(profile(), nullptr);
+ auto function =
+ base::MakeRefCounted<WebstorePrivateBeginInstallWithManifest3Function>();
+ function->SetRenderFrameHost(web_contents->GetMainFrame());
+ ScopedTestDialogAutoConfirm auto_confirm(ScopedTestDialogAutoConfirm::ACCEPT);
+
+ api_test_utils::RunFunction(function.get(),
+ GenerateArgs(kExtensionId, kExtensionManifest),
+ profile());
+ VerifyPendingList({}, profile());
+ VerifyBlockedByPolicyFunctionResult(function.get(), base::string16());
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/default_extensions/BUILD.gn b/chromium/chrome/browser/extensions/default_extensions/BUILD.gn
index 77a0554f54f..4cf3f018f9b 100644
--- a/chromium/chrome/browser/extensions/default_extensions/BUILD.gn
+++ b/chromium/chrome/browser/extensions/default_extensions/BUILD.gn
@@ -4,12 +4,8 @@
if (is_win) {
copy("default_extensions") {
- sources = [
- "external_extensions.json",
- ]
- outputs = [
- "$root_out_dir/extensions/{{source_file_part}}",
- ]
+ sources = [ "external_extensions.json" ]
+ outputs = [ "$root_out_dir/extensions/{{source_file_part}}" ]
}
} else {
# No-op on non-Windows.
diff --git a/chromium/chrome/browser/flags/BUILD.gn b/chromium/chrome/browser/flags/BUILD.gn
new file mode 100644
index 00000000000..05c4d848f50
--- /dev/null
+++ b/chromium/chrome/browser/flags/BUILD.gn
@@ -0,0 +1,85 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/flags/BooleanCachedFieldTrialParameter.java",
+ "android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java",
+ "android/java/src/org/chromium/chrome/browser/flags/CachedFieldTrialParameter.java",
+ "android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java",
+ "android/java/src/org/chromium/chrome/browser/flags/DoubleCachedFieldTrialParameter.java",
+ "android/java/src/org/chromium/chrome/browser/flags/IntCachedFieldTrialParameter.java",
+ "android/java/src/org/chromium/chrome/browser/flags/StringCachedFieldTrialParameter.java",
+ ]
+ deps = [
+ "//base:base_java",
+ "//base:jni_java",
+ "//chrome/browser/preferences:java",
+ ]
+ srcjar_deps = [ ":chrome_android_java_switches_srcjar" ]
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+}
+
+generate_jni("jni_headers") {
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java",
+ "android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java",
+ ]
+}
+
+static_library("flags_android") {
+ sources = [
+ "android/cached_feature_flags.cc",
+ "android/cached_feature_flags.h",
+ ]
+ deps = [
+ ":jni_headers",
+ "//base",
+ "//content/public/common",
+ ]
+}
+
+java_cpp_strings("chrome_android_java_switches_srcjar") {
+ sources = [ "//chrome/common/chrome_switches.cc" ]
+ template = "android/java_templates/ChromeSwitches.java.tmpl"
+}
+
+java_library("flags_junit_tests") {
+ # Skip platform checks since Robolectric depends on requires_android targets.
+ bypass_platform_checks = true
+ testonly = true
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsAnnotationUnitTest.java",
+ "android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsUnitTest.java",
+ "android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureListWithProcessorUnitTest.java",
+ "android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureListWithoutProcessorUnitTest.java",
+ ]
+ deps = [
+ ":java",
+ "//base:base_java",
+ "//base:base_java_test_support",
+ "//base:base_junit_test_support",
+ "//base/test:test_support_java",
+ "//chrome/test/android:chrome_java_test_support",
+ ]
+}
+
+android_library("javatests") {
+ testonly = true
+ sources = [ "android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureListInstrumentationTest.java" ]
+ deps = [
+ ":java",
+ "//base:base_java",
+ "//base:base_java_test_support",
+ "//base/test:test_support_java",
+ "//chrome/android:chrome_java",
+ "//chrome/test/android:chrome_java_test_support",
+ "//third_party/android_sdk:android_test_mock_java",
+ "//third_party/android_support_test_runner:runner_java",
+ "//third_party/junit",
+ "//third_party/mockito:mockito_java",
+ ]
+}
diff --git a/chromium/chrome/browser/image_decoder/BUILD.gn b/chromium/chrome/browser/image_decoder/BUILD.gn
new file mode 100644
index 00000000000..068448ffed5
--- /dev/null
+++ b/chromium/chrome/browser/image_decoder/BUILD.gn
@@ -0,0 +1,45 @@
+# Copyright 2019 The Chromium 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/util/version.gni")
+
+source_set("image_decoder") {
+ deps = [
+ "//base",
+ "//content/public/browser",
+ "//ipc",
+ "//services/data_decoder/public/cpp",
+ "//services/service_manager/public/cpp",
+ "//skia",
+ "//ui/gfx",
+ ]
+
+ sources = [
+ "image_decoder.cc",
+ "image_decoder.h",
+ ]
+}
+
+if (!is_android) {
+ source_set("browser_tests") {
+ testonly = true
+
+ configs += [ "//build/config:precompiled_headers" ]
+ defines = [
+ "HAS_OUT_OF_PROC_TEST_RUNNER",
+ "CHROME_VERSION_MAJOR=" + chrome_version_major,
+ ]
+
+ deps = [
+ "//base",
+ "//chrome/app:generated_resources",
+ "//chrome/test:test_support",
+ "//content/public/browser",
+ "//content/test:test_support",
+ "//ui/base",
+ ]
+
+ sources = [ "image_decoder_browsertest.cc" ]
+ }
+}
diff --git a/chromium/chrome/browser/image_editor/internal/BUILD.gn b/chromium/chrome/browser/image_editor/internal/BUILD.gn
index bf74354fb52..12c1e6dc2dd 100644
--- a/chromium/chrome/browser/image_editor/internal/BUILD.gn
+++ b/chromium/chrome/browser/image_editor/internal/BUILD.gn
@@ -7,9 +7,7 @@ import("//build/config/android/rules.gni")
# Upstream ImageEditor implementation which does nothing. Actual implementation
# lives downstream.
android_library("java") {
- java_files = [ "android/java/src/org/chromium/chrome/browser/image_editor/ImageEditorCoordinatorImpl.java" ]
+ sources = [ "android/java/src/org/chromium/chrome/browser/image_editor/ImageEditorDialogCoordinatorImpl.java" ]
- deps = [
- "//chrome/browser/image_editor/public:java",
- ]
+ deps = [ "//chrome/browser/image_editor/public:java" ]
}
diff --git a/chromium/chrome/browser/image_editor/public/BUILD.gn b/chromium/chrome/browser/image_editor/public/BUILD.gn
index d38e12eae83..1e4d315410d 100644
--- a/chromium/chrome/browser/image_editor/public/BUILD.gn
+++ b/chromium/chrome/browser/image_editor/public/BUILD.gn
@@ -5,5 +5,7 @@
import("//build/config/android/rules.gni")
android_library("java") {
- java_files = [ "android/java/src/org/chromium/chrome/browser/image_editor/ImageEditorCoordinator.java" ]
+ sources = [ "android/java/src/org/chromium/chrome/browser/image_editor/ImageEditorDialogCoordinator.java" ]
+
+ deps = [ "//third_party/android_deps:android_support_v7_appcompat_java" ]
}
diff --git a/chromium/chrome/browser/image_fetcher/BUILD.gn b/chromium/chrome/browser/image_fetcher/BUILD.gn
index bf16ee4a89b..d7dc0ae5526 100644
--- a/chromium/chrome/browser/image_fetcher/BUILD.gn
+++ b/chromium/chrome/browser/image_fetcher/BUILD.gn
@@ -8,17 +8,17 @@ android_library("java") {
deps = [
"//base:base_java",
"//base:jni_java",
- "//chrome/android/public/profiles:java",
+ "//chrome/browser/profiles/android:java",
"//chrome/browser/util:java",
"//content/public/android:content_java",
"//third_party/gif_player:gif_player_java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
- java_files = [
+ sources = [
"android/java/src/org/chromium/chrome/browser/image_fetcher/CachedImageFetcher.java",
+ "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java",
"android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java",
"android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherFactory.java",
- "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcher.java",
"android/java/src/org/chromium/chrome/browser/image_fetcher/InMemoryCachedImageFetcher.java",
"android/java/src/org/chromium/chrome/browser/image_fetcher/NetworkImageFetcher.java",
]
@@ -27,7 +27,5 @@ android_library("java") {
}
generate_jni("jni_headers") {
- sources = [
- "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java",
- ]
+ sources = [ "android/java/src/org/chromium/chrome/browser/image_fetcher/ImageFetcherBridge.java" ]
}
diff --git a/chromium/chrome/browser/media/BUILD.gn b/chromium/chrome/browser/media/BUILD.gn
index 4ffc0e9a556..797a37c3691 100644
--- a/chromium/chrome/browser/media/BUILD.gn
+++ b/chromium/chrome/browser/media/BUILD.gn
@@ -7,16 +7,16 @@ import("//third_party/protobuf/proto_library.gni")
mojom("mojo_bindings") {
sources = [
+ "history/media_history_store.mojom",
"media_engagement_score_details.mojom",
]
public_deps = [
+ "//services/media_session/public/mojom",
"//url/mojom:url_mojom_origin",
]
}
proto_library("media_engagement_preload_proto") {
- sources = [
- "media_engagement_preload.proto",
- ]
+ sources = [ "media_engagement_preload.proto" ]
}
diff --git a/chromium/chrome/browser/media/feeds/BUILD.gn b/chromium/chrome/browser/media/feeds/BUILD.gn
new file mode 100644
index 00000000000..92d3ceee185
--- /dev/null
+++ b/chromium/chrome/browser/media/feeds/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+import("//third_party/protobuf/proto_library.gni")
+
+mojom("mojo_bindings") {
+ sources = [ "media_feeds_store.mojom" ]
+
+ public_deps = [
+ "//services/media_session/public/mojom",
+ "//url/mojom:url_mojom_origin",
+ ]
+}
+
+proto_library("proto") {
+ sources = [ "media_feeds.proto" ]
+}
diff --git a/chromium/chrome/browser/media/feeds/media_feeds_store.mojom b/chromium/chrome/browser/media/feeds/media_feeds_store.mojom
new file mode 100644
index 00000000000..9d24cfd2a11
--- /dev/null
+++ b/chromium/chrome/browser/media/feeds/media_feeds_store.mojom
@@ -0,0 +1,286 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module media_feeds.mojom;
+
+import "services/media_session/public/mojom/media_session.mojom";
+import "mojo/public/mojom/base/string16.mojom";
+import "mojo/public/mojom/base/time.mojom";
+import "url/mojom/url.mojom";
+
+struct MediaFeed {
+ // The ID of the field in storage.
+ int64 id;
+
+ // The URL for the discovered feed.
+ url.mojom.Url url;
+
+ // The last time this feed was discovered.
+ mojo_base.mojom.Time last_discovery_time;
+
+ // The last time this feed was fetched.
+ mojo_base.mojom.Time? last_fetch_time;
+
+ // Whether the user has forcibly opted out of the feed.
+ FeedUserStatus user_status;
+
+ // The result of the last fetch of this feed.
+ FetchResult last_fetch_result;
+
+ // The number of times in a row the feed has failed to be fetched.
+ int64 fetch_failed_count;
+
+ // The time the previously fetched feed should expire in the cache.
+ mojo_base.mojom.Time? cache_expiry_time;
+
+ // The number of items in the last feed fetch.
+ int64 last_fetch_item_count;
+
+ // The number of items in the last feed fetch that are eligible for play next.
+ int64 last_fetch_play_next_count;
+
+ // A field mask of the content types in the last feed fetch.
+ int64 last_fetch_content_types;
+
+ // The logos for the feed.
+ array<media_session.mojom.MediaImage> logos;
+
+ // A display name for the feed.
+ string display_name;
+};
+
+// The result of fetching the feed. This enum is committed to storage so do not
+// change the numbering.
+enum FetchResult {
+ // The feed has never been fetched.
+ kNone = 0,
+
+ // The feed was fetched successfully.
+ kSuccess = 1,
+
+ // The feed failed to fetch because of a backend server error.
+ kFailedBackendError = 2,
+
+ // The feed failed to fetch because of a network error.
+ kFailedNetworkError = 3,
+};
+
+// Whether the user has forcibly opted out of the feed. This enum is committed
+// to storage so do not change the numbering.
+enum FeedUserStatus {
+ // The browser should determine whether to fetch the feed based on metrics.
+ kAuto = 0,
+
+ // The user has opted out of seeing the feed.
+ kDisabled = 1,
+};
+
+// The type of the feed item. This enum is committed to storage so do not
+// change the numbering.
+enum MediaFeedItemType {
+ // 1 << 0. Any video. https://schema.org/VideoObject
+ kVideo = 1,
+
+ // 1 << 1. A TV series. https://schema.org/TVSeries
+ kTVSeries = 2,
+
+ // 1 << 2. A movie. https://schema.org/Movie
+ kMovie = 4,
+};
+
+// The action status for the feed item. This enum is committed to storage so
+// do not change the numbering.
+// https://schema.org/actionStatus
+enum MediaFeedItemActionStatus {
+ kUnknown = 0,
+
+ // The user is currently watching this media.
+ // https://schema.org/ActiveActionStatus
+ kActive = 1,
+
+ // The user has not started watching this media.
+ // https://schema.org/PotentialActionStatus
+ kPotential = 2,
+
+ // The user has finished watching this media.
+ // https://schema.org/CompletedActionStatus
+ kCompleted = 3,
+};
+
+// Official rating for a piece of content (e.g. MPAA PG-13).
+// https://schema.org/contentRating
+struct ContentRating {
+ // The rating agency (e.g. MPAA).
+ string agency;
+
+ // The content rating.
+ string value;
+};
+
+// A counter for a type of interaction e.g. how many likes or dislikes.
+// https://schema.org/InteractionCounter
+enum InteractionCounterType {
+ kWatch,
+ kLike,
+ kDislike,
+};
+
+// The author of the content.
+// https://schema.org/author
+struct Author {
+ // A displayable name for the author.
+ string name;
+
+ // The URL of the author.
+ url.mojom.Url url;
+};
+
+// A third party identifier for a piece of content.
+// https://schema.org/identifier
+struct Identifier {
+ enum Type {
+ kTMSRootId,
+ kTMSId,
+ kPartnerId,
+ };
+
+ Type type;
+ string value;
+};
+
+// An action to start watching a piece of content.
+// https://schema.org/WatchAction
+struct Action {
+ // The URL to watch the content.
+ url.mojom.Url url;
+
+ // The time the content will start playing.
+ mojo_base.mojom.TimeDelta? start_time;
+};
+
+// The content that should be suggested to play next if the user has finished
+// watching the current content.
+struct PlayNextCandidate {
+ // A displayable name of the play next content.
+ string name;
+
+ // The season and episode number of the content.
+ int64 season_number;
+ int64 episode_number;
+
+ // The action to launch the content.
+ Action action;
+
+ // The duration of the content.
+ mojo_base.mojom.TimeDelta duration;
+
+ // The identifiers for the content. We will store up to one of each type.
+ array<Identifier> identifiers;
+};
+
+// https://schema.org/TVEpisode
+struct TVEpisode {
+ // The displayable name of the episode.
+ string name;
+
+ // The season and episode number of the episode.
+ int64 episode_number;
+ int64 season_number;
+
+ // The identifiers for the episode. We will store up to one of each type.
+ array<Identifier> identifiers;
+};
+
+// Details specific to live content.
+struct LiveDetails {
+ // The date/time the feed item became live.
+ mojo_base.mojom.Time? start_time;
+
+ // The date/time the feed item finished becoming live.
+ mojo_base.mojom.Time? end_time;
+};
+
+// The result of checking an item against the Safe Search API.
+enum SafeSearchResult {
+ // We haven't checked this item against the API.
+ kUnknown,
+
+ // We checked this item and it was classified as safe.
+ kSafe,
+
+ // We checked this item and it was classified as unsafe (e.g. adult).
+ kUnsafe,
+};
+
+// The Media Feed Item is an individual item stored in a Media Feed. It
+// represents a single recommendation such as a video or TV show.
+// https://wicg.github.io/media-feeds/index.html#media-feed-item
+struct MediaFeedItem {
+ // The type of this feed item such as a video or TV show.
+ MediaFeedItemType type;
+
+ // The name of the feed item to be displayed to the user.
+ mojo_base.mojom.String16 name;
+
+ // The author that created the content.
+ Author author;
+
+ // The date/time this feed item was published.
+ mojo_base.mojom.Time date_published;
+
+ // Whether the media item is considered "family friendly".
+ bool is_family_friendly;
+
+ // The action status for this feed item.
+ MediaFeedItemActionStatus action_status;
+
+ // The action to be taken on the content.
+ Action action;
+
+ // The interaction counters for this content (e.g. number of likes).
+ map<InteractionCounterType, uint64> interaction_counters;
+
+ // The content ratings for this content.
+ array<ContentRating> content_ratings;
+
+ // The genre of this feed item.
+ array<string> genre;
+
+ // The duration of this feed item.
+ mojo_base.mojom.TimeDelta? duration;
+
+ // Whether the feed item is live.
+ LiveDetails? live;
+
+ // The TV episode data associated with the content.
+ TVEpisode? tv_episode;
+
+ // The content that should be played after this.
+ PlayNextCandidate? play_next_candidate;
+
+ // The identifiers for the content. We will store up to one of each type.
+ array<Identifier> identifiers;
+
+ // How many times this feed item has been displayed in the Chrome UI.
+ uint64 shown_count;
+
+ // Whether the user has previously clicked on this feed item.
+ bool clicked;
+
+ // The images for the feed item.
+ array<media_session.mojom.MediaImage> images;
+
+ // The result of safe search checking this media item.
+ SafeSearchResult safe_search_result;
+};
+
+// MediaFeedStore allows the Media Feeds WebUI to access data from the Media
+// Feeds backend in the browser process for diagnostic purposes.
+interface MediaFeedsStore {
+ // Gets all the discovered media feeds.
+ GetMediaFeeds() => (array<MediaFeed> feeds);
+
+ // Gets the items for the media feed.
+ GetItemsForMediaFeed(int64 feed_id) => (array<MediaFeedItem> items);
+};
diff --git a/chromium/chrome/browser/media/history/media_history_store.mojom b/chromium/chrome/browser/media/history/media_history_store.mojom
new file mode 100644
index 00000000000..c8c48eb8a5f
--- /dev/null
+++ b/chromium/chrome/browser/media/history/media_history_store.mojom
@@ -0,0 +1,87 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module media_history.mojom;
+
+import "mojo/public/mojom/base/time.mojom";
+import "services/media_session/public/mojom/media_session.mojom";
+import "url/mojom/origin.mojom";
+import "url/mojom/url.mojom";
+
+struct MediaHistoryStats {
+ // The row count of the different tables. The key is the table name and the
+ // value is the row count.
+ map<string, int32> table_row_counts;
+};
+
+struct MediaHistoryOriginRow {
+ url.mojom.Origin origin;
+
+ // The total audio+video watchtime for the origin. The cached value is cached
+ // on the origin row for speed and the actual is calculated by adding up
+ // the playback rows.
+ mojo_base.mojom.TimeDelta cached_audio_video_watchtime;
+ mojo_base.mojom.TimeDelta actual_audio_video_watchtime;
+
+ // The last updated time of the row in JS time.
+ double last_updated_time;
+};
+
+// A playback is recorded for each individual player on a page. Child frame
+// playbacks are recorded but we use the top frame url.
+struct MediaHistoryPlaybackRow {
+ // The top frame URL of the page that had the playback.
+ url.mojom.Url url;
+
+ // Whether the playback had audio/video tracks.
+ bool has_audio;
+ bool has_video;
+
+ // The watchtime for the playback.
+ mojo_base.mojom.TimeDelta watchtime;
+
+ // The last updated time of the row in JS time.
+ double last_updated_time;
+};
+
+// There is a single playback session for each web contents that plays videos
+// with audio tracks. It is not recorded for audio-only and video-only sessions.
+// It shares a 1:1 relationship with the media session of the page.
+struct MediaHistoryPlaybackSessionRow {
+ // The id of the session.
+ int64 id;
+
+ // The top frame URL of the page that had the playback session.
+ url.mojom.Url url;
+
+ // The duration and position of the playback session.
+ mojo_base.mojom.TimeDelta duration;
+ mojo_base.mojom.TimeDelta position;
+
+ // The metadata associated with the media session.
+ media_session.mojom.MediaMetadata metadata;
+
+ // The artwork associated with the media session.
+ array<media_session.mojom.MediaImage> artwork;
+
+ // The last updated time of the row in JS time.
+ double last_updated_time;
+};
+
+// MediaHistoryStore allows the Media History WebUI to access data from the
+// Media History database for diagnostic purposes.
+interface MediaHistoryStore {
+ // Gets stats about the Media History database.
+ GetMediaHistoryStats() => (MediaHistoryStats stats);
+
+ // Returns the origin rows from the origins table.
+ GetMediaHistoryOriginRows() => (array<MediaHistoryOriginRow> rows);
+
+ // Returns the playback from the playbacks table.
+ GetMediaHistoryPlaybackRows() => (array<MediaHistoryPlaybackRow> rows);
+
+ // Returns the playback sessions from the sessions table.
+ GetMediaHistoryPlaybackSessionRows() =>
+ (array<MediaHistoryPlaybackSessionRow> rows);
+};
diff --git a/chromium/chrome/browser/media/router/BUILD.gn b/chromium/chrome/browser/media/router/BUILD.gn
index 6ac998b8558..efa5f1245e8 100644
--- a/chromium/chrome/browser/media/router/BUILD.gn
+++ b/chromium/chrome/browser/media/router/BUILD.gn
@@ -62,6 +62,8 @@ static_library("router") {
"presentation/presentation_service_delegate_observers.h",
"presentation/receiver_presentation_service_delegate_impl.cc",
"presentation/receiver_presentation_service_delegate_impl.h",
+ "presentation/web_contents_presentation_manager.cc",
+ "presentation/web_contents_presentation_manager.h",
"route_message_observer.cc",
"route_message_observer.h",
"route_message_util.cc",
@@ -79,6 +81,7 @@ static_library("router") {
# resolution for browser.h, which is used in multiple extension-only
# files.
# TODO(crbug.com/1030821): Resolve circular dependencies
+ "//components/paint_preview/buildflags",
"//components/signin/public/base:signin_buildflags",
"//components/translate/content/common",
"//mojo/public/cpp/bindings",
@@ -102,8 +105,6 @@ static_library("router") {
"mojo/media_router_mojo_metrics.h",
"mojo/media_sink_service_status.cc",
"mojo/media_sink_service_status.h",
- "presentation/independent_otr_profile_manager.cc",
- "presentation/independent_otr_profile_manager.h",
"presentation/presentation_navigation_policy.cc",
"presentation/presentation_navigation_policy.h",
"providers/cast/activity_record.cc",
@@ -161,28 +162,10 @@ static_library("router") {
"providers/openscreen/network_service_async_packet_sender.h",
"providers/openscreen/network_service_quic_packet_writer.cc",
"providers/openscreen/network_service_quic_packet_writer.h",
- "providers/openscreen/platform/chrome_task_runner.cc",
- "providers/openscreen/platform/chrome_task_runner.h",
- "providers/openscreen/platform/chrome_tls_client_connection.cc",
- "providers/openscreen/platform/chrome_tls_client_connection.h",
- "providers/openscreen/platform/chrome_tls_connection_factory.cc",
- "providers/openscreen/platform/chrome_tls_connection_factory.h",
- "providers/openscreen/platform/chrome_udp_socket.cc",
- "providers/openscreen/platform/chrome_udp_socket.h",
- "providers/openscreen/platform/logging.cc",
- "providers/openscreen/platform/mojo_data_pump.cc",
- "providers/openscreen/platform/mojo_data_pump.h",
- "providers/openscreen/platform/network_data_pump.h",
- "providers/openscreen/platform/network_util.cc",
- "providers/openscreen/platform/network_util.h",
- "providers/openscreen/platform/time.cc",
- "providers/openscreen/platform/trace_logging_platform.cc",
]
- configs +=
- [ "//third_party/openscreen/src/build:openscreen_include_dirs" ]
-
deps += [
+ "//components/openscreen_platform:openscreen_platform_network_service",
"//third_party/openscreen/src/osp/public",
"//third_party/openscreen/src/platform",
"//third_party/openscreen/src/util",
@@ -285,8 +268,8 @@ source_set("unittests") {
"providers/cast/cast_session_tracker_unittest.cc",
"providers/cast/dual_media_sink_service_unittest.cc",
"providers/cast/mirroring_activity_record_unittest.cc",
- "providers/cast/mock_activity_record.cc",
- "providers/cast/mock_activity_record.h",
+ "providers/cast/mock_cast_activity_record.cc",
+ "providers/cast/mock_cast_activity_record.h",
"providers/cast/test_util.cc",
"providers/cast/test_util.h",
"providers/dial/dial_activity_manager_unittest.cc",
@@ -297,19 +280,18 @@ source_set("unittests") {
]
}
+ deps = []
+
if (enable_openscreen) {
include_dirs = [ "//third_party/openscreen/src" ]
sources += [
"providers/openscreen/discovery/open_screen_listener_unittest.cc",
"providers/openscreen/network_service_quic_packet_writer_unittest.cc",
- "providers/openscreen/platform/chrome_tls_client_connection_unittest.cc",
- "providers/openscreen/platform/chrome_tls_connection_factory_unittest.cc",
- "providers/openscreen/platform/mojo_data_pump_unittest.cc",
]
}
- deps = [
+ deps += [
":router",
":test_support",
"//base",
@@ -319,6 +301,20 @@ source_set("unittests") {
]
}
+if (enable_openscreen) {
+ test("openscreen_unittests") {
+ deps = [
+ "//base/test:test_support",
+ "//chrome/browser",
+ "//chrome/test:test_support",
+ "//components/openscreen_platform:openscreen_platform_network_service",
+ "//testing/gmock",
+ "//third_party/blink/public/mojom:mojom_platform_headers",
+ "//third_party/openscreen/src:openscreen_unittests_all",
+ ]
+ }
+}
+
fuzzer_test("dial_internal_message_fuzzer") {
sources = [
"providers/dial/dial_internal_message_fuzzer.cc",
@@ -326,6 +322,9 @@ fuzzer_test("dial_internal_message_fuzzer") {
deps = [
":router",
"//base",
+ "//base/test:test_support",
+ "//chrome/browser",
+ "//chrome/test:test_support",
"//components/mirroring/mojom:service",
"//components/translate/content/common",
]
diff --git a/chromium/chrome/browser/media/router/discovery/BUILD.gn b/chromium/chrome/browser/media/router/discovery/BUILD.gn
index c5e3bf57886..902ab86980a 100644
--- a/chromium/chrome/browser/media/router/discovery/BUILD.gn
+++ b/chromium/chrome/browser/media/router/discovery/BUILD.gn
@@ -5,9 +5,7 @@
assert(!is_android)
static_library("discovery") {
- inputs = [
- "$root_gen_dir/chrome/grit/generated_resources.h",
- ]
+ inputs = [ "$root_gen_dir/chrome/grit/generated_resources.h" ]
deps = [
"//base",
"//base:i18n",
diff --git a/chromium/chrome/browser/media/webrtc/OWNERS b/chromium/chrome/browser/media/webrtc/OWNERS
index 1d63dd49b92..104e9a6b385 100644
--- a/chromium/chrome/browser/media/webrtc/OWNERS
+++ b/chromium/chrome/browser/media/webrtc/OWNERS
@@ -1,4 +1,3 @@
-sergeyu@chromium.org
tommi@chromium.org
guidou@chromium.org
@@ -7,10 +6,10 @@ braveyao@chromium.org
# For WebRTC browser tests.
per-file *webrtc*browsertest*=hbos@chromium.org
-per-file *webrtc*browsertest*=phoglund@chromium.org
# For changes related to the tab media indicators.
per-file media_stream_capture_indicator*=miu@chromium.org
+per-file media_stream_capture_indicator*=mfoltz@chromium.org
# For permissions related code.
per-file media_stream_device*=raymes@chromium.org
@@ -19,6 +18,6 @@ per-file media_permission*=raymes@chromium.org
# For WebRTC event logging code.
per-file webrtc_event_log_*=eladalon@chromium.org
-per-file *permission_context*=file://chrome/browser/permissions/PERMISSIONS_OWNERS
+per-file *permission_context*=file://components/permissions/PERMISSIONS_OWNERS
# COMPONENT: Blink>WebRTC
diff --git a/chromium/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc b/chromium/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc
index 44ee73b6ae7..11113830667 100644
--- a/chromium/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc
+++ b/chromium/chrome/browser/media/webrtc/audio_debug_recordings_handler.cc
@@ -12,16 +12,16 @@
#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "components/webrtc_logging/browser/text_log_list.h"
+#include "content/public/browser/audio_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/system_connector.h"
#include "media/audio/audio_debug_recording_session.h"
#include "services/audio/public/cpp/debug_recording_session_factory.h"
-#include "services/service_manager/public/cpp/connector.h"
using content::BrowserThread;
@@ -71,9 +71,8 @@ void AudioDebugRecordingsHandler::StartAudioDebugRecordings(
const RecordingErrorCallback& error_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&GetLogDirectoryAndEnsureExists, browser_context_),
base::BindOnce(&AudioDebugRecordingsHandler::DoStartAudioDebugRecordings,
this, host, delay, callback, error_callback));
@@ -85,9 +84,8 @@ void AudioDebugRecordingsHandler::StopAudioDebugRecordings(
const RecordingErrorCallback& error_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const bool is_manual_stop = true;
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&GetLogDirectoryAndEnsureExists, browser_context_),
base::BindOnce(&AudioDebugRecordingsHandler::DoStopAudioDebugRecordings,
this, host, is_manual_stop,
@@ -112,8 +110,11 @@ void AudioDebugRecordingsHandler::DoStartAudioDebugRecordings(
log_directory, ++current_audio_debug_recordings_id_);
host->EnableAudioDebugRecordings(prefix_path);
+ mojo::PendingRemote<audio::mojom::DebugRecording> debug_recording;
+ content::GetAudioService().BindDebugRecording(
+ debug_recording.InitWithNewPipeAndPassReceiver());
audio_debug_recording_session_ = audio::CreateAudioDebugRecordingSession(
- prefix_path, content::GetSystemConnector()->Clone());
+ prefix_path, std::move(debug_recording));
if (delay.is_zero()) {
const bool is_stopped = false, is_manual_stop = false;
diff --git a/chromium/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chromium/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
index 7e52d84fa42..2d9ab99f816 100644
--- a/chromium/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
+++ b/chromium/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
#include "chrome/browser/media/webrtc/native_desktop_media_list.h"
#include "chrome/browser/media/webrtc/tab_desktop_media_list.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
@@ -27,7 +28,9 @@
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
+#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_capture.h"
#include "content/public/browser/desktop_streams_registry.h"
@@ -304,6 +307,15 @@ void DesktopCaptureAccessHandler::HandleRequest(
return;
}
+ Profile* profile =
+ Profile::FromBrowserContext(web_contents->GetBrowserContext());
+ if (!profile->GetPrefs()->GetBoolean(prefs::kScreenCaptureAllowed)) {
+ std::move(callback).Run(
+ devices, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
+ std::move(ui));
+ return;
+ }
+
if (request.request_type == blink::MEDIA_DEVICE_UPDATE) {
ProcessChangeSourceRequest(web_contents, request, std::move(callback),
extension);
diff --git a/chromium/chrome/browser/media/webrtc/desktop_media_list_ash.cc b/chromium/chrome/browser/media/webrtc/desktop_media_list_ash.cc
index 8f69f01efaa..e66b84ba2c9 100644
--- a/chromium/chrome/browser/media/webrtc/desktop_media_list_ash.cc
+++ b/chromium/chrome/browser/media/webrtc/desktop_media_list_ash.cc
@@ -139,8 +139,8 @@ void DesktopMediaListAsh::CaptureThumbnail(content::DesktopMediaID id,
++pending_window_capture_requests_;
ui::GrabWindowSnapshotAndScaleAsync(
window, window_rect, scaled_rect.size(),
- base::Bind(&DesktopMediaListAsh::OnThumbnailCaptured,
- weak_factory_.GetWeakPtr(), id));
+ base::BindOnce(&DesktopMediaListAsh::OnThumbnailCaptured,
+ weak_factory_.GetWeakPtr(), id));
}
void DesktopMediaListAsh::OnThumbnailCaptured(content::DesktopMediaID id,
diff --git a/chromium/chrome/browser/media/webrtc/desktop_media_list_base.cc b/chromium/chrome/browser/media/webrtc/desktop_media_list_base.cc
index 9d9b7435044..ba64a40697c 100644
--- a/chromium/chrome/browser/media/webrtc/desktop_media_list_base.cc
+++ b/chromium/chrome/browser/media/webrtc/desktop_media_list_base.cc
@@ -166,8 +166,8 @@ void DesktopMediaListBase::UpdateSourceThumbnail(DesktopMediaID id,
// static
uint32_t DesktopMediaListBase::GetImageHash(const gfx::Image& image) {
SkBitmap bitmap = image.AsBitmap();
- uint32_t value = base::Hash(bitmap.getPixels(), bitmap.computeByteSize());
- return value;
+ return base::FastHash(base::make_span(
+ static_cast<uint8_t*>(bitmap.getPixels()), bitmap.computeByteSize()));
}
void DesktopMediaListBase::OnRefreshComplete() {
diff --git a/chromium/chrome/browser/media/webrtc/desktop_media_picker_controller.cc b/chromium/chrome/browser/media/webrtc/desktop_media_picker_controller.cc
index 672acc2264b..74462a827a7 100644
--- a/chromium/chrome/browser/media/webrtc/desktop_media_picker_controller.cc
+++ b/chromium/chrome/browser/media/webrtc/desktop_media_picker_controller.cc
@@ -96,14 +96,15 @@ void DesktopMediaPickerController::ShowPickerDialog() {
return;
}
- picker_->Show(params_, std::move(source_lists_),
- base::Bind(&DesktopMediaPickerController::OnPickerDialogResults,
- // A weak pointer is used here, because although
- // |picker_| can't outlive this object, it can
- // schedule this callback to be invoked
- // asynchronously after it has potentially been
- // destroyed.
- weak_factory_.GetWeakPtr(), std::string()));
+ picker_->Show(
+ params_, std::move(source_lists_),
+ base::BindOnce(&DesktopMediaPickerController::OnPickerDialogResults,
+ // A weak pointer is used here, because although
+ // |picker_| can't outlive this object, it can
+ // schedule this callback to be invoked
+ // asynchronously after it has potentially been
+ // destroyed.
+ weak_factory_.GetWeakPtr(), std::string()));
}
void DesktopMediaPickerController::OnPickerDialogResults(
diff --git a/chromium/chrome/browser/media/webrtc/display_media_access_handler.cc b/chromium/chrome/browser/media/webrtc/display_media_access_handler.cc
index 7e63e08ccf9..4ca36f534dc 100644
--- a/chromium/chrome/browser/media/webrtc/display_media_access_handler.cc
+++ b/chromium/chrome/browser/media/webrtc/display_media_access_handler.cc
@@ -16,6 +16,9 @@
#include "chrome/browser/media/webrtc/desktop_media_picker_factory_impl.h"
#include "chrome/browser/media/webrtc/native_desktop_media_list.h"
#include "chrome/browser/media/webrtc/tab_desktop_media_list.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_service.h"
#include "components/url_formatter/elide_url.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/desktop_capture.h"
@@ -88,6 +91,15 @@ void DisplayMediaAccessHandler::HandleRequest(
const extensions::Extension* extension) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ Profile* profile =
+ Profile::FromBrowserContext(web_contents->GetBrowserContext());
+ if (!profile->GetPrefs()->GetBoolean(prefs::kScreenCaptureAllowed)) {
+ std::move(callback).Run(
+ blink::MediaStreamDevices(),
+ blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, nullptr);
+ return;
+ }
+
#if defined(OS_MACOSX)
// Do not allow picker UI to be shown on a page that isn't in the foreground
// in Mac, because the UI implementation in Mac pops a window over any content
@@ -226,6 +238,9 @@ void DisplayMediaAccessHandler::OnPickerDialogResults(
}
}
+ if (request_result == blink::mojom::MediaStreamRequestResult::OK)
+ UpdateTarget(pending_request.request, media_id);
+
std::move(pending_request.callback)
.Run(devices, request_result, std::move(ui));
queue.pop_front();
diff --git a/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc b/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc
index 954ce697768..4e633de14c0 100644
--- a/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc
+++ b/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.cc
@@ -486,8 +486,12 @@ void MediaCaptureDevicesDispatcher::UpdateVideoScreenCaptureStatus(
DCHECK(blink::IsVideoScreenCaptureMediaType(stream_type));
for (const auto& handler : media_access_handlers_) {
- handler->UpdateVideoScreenCaptureStatus(render_process_id, render_frame_id,
- page_request_id, is_secure);
- break;
+ if (handler->SupportsStreamType(
+ WebContentsFromIds(render_process_id, render_frame_id), stream_type,
+ nullptr)) {
+ handler->UpdateVideoScreenCaptureStatus(
+ render_process_id, render_frame_id, page_request_id, is_secure);
+ break;
+ }
}
}
diff --git a/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h b/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h
index 51f9d9db2b3..074c5d30fde 100644
--- a/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h
+++ b/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher.h
@@ -163,6 +163,8 @@ class MediaCaptureDevicesDispatcher : public content::MediaObserver {
void SetTestVideoCaptureDevices(const blink::MediaStreamDevices& devices);
private:
+ friend class MediaCaptureDevicesDispatcherTest;
+
friend struct base::DefaultSingletonTraits<MediaCaptureDevicesDispatcher>;
MediaCaptureDevicesDispatcher();
diff --git a/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher_unittest.cc b/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher_unittest.cc
new file mode 100644
index 00000000000..30d6696e3ba
--- /dev/null
+++ b/chromium/chrome/browser/media/webrtc/media_capture_devices_dispatcher_unittest.cc
@@ -0,0 +1,94 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
+
+#include <memory>
+
+#include "chrome/browser/media/media_access_handler.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/mediastream/media_stream_request.h"
+
+using testing::_;
+
+namespace {
+
+class MockMediaAccessHandler : public MediaAccessHandler {
+ public:
+ explicit MockMediaAccessHandler(
+ const blink::mojom::MediaStreamType supported_type)
+ : supported_type_(supported_type) {}
+
+ bool SupportsStreamType(content::WebContents* web_contents,
+ const blink::mojom::MediaStreamType type,
+ const extensions::Extension* extension) override {
+ return supported_type_ == type;
+ }
+
+ MOCK_METHOD4(CheckMediaAccessPermission,
+ bool(content::RenderFrameHost* render_frame_host,
+ const GURL& security_origin,
+ blink::mojom::MediaStreamType type,
+ const extensions::Extension* extension));
+ MOCK_METHOD4(HandleRequest,
+ void(content::WebContents* web_contents,
+ const content::MediaStreamRequest& request,
+ content::MediaResponseCallback callback,
+ const extensions::Extension* extension));
+ MOCK_METHOD4(UpdateVideoScreenCaptureStatus,
+ void(int render_process_id,
+ int render_frame_id,
+ int page_request_id,
+ bool is_secure));
+
+ const blink::mojom::MediaStreamType supported_type_;
+};
+
+} // namespace
+
+class MediaCaptureDevicesDispatcherTest
+ : public ChromeRenderViewHostTestHarness {
+ public:
+ MediaCaptureDevicesDispatcherTest() = default;
+ ~MediaCaptureDevicesDispatcherTest() override = default;
+
+ void SetUp() override {
+ ChromeRenderViewHostTestHarness::SetUp();
+ dispatcher_ = MediaCaptureDevicesDispatcher::GetInstance();
+ }
+
+ std::vector<std::unique_ptr<MediaAccessHandler>>& media_access_handlers() {
+ return dispatcher_->media_access_handlers_;
+ }
+
+ void UpdateVideoScreenCaptureStatus(
+ const blink::mojom::MediaStreamType type) {
+ dispatcher_->UpdateVideoScreenCaptureStatus(0, 0, 0, type, false);
+ }
+
+ protected:
+ MediaCaptureDevicesDispatcher* dispatcher_;
+};
+
+TEST_F(MediaCaptureDevicesDispatcherTest, LoopsAllMediaAccessHandlers) {
+ media_access_handlers().clear();
+
+ // Add two handlers.
+ auto stream_type1 = blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE;
+ auto mock1 = std::make_unique<MockMediaAccessHandler>(stream_type1);
+ MockMediaAccessHandler* handler1 = mock1.get();
+ media_access_handlers().push_back(std::move(mock1));
+ auto stream_type2 = blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE;
+ auto mock2 = std::make_unique<MockMediaAccessHandler>(stream_type2);
+ MockMediaAccessHandler* handler2 = mock2.get();
+ media_access_handlers().push_back(std::move(mock2));
+
+ // Expect both to be called.
+ EXPECT_CALL(*handler1, UpdateVideoScreenCaptureStatus(_, _, _, _));
+ UpdateVideoScreenCaptureStatus(stream_type1);
+ EXPECT_CALL(*handler2, UpdateVideoScreenCaptureStatus(_, _, _, _));
+ UpdateVideoScreenCaptureStatus(stream_type2);
+}
diff --git a/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.cc b/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.cc
index 0a1db50c3a8..b0cb4719b82 100644
--- a/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.cc
+++ b/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.cc
@@ -26,9 +26,9 @@ blink::mojom::FeaturePolicyFeature GetFeaturePolicyFeature(
} // namespace
MediaStreamDevicePermissionContext::MediaStreamDevicePermissionContext(
- Profile* profile,
+ content::BrowserContext* browser_context,
const ContentSettingsType content_settings_type)
- : PermissionContextBase(profile,
+ : PermissionContextBase(browser_context,
content_settings_type,
GetFeaturePolicyFeature(content_settings_type)),
content_settings_type_(content_settings_type) {
@@ -40,14 +40,14 @@ MediaStreamDevicePermissionContext::~MediaStreamDevicePermissionContext() {}
void MediaStreamDevicePermissionContext::DecidePermission(
content::WebContents* web_contents,
- const PermissionRequestID& id,
+ const permissions::PermissionRequestID& id,
const GURL& requesting_origin,
const GURL& embedding_origin,
bool user_gesture,
- BrowserPermissionCallback callback) {
- PermissionContextBase::DecidePermission(web_contents, id, requesting_origin,
- embedding_origin, user_gesture,
- std::move(callback));
+ permissions::BrowserPermissionCallback callback) {
+ permissions::PermissionContextBase::DecidePermission(
+ web_contents, id, requesting_origin, embedding_origin, user_gesture,
+ std::move(callback));
}
ContentSetting MediaStreamDevicePermissionContext::GetPermissionStatusInternal(
@@ -67,8 +67,9 @@ ContentSetting MediaStreamDevicePermissionContext::GetPermissionStatusInternal(
urls_policy_name = prefs::kVideoCaptureAllowedUrls;
}
- MediaStreamDevicePolicy policy = GetDevicePolicy(
- profile(), requesting_origin, policy_name, urls_policy_name);
+ MediaStreamDevicePolicy policy =
+ GetDevicePolicy(Profile::FromBrowserContext(browser_context()),
+ requesting_origin, policy_name, urls_policy_name);
switch (policy) {
case ALWAYS_DENY:
@@ -81,8 +82,9 @@ ContentSetting MediaStreamDevicePermissionContext::GetPermissionStatusInternal(
// Check the content setting. TODO(raymes): currently mic/camera permission
// doesn't consider the embedder.
- ContentSetting setting = PermissionContextBase::GetPermissionStatusInternal(
- render_frame_host, requesting_origin, requesting_origin);
+ ContentSetting setting =
+ permissions::PermissionContextBase::GetPermissionStatusInternal(
+ render_frame_host, requesting_origin, requesting_origin);
if (setting == CONTENT_SETTING_DEFAULT)
setting = CONTENT_SETTING_ASK;
diff --git a/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.h b/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.h
index 9a1983462d9..db884d6cb4a 100644
--- a/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.h
+++ b/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context.h
@@ -6,23 +6,25 @@
#define CHROME_BROWSER_MEDIA_WEBRTC_MEDIA_STREAM_DEVICE_PERMISSION_CONTEXT_H_
#include "base/macros.h"
-#include "chrome/browser/permissions/permission_context_base.h"
#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/permissions/permission_context_base.h"
// Common class which handles the mic and camera permissions.
-class MediaStreamDevicePermissionContext : public PermissionContextBase {
+class MediaStreamDevicePermissionContext
+ : public permissions::PermissionContextBase {
public:
- MediaStreamDevicePermissionContext(Profile* profile,
+ MediaStreamDevicePermissionContext(content::BrowserContext* browser_context,
ContentSettingsType content_settings_type);
~MediaStreamDevicePermissionContext() override;
// PermissionContextBase:
- void DecidePermission(content::WebContents* web_contents,
- const PermissionRequestID& id,
- const GURL& requesting_origin,
- const GURL& embedding_origin,
- bool user_gesture,
- BrowserPermissionCallback callback) override;
+ void DecidePermission(
+ content::WebContents* web_contents,
+ const permissions::PermissionRequestID& id,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ bool user_gesture,
+ permissions::BrowserPermissionCallback callback) override;
// TODO(xhwang): GURL.GetOrigin() shouldn't be used as the origin. Need to
// refactor to use url::Origin. crbug.com/527149 is filed for this.
diff --git a/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context_unittest.cc b/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context_unittest.cc
index 17c2a388c8e..a0a5cc7ea6d 100644
--- a/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context_unittest.cc
+++ b/chromium/chrome/browser/media/webrtc/media_stream_device_permission_context_unittest.cc
@@ -10,12 +10,12 @@
#include "build/build_config.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/permissions/permission_request_id.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/permissions/permission_request_id.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "content/public/test/mock_render_process_host.h"
@@ -23,7 +23,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#if !defined(OS_ANDROID)
-#include "chrome/browser/permissions/permission_request_manager.h"
+#include "components/permissions/permission_request_manager.h"
#endif
namespace {
@@ -106,7 +106,7 @@ class MediaStreamDevicePermissionContextTests
#if defined(OS_ANDROID)
InfoBarService::CreateForWebContents(web_contents());
#else
- PermissionRequestManager::CreateForWebContents(web_contents());
+ permissions::PermissionRequestManager::CreateForWebContents(web_contents());
#endif
}
diff --git a/chromium/chrome/browser/media/webrtc/media_stream_devices_controller.cc b/chromium/chrome/browser/media/webrtc/media_stream_devices_controller.cc
index 77cb93346d0..76908e07656 100644
--- a/chromium/chrome/browser/media/webrtc/media_stream_devices_controller.cc
+++ b/chromium/chrome/browser/media/webrtc/media_stream_devices_controller.cc
@@ -18,14 +18,14 @@
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
#include "chrome/browser/media/webrtc/media_stream_device_permissions.h"
-#include "chrome/browser/permissions/permission_manager.h"
-#include "chrome/browser/permissions/permission_request_manager.h"
-#include "chrome/browser/permissions/permission_result.h"
-#include "chrome/browser/permissions/permission_uma_util.h"
-#include "chrome/browser/permissions/permission_util.h"
+#include "chrome/browser/permissions/permission_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
+#include "components/permissions/permission_manager.h"
+#include "components/permissions/permission_result.h"
+#include "components/permissions/permission_uma_util.h"
+#include "components/permissions/permission_util.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/url_formatter/elide_url.h"
@@ -39,8 +39,6 @@
#if defined(OS_ANDROID)
#include "chrome/browser/android/android_theme_resources.h"
-#include "chrome/browser/android/preferences/website_preference_bridge.h"
-#include "chrome/browser/permissions/permission_dialog_delegate.h"
#include "chrome/browser/permissions/permission_update_infobar_delegate_android.h"
#include "ui/android/window_android.h"
#else // !defined(OS_ANDROID)
@@ -128,19 +126,21 @@ void MediaStreamDevicesController::RequestPermissions(
Profile::FromBrowserContext(web_contents->GetBrowserContext());
std::vector<ContentSettingsType> content_settings_types;
- PermissionManager* permission_manager = PermissionManager::Get(profile);
+ permissions::PermissionManager* permission_manager =
+ PermissionManagerFactory::GetForProfile(profile);
bool will_prompt_for_audio = false;
bool will_prompt_for_video = false;
if (controller->ShouldRequestAudio()) {
- PermissionResult permission_status =
+ permissions::PermissionResult permission_status =
permission_manager->GetPermissionStatusForFrame(
ContentSettingsType::MEDIASTREAM_MIC, rfh, request.security_origin);
if (permission_status.content_setting == CONTENT_SETTING_BLOCK) {
controller->denial_reason_ =
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED;
- controller->RunCallback(permission_status.source ==
- PermissionStatusSource::FEATURE_POLICY);
+ controller->RunCallback(
+ permission_status.source ==
+ permissions::PermissionStatusSource::FEATURE_POLICY);
return;
}
@@ -149,15 +149,16 @@ void MediaStreamDevicesController::RequestPermissions(
permission_status.content_setting == CONTENT_SETTING_ASK;
}
if (controller->ShouldRequestVideo()) {
- PermissionResult permission_status =
+ permissions::PermissionResult permission_status =
permission_manager->GetPermissionStatusForFrame(
ContentSettingsType::MEDIASTREAM_CAMERA, rfh,
request.security_origin);
if (permission_status.content_setting == CONTENT_SETTING_BLOCK) {
controller->denial_reason_ =
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED;
- controller->RunCallback(permission_status.source ==
- PermissionStatusSource::FEATURE_POLICY);
+ controller->RunCallback(
+ permission_status.source ==
+ permissions::PermissionStatusSource::FEATURE_POLICY);
return;
}
@@ -169,7 +170,7 @@ void MediaStreamDevicesController::RequestPermissions(
permission_manager->RequestPermissions(
content_settings_types, rfh, request.security_origin,
request.user_gesture,
- base::Bind(
+ base::BindOnce(
&MediaStreamDevicesController::RequestAndroidPermissionsIfNeeded,
web_contents, base::Passed(&controller), will_prompt_for_audio,
will_prompt_for_video));
@@ -219,7 +220,7 @@ void MediaStreamDevicesController::RequestAndroidPermissionsIfNeeded(
PermissionUpdateInfoBarDelegate::Create(
web_contents, content_settings_types,
base::BindOnce(&MediaStreamDevicesController::AndroidOSPromptAnswered,
- base::Passed(&controller), responses));
+ std::move(controller), responses));
return;
case ShowPermissionInfoBarState::CANNOT_SHOW_PERMISSION_INFOBAR: {
std::vector<ContentSetting> blocked_responses(responses.size(),
@@ -282,16 +283,18 @@ void MediaStreamDevicesController::PromptAnsweredGroupedRequest(
audio_setting_ = responses.front();
blocked_by_feature_policy &=
audio_setting_ == CONTENT_SETTING_BLOCK &&
- PermissionIsBlockedForReason(ContentSettingsType::MEDIASTREAM_MIC,
- PermissionStatusSource::FEATURE_POLICY);
+ PermissionIsBlockedForReason(
+ ContentSettingsType::MEDIASTREAM_MIC,
+ permissions::PermissionStatusSource::FEATURE_POLICY);
}
if (ShouldRequestVideo()) {
video_setting_ = responses.back();
blocked_by_feature_policy &=
video_setting_ == CONTENT_SETTING_BLOCK &&
- PermissionIsBlockedForReason(ContentSettingsType::MEDIASTREAM_CAMERA,
- PermissionStatusSource::FEATURE_POLICY);
+ PermissionIsBlockedForReason(
+ ContentSettingsType::MEDIASTREAM_CAMERA,
+ permissions::PermissionStatusSource::FEATURE_POLICY);
}
for (ContentSetting response : responses) {
@@ -514,7 +517,7 @@ void MediaStreamDevicesController::UpdateTabSpecificContentSettings(
}
content_settings_->OnMediaStreamPermissionSet(
- PermissionManager::Get(profile_)->GetCanonicalOrigin(
+ PermissionManagerFactory::GetForProfile(profile_)->GetCanonicalOrigin(
ContentSettingsType::MEDIASTREAM_CAMERA, request_.security_origin,
web_contents_->GetLastCommittedURL()),
microphone_camera_state, selected_audio_device, selected_video_device,
@@ -551,8 +554,8 @@ ContentSetting MediaStreamDevicesController::GetContentSetting(
}
// Don't request if the kill switch is on.
- if (PermissionIsBlockedForReason(content_type,
- PermissionStatusSource::KILL_SWITCH)) {
+ if (PermissionIsBlockedForReason(
+ content_type, permissions::PermissionStatusSource::KILL_SWITCH)) {
*denial_reason = blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON;
return CONTENT_SETTING_BLOCK;
}
@@ -569,7 +572,7 @@ bool MediaStreamDevicesController::IsUserAcceptAllowed(
return false;
std::vector<std::string> android_permissions;
- WebsitePreferenceBridge::GetAndroidPermissionsForContentSetting(
+ permissions::PermissionUtil::GetAndroidPermissionsForContentSetting(
content_type, &android_permissions);
for (const auto& android_permission : android_permissions) {
if (!window_android->HasPermission(android_permission) &&
@@ -588,14 +591,15 @@ bool MediaStreamDevicesController::IsUserAcceptAllowed(
bool MediaStreamDevicesController::PermissionIsBlockedForReason(
ContentSettingsType content_type,
- PermissionStatusSource reason) const {
+ permissions::PermissionStatusSource reason) const {
// TODO(raymes): This function wouldn't be needed if
// PermissionManager::RequestPermissions returned a denial reason.
content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
request_.render_process_id, request_.render_frame_id);
- PermissionResult result =
- PermissionManager::Get(profile_)->GetPermissionStatusForFrame(
- content_type, rfh, request_.security_origin);
+ permissions::PermissionResult result =
+ PermissionManagerFactory::GetForProfile(profile_)
+ ->GetPermissionStatusForFrame(content_type, rfh,
+ request_.security_origin);
if (result.source == reason) {
DCHECK_EQ(CONTENT_SETTING_BLOCK, result.content_setting);
return true;
diff --git a/chromium/chrome/browser/media/webrtc/media_stream_devices_controller.h b/chromium/chrome/browser/media/webrtc/media_stream_devices_controller.h
index 4b5920a2c9b..07ef0cbccef 100644
--- a/chromium/chrome/browser/media/webrtc/media_stream_devices_controller.h
+++ b/chromium/chrome/browser/media/webrtc/media_stream_devices_controller.h
@@ -19,7 +19,10 @@
class MediaStreamDevicesController;
class Profile;
class TabSpecificContentSettings;
+
+namespace permissions {
enum class PermissionStatusSource;
+}
namespace content {
class WebContents;
@@ -104,8 +107,9 @@ class MediaStreamDevicesController {
// requested devices.
bool IsUserAcceptAllowed(ContentSettingsType content_type) const;
- bool PermissionIsBlockedForReason(ContentSettingsType content_type,
- PermissionStatusSource reason) const;
+ bool PermissionIsBlockedForReason(
+ ContentSettingsType content_type,
+ permissions::PermissionStatusSource reason) const;
// The current state of the audio/video content settings which may be updated
// through the lifetime of the request.
diff --git a/chromium/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc b/chromium/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
index 94cc27d2831..ad88c0d1866 100644
--- a/chromium/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
@@ -16,18 +16,18 @@
#include "chrome/browser/media/webrtc/media_stream_device_permissions.h"
#include "chrome/browser/media/webrtc/media_stream_devices_controller.h"
#include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
-#include "chrome/browser/permissions/permission_context_base.h"
-#include "chrome/browser/permissions/permission_request.h"
-#include "chrome/browser/permissions/permission_request_manager.h"
-#include "chrome/browser/permissions/permission_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/permissions/permission_context_base.h"
+#include "components/permissions/permission_request.h"
+#include "components/permissions/permission_request_manager.h"
+#include "components/permissions/permission_util.h"
+#include "components/permissions/test/mock_permission_prompt_factory.h"
#include "components/prefs/pref_service.h"
#include "components/variations/variations_associated_data.h"
#include "content/public/browser/render_frame_host.h"
@@ -166,7 +166,7 @@ class MediaStreamDevicesControllerTest : public WebRtcTestBase {
GetContentSettings()->GetMicrophoneCameraState());
}
- MockPermissionPromptFactory* prompt_factory() {
+ permissions::MockPermissionPromptFactory* prompt_factory() {
return prompt_factory_.get();
}
@@ -176,10 +176,11 @@ class MediaStreamDevicesControllerTest : public WebRtcTestBase {
ASSERT_TRUE(embedded_test_server()->Start());
- PermissionRequestManager* manager =
- PermissionRequestManager::FromWebContents(
+ permissions::PermissionRequestManager* manager =
+ permissions::PermissionRequestManager::FromWebContents(
browser()->tab_strip_model()->GetActiveWebContents());
- prompt_factory_.reset(new MockPermissionPromptFactory(manager));
+ prompt_factory_.reset(
+ new permissions::MockPermissionPromptFactory(manager));
// Cleanup.
media_stream_devices_.clear();
@@ -218,7 +219,7 @@ class MediaStreamDevicesControllerTest : public WebRtcTestBase {
base::Closure quit_closure_;
- std::unique_ptr<MockPermissionPromptFactory> prompt_factory_;
+ std::unique_ptr<permissions::MockPermissionPromptFactory> prompt_factory_;
};
// Request and allow microphone access.
@@ -227,11 +228,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, RequestAndAllowMic) {
SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_ALLOWED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), std::string()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_MIC));
@@ -255,11 +257,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, RequestAndAllowCam) {
SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(std::string(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_CAMERA));
@@ -283,11 +286,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, RequestAndBlockMic) {
SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_DENIED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), std::string()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_MIC));
@@ -312,11 +316,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, RequestAndBlockCam) {
SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_DENIED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(std::string(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_CAMERA));
@@ -343,11 +348,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_MIC));
@@ -378,11 +384,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_DENIED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_MIC));
@@ -416,11 +423,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_DENIED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_MIC));
@@ -454,11 +462,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_MIC));
@@ -492,11 +501,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_DENIED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), std::string()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_MIC));
EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
@@ -510,8 +520,8 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
RequestPermissions(
GetWebContents(), CreateRequest(std::string(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_CAMERA));
EXPECT_FALSE(GetContentSettings()->IsContentBlocked(
@@ -540,11 +550,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(std::string(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_TRUE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_CAMERA));
EXPECT_FALSE(GetContentSettings()->IsContentBlocked(
@@ -574,11 +585,12 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_DENIED);
// Ensure the prompt is accepted if necessary such that tab specific content
// settings are updated.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), std::string()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
EXPECT_FALSE(GetContentSettings()->IsContentAllowed(
ContentSettingsType::MEDIASTREAM_MIC));
EXPECT_TRUE(GetContentSettings()->IsContentBlocked(
@@ -681,25 +693,29 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, ContentSettings) {
if (test.ExpectMicInfobar() || test.ExpectCamInfobar()) {
if (test.accept_infobar) {
prompt_factory()->set_response_type(
- PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestManager::ACCEPT_ALL);
} else {
- prompt_factory()->set_response_type(PermissionRequestManager::DENY_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::DENY_ALL);
}
} else {
- prompt_factory()->set_response_type(PermissionRequestManager::NONE);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::NONE);
}
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
ASSERT_LE(prompt_factory()->TotalRequestCount(), 2);
- ASSERT_EQ(test.ExpectMicInfobar(),
- prompt_factory()->RequestTypeSeen(
- PermissionRequestType::PERMISSION_MEDIASTREAM_MIC));
- ASSERT_EQ(test.ExpectCamInfobar(),
- prompt_factory()->RequestTypeSeen(
- PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA));
+ ASSERT_EQ(
+ test.ExpectMicInfobar(),
+ prompt_factory()->RequestTypeSeen(
+ permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_MIC));
+ ASSERT_EQ(
+ test.ExpectCamInfobar(),
+ prompt_factory()->RequestTypeSeen(
+ permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA));
// Check the media stream result is expected and the devices returned are
// expected;
@@ -719,8 +735,8 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
InitWithUrl(GURL(chrome::kChromeUIVersionURL));
RequestPermissions(
GetWebContents(), CreateRequest(std::string(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
@@ -738,16 +754,17 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
"/index.html";
InitWithUrl(GURL(pdf_extension_page));
// Test that a prompt is required.
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
ASSERT_EQ(2, prompt_factory()->TotalRequestCount());
ASSERT_TRUE(prompt_factory()->RequestTypeSeen(
- PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA));
+ permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA));
ASSERT_TRUE(prompt_factory()->RequestTypeSeen(
- PermissionRequestType::PERMISSION_MEDIASTREAM_MIC));
+ permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_MIC));
// Accept the prompt.
ASSERT_EQ(blink::mojom::MediaStreamRequestResult::OK, media_stream_result());
@@ -760,8 +777,8 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
prompt_factory()->ResetCounts();
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
ASSERT_EQ(blink::mojom::MediaStreamRequestResult::OK, media_stream_result());
@@ -775,14 +792,15 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
PepperRequestInsecure) {
InitWithUrl(GURL("http://www.example.com"));
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
RequestPermissions(
GetWebContents(),
CreateRequestWithType(example_audio_id(), example_video_id(),
blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
ASSERT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
@@ -796,7 +814,8 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, WebContentsDestroyed) {
InitWithUrl(GURL("http://www.example.com"));
- prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
+ prompt_factory()->set_response_type(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
content::MediaStreamRequest request =
CreateRequest(example_audio_id(), example_video_id());
@@ -806,8 +825,8 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, WebContentsDestroyed) {
RequestPermissions(
nullptr, request,
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
ASSERT_EQ(blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN,
@@ -822,25 +841,25 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, WebContentsDestroyed) {
IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
RequestAndKillSwitchMicCam) {
std::map<std::string, std::string> params;
- params[PermissionUtil::GetPermissionString(
+ params[permissions::PermissionUtil::GetPermissionString(
ContentSettingsType::MEDIASTREAM_MIC)] =
- PermissionContextBase::kPermissionsKillSwitchBlockedValue;
- params[PermissionUtil::GetPermissionString(
+ permissions::PermissionContextBase::kPermissionsKillSwitchBlockedValue;
+ params[permissions::PermissionUtil::GetPermissionString(
ContentSettingsType::MEDIASTREAM_CAMERA)] =
- PermissionContextBase::kPermissionsKillSwitchBlockedValue;
+ permissions::PermissionContextBase::kPermissionsKillSwitchBlockedValue;
variations::AssociateVariationParams(
- PermissionContextBase::kPermissionsKillSwitchFieldStudy,
+ permissions::PermissionContextBase::kPermissionsKillSwitchFieldStudy,
"TestGroup", params);
base::FieldTrialList::CreateFieldTrial(
- PermissionContextBase::kPermissionsKillSwitchFieldStudy,
+ permissions::PermissionContextBase::kPermissionsKillSwitchFieldStudy,
"TestGroup");
InitWithUrl(embedded_test_server()->GetURL("/simple.html"));
SetDevicePolicy(DEVICE_TYPE_AUDIO, ACCESS_ALLOWED);
SetDevicePolicy(DEVICE_TYPE_VIDEO, ACCESS_ALLOWED);
RequestPermissions(
GetWebContents(), CreateRequest(example_audio_id(), example_video_id()),
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
@@ -874,8 +893,8 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
request.render_frame_id = child_frame->GetRoutingID();
RequestPermissions(
GetWebContents(), request,
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
@@ -911,8 +930,8 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
request.render_frame_id = child_frame->GetRoutingID();
RequestPermissions(
GetWebContents(), request,
- base::Bind(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
- base::Unretained(this)));
+ base::BindOnce(&MediaStreamDevicesControllerTest::OnMediaStreamResponse,
+ base::Unretained(this)));
ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
diff --git a/chromium/chrome/browser/media/webrtc/media_stream_infobar_browsertest.cc b/chromium/chrome/browser/media/webrtc/media_stream_infobar_browsertest.cc
index 9fe9d9c230e..542e453329d 100644
--- a/chromium/chrome/browser/media/webrtc/media_stream_infobar_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/media_stream_infobar_browsertest.cc
@@ -38,9 +38,12 @@ class MediaStreamPermissionTest : public WebRtcTestBase {
~MediaStreamPermissionTest() override {}
// InProcessBrowserTest:
- void SetUpCommandLine(base::CommandLine* command_line) override {
+ void SetUp() override {
+ WebRtcTestBase::SetUp();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
// This test expects to run with fake devices but real UI.
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
+ EXPECT_TRUE(
+ command_line->HasSwitch(switches::kUseFakeDeviceForMediaStream));
EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream))
<< "Since this test tests the UI we want the real UI!";
}
diff --git a/chromium/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chromium/chrome/browser/media/webrtc/native_desktop_media_list.cc
index 2b109bd1dea..224d52b8353 100644
--- a/chromium/chrome/browser/media/webrtc/native_desktop_media_list.cc
+++ b/chromium/chrome/browser/media/webrtc/native_desktop_media_list.cc
@@ -44,8 +44,9 @@ const int kDefaultNativeDesktopMediaListUpdatePeriod = 1000;
// Returns a hash of a DesktopFrame content to detect when image for a desktop
// media source has changed.
uint32_t GetFrameHash(webrtc::DesktopFrame* frame) {
+ // TODO(dcheng): Is this vulnerable to overflow??
int data_size = frame->stride() * frame->size().height();
- return base::Hash(frame->data(), data_size);
+ return base::FastHash(base::make_span(frame->data(), data_size));
}
gfx::ImageSkia ScaleDesktopFrame(std::unique_ptr<webrtc::DesktopFrame> frame,
@@ -375,8 +376,8 @@ void NativeDesktopMediaList::CaptureAuraWindowThumbnail(
pending_aura_capture_requests_++;
ui::GrabWindowSnapshotAndScaleAsyncAura(
window, window_rect, scaled_rect.size(),
- base::Bind(&NativeDesktopMediaList::OnAuraThumbnailCaptured,
- weak_factory_.GetWeakPtr(), id));
+ base::BindOnce(&NativeDesktopMediaList::OnAuraThumbnailCaptured,
+ weak_factory_.GetWeakPtr(), id));
}
void NativeDesktopMediaList::OnAuraThumbnailCaptured(const DesktopMediaID& id,
diff --git a/chromium/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc b/chromium/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
index fe430e586e3..5de558d6eaf 100644
--- a/chromium/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
+++ b/chromium/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
@@ -13,6 +13,7 @@
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc b/chromium/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
index d2ca1d829cd..50b1ffab023 100644
--- a/chromium/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
+++ b/chromium/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
@@ -8,16 +8,18 @@
#include <utility>
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/metrics/field_trial.h"
#include "base/task/post_task.h"
#include "build/build_config.h"
#include "chrome/browser/media/webrtc/media_stream_device_permissions.h"
#include "chrome/browser/media/webrtc/media_stream_devices_controller.h"
-#include "chrome/browser/permissions/permission_manager.h"
-#include "chrome/browser/permissions/permission_result.h"
+#include "chrome/browser/permissions/permission_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/permissions/permission_manager.h"
+#include "components/permissions/permission_result.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
@@ -27,10 +29,10 @@
#if defined(OS_ANDROID)
#include <vector>
-#include "chrome/browser/android/chrome_feature_list.h"
+#include "chrome/browser/flags/android/chrome_feature_list.h"
#include "chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.h"
-#include "chrome/browser/permissions/permission_uma_util.h"
-#include "chrome/browser/permissions/permission_util.h"
+#include "components/permissions/permission_uma_util.h"
+#include "components/permissions/permission_util.h"
#endif // defined(OS_ANDROID)
#if defined(OS_MACOSX)
@@ -107,7 +109,8 @@ bool PermissionBubbleMediaAccessHandler::CheckMediaAccessPermission(
DCHECK(!security_origin.is_empty());
GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin();
- PermissionManager* permission_manager = PermissionManager::Get(profile);
+ permissions::PermissionManager* permission_manager =
+ PermissionManagerFactory::GetForProfile(profile);
return permission_manager
->GetPermissionStatusForFrame(content_settings_type,
render_frame_host, security_origin)
@@ -165,16 +168,17 @@ void PermissionBubbleMediaAccessHandler::ProcessQueuedAccessRequest(
if (blink::IsScreenCaptureMediaType(request.video_type)) {
ScreenCaptureInfoBarDelegateAndroid::Create(
web_contents, request,
- base::Bind(&PermissionBubbleMediaAccessHandler::OnAccessRequestResponse,
- base::Unretained(this), web_contents, request_id));
+ base::BindOnce(
+ &PermissionBubbleMediaAccessHandler::OnAccessRequestResponse,
+ base::Unretained(this), web_contents, request_id));
return;
}
#endif
MediaStreamDevicesController::RequestPermissions(
- request,
- base::Bind(&PermissionBubbleMediaAccessHandler::OnAccessRequestResponse,
- base::Unretained(this), web_contents, request_id));
+ request, base::BindOnce(
+ &PermissionBubbleMediaAccessHandler::OnAccessRequestResponse,
+ base::Unretained(this), web_contents, request_id));
}
void PermissionBubbleMediaAccessHandler::UpdateMediaRequestState(
diff --git a/chromium/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc b/chromium/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc
index d891933c061..3c30420ad16 100644
--- a/chromium/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc
+++ b/chromium/chrome/browser/media/webrtc/screen_capture_infobar_delegate_android.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
#include "chrome/grit/generated_resources.h"
#include "components/infobars/core/infobar.h"
+#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/elide_url.h"
#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/web_contents.h"
diff --git a/chromium/chrome/browser/media/webrtc/tab_capture_access_handler.cc b/chromium/chrome/browser/media/webrtc/tab_capture_access_handler.cc
index 8a3fe7e1918..7058728f8ee 100644
--- a/chromium/chrome/browser/media/webrtc/tab_capture_access_handler.cc
+++ b/chromium/chrome/browser/media/webrtc/tab_capture_access_handler.cc
@@ -10,6 +10,8 @@
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/media_stream_capture_indicator.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_service.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/permissions/permissions_data.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
@@ -55,6 +57,12 @@ void TabCaptureAccessHandler::HandleRequest(
std::move(ui));
return;
}
+ if (!profile->GetPrefs()->GetBoolean(prefs::kScreenCaptureAllowed)) {
+ std::move(callback).Run(
+ devices, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
+ std::move(ui));
+ return;
+ }
// |extension| may be null if the tabCapture starts with
// tabCapture.getMediaStreamId().
// TODO(crbug.com/831722): Deprecate tabCaptureRegistry soon.
diff --git a/chromium/chrome/browser/media/webrtc/tab_desktop_media_list.cc b/chromium/chrome/browser/media/webrtc/tab_desktop_media_list.cc
index 00df7fa7d40..76e92110bed 100644
--- a/chromium/chrome/browser/media/webrtc/tab_desktop_media_list.cc
+++ b/chromium/chrome/browser/media/webrtc/tab_desktop_media_list.cc
@@ -10,6 +10,7 @@
#include "base/bind_helpers.h"
#include "base/hash/hash.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
@@ -65,8 +66,8 @@ TabDesktopMediaList::TabDesktopMediaList()
: DesktopMediaListBase(base::TimeDelta::FromMilliseconds(
kDefaultTabDesktopMediaListUpdatePeriod)) {
type_ = DesktopMediaID::TYPE_WEB_CONTENTS;
- thumbnail_task_runner_ = base::CreateSequencedTaskRunner(
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE});
+ thumbnail_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
}
TabDesktopMediaList::~TabDesktopMediaList() {}
@@ -148,9 +149,9 @@ void TabDesktopMediaList::Refresh(bool update_thumnails) {
// current thread.
base::PostTaskAndReplyWithResult(
thumbnail_task_runner_.get(), FROM_HERE,
- base::Bind(&CreateEnclosedFaviconImage, thumbnail_size_, it.second),
- base::Bind(&TabDesktopMediaList::UpdateSourceThumbnail,
- weak_factory_.GetWeakPtr(), it.first));
+ base::BindOnce(&CreateEnclosedFaviconImage, thumbnail_size_, it.second),
+ base::BindOnce(&TabDesktopMediaList::UpdateSourceThumbnail,
+ weak_factory_.GetWeakPtr(), it.first));
}
// OnRefreshComplete() needs to be called after all calls for
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_apprtc_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_apprtc_browsertest.cc
index e46f6188f28..d6c52c727a2 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_apprtc_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_apprtc_browsertest.cc
@@ -13,12 +13,12 @@
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/media/webrtc/webrtc_browsertest_base.h"
#include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
-#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "components/permissions/permission_request_manager.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "media/base/media_switches.h"
@@ -51,6 +51,7 @@ class WebRtcApprtcBrowserTest : public WebRtcTestBase {
command_line->AppendSwitch(switches::kUseGpuInTests);
// This test fails on some Mac bots if no default devices are specified on
// the command line.
+ command_line->RemoveSwitch(switches::kUseFakeDeviceForMediaStream);
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
switches::kUseFakeDeviceForMediaStream,
"audio-input-default-id=default,video-input-default-id=default");
@@ -225,8 +226,9 @@ IN_PROC_BROWSER_TEST_F(WebRtcApprtcBrowserTest, MANUAL_WorksOnApprtc) {
chrome::AddTabAt(browser(), GURL(), -1, true);
content::WebContents* left_tab =
browser()->tab_strip_model()->GetActiveWebContents();
- PermissionRequestManager::FromWebContents(left_tab)
- ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestManager::FromWebContents(left_tab)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
InfoBarResponder left_infobar_responder(
InfoBarService::FromWebContents(left_tab), InfoBarResponder::ACCEPT);
ui_test_utils::NavigateToURL(browser(), room_url);
@@ -242,8 +244,9 @@ IN_PROC_BROWSER_TEST_F(WebRtcApprtcBrowserTest, MANUAL_WorksOnApprtc) {
chrome::AddTabAt(browser(), GURL(), -1, true);
content::WebContents* right_tab =
browser()->tab_strip_model()->GetActiveWebContents();
- PermissionRequestManager::FromWebContents(right_tab)
- ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestManager::FromWebContents(right_tab)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
InfoBarResponder right_infobar_responder(
InfoBarService::FromWebContents(right_tab), InfoBarResponder::ACCEPT);
ui_test_utils::NavigateToURL(browser(), room_url);
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_browsertest.cc
index c9a089c7855..883a2821bd1 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_browsertest.cc
@@ -55,9 +55,6 @@ class WebRtcBrowserTest : public WebRtcTestBase {
// Ensure the infobar is enabled, since we expect that in this test.
EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
- // Always use fake devices.
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
-
// Flag used by TestWebAudioMediaStream to force garbage collection.
command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose-gc");
}
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc b/chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
index 3affb26a72b..806b5913a53 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
@@ -21,13 +21,14 @@
#include "build/build_config.h"
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
#include "chrome/browser/media/webrtc/webrtc_browsertest_common.h"
-#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "components/permissions/permission_request_manager.h"
+#include "components/permissions/test/permission_request_observer.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/extension_registry.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -102,42 +103,6 @@ bool JavascriptErrorDetectingLogHandler(int severity,
return false;
}
-// PermissionRequestObserver ---------------------------------------------------
-
-// Used to observe the creation of permission prompt without responding.
-class PermissionRequestObserver : public PermissionRequestManager::Observer {
- public:
- explicit PermissionRequestObserver(content::WebContents* web_contents)
- : request_manager_(
- PermissionRequestManager::FromWebContents(web_contents)),
- request_shown_(false),
- message_loop_runner_(new content::MessageLoopRunner) {
- request_manager_->AddObserver(this);
- }
- ~PermissionRequestObserver() override {
- // Safe to remove twice if it happens.
- request_manager_->RemoveObserver(this);
- }
-
- void Wait() { message_loop_runner_->Run(); }
-
- bool request_shown() const { return request_shown_; }
-
- private:
- // PermissionRequestManager::Observer
- void OnBubbleAdded() override {
- request_shown_ = true;
- request_manager_->RemoveObserver(this);
- message_loop_runner_->Quit();
- }
-
- PermissionRequestManager* request_manager_;
- bool request_shown_;
- scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(PermissionRequestObserver);
-};
-
std::vector<std::string> JsonArrayToVectorOfStrings(
const std::string& json_array) {
std::unique_ptr<base::Value> value =
@@ -188,11 +153,12 @@ bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAccept(
content::WebContents* tab_contents,
const std::string& constraints) const {
std::string result;
- PermissionRequestManager::FromWebContents(tab_contents)
- ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
- PermissionRequestObserver permissionRequestObserver(tab_contents);
+ permissions::PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestObserver observer(tab_contents);
GetUserMedia(tab_contents, constraints);
- EXPECT_TRUE(permissionRequestObserver.request_shown());
+ EXPECT_TRUE(observer.request_shown());
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
return kOkGotStream == result;
@@ -202,8 +168,9 @@ bool WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndAcceptIfPrompted(
content::WebContents* tab_contents,
const std::string& constraints) const {
std::string result;
- PermissionRequestManager::FromWebContents(tab_contents)
- ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
GetUserMedia(tab_contents, constraints);
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
@@ -219,11 +186,12 @@ void WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndDeny(
content::WebContents* tab_contents,
const std::string& constraints) const {
std::string result;
- PermissionRequestManager::FromWebContents(tab_contents)
- ->set_auto_response_for_test(PermissionRequestManager::DENY_ALL);
- PermissionRequestObserver permissionRequestObserver(tab_contents);
+ permissions::PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::DENY_ALL);
+ permissions::PermissionRequestObserver observer(tab_contents);
GetUserMedia(tab_contents, constraints);
- EXPECT_TRUE(permissionRequestObserver.request_shown());
+ EXPECT_TRUE(observer.request_shown());
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
EXPECT_EQ(kFailedWithNotAllowedError, result);
@@ -232,11 +200,12 @@ void WebRtcTestBase::GetUserMediaWithSpecificConstraintsAndDeny(
void WebRtcTestBase::GetUserMediaAndDismiss(
content::WebContents* tab_contents) const {
std::string result;
- PermissionRequestManager::FromWebContents(tab_contents)
- ->set_auto_response_for_test(PermissionRequestManager::DISMISS);
- PermissionRequestObserver permissionRequestObserver(tab_contents);
+ permissions::PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::DISMISS);
+ permissions::PermissionRequestObserver observer(tab_contents);
GetUserMedia(tab_contents, kAudioVideoCallConstraints);
- EXPECT_TRUE(permissionRequestObserver.request_shown());
+ EXPECT_TRUE(observer.request_shown());
// A dismiss should be treated like a deny.
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
@@ -254,11 +223,12 @@ void WebRtcTestBase::GetUserMediaAndExpectAutoAcceptWithoutPrompt(
// we set an auto-response to avoid leaving the prompt hanging. The choice of
// DENY_ALL makes sure that the response to the prompt doesn't accidentally
// result in a newly granted media stream permission.
- PermissionRequestManager::FromWebContents(tab_contents)
- ->set_auto_response_for_test(PermissionRequestManager::DENY_ALL);
- PermissionRequestObserver permissionRequestObserver(tab_contents);
+ permissions::PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::DENY_ALL);
+ permissions::PermissionRequestObserver observer(tab_contents);
GetUserMedia(tab_contents, kAudioVideoCallConstraints);
- EXPECT_FALSE(permissionRequestObserver.request_shown());
+ EXPECT_FALSE(observer.request_shown());
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
EXPECT_EQ(kOkGotStream, result);
@@ -275,11 +245,12 @@ void WebRtcTestBase::GetUserMediaAndExpectAutoDenyWithoutPrompt(
// we set an auto-response to avoid leaving the prompt hanging. The choice of
// ACCEPT_ALL makes sure that the response to the prompt doesn't accidentally
// result in a newly granted media stream permission.
- PermissionRequestManager::FromWebContents(tab_contents)
- ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
- PermissionRequestObserver permissionRequestObserver(tab_contents);
+ permissions::PermissionRequestManager::FromWebContents(tab_contents)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestObserver observer(tab_contents);
GetUserMedia(tab_contents, kAudioVideoCallConstraints);
- EXPECT_FALSE(permissionRequestObserver.request_shown());
+ EXPECT_FALSE(observer.request_shown());
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
tab_contents->GetMainFrame(), "obtainGetUserMediaResult();", &result));
EXPECT_EQ(kFailedWithNotAllowedError, result);
@@ -305,14 +276,15 @@ content::WebContents*
WebRtcTestBase::OpenPageAndGetUserMediaInNewTabWithConstraints(
const GURL& url,
const std::string& constraints) const {
- chrome::AddTabAt(browser(), GURL(), -1, true);
+ chrome::AddTabAt(browser(), GURL(url::kAboutBlankURL), -1, true);
ui_test_utils::NavigateToURL(browser(), url);
content::WebContents* new_tab =
browser()->tab_strip_model()->GetActiveWebContents();
// Accept if necessary, but don't expect a prompt (because auto-accept is also
// okay).
- PermissionRequestManager::FromWebContents(new_tab)
- ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestManager::FromWebContents(new_tab)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
GetUserMedia(new_tab, constraints);
std::string result;
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
@@ -329,15 +301,16 @@ content::WebContents* WebRtcTestBase::OpenTestPageAndGetUserMediaInNewTab(
content::WebContents* WebRtcTestBase::OpenTestPageInNewTab(
const std::string& test_page) const {
- chrome::AddTabAt(browser(), GURL(), -1, true);
+ chrome::AddTabAt(browser(), GURL(url::kAboutBlankURL), -1, true);
GURL url = embedded_test_server()->GetURL(test_page);
ui_test_utils::NavigateToURL(browser(), url);
content::WebContents* new_tab =
browser()->tab_strip_model()->GetActiveWebContents();
// Accept if necessary, but don't expect a prompt (because auto-accept is also
// okay).
- PermissionRequestManager::FromWebContents(new_tab)
- ->set_auto_response_for_test(PermissionRequestManager::ACCEPT_ALL);
+ permissions::PermissionRequestManager::FromWebContents(new_tab)
+ ->set_auto_response_for_test(
+ permissions::PermissionRequestManager::ACCEPT_ALL);
return new_tab;
}
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
index 1b757d9f528..b306be0be94 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_desktop_capture_browsertest.cc
@@ -35,9 +35,6 @@ class WebRtcDesktopCaptureBrowserTest : public WebRtcTestBase {
// Ensure the infobar is enabled, since we expect that in this test.
EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
- // Always use fake devices.
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
-
// Flags use to automatically select the right dekstop source and get
// around security restrictions.
command_line->AppendSwitchASCII(switches::kAutoSelectDesktopCaptureSource,
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc
index c8897585016..47b9a0d487d 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_disable_encryption_flag_browsertest.cc
@@ -37,9 +37,6 @@ class WebRtcDisableEncryptionFlagBrowserTest : public WebRtcTestBase {
}
void SetUpCommandLine(base::CommandLine* command_line) override {
- // This test should run with fake devices.
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
-
// Disable encryption with the command line flag.
command_line->AppendSwitch(switches::kDisableWebRtcEncryption);
}
@@ -51,7 +48,9 @@ class WebRtcDisableEncryptionFlagBrowserTest : public WebRtcTestBase {
// Makes a call and checks that there's encryption or not in the SDP offer.
// TODO(crbug.com/910216): De-flake this for ChromeOs.
// TODO(crbug.com/984879): De-flake this for MSAN Linux.
-#if defined(OS_CHROMEOS) || (defined(OS_LINUX) && defined(MEMORY_SANITIZER))
+#if defined(OS_CHROMEOS) || \
+ (defined(OS_LINUX) && defined(MEMORY_SANITIZER)) || \
+ (defined(OS_WIN) && defined(ADDRESS_SANITIZER))
#define MAYBE_VerifyEncryption DISABLED_VerifyEncryption
#else
#define MAYBE_VerifyEncryption VerifyEncryption
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager.cc b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
index cf63098bc97..08e960e8871 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
@@ -8,14 +8,14 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/memory/ptr_util.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
-#include "components/policy/core/common/policy_service.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
@@ -23,14 +23,6 @@
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/render_process_host.h"
-#if defined OS_CHROMEOS
-#include "chrome/browser/chromeos/profiles/profile_helper.h"
-#endif
-
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
-#include "chrome/browser/policy/chrome_browser_policy_connector.h"
-#endif
-
namespace webrtc_event_logging {
namespace {
@@ -104,40 +96,6 @@ bool IsRemoteLoggingFeatureEnabled() {
return enabled;
}
-// Checks whether the Profile is considered managed. Used to
-// determine the default value for the policy controlling event logging.
-bool IsBrowserManagedForProfile(const Profile* profile) {
-// For Chrome OS, exclude the signin profile and ephemeral profiles.
-#if defined(OS_CHROMEOS)
- if (chromeos::ProfileHelper::IsSigninProfile(profile) ||
- chromeos::ProfileHelper::IsEphemeralUserProfile(profile)) {
- return false;
- }
-#endif
-
- // Child accounts should not have a logging default of true so
- // we do not consider them as being managed here.
- if (profile->IsChild()) {
- return false;
- }
-
- if (profile->GetProfilePolicyConnector()
- ->policy_service()
- ->IsInitializationComplete(policy::POLICY_DOMAIN_CHROME) &&
- profile->GetProfilePolicyConnector()->IsManaged()) {
- return true;
- }
-
- // For desktop, machine level policies (Windows, Linux, Mac OS) can affect
- // user profiles, so we consider these profiles managed.
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
- return g_browser_process->browser_policy_connector()
- ->HasMachineLevelPolicies();
-#else
- return false;
-#endif
-}
-
BrowserContext* GetBrowserContext(int render_process_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* const host = RenderProcessHost::FromID(render_process_id);
@@ -183,9 +141,8 @@ base::FilePath WebRtcEventLogManager::GetRemoteBoundWebRtcEventLogsDir(
}
WebRtcEventLogManager::WebRtcEventLogManager()
- : task_runner_(base::CreateUpdateableSequencedTaskRunner(
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::BEST_EFFORT,
+ : task_runner_(base::ThreadPool::CreateUpdateableSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::ThreadPolicy::PREFER_BACKGROUND,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
num_user_blocking_tasks_(0),
@@ -561,15 +518,9 @@ bool WebRtcEventLogManager::IsRemoteLoggingAllowedForBrowserContext(
if (webrtc_event_log_collection_allowed_pref->IsDefaultValue()) {
// The pref has not been set. GetBoolean would only return the default
// value. However, there is no single default value,
- // because it depends on whether Chrome is managed,
- // so we check whether Chrome is managed.
- // TODO(https://crbug.com/980132): use generalized policy default
- // mechanism when it is available.
- const bool managed = IsBrowserManagedForProfile(profile);
- constexpr bool kCollectionAllowedDefaultManaged = true;
- constexpr bool kCollectionAllowedDefaultUnManaged = false;
- return managed ? kCollectionAllowedDefaultManaged
- : kCollectionAllowedDefaultUnManaged;
+ // because it depends on whether the profile receives cloud-based
+ // enterprise policies.
+ return DoesProfileDefaultToLoggingEnabled(profile);
}
// There is a non-default value set, so this value is authoritative.
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc
index 59ad7a2b45e..12e076407cb 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.cc
@@ -17,11 +17,18 @@
#include "base/strings/stringprintf.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/unguessable_token.h"
+#include "chrome/browser/policy/profile_policy_connector.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/policy/core/common/policy_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
#include "third_party/zlib/zlib.h"
+#if defined OS_CHROMEOS
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#endif
+
namespace webrtc_event_logging {
using BrowserContextId = WebRtcEventLogPeerConnectionKey::BrowserContextId;
@@ -1010,4 +1017,41 @@ size_t ExtractRemoteBoundWebRtcEventLogWebAppIdFromPath(
return ExtractWebAppId(id_str);
}
+bool DoesProfileDefaultToLoggingEnabled(const Profile* const profile) {
+// For Chrome OS, exclude special profiles and users.
+#if defined(OS_CHROMEOS)
+ const user_manager::User* user =
+ chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
+ // We do not log an error here since this can happen in several cases,
+ // e.g. for signin profiles or lock screen app profiles.
+ if (!user) {
+ return false;
+ }
+ const user_manager::UserType user_type = user->GetType();
+ if (user_type != user_manager::USER_TYPE_REGULAR) {
+ return false;
+ }
+ if (chromeos::ProfileHelper::IsEphemeralUserProfile(profile)) {
+ return false;
+ }
+#endif
+
+ // We only want a default of true for regular (i.e. logged-in) profiles
+ // receiving cloud-based user-level enterprise policies. Supervised (child)
+ // profiles are considered regular and can also receive cloud policies in some
+ // cases (e.g. on Chrome OS). Although currently this should be covered by the
+ // other checks, let's explicitly check to anticipate edge cases and make the
+ // requirement explicit.
+ if (!profile->IsRegularProfile() || profile->IsSupervised()) {
+ return false;
+ }
+
+ const policy::ProfilePolicyConnector* const policy_connector =
+ profile->GetProfilePolicyConnector();
+
+ return policy_connector->policy_service()->IsInitializationComplete(
+ policy::POLICY_DOMAIN_CHROME) &&
+ policy_connector->IsManaged();
+}
+
} // namespace webrtc_event_logging
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.h b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.h
index c6479729a94..7dd07476c68 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.h
+++ b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common.h
@@ -13,6 +13,8 @@
#include "base/time/time.h"
#include "build/build_config.h"
+class Profile;
+
namespace content {
class BrowserContext;
} // namespace content
@@ -538,6 +540,9 @@ std::string ExtractRemoteBoundWebRtcEventLogLocalIdFromPath(
size_t ExtractRemoteBoundWebRtcEventLogWebAppIdFromPath(
const base::FilePath& path);
+// Used to determine the default value for the policy controlling event logging.
+bool DoesProfileDefaultToLoggingEnabled(const Profile* const profile);
+
} // namespace webrtc_event_logging
#endif // CHROME_BROWSER_MEDIA_WEBRTC_WEBRTC_EVENT_LOG_MANAGER_COMMON_H_
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc
index 400d4391500..23afb746bae 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_common_unittest.cc
@@ -19,6 +19,16 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/zlib/google/compression_utils.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/account_id/account_id.h"
+#include "components/user_manager/scoped_user_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#endif
+
namespace webrtc_event_logging {
namespace {
@@ -652,4 +662,90 @@ TEST_F(GzippedLogFileWriterTest,
EXPECT_FALSE(base::PathExists(path_)); // Errored files deleted by Close().
}
+#if defined(OS_CHROMEOS)
+
+struct DoesProfileDefaultToLoggingEnabledForUserTypeTestCase {
+ user_manager::UserType user_type;
+ bool defaults_to_logging_enabled;
+};
+
+class DoesProfileDefaultToLoggingEnabledForUserTypeParametrizedTest
+ : public ::testing::TestWithParam<
+ DoesProfileDefaultToLoggingEnabledForUserTypeTestCase> {
+ protected:
+ content::BrowserTaskEnvironment task_environment_;
+};
+
+TEST_P(DoesProfileDefaultToLoggingEnabledForUserTypeParametrizedTest,
+ WebRtcPolicyDefaultTest) {
+ DoesProfileDefaultToLoggingEnabledForUserTypeTestCase test_case = GetParam();
+
+ TestingProfile::Builder profile_builder;
+ profile_builder.OverridePolicyConnectorIsManagedForTesting(true);
+ std::unique_ptr<TestingProfile> testing_profile = profile_builder.Build();
+ std::unique_ptr<testing::NiceMock<chromeos::FakeChromeUserManager>>
+ fake_user_manager_ = std::make_unique<
+ testing::NiceMock<chromeos::FakeChromeUserManager>>();
+ // We use a standard Gaia account by default:
+ AccountId account_id = AccountId::FromUserEmailGaiaId("name", "id");
+
+ switch (test_case.user_type) {
+ case user_manager::USER_TYPE_REGULAR:
+ fake_user_manager_->AddUserWithAffiliationAndTypeAndProfile(
+ account_id, false, test_case.user_type, testing_profile.get());
+ break;
+ case user_manager::USER_TYPE_GUEST:
+ account_id = fake_user_manager_->GetGuestAccountId();
+ fake_user_manager_->AddGuestUser();
+ break;
+ case user_manager::USER_TYPE_PUBLIC_ACCOUNT:
+ fake_user_manager_->AddPublicAccountUser(account_id);
+ break;
+ case user_manager::USER_TYPE_SUPERVISED:
+ fake_user_manager_->AddSupervisedUser(account_id);
+ break;
+ case user_manager::USER_TYPE_KIOSK_APP:
+ fake_user_manager_->AddKioskAppUser(account_id);
+ break;
+ case user_manager::USER_TYPE_CHILD:
+ fake_user_manager_->AddChildUser(account_id);
+ break;
+ case user_manager::USER_TYPE_ARC_KIOSK_APP:
+ fake_user_manager_->AddArcKioskAppUser(account_id);
+ break;
+ case user_manager::USER_TYPE_ACTIVE_DIRECTORY:
+ account_id = AccountId::AdFromObjGuid("guid");
+ fake_user_manager_->AddUserWithAffiliationAndTypeAndProfile(
+ account_id, false, test_case.user_type, testing_profile.get());
+ break;
+ default:
+ FAIL() << "Invalid test setup. Unexpected user type.";
+ break;
+ }
+
+ fake_user_manager_->LoginUser(account_id);
+ std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_ =
+ std::make_unique<user_manager::ScopedUserManager>(
+ std::move(fake_user_manager_));
+
+ EXPECT_EQ(DoesProfileDefaultToLoggingEnabled(testing_profile.get()),
+ test_case.defaults_to_logging_enabled);
+}
+
+INSTANTIATE_TEST_CASE_P(
+ WebRtcPolicyDefaultTests,
+ DoesProfileDefaultToLoggingEnabledForUserTypeParametrizedTest,
+ testing::ValuesIn(
+ std::vector<DoesProfileDefaultToLoggingEnabledForUserTypeTestCase>{
+ {user_manager::USER_TYPE_REGULAR, true},
+ {user_manager::USER_TYPE_GUEST, false},
+ {user_manager::USER_TYPE_PUBLIC_ACCOUNT, false},
+ {user_manager::USER_TYPE_SUPERVISED, false},
+ {user_manager::USER_TYPE_KIOSK_APP, false},
+ {user_manager::USER_TYPE_CHILD, false},
+ {user_manager::USER_TYPE_ARC_KIOSK_APP, false},
+ {user_manager::USER_TYPE_ACTIVE_DIRECTORY, false}}));
+
+#endif // defined(OS_CHROMEOS)
+
} // namespace webrtc_event_logging
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc
index b46470fa284..c4757115f34 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_event_log_manager_unittest.cc
@@ -21,6 +21,7 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/run_loop.h"
@@ -65,6 +66,14 @@
#include "components/policy/core/common/policy_types.h"
#endif
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/account_id/account_id.h"
+#include "components/user_manager/scoped_user_manager.h"
+#endif
+
namespace webrtc_event_logging {
#if defined(OS_WIN)
@@ -612,6 +621,17 @@ class WebRtcEventLogManagerTestBase : public ::testing::Test {
bool is_managed_profile,
bool has_device_level_policies,
base::Optional<bool> policy_allows_remote_logging) {
+ return CreateBrowserContextWithCustomSupervision(
+ profile_name, is_managed_profile, has_device_level_policies,
+ false /* is_supervised */, policy_allows_remote_logging);
+ }
+ virtual std::unique_ptr<TestingProfile>
+ CreateBrowserContextWithCustomSupervision(
+ std::string profile_name,
+ bool is_managed_profile,
+ bool has_device_level_policies,
+ bool is_supervised,
+ base::Optional<bool> policy_allows_remote_logging) {
// If profile name not specified, select a unique name.
if (profile_name.empty()) {
static size_t index = 0;
@@ -655,9 +675,8 @@ class WebRtcEventLogManagerTestBase : public ::testing::Test {
provider_.UpdateChromePolicy(policy_map);
#else
if (has_device_level_policies) {
- // This should never happen.
- // Device level policies cannot be set on Chrome OS and Android.
- EXPECT_TRUE(false);
+ ADD_FAILURE() << "Invalid test setup. Chrome platform policies cannot be "
+ "set on Chrome OS and Android.";
}
#endif
@@ -668,6 +687,9 @@ class WebRtcEventLogManagerTestBase : public ::testing::Test {
profile_builder.SetPrefService(base::WrapUnique(regular_prefs));
profile_builder.OverridePolicyConnectorIsManagedForTesting(
is_managed_profile);
+ if (is_supervised) {
+ profile_builder.SetSupervisedUserId("id");
+ }
std::unique_ptr<TestingProfile> profile = profile_builder.Build();
// Blocks on the unit under test's task runner, so that we won't proceed
@@ -1030,6 +1052,11 @@ class WebRtcEventLogManagerTestPolicy : public WebRtcEventLogManagerTestBase {
WebRtcEventLogManagerTestBase::SetUp();
}
+#if defined(OS_CHROMEOS)
+ std::unique_ptr<user_manager::ScopedUserManager> GetScopedUserManager(
+ user_manager::UserType user_type);
+#endif
+
void TestManagedProfileAfterBeingExplicitlySet(bool explicitly_set_value);
};
@@ -3958,11 +3985,37 @@ TEST_F(WebRtcEventLogManagerTestPolicy, NotManagedRejectsRemoteLogging) {
EXPECT_EQ(StartRemoteLogging(key), allow_remote_logging);
}
+#if defined(OS_CHROMEOS)
+std::unique_ptr<user_manager::ScopedUserManager>
+WebRtcEventLogManagerTestPolicy::GetScopedUserManager(
+ user_manager::UserType user_type) {
+ const AccountId kAccountId = AccountId::FromUserEmailGaiaId("name", "id");
+ auto mock_user_manager =
+ std::make_unique<testing::NiceMock<chromeos::FakeChromeUserManager>>();
+ // On Chrome OS, there are different user types, some of which can be
+ // affiliated with the device if the device is enterprise-enrolled, i.e. the
+ // logged in account belongs to the org that owns the device. For our
+ // purposes here, affiliation does not matter for the determination of the
+ // policy default, so we can set it to false here. We do not need a user
+ // to profile mapping either, so profile can be a nullptr.
+ mock_user_manager->AddUserWithAffiliationAndTypeAndProfile(
+ kAccountId, /*is_affiliated*/ false, user_type, /*profile*/ nullptr);
+ return std::make_unique<user_manager::ScopedUserManager>(
+ std::move(mock_user_manager));
+}
+#endif
+
TEST_F(WebRtcEventLogManagerTestPolicy,
ManagedProfileAllowsRemoteLoggingByDefault) {
SetUp(true); // Feature generally enabled (kill-switch not engaged).
const bool allow_remote_logging = true;
+
+#if defined(OS_CHROMEOS)
+ std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager =
+ GetScopedUserManager(user_manager::USER_TYPE_REGULAR);
+#endif
+
auto browser_context = CreateBrowserContext(
"name", true /* is_managed_profile */,
false /* has_device_level_policies */, base::nullopt);
@@ -3975,12 +4028,44 @@ TEST_F(WebRtcEventLogManagerTestPolicy,
EXPECT_EQ(StartRemoteLogging(key), allow_remote_logging);
}
+// Currently we only test the case of supervised child profiles for Chrome OS
+// here. Other user types for Chrome OS are tested in the unit test for
+// ProfileDefaultsToLoggingEnabledTestCase in
+// webrtc_event_log_manager_common_unittest because the test setup in this
+// class currently does not seem to allow for an easy setup of some user types.
+// TODO(crbug.com/1035829): Figure out whether this can be resolved by tweaking
+// the test setup or whether the Active Directory services need to be adapted
+// for easy testing.
+TEST_F(WebRtcEventLogManagerTestPolicy,
+ ManagedProfileDoesNotAllowRemoteLoggingForSupervisedProfiles) {
+ SetUp(true); // Feature generally enabled (kill-switch not engaged).
+
+ const bool allow_remote_logging = false;
+
+#if defined(OS_CHROMEOS)
+ std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager =
+ GetScopedUserManager(user_manager::USER_TYPE_CHILD);
+#endif
+
+ auto browser_context = CreateBrowserContextWithCustomSupervision(
+ "name", true /* is_managed_profile */,
+ false /* has_device_level_policies */, true /* is_supervised */,
+ base::nullopt);
+
+ auto rph = std::make_unique<MockRenderProcessHost>(browser_context.get());
+ const auto key = GetPeerConnectionKey(rph.get(), kLid);
+
+ ASSERT_TRUE(PeerConnectionAdded(key));
+ ASSERT_TRUE(PeerConnectionSessionIdSet(key));
+ EXPECT_EQ(StartRemoteLogging(key), allow_remote_logging);
+}
+
#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
TEST_F(WebRtcEventLogManagerTestPolicy,
- ManagedByPlatformPoliciesAllowsRemoteLoggingByDefault) {
+ OnlyManagedByPlatformPoliciesDoesNotAllowRemoteLoggingByDefault) {
SetUp(true); // Feature generally enabled (kill-switch not engaged).
- const bool allow_remote_logging = true;
+ const bool allow_remote_logging = false;
auto browser_context =
CreateBrowserContext("name", false /* is_managed_profile */,
true /* has_device_level_policies */, base::nullopt);
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
index c7490acebf8..be5c5c0bd74 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
@@ -120,6 +120,7 @@ class WebRtcGetDisplayMediaBrowserTestWithFakeUI
command_line->AppendSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
+ command_line->RemoveSwitch(switches::kUseFakeDeviceForMediaStream);
command_line->AppendSwitchASCII(
switches::kUseFakeDeviceForMediaStream,
base::StringPrintf("display-media-type=%s",
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_getmediadevices_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_getmediadevices_browsertest.cc
index e786c6d6f25..4e0c5b525f6 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_getmediadevices_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_getmediadevices_browsertest.cc
@@ -58,9 +58,6 @@ class WebRtcGetMediaDevicesBrowserTest
void SetUpCommandLine(base::CommandLine* command_line) override {
// Ensure the infobar is enabled, since we expect that in this test.
EXPECT_FALSE(command_line->HasSwitch(switches::kUseFakeUIForMediaStream));
-
- // Always use fake devices.
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
}
protected:
@@ -235,7 +232,7 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetMediaDevicesBrowserTest,
std::vector<MediaDeviceInfo> devices;
EnumerateDevices(tab1, &devices);
- chrome::AddTabAt(browser(), GURL(), -1, true);
+ chrome::AddTabAt(browser(), GURL(url::kAboutBlankURL), -1, true);
ui_test_utils::NavigateToURL(browser(), url);
content::WebContents* tab2 =
browser()->tab_strip_model()->GetActiveWebContents();
@@ -266,6 +263,9 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetMediaDevicesBrowserTest,
ui_test_utils::NavigateToURL(browser(), url);
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
+
+ EXPECT_TRUE(GetUserMediaAndAccept(tab));
+
std::vector<MediaDeviceInfo> devices;
EnumerateDevices(tab, &devices);
@@ -295,10 +295,13 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetMediaDevicesBrowserTest,
->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
content::WebContents* tab1 =
browser()->tab_strip_model()->GetActiveWebContents();
+
+ EXPECT_TRUE(GetUserMediaAndAccept(tab1));
+
std::vector<MediaDeviceInfo> devices;
EnumerateDevices(tab1, &devices);
- chrome::AddTabAt(browser(), GURL(), -1, true);
+ chrome::AddTabAt(browser(), GURL(url::kAboutBlankURL), -1, true);
ui_test_utils::NavigateToURL(browser(), url);
content::WebContents* tab2 =
browser()->tab_strip_model()->GetActiveWebContents();
@@ -319,6 +322,9 @@ IN_PROC_BROWSER_TEST_F(WebRtcGetMediaDevicesBrowserTest,
->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
content::WebContents* tab =
browser()->tab_strip_model()->GetActiveWebContents();
+
+ EXPECT_TRUE(GetUserMediaAndAccept(tab));
+
std::vector<MediaDeviceInfo> devices;
EnumerateDevices(tab, &devices);
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_internals_integration_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_internals_integration_browsertest.cc
index 3c49d176b84..8d930d2a051 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_internals_integration_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_internals_integration_browsertest.cc
@@ -28,8 +28,6 @@ class WebRTCInternalsIntegrationBrowserTest : public WebRtcTestBase {
void SetUpCommandLine(base::CommandLine* command_line) override {
InProcessBrowserTest::SetUpDefaultCommandLine(command_line);
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
-
{
base::ScopedAllowBlockingForTesting allow_blocking;
ASSERT_TRUE(local_logs_dir_.CreateUniqueTempDir());
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_internals_perf_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_internals_perf_browsertest.cc
index 08e26798891..a6fdde29865 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_internals_perf_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_internals_perf_browsertest.cc
@@ -60,7 +60,6 @@ class WebRtcInternalsPerfBrowserTest : public WebRtcTestBase {
.AddExtension(test::kY4mFileExtension);
command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture,
input_video);
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
}
// Tries to extract data from peerConnectionDataStore in the webrtc-internals
@@ -102,7 +101,7 @@ class WebRtcInternalsPerfBrowserTest : public WebRtcTestBase {
std::unique_ptr<base::DictionaryValue> MeasureWebRtcInternalsData(
int duration_msec) {
- chrome::AddTabAt(browser(), GURL(), -1, true);
+ chrome::AddTabAt(browser(), GURL(url::kAboutBlankURL), -1, true);
ui_test_utils::NavigateToURL(browser(), GURL("chrome://webrtc-internals"));
content::WebContents* webrtc_internals_tab =
browser()->tab_strip_model()->GetActiveWebContents();
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_log_uploader.cc b/chromium/chrome/browser/media/webrtc/webrtc_log_uploader.cc
index 1b386f4a803..61851b8c669 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_log_uploader.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_log_uploader.cc
@@ -18,6 +18,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
@@ -93,9 +94,8 @@ WebRtcLogUploader::UploadDoneData::~UploadDoneData() = default;
WebRtcLogUploader::WebRtcLogUploader()
: main_task_runner_(base::SequencedTaskRunnerHandle::Get()),
- background_task_runner_(
- base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::BEST_EFFORT})) {}
+ background_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT})) {}
WebRtcLogUploader::~WebRtcLogUploader() {
DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_);
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_log_util.cc b/chromium/chrome/browser/media/webrtc/webrtc_log_util.cc
index f724e04d6e1..35a0a0730d0 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_log_util.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_log_util.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_attributes_entry.h"
@@ -25,9 +26,8 @@ void WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles() {
g_browser_process->profile_manager()->GetProfileAttributesStorage().
GetAllProfilesAttributes();
for (ProfileAttributesEntry* entry : entries) {
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(
&webrtc_logging::DeleteOldWebRtcLogFiles,
webrtc_logging::TextLogList::
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc b/chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc
index af4e3ba2ab7..8a11beeab8a 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_logging_controller.cc
@@ -180,8 +180,11 @@ void WebRtcLoggingController::StoreLog(const std::string& log_id,
}
if (rtp_dump_handler_) {
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(stop_rtp_dump_callback_, true, true));
+ if (stop_rtp_dump_callback_) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(stop_rtp_dump_callback_), true, true));
+ }
rtp_dump_handler_->StopOngoingDumps(base::Bind(
&WebRtcLoggingController::StoreLogContinue, this, log_id, callback));
@@ -204,14 +207,14 @@ void WebRtcLoggingController::StoreLogContinue(
log_uploader_->background_task_runner().get(), FROM_HERE,
base::BindOnce(log_directory_getter_),
base::BindOnce(&WebRtcLoggingController::StoreLogInDirectory, this,
- log_id, base::Passed(&log_paths), callback));
+ log_id, std::move(log_paths), callback));
}
void WebRtcLoggingController::StartRtpDump(
RtpDumpType type,
const GenericDoneCallback& callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(stop_rtp_dump_callback_.is_null());
+ DCHECK(!stop_rtp_dump_callback_);
content::RenderProcessHost* host =
content::RenderProcessHost::FromID(render_process_id_);
@@ -244,10 +247,10 @@ void WebRtcLoggingController::StopRtpDump(RtpDumpType type,
return;
}
- if (!stop_rtp_dump_callback_.is_null()) {
+ if (stop_rtp_dump_callback_) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::BindOnce(stop_rtp_dump_callback_,
+ base::BindOnce(std::move(stop_rtp_dump_callback_),
type == RTP_DUMP_INCOMING || type == RTP_DUMP_BOTH,
type == RTP_DUMP_OUTGOING || type == RTP_DUMP_BOTH));
}
@@ -366,8 +369,6 @@ WebRtcLoggingController::WebRtcLoggingController(
upload_log_on_render_close_(false),
text_log_handler_(
std::make_unique<WebRtcTextLogHandler>(render_process_id)),
- rtp_dump_handler_(),
- stop_rtp_dump_callback_(),
log_uploader_(log_uploader) {
DCHECK(log_uploader_);
}
@@ -415,8 +416,11 @@ void WebRtcLoggingController::TriggerUpload(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (rtp_dump_handler_) {
- base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(stop_rtp_dump_callback_, true, true));
+ if (stop_rtp_dump_callback_) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(stop_rtp_dump_callback_), true, true));
+ }
rtp_dump_handler_->StopOngoingDumps(
base::Bind(&WebRtcLoggingController::DoUploadLogAndRtpDumps, this,
@@ -552,7 +556,6 @@ bool WebRtcLoggingController::ReleaseRtpDumps(WebRtcLogPaths* log_paths) {
log_paths->outgoing_rtp_dump = rtp_dumps.outgoing_dump_path;
rtp_dump_handler_.reset();
- stop_rtp_dump_callback_.Reset();
return true;
}
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc b/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc
index f502a329ef1..1bc27e2a6d9 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "chrome/browser/media/webrtc/webrtc_rtp_dump_writer.h"
@@ -61,17 +62,15 @@ WebRtcRtpDumpHandler::~WebRtcRtpDumpHandler() {
}
if (incoming_state_ != STATE_NONE && !incoming_dump_path_.empty()) {
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(base::IgnoreResult(&base::DeleteFile),
incoming_dump_path_, false));
}
if (outgoing_state_ != STATE_NONE && !outgoing_dump_path_.empty()) {
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(base::IgnoreResult(&base::DeleteFile),
outgoing_dump_path_, false));
}
@@ -294,11 +293,10 @@ void WebRtcRtpDumpHandler::OnDumpEnded(const base::Closure& callback,
incoming_state_ = STATE_STOPPED;
if (!incoming_success) {
- base::PostTask(FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::BEST_EFFORT},
- base::BindOnce(base::IgnoreResult(&base::DeleteFile),
- incoming_dump_path_, false));
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(base::IgnoreResult(&base::DeleteFile),
+ incoming_dump_path_, false));
DVLOG(2) << "Deleted invalid incoming dump "
<< incoming_dump_path_.value();
@@ -311,11 +309,10 @@ void WebRtcRtpDumpHandler::OnDumpEnded(const base::Closure& callback,
outgoing_state_ = STATE_STOPPED;
if (!outgoing_success) {
- base::PostTask(FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::BEST_EFFORT},
- base::BindOnce(base::IgnoreResult(&base::DeleteFile),
- outgoing_dump_path_, false));
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(base::IgnoreResult(&base::DeleteFile),
+ outgoing_dump_path_, false));
DVLOG(2) << "Deleted invalid outgoing dump "
<< outgoing_dump_path_.value();
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer.cc b/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer.cc
index d676f226252..c9262a4a559 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/zlib/zlib.h"
@@ -259,9 +260,8 @@ WebRtcRtpDumpWriter::WebRtcRtpDumpWriter(
: max_dump_size_(max_dump_size),
max_dump_size_reached_callback_(max_dump_size_reached_callback),
total_dump_size_on_disk_(0),
- background_task_runner_(
- base::CreateSequencedTaskRunner({base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::BEST_EFFORT})),
+ background_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT})),
incoming_file_thread_worker_(new FileWorker(incoming_dump_path)),
outgoing_file_thread_worker_(new FileWorker(outgoing_dump_path)) {}
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer_unittest.cc b/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer_unittest.cc
index 606aca3fec2..d6aec5d5f2d 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer_unittest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_rtp_dump_writer_unittest.cc
@@ -17,6 +17,7 @@
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
+#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_utils.h"
@@ -284,7 +285,13 @@ TEST_F(WebRtcRtpDumpWriterTest, WriteAndFlushSmallSizeDump) {
VerifyDumps(1, 1);
}
-TEST_F(WebRtcRtpDumpWriterTest, WriteOverMaxLimit) {
+// Flaky test disabled on Windows (https://crbug.com/1044271).
+#if defined(OS_WIN)
+#define MAYBE_WriteOverMaxLimit DISABLED_WriteOverMaxLimit
+#else
+#define MAYBE_WriteOverMaxLimit WriteOverMaxLimit
+#endif
+TEST_F(WebRtcRtpDumpWriterTest, MAYBE_WriteOverMaxLimit) {
// Reset the writer with a small max size limit.
writer_.reset(new WebRtcRtpDumpWriter(
incoming_dump_path_,
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_simulcast_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_simulcast_browsertest.cc
index 582f04f5474..9170629d897 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_simulcast_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_simulcast_browsertest.cc
@@ -37,17 +37,14 @@ class WebRtcSimulcastBrowserTest : public WebRtcTestBase {
// The video playback will not work without a GPU, so force its use here.
command_line->AppendSwitch(switches::kUseGpuInTests);
-
- // Use fake devices in order to run on VMs.
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
}
};
-// Fails/times out on Windows and Chrome OS. Flaky on Mac.
+// Fails/times out on Windows and Chrome OS. Flaky on Mac and Linux.
// http://crbug.com/452623
// http://crbug.com/1004546
// MSan reports errors. http://crbug.com/452892
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) || \
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
defined(MEMORY_SANITIZER)
#define MAYBE_TestVgaReturnsTwoSimulcastStreams DISABLED_TestVgaReturnsTwoSimulcastStreams
#else
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_stats_perf_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_stats_perf_browsertest.cc
index 133b9fa16b9..54ad5dd1af3 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_stats_perf_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_stats_perf_browsertest.cc
@@ -85,7 +85,6 @@ class WebRtcStatsPerfBrowserTest : public WebRtcTestBase {
.AddExtension(test::kY4mFileExtension);
command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture,
input_video);
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
}
void StartCall(const std::string& audio_codec,
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc
index 2967c4816b6..10ad09dcd40 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc
@@ -113,7 +113,7 @@ void AssociateEvents(trace_analyzer::TraceAnalyzer* analyzer,
}
content::WebContents* OpenWebrtcInternalsTab(Browser* browser) {
- chrome::AddTabAt(browser, GURL(), -1, true);
+ chrome::AddTabAt(browser, GURL(url::kAboutBlankURL), -1, true);
ui_test_utils::NavigateToURL(browser, GURL("chrome://webrtc-internals"));
return browser->tab_strip_model()->GetActiveWebContents();
}
@@ -177,22 +177,14 @@ std::vector<double> ParseGoogMaxDecodeFromWebrtcInternalsTab(
// lifetime of a single video frame by synchronizing on the timestamps values
// attached to trace events. Then, it calculates the duration and related stats.
-// TODO(https://crbug.com/993020): Fix flakes on Windows bots.
-#if defined(OS_WIN)
-#define MAYBE_WebRtcVideoDisplayPerfBrowserTest \
- DISABLED_WebRtcVideoDisplayPerfBrowserTest
-#else
-#define MAYBE_WebRtcVideoDisplayPerfBrowserTest \
- WebRtcVideoDisplayPerfBrowserTest
-#endif
-class MAYBE_WebRtcVideoDisplayPerfBrowserTest
+class WebRtcVideoDisplayPerfBrowserTest
: public WebRtcTestBase,
public testing::WithParamInterface<
std::tuple<gfx::Size /* resolution */,
int /* fps */,
bool /* disable_render_smoothness_algorithm */>> {
public:
- MAYBE_WebRtcVideoDisplayPerfBrowserTest() {
+ WebRtcVideoDisplayPerfBrowserTest() {
const auto& params = GetParam();
const gfx::Size& resolution = std::get<0>(params);
test_config_ = {resolution.width(), resolution.height(),
@@ -205,6 +197,7 @@ class MAYBE_WebRtcVideoDisplayPerfBrowserTest
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
+ command_line->RemoveSwitch(switches::kUseFakeDeviceForMediaStream);
command_line->AppendSwitchASCII(
switches::kUseFakeDeviceForMediaStream,
base::StringPrintf("fps=%d", test_config_.fps));
@@ -460,20 +453,20 @@ class MAYBE_WebRtcVideoDisplayPerfBrowserTest
};
INSTANTIATE_TEST_SUITE_P(WebRtcVideoDisplayPerfBrowserTests,
- MAYBE_WebRtcVideoDisplayPerfBrowserTest,
+ WebRtcVideoDisplayPerfBrowserTest,
testing::Combine(testing::Values(gfx::Size(1280, 720),
gfx::Size(1920,
1080)),
testing::Values(30, 60),
testing::Bool()));
-IN_PROC_BROWSER_TEST_P(MAYBE_WebRtcVideoDisplayPerfBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcVideoDisplayPerfBrowserTest,
MANUAL_TestVideoDisplayPerfVP9) {
TestVideoDisplayPerf("VP9");
}
#if BUILDFLAG(RTC_USE_H264)
-IN_PROC_BROWSER_TEST_P(MAYBE_WebRtcVideoDisplayPerfBrowserTest,
+IN_PROC_BROWSER_TEST_P(WebRtcVideoDisplayPerfBrowserTest,
MANUAL_TestVideoDisplayPerfH264) {
if (!base::FeatureList::IsEnabled(
blink::features::kWebRtcH264WithOpenH264FFmpeg)) {
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_video_high_bitrate_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_video_high_bitrate_browsertest.cc
index 535da410ffa..14e42e44227 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_video_high_bitrate_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_video_high_bitrate_browsertest.cc
@@ -66,7 +66,6 @@ class WebRtcVideoHighBitrateBrowserTest : public WebRtcTestBase {
void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(switches::kUseFakeCodecForPeerConnection);
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
command_line->AppendSwitch(switches::kUseGpuInTests);
}
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
index d5a882e3a79..680588e51c3 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_video_quality_browsertest.cc
@@ -115,7 +115,6 @@ class WebRtcVideoQualityBrowserTest : public WebRtcTestBase,
.AddExtension(test::kY4mFileExtension);
command_line->AppendSwitchPath(switches::kUseFileForFakeVideoCapture,
webrtc_reference_video_y4m_);
- command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
// The video playback will not work without a GPU, so force its use here.
command_line->AppendSwitch(switches::kUseGpuInTests);
@@ -158,6 +157,8 @@ class WebRtcVideoQualityBrowserTest : public WebRtcTestBase,
ffmpeg_command.AppendArg(base::StringPrintf("%dx%d", width, height));
ffmpeg_command.AppendArg("-b:v");
ffmpeg_command.AppendArg(base::StringPrintf("%d", 120 * width * height));
+ ffmpeg_command.AppendArg("-vsync");
+ ffmpeg_command.AppendArg("passthrough");
ffmpeg_command.AppendArgPath(yuv_video_filename);
// We produce an output file that will later be used as an input to the
diff --git a/chromium/chrome/browser/media/webrtc/webrtc_webcam_browsertest.cc b/chromium/chrome/browser/media/webrtc/webrtc_webcam_browsertest.cc
index db5eeb4e8eb..6d6d5e4c030 100644
--- a/chromium/chrome/browser/media/webrtc/webrtc_webcam_browsertest.cc
+++ b/chromium/chrome/browser/media/webrtc/webrtc_webcam_browsertest.cc
@@ -58,6 +58,7 @@ class WebRtcWebcamBrowserTest
}
void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->RemoveSwitch(switches::kUseFakeDeviceForMediaStream);
EXPECT_FALSE(command_line->HasSwitch(
switches::kUseFakeDeviceForMediaStream));
EXPECT_FALSE(command_line->HasSwitch(
diff --git a/chromium/chrome/browser/metrics/BUILD.gn b/chromium/chrome/browser/metrics/BUILD.gn
index 5401072ed4a..9b4525767a2 100644
--- a/chromium/chrome/browser/metrics/BUILD.gn
+++ b/chromium/chrome/browser/metrics/BUILD.gn
@@ -4,6 +4,32 @@
import("//components/metrics/generate_expired_histograms_array.gni")
+source_set("test_support") {
+ testonly = true
+ sources = [
+ "testing/demographic_metrics_test_utils.cc",
+ "testing/demographic_metrics_test_utils.h",
+ "testing/sync_metrics_test_utils.cc",
+ "testing/sync_metrics_test_utils.h",
+ ]
+
+ deps = [
+ "//base",
+ "//chrome/browser",
+ "//components/network_time",
+ "//components/prefs",
+ "//components/signin/public/identity_manager",
+ "//components/sync",
+ "//components/sync/base",
+ "//components/sync/test/fake_server",
+ "//third_party/metrics_proto",
+ ]
+
+ if (!is_fuchsia) {
+ deps += [ "//chrome/test:sync_integration_test_support" ]
+ }
+}
+
generate_expired_histograms_array("expired_histograms_array") {
inputs = [
"//tools/metrics/histograms/histograms.xml",
diff --git a/chromium/chrome/browser/metrics/perf/BUILD.gn b/chromium/chrome/browser/metrics/perf/BUILD.gn
index 6c3697f9a75..b5bbd293756 100644
--- a/chromium/chrome/browser/metrics/perf/BUILD.gn
+++ b/chromium/chrome/browser/metrics/perf/BUILD.gn
@@ -6,9 +6,7 @@ import("//build/config/ui.gni")
import("//testing/test.gni")
test("profile_provider_unittest") {
- sources = [
- "profile_provider_unittest_main.cc",
- ]
+ sources = [ "profile_provider_unittest_main.cc" ]
deps = [
"//base",
"//base/test:test_support",
diff --git a/chromium/chrome/browser/nacl_host/test/BUILD.gn b/chromium/chrome/browser/nacl_host/test/BUILD.gn
index 3f9c9f2d24d..2675547e6a9 100644
--- a/chromium/chrome/browser/nacl_host/test/BUILD.gn
+++ b/chromium/chrome/browser/nacl_host/test/BUILD.gn
@@ -6,9 +6,7 @@ import("//components/nacl/features.gni")
if (enable_nacl && (is_linux || is_win)) {
executable("mock_nacl_gdb") {
- sources = [
- "mock_nacl_gdb.cc",
- ]
+ sources = [ "mock_nacl_gdb.cc" ]
deps = [
"//base",
diff --git a/chromium/chrome/browser/net/BUILD.gn b/chromium/chrome/browser/net/BUILD.gn
index fb244ad296d..0a05d7789d2 100644
--- a/chromium/chrome/browser/net/BUILD.gn
+++ b/chromium/chrome/browser/net/BUILD.gn
@@ -5,7 +5,5 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("probe_message_proto") {
- sources = [
- "probe_message.proto",
- ]
+ sources = [ "probe_message.proto" ]
}
diff --git a/chromium/chrome/browser/net/cert_verify_proc_browsertest.cc b/chromium/chrome/browser/net/cert_verify_proc_browsertest.cc
new file mode 100644
index 00000000000..22e89e6d74d
--- /dev/null
+++ b/chromium/chrome/browser/net/cert_verify_proc_browsertest.cc
@@ -0,0 +1,151 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/json/json_reader.h"
+#include "build/build_config.h"
+#include "chrome/test/base/chrome_test_utils.h"
+#include "content/public/browser/network_service_instance.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/network/public/cpp/network_switches.h"
+
+#if defined(OS_ANDROID)
+#include "chrome/test/base/android/android_browser_test.h"
+#else
+#include "chrome/test/base/in_process_browser_test.h"
+#endif
+
+// Base class for tests that want to record a net log. The subclass should
+// implement the VerifyNetLog method which will be called after the test body
+// completes.
+class NetLogPlatformBrowserTestBase : public PlatformBrowserTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ ASSERT_TRUE(tmp_dir_.CreateUniqueTempDir());
+ net_log_path_ = tmp_dir_.GetPath().AppendASCII("netlog.json");
+ command_line->AppendSwitchPath(network::switches::kLogNetLog,
+ net_log_path_);
+ }
+
+ void TearDownInProcessBrowserTestFixture() override {
+ // When using the --log-net-log command line param, the net log is
+ // finalized during the destruction of the network service, which is
+ // started before this method is called, but completes asynchronously.
+ //
+ // Try for up to 5 seconds to read the netlog file.
+ constexpr base::TimeDelta kMaxWaitTime = base::TimeDelta::FromSeconds(5);
+ constexpr base::TimeDelta kWaitInterval =
+ base::TimeDelta::FromMilliseconds(50);
+ int tries_left = kMaxWaitTime / kWaitInterval;
+
+ base::Optional<base::Value> parsed_net_log;
+ while (true) {
+ std::string file_contents;
+ ASSERT_TRUE(base::ReadFileToString(net_log_path_, &file_contents));
+
+ parsed_net_log = base::JSONReader::Read(file_contents);
+ if (parsed_net_log)
+ break;
+
+ if (--tries_left <= 0)
+ break;
+ // The netlog file did not parse as valid JSON. Probably the Network
+ // Service is still shutting down. Wait a bit and try again.
+ base::PlatformThread::Sleep(kWaitInterval);
+ }
+ ASSERT_TRUE(parsed_net_log);
+
+ VerifyNetLog(&parsed_net_log.value());
+
+ PlatformBrowserTest::TearDownInProcessBrowserTestFixture();
+ }
+
+ // Subclasses should override this to implement the test verification
+ // conditions. It will be called after the test fixture has been torn down.
+ virtual void VerifyNetLog(base::Value* parsed_net_log) = 0;
+
+ protected:
+ content::WebContents* GetActiveWebContents() {
+ return chrome_test_utils::GetActiveWebContents(this);
+ }
+
+ private:
+ base::FilePath net_log_path_;
+ base::ScopedTempDir tmp_dir_;
+};
+
+// This is an integration test to ensure that CertVerifyProc netlog events
+// continue to be logged once cert verification is moved out of the network
+// service process. (See crbug.com/1015134 and crbug.com/1040681.)
+class CertVerifyProcNetLogBrowserTest : public NetLogPlatformBrowserTestBase {
+ public:
+ void SetUpOnMainThread() override {
+ PlatformBrowserTest::SetUpOnMainThread();
+
+ host_resolver()->AddRule("*", "127.0.0.1");
+
+ https_server_.ServeFilesFromSourceDirectory("chrome/test/data/");
+ https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
+ }
+
+ void VerifyNetLog(base::Value* parsed_net_log) override {
+ base::DictionaryValue* main;
+ ASSERT_TRUE(parsed_net_log->GetAsDictionary(&main));
+
+ base::Value* events = main->FindListKey("events");
+ ASSERT_TRUE(events);
+
+ bool found_cert_verify_proc_event = false;
+ for (const auto& event : events->GetList()) {
+ base::Optional<int> event_type = event.FindIntKey("type");
+ ASSERT_TRUE(event_type.has_value());
+ if (event_type ==
+ static_cast<int>(net::NetLogEventType::CERT_VERIFY_PROC)) {
+ base::Optional<int> phase = event.FindIntKey("phase");
+ if (!phase.has_value() ||
+ *phase != static_cast<int>(net::NetLogEventPhase::BEGIN)) {
+ continue;
+ }
+ const base::Value* params = event.FindDictKey("params");
+ if (!params)
+ continue;
+ const std::string* host = params->FindStringKey("host");
+ if (host && *host == kTestHost) {
+ found_cert_verify_proc_event = true;
+ break;
+ }
+ }
+ }
+
+ EXPECT_TRUE(found_cert_verify_proc_event);
+ }
+
+ const std::string kTestHost = "netlog-example.a.test";
+
+ protected:
+ net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
+};
+
+IN_PROC_BROWSER_TEST_F(CertVerifyProcNetLogBrowserTest, Test) {
+ ASSERT_TRUE(https_server_.Start());
+
+ // Request using a unique host name to ensure that the cert verification wont
+ // use a cached result for 127.0.0.1 that happened before the test starts
+ // logging.
+ EXPECT_TRUE(content::NavigateToURL(
+ GetActiveWebContents(),
+ https_server_.GetURL(kTestHost, "/ssl/google.html")));
+
+ // Technically there is no guarantee that if the cert verifier is running out
+ // of process that the netlog mojo messages will be delivered before the cert
+ // verification mojo result. See:
+ // https://chromium.googlesource.com/chromium/src/+/master/docs/mojo_ipc_conversion.md#Ordering-Considerations
+ // Hopefully this won't be flaky.
+ base::RunLoop().RunUntilIdle();
+ content::FlushNetworkServiceInstanceForTesting();
+}
diff --git a/chromium/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc b/chromium/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc
index 140e2f492b6..4f8b47a1bf5 100644
--- a/chromium/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc
+++ b/chromium/chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc
@@ -24,6 +24,10 @@
#include "services/strings/grit/services_strings.h"
#endif
+#if defined(OS_WIN)
+#include "services/service_manager/sandbox/sandbox_type.h"
+#endif
+
namespace {
proxy_resolver::mojom::ProxyResolverFactory* GetProxyResolverFactory() {
@@ -42,14 +46,10 @@ proxy_resolver::mojom::ProxyResolverFactory* GetProxyResolverFactory() {
content::ServiceProcessHost::Launch(
remote->BindNewPipeAndPassReceiver(),
content::ServiceProcessHost::Options()
-#if defined(OS_MACOSX)
- // The proxy_resolver service runs V8, so it needs to run in the
- // helper application that has the com.apple.security.cs.allow-jit
- // code signing entitlement, which is CHILD_RENDERER. The service
- // still runs under the utility process sandbox.
- .WithChildFlags(content::ChildProcessHost::CHILD_RENDERER)
-#endif
.WithDisplayName(IDS_PROXY_RESOLVER_DISPLAY_NAME)
+#if defined(OS_WIN)
+ .WithSandboxType(service_manager::SandboxType::kProxyResolver)
+#endif
.Pass());
// The service will report itself idle once there are no more bound
diff --git a/chromium/chrome/browser/net/chrome_network_service_restart_browsertest.cc b/chromium/chrome/browser/net/chrome_network_service_restart_browsertest.cc
index f8e53f408e4..1c96790cc0d 100644
--- a/chromium/chrome/browser/net/chrome_network_service_restart_browsertest.cc
+++ b/chromium/chrome/browser/net/chrome_network_service_restart_browsertest.cc
@@ -43,10 +43,8 @@ IN_PROC_BROWSER_TEST_F(ChromeNetworkServiceRestartBrowserTest,
StoragePartitionGetNetworkContext) {
if (content::IsInProcessNetworkService())
return;
-#if defined(OS_MACOSX)
// |NetworkServiceTestHelper| doesn't work on browser_tests on macOS.
- return;
-#endif
+#if !defined(OS_MACOSX)
StoragePartition* partition =
BrowserContext::GetDefaultStoragePartition(browser()->profile());
@@ -65,6 +63,7 @@ IN_PROC_BROWSER_TEST_F(ChromeNetworkServiceRestartBrowserTest,
EXPECT_NE(old_network_context, partition->GetNetworkContext());
EXPECT_EQ(net::OK,
LoadBasicRequest(partition->GetNetworkContext(), GetTestURL()));
+#endif
}
// Make sure |SystemNetworkContextManager::GetContext()| returns valid interface
@@ -73,10 +72,8 @@ IN_PROC_BROWSER_TEST_F(ChromeNetworkServiceRestartBrowserTest,
SystemNetworkContextManagerGetContext) {
if (content::IsInProcessNetworkService())
return;
-#if defined(OS_MACOSX)
// |NetworkServiceTestHelper| doesn't work on browser_tests on macOS.
- return;
-#endif
+#if !defined(OS_MACOSX)
SystemNetworkContextManager* system_network_context_manager =
g_browser_process->system_network_context_manager();
@@ -96,6 +93,7 @@ IN_PROC_BROWSER_TEST_F(ChromeNetworkServiceRestartBrowserTest,
EXPECT_EQ(net::OK,
LoadBasicRequest(system_network_context_manager->GetContext(),
GetTestURL()));
+#endif
}
} // namespace content
diff --git a/chromium/chrome/browser/net/cookie_policy_browsertest.cc b/chromium/chrome/browser/net/cookie_policy_browsertest.cc
index ec92518a328..f92af6aca26 100644
--- a/chromium/chrome/browser/net/cookie_policy_browsertest.cc
+++ b/chromium/chrome/browser/net/cookie_policy_browsertest.cc
@@ -21,6 +21,7 @@
#include "components/network_session_configurator/common/network_switches.h"
#include "components/prefs/pref_service.h"
#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
@@ -32,9 +33,8 @@ using content::BrowserThread;
namespace {
const std::vector<std::string> kStorageTypes{
- "Cookie", "LocalStorage", "FileSystem", "SessionStorage",
- "IndexedDb", "WebSql", "CacheStorage", "ServiceWorker",
-};
+ "Cookie", "LocalStorage", "FileSystem", "SessionStorage", "IndexedDb",
+ "WebSql", "CacheStorage", "ServiceWorker", "CookieStore"};
const std::vector<std::string> kCrossTabCommunicationTypes{
"SharedWorker",
@@ -59,6 +59,8 @@ class CookiePolicyBrowserTest : public InProcessBrowserTest {
// HTTPS server only serves a valid cert for localhost, so this is needed
// to load pages from other hosts without an error.
command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
+ command_line->AppendSwitchASCII(switches::kEnableBlinkFeatures,
+ "CookieStoreDocument");
}
void SetBlockThirdPartyCookies(bool value) {
@@ -75,7 +77,7 @@ class CookiePolicyBrowserTest : public InProcessBrowserTest {
GURL main_url(https_server_.GetURL(host, "/iframe.html"));
ui_test_utils::NavigateToURLWithDisposition(
browser(), main_url, WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
}
void NavigateFrameTo(const std::string& host, const std::string& path) {
diff --git a/chromium/chrome/browser/net/dns_probe_browsertest.cc b/chromium/chrome/browser/net/dns_probe_browsertest.cc
index 4a140b8005f..3fc6670b241 100644
--- a/chromium/chrome/browser/net/dns_probe_browsertest.cc
+++ b/chromium/chrome/browser/net/dns_probe_browsertest.cc
@@ -11,9 +11,11 @@
#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/default_tick_clock.h"
+#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/dns_probe_service_factory.h"
#include "chrome/browser/net/dns_probe_test_util.h"
+#include "chrome/browser/net/dns_util.h"
#include "chrome/browser/net/net_error_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
@@ -24,6 +26,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
+#include "components/embedder_support/pref_names.h"
#include "components/error_page/common/net_error_info.h"
#include "components/google/core/common/google_util.h"
#include "components/prefs/pref_service.h"
@@ -43,6 +46,10 @@
#include "services/network/public/cpp/features.h"
#include "testing/gtest/include/gtest/gtest.h"
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#endif
+
using base::Bind;
using base::BindOnce;
using base::Callback;
@@ -99,6 +106,10 @@ class DelayingDnsProbeService : public DnsProbeService {
delayed_probes_.push_back(std::move(callback));
}
+ net::DnsConfigOverrides GetCurrentConfigOverridesForTesting() override {
+ return dns_probe_service_impl_->GetCurrentConfigOverridesForTesting();
+ }
+
void StartDelayedProbes() {
CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -343,15 +354,15 @@ class DnsProbeBrowserTest : public InProcessBrowserTest {
// DnsProbeStatus messages of its currently active tab monitored.
void SetActiveBrowser(Browser* browser);
- // Sets the results the FakeHostResolver will return for the system and
- // public DnsProbeRunners. Since this mocks out the
- // NetworkContext & HostResolver used by the DnsProbeService it doesn't really
- // give an end-to-end test, but content::TestHostResolver mocks don't affect
- // the probes since they use HostResolverSource::DNS, so this is the best
- // that can be done currently.
+ // Sets the results the FakeHostResolver will return for the current config
+ // and Google config DnsProbeRunners. Since this mocks out the NetworkContext
+ // and HostResolver used by the DnsProbeService it doesn't really give an
+ // end-to-end test, but content::TestHostResolver mocks don't affect the
+ // probes since they use HostResolverSource::DNS, so this is the best that
+ // can be done currently.
void SetFakeHostResolverResults(
- std::vector<FakeHostResolver::SingleResult> system_results,
- std::vector<FakeHostResolver::SingleResult> public_results);
+ std::vector<FakeHostResolver::SingleResult> current_config_results,
+ std::vector<FakeHostResolver::SingleResult> google_config_results);
void SetCorrectionServiceBroken(bool broken);
void SetCorrectionServiceDelayRequests(bool delay_requests);
@@ -425,7 +436,7 @@ void DnsProbeBrowserTest::SetUpOnMainThread() {
NetErrorTabHelper::set_state_for_testing(NetErrorTabHelper::TESTING_DEFAULT);
browser()->profile()->GetPrefs()->SetBoolean(
- prefs::kAlternateErrorPagesEnabled, true);
+ embedder_support::kAlternateErrorPagesEnabled, true);
base::PostTask(FROM_HERE, {BrowserThread::IO},
BindOnce(&DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread,
@@ -496,12 +507,12 @@ void DnsProbeBrowserTest::SetActiveBrowser(Browser* browser) {
}
void DnsProbeBrowserTest::SetFakeHostResolverResults(
- std::vector<FakeHostResolver::SingleResult> system_results,
- std::vector<FakeHostResolver::SingleResult> public_results) {
+ std::vector<FakeHostResolver::SingleResult> current_config_results,
+ std::vector<FakeHostResolver::SingleResult> google_config_results) {
ASSERT_FALSE(network_context_);
network_context_ = std::make_unique<FakeHostResolverNetworkContext>(
- std::move(system_results), std::move(public_results));
+ std::move(current_config_results), std::move(google_config_results));
}
void DnsProbeBrowserTest::SetCorrectionServiceBroken(bool broken) {
@@ -656,6 +667,45 @@ class DnsProbeFailingProbesTest : public DnsProbeBrowserTest {
}
};
+class DnsProbeCurrentConfigFailingProbesTest : public DnsProbeBrowserTest {
+ protected:
+ void SetUpOnMainThread() override {
+ SetFakeHostResolverResults(
+ {{net::ERR_NAME_NOT_RESOLVED,
+ net::ResolveErrorInfo(net::ERR_NAME_NOT_RESOLVED),
+ FakeHostResolver::kNoResponse}},
+ {{net::OK, net::ResolveErrorInfo(net::OK),
+ FakeHostResolver::kOneAddressResponse}});
+ DnsProbeBrowserTest::SetUpOnMainThread();
+ }
+};
+
+class DnsProbeCurrentSecureConfigFailingProbesTest
+ : public DnsProbeBrowserTest {
+ protected:
+ void SetUpOnMainThread() override {
+#if defined(OS_WIN)
+ // Mark as not enterprise managed to prevent the secure DNS mode from
+ // being downgraded to off.
+ base::win::ScopedDomainStateForTesting scoped_domain(false);
+#endif
+
+ PrefService* local_state = g_browser_process->local_state();
+ local_state->SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeSecure);
+ local_state->SetString(prefs::kDnsOverHttpsTemplates,
+ "https://bar.test/dns-query{?dns}");
+
+ SetFakeHostResolverResults(
+ {{net::ERR_NAME_NOT_RESOLVED,
+ net::ResolveErrorInfo(net::ERR_NAME_NOT_RESOLVED),
+ FakeHostResolver::kNoResponse}},
+ {{net::OK, net::ResolveErrorInfo(net::OK),
+ FakeHostResolver::kOneAddressResponse}});
+ DnsProbeBrowserTest::SetUpOnMainThread();
+ }
+};
+
// Test Fixture for tests where the DNS probes should fail to connect to a DNS
// server (timeout or unreachable host).
class DnsProbeUnreachableProbesTest : public DnsProbeBrowserTest {
@@ -747,6 +797,52 @@ IN_PROC_BROWSER_TEST_F(DnsProbeSuccessfulProbesTest,
ExpectDisplayingCorrections("ERR_NAME_NOT_RESOLVED");
}
+IN_PROC_BROWSER_TEST_F(DnsProbeCurrentConfigFailingProbesTest, BadConfig) {
+ SetCorrectionServiceBroken(true);
+
+ NavigateToDnsError(2);
+
+ EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());
+ EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());
+
+ // Checking the page runs the RunLoop, so make sure nothing hairy happens.
+ EXPECT_EQ(0, pending_status_count());
+ ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED");
+ EXPECT_EQ(0, pending_status_count());
+
+ StartDelayedProbes(1);
+
+ EXPECT_EQ(error_page::DNS_PROBE_FINISHED_BAD_CONFIG, WaitForSentStatus());
+
+ // Checking the page runs the RunLoop, so make sure nothing hairy happens.
+ EXPECT_EQ(0, pending_status_count());
+ ExpectDisplayingLocalErrorPage("DNS_PROBE_FINISHED_BAD_CONFIG");
+}
+
+IN_PROC_BROWSER_TEST_F(DnsProbeCurrentSecureConfigFailingProbesTest,
+ BadSecureConfig) {
+ SetCorrectionServiceBroken(true);
+
+ NavigateToDnsError(2);
+
+ EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());
+ EXPECT_EQ(error_page::DNS_PROBE_STARTED, WaitForSentStatus());
+
+ // Checking the page runs the RunLoop, so make sure nothing hairy happens.
+ EXPECT_EQ(0, pending_status_count());
+ ExpectDisplayingLocalErrorPage("DNS_PROBE_STARTED");
+ EXPECT_EQ(0, pending_status_count());
+
+ StartDelayedProbes(1);
+
+ EXPECT_EQ(error_page::DNS_PROBE_FINISHED_BAD_SECURE_CONFIG,
+ WaitForSentStatus());
+
+ // Checking the page runs the RunLoop, so make sure nothing hairy happens.
+ EXPECT_EQ(0, pending_status_count());
+ ExpectDisplayingLocalErrorPage("DNS_PROBE_FINISHED_BAD_SECURE_CONFIG");
+}
+
// Make sure probes update DNS error page properly when they're supposed to.
IN_PROC_BROWSER_TEST_F(DnsProbeUnreachableProbesTest,
NoInternetProbeResultWithBrokenCorrections) {
@@ -899,7 +995,7 @@ IN_PROC_BROWSER_TEST_F(DnsProbeSuccessfulProbesTest, NoProbeInSubframe) {
IN_PROC_BROWSER_TEST_F(DnsProbeUnreachableProbesTest, ProbesDisabled) {
// Disable probes (And corrections).
browser()->profile()->GetPrefs()->SetBoolean(
- prefs::kAlternateErrorPagesEnabled, false);
+ embedder_support::kAlternateErrorPagesEnabled, false);
SetCorrectionServiceBroken(true);
@@ -917,7 +1013,7 @@ IN_PROC_BROWSER_TEST_F(DnsProbeUnreachableProbesTest, ProbesDisabled) {
IN_PROC_BROWSER_TEST_F(DnsProbeFailingProbesTest, CorrectionsDisabled) {
// Disable corrections.
browser()->profile()->GetPrefs()->SetBoolean(
- prefs::kAlternateErrorPagesEnabled, false);
+ embedder_support::kAlternateErrorPagesEnabled, false);
// Requests to the correction service should work if any are made, so the test
// fails if that happens unexpectedly.
SetCorrectionServiceBroken(false);
diff --git a/chromium/chrome/browser/net/dns_probe_runner.cc b/chromium/chrome/browser/net/dns_probe_runner.cc
index 9fe42124c15..e3aa334abc6 100644
--- a/chromium/chrome/browser/net/dns_probe_runner.cc
+++ b/chromium/chrome/browser/net/dns_probe_runner.cc
@@ -95,7 +95,8 @@ void DnsProbeRunner::RunProbe(base::OnceClosure callback) {
network::mojom::ResolveHostParameters::New();
parameters->dns_query_type = net::DnsQueryType::A;
parameters->source = net::HostResolverSource::DNS;
- parameters->allow_cached_response = false;
+ parameters->cache_usage =
+ network::mojom::ResolveHostParameters::CacheUsage::DISALLOWED;
// Use transient NIKs - don't want cached responses anyways, so no benefit
// from sharing a cache, beyond multiple probes not evicting anything.
diff --git a/chromium/chrome/browser/net/dns_probe_runner.h b/chromium/chrome/browser/net/dns_probe_runner.h
index 3b49a90dd3a..0cd8f3282cc 100644
--- a/chromium/chrome/browser/net/dns_probe_runner.h
+++ b/chromium/chrome/browser/net/dns_probe_runner.h
@@ -14,7 +14,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/resolve_host_client_base.h"
-#include "services/network/public/mojom/host_resolver.mojom.h"
+#include "services/network/public/mojom/host_resolver.mojom-forward.h"
namespace network {
namespace mojom {
@@ -74,6 +74,10 @@ class DnsProbeRunner : public network::ResolveHostClientBase {
const net::ResolveErrorInfo& resolve_error_info,
const base::Optional<net::AddressList>& resolved_addresses) override;
+ net::DnsConfigOverrides GetConfigOverridesForTesting() {
+ return dns_config_overrides_;
+ }
+
private:
void CreateHostResolver();
void OnMojoConnectionError();
diff --git a/chromium/chrome/browser/net/dns_probe_runner_unittest.cc b/chromium/chrome/browser/net/dns_probe_runner_unittest.cc
index b085e03eae7..b23fed2a7c4 100644
--- a/chromium/chrome/browser/net/dns_probe_runner_unittest.cc
+++ b/chromium/chrome/browser/net/dns_probe_runner_unittest.cc
@@ -173,6 +173,21 @@ TEST_F(DnsProbeRunnerTest, Probe_DnsNotRun) {
RunTest(DnsProbeRunner::UNKNOWN);
}
+TEST_F(DnsProbeRunnerTest, Probe_SecureDnsHostnameNotResolved) {
+ SetupTest(net::ERR_NAME_NOT_RESOLVED,
+ net::ResolveErrorInfo(
+ net::ERR_DNS_SECURE_RESOLVER_HOSTNAME_RESOLUTION_FAILED),
+ FakeHostResolver::kNoResponse);
+ RunTest(DnsProbeRunner::UNREACHABLE);
+}
+
+TEST_F(DnsProbeRunnerTest, Probe_SecureDnsCertificateError) {
+ SetupTest(net::ERR_NAME_NOT_RESOLVED,
+ net::ResolveErrorInfo(net::ERR_CERT_COMMON_NAME_INVALID),
+ FakeHostResolver::kNoResponse);
+ RunTest(DnsProbeRunner::UNREACHABLE);
+}
+
TEST_F(DnsProbeRunnerTest, TwoProbes) {
SetupTest({{net::OK, net::ResolveErrorInfo(net::OK),
FakeHostResolver::kOneAddressResponse},
diff --git a/chromium/chrome/browser/net/dns_probe_service.h b/chromium/chrome/browser/net/dns_probe_service.h
index 90b1470e10f..5d72cc146dc 100644
--- a/chromium/chrome/browser/net/dns_probe_service.h
+++ b/chromium/chrome/browser/net/dns_probe_service.h
@@ -11,12 +11,13 @@
#include "base/callback.h"
#include "components/error_page/common/net_error_info.h"
#include "components/keyed_service/core/keyed_service.h"
+#include "net/dns/dns_config_overrides.h"
namespace chrome_browser_net {
-// Probes the system and public DNS servers to determine the (probable) cause
-// of a recent DNS-related page load error. Coalesces multiple probe requests
-// (perhaps from multiple tabs) and caches the results.
+// Probes the current DNS config servers and Google DNS servers to determine
+// the (probable) cause of a recent DNS-related page load error. Coalesces
+// multiple probe requests (perhaps from multiple tabs) and caches the results.
//
// Uses a single DNS attempt per config, and doesn't randomize source ports.
//
@@ -30,6 +31,9 @@ class DnsProbeService : public KeyedService {
// in progress or recently completed. |callback| will be called
// asynchronously with the probe result.
virtual void ProbeDns(ProbeCallback callback) = 0;
+
+ // Returns the DnsConfigOverrides being used to mimic the current DNS config.
+ virtual net::DnsConfigOverrides GetCurrentConfigOverridesForTesting() = 0;
};
} // namespace chrome_browser_net
diff --git a/chromium/chrome/browser/net/dns_probe_service_factory.cc b/chromium/chrome/browser/net/dns_probe_service_factory.cc
index 9a19fe4a561..8cf9f5c58fb 100644
--- a/chromium/chrome/browser/net/dns_probe_service_factory.cc
+++ b/chromium/chrome/browser/net/dns_probe_service_factory.cc
@@ -15,8 +15,11 @@
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/dns_probe_runner.h"
#include "chrome/browser/net/dns_probe_service.h"
+#include "chrome/browser/net/stub_resolver_config_reader.h"
+#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_context.h"
@@ -26,6 +29,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
+#include "net/dns/public/dns_over_https_server_config.h"
#include "net/dns/public/dns_protocol.h"
#include "services/network/public/mojom/network_service.mojom.h"
@@ -43,39 +47,6 @@ const int kMaxResultAgeMs = 5000;
const uint8_t kGooglePublicDns1[] = {8, 8, 8, 8};
const uint8_t kGooglePublicDns2[] = {8, 8, 4, 4};
-error_page::DnsProbeStatus EvaluateResults(
- DnsProbeRunner::Result system_result,
- DnsProbeRunner::Result public_result) {
- // If the system DNS is working, assume the domain doesn't exist.
- if (system_result == DnsProbeRunner::CORRECT)
- return error_page::DNS_PROBE_FINISHED_NXDOMAIN;
-
- // If the system DNS is unknown (e.g. on Android), but the public server is
- // reachable, assume the domain doesn't exist.
- if (system_result == DnsProbeRunner::UNKNOWN &&
- public_result == DnsProbeRunner::CORRECT) {
- return error_page::DNS_PROBE_FINISHED_NXDOMAIN;
- }
-
- // If the system DNS is not working but another public server is, assume the
- // DNS config is bad (or perhaps the DNS servers are down or broken).
- if (public_result == DnsProbeRunner::CORRECT)
- return error_page::DNS_PROBE_FINISHED_BAD_CONFIG;
-
- // If the system DNS is not working and another public server is unreachable,
- // assume the internet connection is down (note that system DNS may be a
- // router on the LAN, so it may be reachable but returning errors.)
- if (public_result == DnsProbeRunner::UNREACHABLE)
- return error_page::DNS_PROBE_FINISHED_NO_INTERNET;
-
- // Otherwise: the system DNS is not working and another public server is
- // responding but with errors or incorrect results. This is an awkward case;
- // an invasive captive portal or a restrictive firewall may be intercepting
- // or rewriting DNS traffic, or the public server may itself be failing or
- // down.
- return error_page::DNS_PROBE_FINISHED_INCONCLUSIVE;
-}
-
void HistogramProbe(error_page::DnsProbeStatus status,
base::TimeDelta elapsed) {
DCHECK(error_page::DnsProbeStatusIsFinished(status));
@@ -100,15 +71,7 @@ GetDnsConfigChangeManager() {
return dns_config_change_manager_remote;
}
-net::DnsConfigOverrides SystemOverrides() {
- net::DnsConfigOverrides overrides;
- overrides.search = {};
- overrides.attempts = 1;
- overrides.randomize_ports = false;
- return overrides;
-}
-
-net::DnsConfigOverrides PublicOverrides() {
+net::DnsConfigOverrides GoogleConfigOverrides() {
net::DnsConfigOverrides overrides =
net::DnsConfigOverrides::CreateOverridingEverythingWithDefaults();
overrides.nameservers = std::vector<net::IPEndPoint>{
@@ -118,6 +81,7 @@ net::DnsConfigOverrides PublicOverrides() {
net::dns_protocol::kDefaultPort)};
overrides.attempts = 1;
overrides.randomize_ports = false;
+ overrides.secure_dns_mode = net::DnsConfig::SecureDnsMode::OFF;
return overrides;
}
@@ -138,6 +102,7 @@ class DnsProbeServiceImpl
// DnsProbeService implementation:
void ProbeDns(DnsProbeService::ProbeCallback callback) override;
+ net::DnsConfigOverrides GetCurrentConfigOverridesForTesting() override;
// mojom::network::DnsConfigChangeManagerClient implementation:
void OnDnsConfigChanged() override;
@@ -149,9 +114,18 @@ class DnsProbeServiceImpl
STATE_RESULT_CACHED,
};
- // Starts a probe (runs system and public probes).
+ // Create the current config runner using overrides that will mimic the
+ // current secure DNS mode and pre-specified DoH servers.
+ void SetUpCurrentConfigRunner();
+
+ // Starts a probe (runs probes for both the current config and google config)
void StartProbes();
void OnProbeComplete();
+ // Determine what error page should be shown given the results of the two
+ // probe runners.
+ error_page::DnsProbeStatus EvaluateResults(
+ DnsProbeRunner::Result current_config_result,
+ DnsProbeRunner::Result google_config_result);
// Calls all |pending_callbacks_| with the |cached_result_|.
void CallCallbacks();
// Calls callback by posting a task to the same sequence. |pending_callbacks_|
@@ -173,9 +147,17 @@ class DnsProbeServiceImpl
NetworkContextGetter network_context_getter_;
DnsConfigChangeManagerGetter dns_config_change_manager_getter_;
mojo::Receiver<network::mojom::DnsConfigChangeManagerClient> receiver_{this};
- // DnsProbeRunners for the system DNS configuration and a public DNS server.
- DnsProbeRunner system_runner_;
- DnsProbeRunner public_runner_;
+ net::DnsConfig::SecureDnsMode current_config_secure_dns_mode_ =
+ net::DnsConfig::SecureDnsMode::OFF;
+
+ // DnsProbeRunners for the current DNS configuration and a Google DNS
+ // configuration. Both runners will have the insecure async resolver enabled
+ // regardless of the platform. This is out of necessity for the Google config
+ // runner, where the nameservers are being changed. For the current config
+ // runner, the insecure async resolver will only be used when the runner is
+ // not operating in SECURE mode.
+ std::unique_ptr<DnsProbeRunner> current_config_runner_;
+ std::unique_ptr<DnsProbeRunner> google_config_runner_;
// Time source for cache expiry.
const base::TickClock* tick_clock_; // Not owned.
@@ -198,10 +180,11 @@ DnsProbeServiceImpl::DnsProbeServiceImpl(
: state_(STATE_NO_RESULT),
network_context_getter_(network_context_getter),
dns_config_change_manager_getter_(dns_config_change_manager_getter),
- system_runner_(SystemOverrides(), network_context_getter),
- public_runner_(PublicOverrides(), network_context_getter),
tick_clock_(tick_clock) {
SetupDnsConfigChangeNotifications();
+ google_config_runner_ = std::make_unique<DnsProbeRunner>(
+ GoogleConfigOverrides(), network_context_getter_);
+ SetUpCurrentConfigRunner();
}
DnsProbeServiceImpl::~DnsProbeServiceImpl() {
@@ -228,40 +211,84 @@ void DnsProbeServiceImpl::ProbeDns(ProbeCallback callback) {
}
}
+net::DnsConfigOverrides
+DnsProbeServiceImpl::GetCurrentConfigOverridesForTesting() {
+ DCHECK(current_config_runner_);
+ return current_config_runner_->GetConfigOverridesForTesting();
+}
+
void DnsProbeServiceImpl::OnDnsConfigChanged() {
+ SetUpCurrentConfigRunner();
ClearCachedResult();
}
+void DnsProbeServiceImpl::SetUpCurrentConfigRunner() {
+ bool insecure_stub_resolver_enabled;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+ SystemNetworkContextManager::GetStubResolverConfigReader()->GetConfiguration(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &current_config_secure_dns_mode_,
+ &dns_over_https_servers);
+
+ net::DnsConfigOverrides current_config_overrides;
+ current_config_overrides.search = std::vector<std::string>();
+ current_config_overrides.attempts = 1;
+ current_config_overrides.randomize_ports = false;
+
+ if (current_config_secure_dns_mode_ ==
+ net::DnsConfig::SecureDnsMode::SECURE) {
+ if (!dns_over_https_servers.empty()) {
+ current_config_overrides.dns_over_https_servers.emplace();
+ for (auto& doh_server : dns_over_https_servers) {
+ current_config_overrides.dns_over_https_servers.value().push_back(
+ std::move(doh_server));
+ }
+ }
+ current_config_overrides.secure_dns_mode =
+ net::DnsConfig::SecureDnsMode::SECURE;
+ } else {
+ // A DNS error that occurred in automatic mode must have had an insecure
+ // DNS failure. For efficiency, probe queries in this case can just be
+ // issued in OFF mode.
+ current_config_overrides.secure_dns_mode =
+ net::DnsConfig::SecureDnsMode::OFF;
+ }
+
+ current_config_runner_ = std::make_unique<DnsProbeRunner>(
+ current_config_overrides, network_context_getter_);
+}
+
void DnsProbeServiceImpl::StartProbes() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(STATE_NO_RESULT, state_);
- DCHECK(!system_runner_.IsRunning());
- DCHECK(!public_runner_.IsRunning());
+ DCHECK(!current_config_runner_->IsRunning());
+ DCHECK(!google_config_runner_->IsRunning());
// Unretained safe because the callback will not be run if the DnsProbeRunner
// is destroyed.
- system_runner_.RunProbe(base::BindOnce(&DnsProbeServiceImpl::OnProbeComplete,
- base::Unretained(this)));
- public_runner_.RunProbe(base::BindOnce(&DnsProbeServiceImpl::OnProbeComplete,
- base::Unretained(this)));
+ current_config_runner_->RunProbe(base::BindOnce(
+ &DnsProbeServiceImpl::OnProbeComplete, base::Unretained(this)));
+ google_config_runner_->RunProbe(base::BindOnce(
+ &DnsProbeServiceImpl::OnProbeComplete, base::Unretained(this)));
probe_start_time_ = tick_clock_->NowTicks();
state_ = STATE_PROBE_RUNNING;
- DCHECK(system_runner_.IsRunning());
- DCHECK(public_runner_.IsRunning());
+ DCHECK(current_config_runner_->IsRunning());
+ DCHECK(google_config_runner_->IsRunning());
}
void DnsProbeServiceImpl::OnProbeComplete() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(STATE_PROBE_RUNNING, state_);
- DCHECK(!system_runner_.IsRunning() || !public_runner_.IsRunning());
+ DCHECK(!current_config_runner_->IsRunning() ||
+ !google_config_runner_->IsRunning());
- if (system_runner_.IsRunning() || public_runner_.IsRunning())
+ if (current_config_runner_->IsRunning() || google_config_runner_->IsRunning())
return;
- cached_result_ =
- EvaluateResults(system_runner_.result(), public_runner_.result());
+ cached_result_ = EvaluateResults(current_config_runner_->result(),
+ google_config_runner_->result());
state_ = STATE_RESULT_CACHED;
HistogramProbe(cached_result_, tick_clock_->NowTicks() - probe_start_time_);
@@ -269,6 +296,45 @@ void DnsProbeServiceImpl::OnProbeComplete() {
CallCallbacks();
}
+error_page::DnsProbeStatus DnsProbeServiceImpl::EvaluateResults(
+ DnsProbeRunner::Result current_config_result,
+ DnsProbeRunner::Result google_config_result) {
+ // If the current DNS config is working, assume the domain doesn't exist.
+ if (current_config_result == DnsProbeRunner::CORRECT)
+ return error_page::DNS_PROBE_FINISHED_NXDOMAIN;
+
+ // If the current DNS config is unknown (e.g. on Android), but Google DNS is
+ // reachable, assume the domain doesn't exist.
+ if (current_config_result == DnsProbeRunner::UNKNOWN &&
+ google_config_result == DnsProbeRunner::CORRECT) {
+ return error_page::DNS_PROBE_FINISHED_NXDOMAIN;
+ }
+
+ // If the current DNS config is not working but Google DNS is, assume the DNS
+ // config is bad (or perhaps the DNS servers are down or broken). If the
+ // current DNS config is in secure mode, return an error indicating that this
+ // is a secure DNS config issue.
+ if (google_config_result == DnsProbeRunner::CORRECT) {
+ return (current_config_secure_dns_mode_ ==
+ net::DnsConfig::SecureDnsMode::SECURE)
+ ? error_page::DNS_PROBE_FINISHED_BAD_SECURE_CONFIG
+ : error_page::DNS_PROBE_FINISHED_BAD_CONFIG;
+ }
+
+ // If the current DNS config is not working and Google DNS is unreachable,
+ // assume the internet connection is down (note that current DNS may be a
+ // router on the LAN, so it may be reachable but returning errors.)
+ if (google_config_result == DnsProbeRunner::UNREACHABLE)
+ return error_page::DNS_PROBE_FINISHED_NO_INTERNET;
+
+ // Otherwise: the current DNS config is not working and Google DNS is
+ // responding but with errors or incorrect results. This is an awkward case;
+ // an invasive captive portal or a restrictive firewall may be intercepting
+ // or rewriting DNS traffic, or the public server may itself be failing or
+ // down.
+ return error_page::DNS_PROBE_FINISHED_INCONCLUSIVE;
+}
+
void DnsProbeServiceImpl::CallCallbacks() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(STATE_RESULT_CACHED, state_);
diff --git a/chromium/chrome/browser/net/dns_probe_service_factory.h b/chromium/chrome/browser/net/dns_probe_service_factory.h
index aa08409541c..f884fce94bb 100644
--- a/chromium/chrome/browser/net/dns_probe_service_factory.h
+++ b/chromium/chrome/browser/net/dns_probe_service_factory.h
@@ -12,7 +12,7 @@
#include "base/time/tick_clock.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
#include "mojo/public/cpp/bindings/remote.h"
-#include "services/network/public/mojom/host_resolver.mojom.h"
+#include "services/network/public/mojom/host_resolver.mojom-forward.h"
class KeyedService;
diff --git a/chromium/chrome/browser/net/dns_probe_service_factory_unittest.cc b/chromium/chrome/browser/net/dns_probe_service_factory_unittest.cc
index 299f2d475a2..33435a86be6 100644
--- a/chromium/chrome/browser/net/dns_probe_service_factory_unittest.cc
+++ b/chromium/chrome/browser/net/dns_probe_service_factory_unittest.cc
@@ -13,10 +13,18 @@
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/test/simple_test_tick_clock.h"
+#include "build/build_config.h"
#include "chrome/browser/net/dns_probe_runner.h"
#include "chrome/browser/net/dns_probe_service.h"
#include "chrome/browser/net/dns_probe_test_util.h"
+#include "chrome/browser/net/dns_util.h"
+#include "chrome/browser/net/stub_resolver_config_reader.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
+#include "chrome/test/base/testing_browser_process.h"
#include "components/error_page/common/net_error_info.h"
+#include "components/prefs/pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -32,7 +40,18 @@ namespace {
class DnsProbeServiceTest : public testing::Test {
public:
DnsProbeServiceTest()
- : callback_called_(false), callback_result_(error_page::DNS_PROBE_MAX) {}
+ : callback_called_(false), callback_result_(error_page::DNS_PROBE_MAX) {
+ local_state_ = std::make_unique<ScopedTestingLocalState>(
+ TestingBrowserProcess::GetGlobal());
+
+ // SystemNetworkContextManager cannot be instantiated here, which normally
+ // owns the StubResolverConfigReader instance, so inject a
+ // StubResolverConfigReader instance here.
+ stub_resolver_config_reader_ =
+ std::make_unique<StubResolverConfigReader>(local_state_->Get());
+ SystemNetworkContextManager::set_stub_resolver_config_reader_for_testing(
+ stub_resolver_config_reader_.get());
+ }
void Probe() {
service_->ProbeDns(base::BindOnce(&DnsProbeServiceTest::ProbeCallback,
@@ -56,12 +75,12 @@ class DnsProbeServiceTest : public testing::Test {
}
void ConfigureTest(
- std::vector<FakeHostResolver::SingleResult> system_results,
- std::vector<FakeHostResolver::SingleResult> public_results) {
+ std::vector<FakeHostResolver::SingleResult> current_config_results,
+ std::vector<FakeHostResolver::SingleResult> google_config_results) {
ASSERT_FALSE(network_context_);
network_context_ = std::make_unique<FakeHostResolverNetworkContext>(
- std::move(system_results), std::move(public_results));
+ std::move(current_config_results), std::move(google_config_results));
service_ = DnsProbeServiceFactory::CreateForTesting(
base::BindRepeating(&DnsProbeServiceTest::GetNetworkContext,
@@ -93,6 +112,13 @@ class DnsProbeServiceTest : public testing::Test {
return !!dns_config_change_manager_;
}
+ DnsProbeService* probe_service() const { return service_.get(); }
+
+ TestingPrefServiceSimple* local_state() { return local_state_->Get(); }
+
+ const std::string kDohTemplateGet = "https://bar.test/dns-query{?dns}";
+ const std::string kDohTemplatePost = "https://bar.test/dns-query";
+
private:
void ProbeCallback(DnsProbeStatus result) {
EXPECT_FALSE(callback_called_);
@@ -105,6 +131,8 @@ class DnsProbeServiceTest : public testing::Test {
std::unique_ptr<FakeHostResolverNetworkContext> network_context_;
std::unique_ptr<FakeDnsConfigChangeManager> dns_config_change_manager_;
std::unique_ptr<DnsProbeService> service_;
+ std::unique_ptr<ScopedTestingLocalState> local_state_;
+ std::unique_ptr<StubResolverConfigReader> stub_resolver_config_reader_;
bool callback_called_;
DnsProbeStatus callback_result_;
};
@@ -154,6 +182,37 @@ TEST_F(DnsProbeServiceTest, Probe_FAIL_OK) {
RunTest(error_page::DNS_PROBE_FINISHED_BAD_CONFIG);
}
+TEST_F(DnsProbeServiceTest, Probe_FAIL_OK_automatic) {
+ // Set the DoH prefs using the managed pref store to prevent the mode from
+ // being downgraded to off if the test environment is managed.
+ local_state()->SetManagedPref(
+ prefs::kDnsOverHttpsMode,
+ std::make_unique<base::Value>(
+ chrome_browser_net::kDnsOverHttpsModeAutomatic));
+ ConfigureTest({{net::ERR_NAME_NOT_RESOLVED,
+ net::ResolveErrorInfo(net::ERR_NAME_NOT_RESOLVED),
+ FakeHostResolver::kNoResponse}},
+ {{net::OK, net::ResolveErrorInfo(net::OK),
+ FakeHostResolver::kOneAddressResponse}});
+ RunTest(error_page::DNS_PROBE_FINISHED_BAD_CONFIG);
+}
+
+TEST_F(DnsProbeServiceTest, Probe_FAIL_OK_secure) {
+ // Set the DoH prefs using the managed pref store to prevent the mode from
+ // being downgraded to off if the test environment is managed.
+ local_state()->SetManagedPref(
+ prefs::kDnsOverHttpsMode,
+ std::make_unique<base::Value>(
+ chrome_browser_net::kDnsOverHttpsModeSecure));
+ ConfigureTest({{net::ERR_NAME_NOT_RESOLVED,
+ net::ResolveErrorInfo(
+ net::ERR_DNS_SECURE_RESOLVER_HOSTNAME_RESOLUTION_FAILED),
+ FakeHostResolver::kNoResponse}},
+ {{net::OK, net::ResolveErrorInfo(net::OK),
+ FakeHostResolver::kOneAddressResponse}});
+ RunTest(error_page::DNS_PROBE_FINISHED_BAD_SECURE_CONFIG);
+}
+
TEST_F(DnsProbeServiceTest, Probe_FAIL_FAIL) {
ConfigureTest({{net::ERR_NAME_NOT_RESOLVED,
net::ResolveErrorInfo(net::ERR_NAME_NOT_RESOLVED),
@@ -241,6 +300,67 @@ TEST_F(DnsProbeServiceTest, MojoConnectionError) {
RunTest(error_page::DNS_PROBE_FINISHED_NO_INTERNET);
}
+TEST_F(DnsProbeServiceTest, CurrentConfig_Automatic) {
+ // Set the DoH prefs using the managed pref store to prevent the mode from
+ // being downgraded to off if the test environment is managed.
+ local_state()->SetManagedPref(
+ prefs::kDnsOverHttpsMode,
+ std::make_unique<base::Value>(
+ chrome_browser_net::kDnsOverHttpsModeAutomatic));
+ local_state()->SetManagedPref(
+ prefs::kDnsOverHttpsTemplates,
+ std::make_unique<base::Value>(kDohTemplateGet + " " + kDohTemplatePost));
+ ConfigureTest({}, {});
+ net::DnsConfigOverrides overrides =
+ probe_service()->GetCurrentConfigOverridesForTesting();
+
+ EXPECT_TRUE(overrides.search.has_value());
+ EXPECT_EQ(0u, overrides.search->size());
+ EXPECT_TRUE(overrides.attempts.has_value());
+ EXPECT_EQ(1, overrides.attempts.value());
+ EXPECT_TRUE(overrides.randomize_ports.has_value());
+ EXPECT_FALSE(overrides.randomize_ports.value());
+
+ EXPECT_TRUE(overrides.secure_dns_mode.has_value());
+ EXPECT_EQ(net::DnsConfig::SecureDnsMode::OFF,
+ overrides.secure_dns_mode.value());
+ EXPECT_FALSE(overrides.dns_over_https_servers.has_value());
+}
+
+TEST_F(DnsProbeServiceTest, CurrentConfig_Secure) {
+ // Set the DoH prefs using the managed pref store to prevent the mode from
+ // being downgraded to off if the test environment is managed.
+ local_state()->SetManagedPref(
+ prefs::kDnsOverHttpsMode,
+ std::make_unique<base::Value>(
+ chrome_browser_net::kDnsOverHttpsModeSecure));
+ local_state()->SetManagedPref(
+ prefs::kDnsOverHttpsTemplates,
+ std::make_unique<base::Value>(kDohTemplateGet + " " + kDohTemplatePost));
+ ConfigureTest({}, {});
+ net::DnsConfigOverrides overrides =
+ probe_service()->GetCurrentConfigOverridesForTesting();
+
+ EXPECT_TRUE(overrides.search.has_value());
+ EXPECT_EQ(0u, overrides.search->size());
+ EXPECT_TRUE(overrides.attempts.has_value());
+ EXPECT_EQ(1, overrides.attempts.value());
+ EXPECT_TRUE(overrides.randomize_ports.has_value());
+ EXPECT_FALSE(overrides.randomize_ports.value());
+
+ EXPECT_TRUE(overrides.secure_dns_mode.has_value());
+ EXPECT_EQ(net::DnsConfig::SecureDnsMode::SECURE,
+ overrides.secure_dns_mode.value());
+ EXPECT_TRUE(overrides.dns_over_https_servers.has_value());
+ ASSERT_EQ(2u, overrides.dns_over_https_servers->size());
+ EXPECT_EQ(kDohTemplateGet,
+ overrides.dns_over_https_servers->at(0).server_template);
+ EXPECT_FALSE(overrides.dns_over_https_servers->at(0).use_post);
+ EXPECT_EQ(kDohTemplatePost,
+ overrides.dns_over_https_servers->at(1).server_template);
+ EXPECT_TRUE(overrides.dns_over_https_servers->at(1).use_post);
+}
+
} // namespace
} // namespace chrome_browser_net
diff --git a/chromium/chrome/browser/net/dns_probe_test_util.cc b/chromium/chrome/browser/net/dns_probe_test_util.cc
index 9cc03633e15..97ebe252b4b 100644
--- a/chromium/chrome/browser/net/dns_probe_test_util.cc
+++ b/chromium/chrome/browser/net/dns_probe_test_util.cc
@@ -115,10 +115,10 @@ void HangingHostResolver::MdnsListen(
}
FakeHostResolverNetworkContext::FakeHostResolverNetworkContext(
- std::vector<FakeHostResolver::SingleResult> system_result_list,
- std::vector<FakeHostResolver::SingleResult> public_result_list)
- : system_result_list_(std::move(system_result_list)),
- public_result_list_(std::move(public_result_list)) {}
+ std::vector<FakeHostResolver::SingleResult> current_config_result_list,
+ std::vector<FakeHostResolver::SingleResult> google_config_result_list)
+ : current_config_result_list_(std::move(current_config_result_list)),
+ google_config_result_list_(std::move(google_config_result_list)) {}
FakeHostResolverNetworkContext::~FakeHostResolverNetworkContext() = default;
@@ -127,14 +127,14 @@ void FakeHostResolverNetworkContext::CreateHostResolver(
mojo::PendingReceiver<network::mojom::HostResolver> receiver) {
ASSERT_TRUE(config_overrides);
if (!config_overrides->nameservers) {
- if (!system_resolver_) {
- system_resolver_ = std::make_unique<FakeHostResolver>(
- std::move(receiver), system_result_list_);
+ if (!current_config_resolver_) {
+ current_config_resolver_ = std::make_unique<FakeHostResolver>(
+ std::move(receiver), current_config_result_list_);
}
} else {
- if (!public_resolver_) {
- public_resolver_ = std::make_unique<FakeHostResolver>(
- std::move(receiver), public_result_list_);
+ if (!google_config_resolver_) {
+ google_config_resolver_ = std::make_unique<FakeHostResolver>(
+ std::move(receiver), google_config_result_list_);
}
}
}
diff --git a/chromium/chrome/browser/net/dns_probe_test_util.h b/chromium/chrome/browser/net/dns_probe_test_util.h
index 1a942075774..eb17bd6bb4e 100644
--- a/chromium/chrome/browser/net/dns_probe_test_util.h
+++ b/chromium/chrome/browser/net/dns_probe_test_util.h
@@ -13,7 +13,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/dns/public/resolve_error_info.h"
-#include "services/network/public/mojom/host_resolver.mojom.h"
+#include "services/network/public/mojom/host_resolver.mojom-forward.h"
#include "services/network/test/test_network_context.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -93,8 +93,8 @@ class HangingHostResolver : public network::mojom::HostResolver {
class FakeHostResolverNetworkContext : public network::TestNetworkContext {
public:
FakeHostResolverNetworkContext(
- std::vector<FakeHostResolver::SingleResult> system_result_list,
- std::vector<FakeHostResolver::SingleResult> public_result_list);
+ std::vector<FakeHostResolver::SingleResult> current_config_result_list,
+ std::vector<FakeHostResolver::SingleResult> google_config_result_list);
~FakeHostResolverNetworkContext() override;
void CreateHostResolver(
@@ -102,10 +102,10 @@ class FakeHostResolverNetworkContext : public network::TestNetworkContext {
mojo::PendingReceiver<network::mojom::HostResolver> receiver) override;
private:
- std::vector<FakeHostResolver::SingleResult> system_result_list_;
- std::vector<FakeHostResolver::SingleResult> public_result_list_;
- std::unique_ptr<FakeHostResolver> system_resolver_;
- std::unique_ptr<FakeHostResolver> public_resolver_;
+ std::vector<FakeHostResolver::SingleResult> current_config_result_list_;
+ std::vector<FakeHostResolver::SingleResult> google_config_result_list_;
+ std::unique_ptr<FakeHostResolver> current_config_resolver_;
+ std::unique_ptr<FakeHostResolver> google_config_resolver_;
};
class FakeDnsConfigChangeManager
diff --git a/chromium/chrome/browser/net/dns_util.cc b/chromium/chrome/browser/net/dns_util.cc
index 42261d69b1b..d03c1e00a9a 100644
--- a/chromium/chrome/browser/net/dns_util.cc
+++ b/chromium/chrome/browser/net/dns_util.cc
@@ -4,56 +4,80 @@
#include "chrome/browser/net/dns_util.h"
-#include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+#include <algorithm>
+#include <string>
+
+#include "base/feature_list.h"
+#include "base/strings/string_split.h"
+#include "chrome/common/chrome_features.h"
+#include "components/embedder_support/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "net/dns/public/util.h"
#include "net/third_party/uri_template/uri_template.h"
#include "url/gurl.h"
-#if defined(OS_WIN)
-#include "base/enterprise_util.h"
-#endif
-
namespace chrome_browser_net {
-bool IsValidDohTemplate(const std::string& server_template,
- std::string* server_method) {
- std::string url_string;
- std::string test_query = "this_is_a_test_query";
- std::unordered_map<std::string, std::string> template_params(
- {{"dns", test_query}});
- std::set<std::string> vars_found;
- bool valid_template = uri_template::Expand(server_template, template_params,
- &url_string, &vars_found);
- if (!valid_template) {
- // The URI template is malformed.
- return false;
- }
- GURL url(url_string);
- if (!url.is_valid() || !url.SchemeIs("https")) {
- // The expanded template must be a valid HTTPS URL.
- return false;
+namespace {
+
+const char kAlternateErrorPagesBackup[] = "alternate_error_pages.backup";
+
+} // namespace
+
+void RegisterDNSProbesSettingBackupPref(PrefRegistrySimple* registry) {
+ registry->RegisterBooleanPref(kAlternateErrorPagesBackup, true);
+}
+
+void MigrateDNSProbesSettingToOrFromBackup(PrefService* prefs) {
+ // If the privacy settings redesign is enabled and the user value of the
+ // preference hasn't been backed up yet, back it up, and clear it. That way,
+ // the preference will revert to using the hardcoded default value (unless
+ // it's managed by a policy or an extension). This is necessary, as the
+ // privacy settings redesign removed the user-facing toggle, and so the
+ // user value of the preference is no longer modifiable.
+ if (base::FeatureList::IsEnabled(features::kPrivacySettingsRedesign) &&
+ !prefs->HasPrefPath(kAlternateErrorPagesBackup)) {
+ // If the user never changed the value of the preference and still uses the
+ // hardcoded default value, we'll consider it to be the user value for
+ // the purposes of this migration.
+ const base::Value* user_value =
+ prefs->FindPreference(embedder_support::kAlternateErrorPagesEnabled)
+ ->HasUserSetting()
+ ? prefs->GetUserPrefValue(
+ embedder_support::kAlternateErrorPagesEnabled)
+ : prefs->GetDefaultPrefValue(
+ embedder_support::kAlternateErrorPagesEnabled);
+
+ DCHECK(user_value->is_bool());
+ prefs->SetBoolean(kAlternateErrorPagesBackup, user_value->GetBool());
+ prefs->ClearPref(embedder_support::kAlternateErrorPagesEnabled);
}
- if (url.host().find(test_query) != std::string::npos) {
- // The dns variable may not be part of the hostname.
- return false;
+
+ // If the privacy settings redesign is rolled back and there is a backed up
+ // value of the preference, restore it to the original preference, and clear
+ // the backup.
+ if (!base::FeatureList::IsEnabled(features::kPrivacySettingsRedesign) &&
+ prefs->HasPrefPath(kAlternateErrorPagesBackup)) {
+ prefs->SetBoolean(embedder_support::kAlternateErrorPagesEnabled,
+ prefs->GetBoolean(kAlternateErrorPagesBackup));
+ prefs->ClearPref(kAlternateErrorPagesBackup);
}
- // If the template contains a dns variable, use GET, otherwise use POST.
- DCHECK(server_method);
- *server_method =
- (vars_found.find("dns") == vars_found.end()) ? "POST" : "GET";
- return true;
}
-bool ShouldDisableDohForManaged() {
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
- if (g_browser_process->browser_policy_connector()->HasMachineLevelPolicies())
- return true;
-#endif
-#if defined(OS_WIN)
- if (base::IsMachineExternallyManaged())
- return true;
-#endif
- return false;
+std::vector<base::StringPiece> SplitDohTemplateGroup(base::StringPiece group) {
+ // Templates in a group are whitespace-separated.
+ return SplitStringPiece(group, " ", base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY);
}
+
+bool IsValidDohTemplateGroup(base::StringPiece group) {
+ // All templates must be valid for the group to be considered valid.
+ std::vector<base::StringPiece> templates = SplitDohTemplateGroup(group);
+ return std::all_of(templates.begin(), templates.end(), [](auto t) {
+ std::string method;
+ return net::dns_util::IsValidDohTemplate(t, &method);
+ });
+}
+
} // namespace chrome_browser_net
diff --git a/chromium/chrome/browser/net/dns_util.h b/chromium/chrome/browser/net/dns_util.h
index 7935013d0f4..89b155d7310 100644
--- a/chromium/chrome/browser/net/dns_util.h
+++ b/chromium/chrome/browser/net/dns_util.h
@@ -5,28 +5,50 @@
#ifndef CHROME_BROWSER_NET_DNS_UTIL_H_
#define CHROME_BROWSER_NET_DNS_UTIL_H_
-#include <string>
+#include <vector>
+
+#include "base/strings/string_piece.h"
+
+class PrefRegistrySimple;
+class PrefService;
namespace chrome_browser_net {
-// Returns true if the URI template is acceptable for sending requests. If so,
-// the |server_method| is set to "GET" if the template contains a "dns" variable
-// and to "POST" otherwise. Any "dns" variable may not be part of the hostname,
-// and the expanded template must parse to a valid HTTPS URL.
-bool IsValidDohTemplate(const std::string& server_template,
- std::string* server_method);
+// Implements the whitespace-delimited group syntax for DoH templates.
+std::vector<base::StringPiece> SplitDohTemplateGroup(base::StringPiece group);
-// Returns true if there are any active machine level policies or if the machine
-// is domain joined. This special logic is used to disable DoH by default for
-// Desktop platforms (the enterprise policy field default_for_enterprise_users
-// only applies to ChromeOS). We don't attempt enterprise detection on Android
-// at this time.
-bool ShouldDisableDohForManaged();
+// Returns true if a group of templates are all valid per
+// net::dns_util::IsValidDohTemplate(). This should be checked before updating
+// stored preferences.
+bool IsValidDohTemplateGroup(base::StringPiece group);
const char kDnsOverHttpsModeOff[] = "off";
const char kDnsOverHttpsModeAutomatic[] = "automatic";
const char kDnsOverHttpsModeSecure[] = "secure";
+// Forced management description types. We will check for the override cases in
+// the order they are listed in the enum.
+enum class SecureDnsUiManagementMode {
+ // Chrome did not override the secure DNS settings.
+ kNoOverride,
+ // Secure DNS was disabled due to detection of a managed environment.
+ kDisabledManaged,
+ // Secure DNS was disabled due to detection of OS-level parental controls.
+ kDisabledParentalControls,
+};
+
+// Registers the backup preference required for the DNS probes setting reset.
+// TODO(crbug.com/1062698): Remove this once the privacy settings redesign
+// is fully launched.
+void RegisterDNSProbesSettingBackupPref(PrefRegistrySimple* registry);
+
+// Backs up the unneeded preference controlling DNS and captive portal probes
+// once the privacy settings redesign is enabled, or restores the backup
+// in case the feature is rolled back.
+// TODO(crbug.com/1062698): Remove this once the privacy settings redesign
+// is fully launched.
+void MigrateDNSProbesSettingToOrFromBackup(PrefService* prefs);
+
} // namespace chrome_browser_net
#endif // CHROME_BROWSER_NET_DNS_UTIL_H_
diff --git a/chromium/chrome/browser/net/dns_util_unittest.cc b/chromium/chrome/browser/net/dns_util_unittest.cc
index ee112b15f03..578ca7a3d9b 100644
--- a/chromium/chrome/browser/net/dns_util_unittest.cc
+++ b/chromium/chrome/browser/net/dns_util_unittest.cc
@@ -1,49 +1,168 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/net/dns_util.h"
+#include <memory>
+
+#include "base/test/scoped_feature_list.h"
+#include "chrome/common/chrome_features.h"
+#include "components/embedder_support/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/testing_pref_service.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gtest/include/gtest/gtest.h"
-TEST(NetDnsUtilTest, IsValidDohTemplate) {
- std::string server_method;
- EXPECT_TRUE(chrome_browser_net::IsValidDohTemplate(
- "https://dnsserver.example.net/dns-query{?dns}", &server_method));
- EXPECT_EQ("GET", server_method);
-
- EXPECT_TRUE(chrome_browser_net::IsValidDohTemplate(
- "https://dnsserver.example.net/dns-query{?dns,extra}", &server_method));
- EXPECT_EQ("GET", server_method);
-
- EXPECT_TRUE(chrome_browser_net::IsValidDohTemplate(
- "https://dnsserver.example.net/dns-query{?query}", &server_method));
- EXPECT_EQ("POST", server_method);
-
- EXPECT_TRUE(chrome_browser_net::IsValidDohTemplate(
- "https://dnsserver.example.net/dns-query", &server_method));
- EXPECT_EQ("POST", server_method);
-
- EXPECT_TRUE(chrome_browser_net::IsValidDohTemplate(
- "https://query:{dns}@dnsserver.example.net", &server_method));
- EXPECT_EQ("GET", server_method);
-
- EXPECT_TRUE(chrome_browser_net::IsValidDohTemplate(
- "https://dnsserver.example.net{/dns}", &server_method));
- EXPECT_EQ("GET", server_method);
-
- // Invalid template format
- EXPECT_FALSE(chrome_browser_net::IsValidDohTemplate(
- "https://dnsserver.example.net/dns-query{{?dns}}", &server_method));
- // Must be HTTPS
- EXPECT_FALSE(chrome_browser_net::IsValidDohTemplate(
- "http://dnsserver.example.net/dns-query", &server_method));
- EXPECT_FALSE(chrome_browser_net::IsValidDohTemplate(
- "http://dnsserver.example.net/dns-query{?dns}", &server_method));
- // Template must expand to a valid URL
- EXPECT_FALSE(
- chrome_browser_net::IsValidDohTemplate("https://{?dns}", &server_method));
- // The hostname must not contain the dns variable
- EXPECT_FALSE(chrome_browser_net::IsValidDohTemplate(
- "https://{dns}.dnsserver.net", &server_method));
+using testing::ElementsAre;
+
+namespace chrome_browser_net {
+
+namespace {
+
+const char kAlternateErrorPagesBackup[] = "alternate_error_pages.backup";
+
+} // namespace
+
+class DNSUtilTest : public testing::Test {
+ public:
+ void SetUp() override { DisableRedesign(); }
+
+ void EnableRedesign() {
+ scoped_feature_list_.Reset();
+ scoped_feature_list_.InitAndEnableFeatureWithParameters(
+ features::kPrivacySettingsRedesign, base::FieldTrialParams());
+ }
+
+ void DisableRedesign() { scoped_feature_list_.Reset(); }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(DNSUtilTest, MigrateDNSProbesPref) {
+ TestingPrefServiceSimple prefs;
+ prefs.registry()->RegisterBooleanPref(
+ embedder_support::kAlternateErrorPagesEnabled, true);
+ prefs.registry()->RegisterBooleanPref(kAlternateErrorPagesBackup, true);
+
+ const PrefService::Preference* current_pref =
+ prefs.FindPreference(embedder_support::kAlternateErrorPagesEnabled);
+ const PrefService::Preference* backup_pref =
+ prefs.FindPreference(kAlternateErrorPagesBackup);
+
+ // No migration happens if the privacy settings redesign is not enabled.
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_FALSE(backup_pref->HasUserSetting());
+
+ // The hardcoded default value of TRUE gets correctly migrated.
+ EnableRedesign();
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_FALSE(current_pref->HasUserSetting());
+ EXPECT_TRUE(backup_pref->HasUserSetting());
+ EXPECT_TRUE(prefs.GetBoolean(kAlternateErrorPagesBackup));
+
+ // And correctly restored.
+ DisableRedesign();
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_TRUE(current_pref->HasUserSetting());
+ EXPECT_TRUE(prefs.GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
+ EXPECT_FALSE(backup_pref->HasUserSetting());
+
+ // An explicit user value of TRUE will be correctly migrated.
+ EnableRedesign();
+ prefs.SetBoolean(embedder_support::kAlternateErrorPagesEnabled, true);
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_FALSE(current_pref->HasUserSetting());
+ EXPECT_TRUE(backup_pref->HasUserSetting());
+ EXPECT_TRUE(prefs.GetBoolean(kAlternateErrorPagesBackup));
+
+ // And correctly restored.
+ DisableRedesign();
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_TRUE(current_pref->HasUserSetting());
+ EXPECT_TRUE(prefs.GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
+ EXPECT_FALSE(backup_pref->HasUserSetting());
+
+ // An explicit user value of FALSE will also be correctly migrated.
+ EnableRedesign();
+ prefs.SetBoolean(embedder_support::kAlternateErrorPagesEnabled, false);
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_FALSE(current_pref->HasUserSetting());
+ EXPECT_TRUE(backup_pref->HasUserSetting());
+ EXPECT_FALSE(prefs.GetBoolean(kAlternateErrorPagesBackup));
+
+ // And correctly restored.
+ DisableRedesign();
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_TRUE(current_pref->HasUserSetting());
+ EXPECT_FALSE(prefs.GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
+ EXPECT_FALSE(backup_pref->HasUserSetting());
+
+ // A policy-sourced value of TRUE takes precedence over the user-sourced value
+ // of FALSE when the preference is evaluated. However, it will still be the
+ // user-sourced value of FALSE that will be migrated.
+ prefs.SetManagedPref(embedder_support::kAlternateErrorPagesEnabled,
+ std::make_unique<base::Value>(true));
+ EnableRedesign();
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_FALSE(current_pref->HasUserSetting());
+ EXPECT_TRUE(backup_pref->HasUserSetting());
+ EXPECT_FALSE(prefs.GetBoolean(kAlternateErrorPagesBackup));
+
+ // And correctly restored.
+ DisableRedesign();
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_TRUE(current_pref->HasUserSetting());
+ {
+ const base::Value* user_pref =
+ prefs.GetUserPref(embedder_support::kAlternateErrorPagesEnabled);
+ ASSERT_TRUE(user_pref->is_bool());
+ EXPECT_FALSE(user_pref->GetBool());
+ }
+ EXPECT_FALSE(backup_pref->HasUserSetting());
+
+ // After clearing the user-sourced value, the hardcoded value of TRUE should
+ // be the value which is migrated, even if it is overridden by
+ // a policy-sourced value of FALSE.
+ prefs.ClearPref(embedder_support::kAlternateErrorPagesEnabled);
+ prefs.SetManagedPref(embedder_support::kAlternateErrorPagesEnabled,
+ std::make_unique<base::Value>(false));
+ EnableRedesign();
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_FALSE(current_pref->HasUserSetting());
+ EXPECT_TRUE(backup_pref->HasUserSetting());
+ EXPECT_TRUE(prefs.GetBoolean(kAlternateErrorPagesBackup));
+
+ // And correctly restored.
+ DisableRedesign();
+ MigrateDNSProbesSettingToOrFromBackup(&prefs);
+ EXPECT_TRUE(current_pref->HasUserSetting());
+ {
+ const base::Value* user_pref =
+ prefs.GetUserPref(embedder_support::kAlternateErrorPagesEnabled);
+ ASSERT_TRUE(user_pref->is_bool());
+ EXPECT_TRUE(user_pref->GetBool());
+ }
+ EXPECT_FALSE(backup_pref->HasUserSetting());
+}
+
+TEST(DNSUtil, SplitDohTemplateGroup) {
+ EXPECT_THAT(SplitDohTemplateGroup("a"), ElementsAre("a"));
+ EXPECT_THAT(SplitDohTemplateGroup("a b"), ElementsAre("a", "b"));
+ EXPECT_THAT(SplitDohTemplateGroup("a \tb\nc"), ElementsAre("a", "b\nc"));
+ EXPECT_THAT(SplitDohTemplateGroup(" \ta b\n"), ElementsAre("a", "b"));
}
+
+TEST(DNSUtil, IsValidDohTemplateGroup) {
+ EXPECT_TRUE(IsValidDohTemplateGroup(""));
+ EXPECT_TRUE(IsValidDohTemplateGroup("https://valid"));
+ EXPECT_TRUE(IsValidDohTemplateGroup("https://valid https://valid2"));
+
+ EXPECT_FALSE(IsValidDohTemplateGroup("https://valid invalid"));
+ EXPECT_FALSE(IsValidDohTemplateGroup("invalid https://valid"));
+ EXPECT_FALSE(IsValidDohTemplateGroup("invalid"));
+ EXPECT_FALSE(IsValidDohTemplateGroup("invalid invalid2"));
+}
+
+} // namespace chrome_browser_net
diff --git a/chromium/chrome/browser/net/file_downloader.cc b/chromium/chrome/browser/net/file_downloader.cc
index 93edaf36fa1..9aa8484b578 100644
--- a/chromium/chrome/browser/net/file_downloader.cc
+++ b/chromium/chrome/browser/net/file_downloader.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
#include "base/task_runner_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
@@ -48,14 +49,13 @@ FileDownloader::FileDownloader(
base::Unretained(this)));
} else {
base::PostTaskAndReplyWithResult(
- base::CreateTaskRunner(
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::BEST_EFFORT,
+ base::ThreadPool::CreateTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})
.get(),
- FROM_HERE, base::Bind(&base::PathExists, local_path_),
- base::Bind(&FileDownloader::OnFileExistsCheckDone,
- weak_ptr_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&base::PathExists, local_path_),
+ base::BindOnce(&FileDownloader::OnFileExistsCheckDone,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
@@ -76,13 +76,13 @@ void FileDownloader::OnSimpleDownloadComplete(base::FilePath response_path) {
}
base::PostTaskAndReplyWithResult(
- base::CreateTaskRunner({base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})
+ base::ThreadPool::CreateTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN})
.get(),
- FROM_HERE, base::Bind(&base::Move, response_path, local_path_),
- base::Bind(&FileDownloader::OnFileMoveDone,
- weak_ptr_factory_.GetWeakPtr()));
+ FROM_HERE, base::BindOnce(&base::Move, response_path, local_path_),
+ base::BindOnce(&FileDownloader::OnFileMoveDone,
+ weak_ptr_factory_.GetWeakPtr()));
}
void FileDownloader::OnFileExistsCheckDone(bool exists) {
diff --git a/chromium/chrome/browser/net/ftp_browsertest.cc b/chromium/chrome/browser/net/ftp_browsertest.cc
index 1156e761a14..bf0e9fe3d0a 100644
--- a/chromium/chrome/browser/net/ftp_browsertest.cc
+++ b/chromium/chrome/browser/net/ftp_browsertest.cc
@@ -12,6 +12,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/external_protocol/external_protocol_handler.h"
#include "chrome/browser/profiles/profile.h"
@@ -78,8 +79,8 @@ class FakeDefaultProtocolClientWorker
}
void SetAsDefaultImpl(const base::Closure& on_finished_callback) override {
- base::GetContinuationTaskRunner()->PostTask(FROM_HERE,
- on_finished_callback);
+ base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ on_finished_callback);
}
DISALLOW_COPY_AND_ASSIGN(FakeDefaultProtocolClientWorker);
diff --git a/chromium/chrome/browser/net/load_timing_browsertest.cc b/chromium/chrome/browser/net/load_timing_browsertest.cc
index 08133863ccd..49b076abdbb 100644
--- a/chromium/chrome/browser/net/load_timing_browsertest.cc
+++ b/chromium/chrome/browser/net/load_timing_browsertest.cc
@@ -12,6 +12,7 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/net/profile_network_context_service.h"
@@ -25,6 +26,7 @@
#include "components/proxy_config/proxy_config_dictionary.h"
#include "components/proxy_config/proxy_config_pref_names.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_features.h"
#include "content/public/test/browser_test_utils.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "url/gurl.h"
@@ -52,10 +54,8 @@ struct TimingDeltas {
class LoadTimingBrowserTest : public InProcessBrowserTest {
public:
- LoadTimingBrowserTest() {
- }
-
- ~LoadTimingBrowserTest() override {}
+ LoadTimingBrowserTest() = default;
+ ~LoadTimingBrowserTest() override = default;
// Reads applicable times from performance.timing and writes them to
// |navigation_deltas|. Proxy times and send end cannot be read from the
@@ -183,7 +183,21 @@ IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, MAYBE_Proxy) {
EXPECT_EQ(navigation_deltas.ssl_start, -1);
}
-IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTest, FTP) {
+// Test fixture for tests that depend on FTP support. Moved out to a separate
+// fixture since remaining functionality should be tested without FTP support.
+//
+// TODO(https://crbug.com/333943): Remove FTP specific tests and test fixtures.
+class LoadTimingBrowserTestWithFtp : public LoadTimingBrowserTest {
+ public:
+ LoadTimingBrowserTestWithFtp() {
+ scoped_feature_list_.InitAndEnableFeature(features::kFtpProtocol);
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(LoadTimingBrowserTestWithFtp, FTP) {
net::SpawnedTestServer ftp_server(net::SpawnedTestServer::TYPE_FTP,
base::FilePath());
ASSERT_TRUE(ftp_server.Start());
diff --git a/chromium/chrome/browser/net/net_error_tab_helper.cc b/chromium/chrome/browser/net/net_error_tab_helper.cc
index 534c6c83906..7f17b1aaa04 100644
--- a/chromium/chrome/browser/net/net_error_tab_helper.cc
+++ b/chromium/chrome/browser/net/net_error_tab_helper.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/render_messages.h"
+#include "components/embedder_support/pref_names.h"
#include "components/error_page/common/net_error_info.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
@@ -88,7 +89,7 @@ void NetErrorTabHelper::DidFinishNavigation(
if (!navigation_handle->IsInMainFrame())
return;
- if (net::IsDnsError(navigation_handle->GetNetErrorCode())) {
+ if (net::IsHostnameResolutionError(navigation_handle->GetNetErrorCode())) {
dns_error_active_ = true;
OnMainFrameDnsError();
}
@@ -214,7 +215,7 @@ void NetErrorTabHelper::OnSetIsShowingDownloadButtonInErrorPage(
// static
void NetErrorTabHelper::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* prefs) {
- // prefs::kAlternateErrorPagesEnabled is registered by
+ // embedder_support::kAlternateErrorPagesEnabled is registered by
// NavigationCorrectionTabObserver.
prefs->RegisterIntegerPref(prefs::kNetworkEasterEggHighScore, 0,
@@ -227,8 +228,7 @@ void NetErrorTabHelper::InitializePref(WebContents* contents) {
BrowserContext* browser_context = contents->GetBrowserContext();
Profile* profile = Profile::FromBrowserContext(browser_context);
resolve_errors_with_web_service_.Init(
- prefs::kAlternateErrorPagesEnabled,
- profile->GetPrefs());
+ embedder_support::kAlternateErrorPagesEnabled, profile->GetPrefs());
easter_egg_high_score_.Init(prefs::kNetworkEasterEggHighScore,
profile->GetPrefs());
}
diff --git a/chromium/chrome/browser/net/network_connection_tracker_browsertest.cc b/chromium/chrome/browser/net/network_connection_tracker_browsertest.cc
index f3576d87459..475f652dee0 100644
--- a/chromium/chrome/browser/net/network_connection_tracker_browsertest.cc
+++ b/chromium/chrome/browser/net/network_connection_tracker_browsertest.cc
@@ -111,12 +111,10 @@ class NetworkConnectionTrackerBrowserTest : public InProcessBrowserTest {
// Basic test to make sure NetworkConnectionTracker is set up.
IN_PROC_BROWSER_TEST_F(NetworkConnectionTrackerBrowserTest,
NetworkConnectionTracker) {
-#if defined(OS_CHROMEOS) || defined(OS_MACOSX)
// NetworkService on ChromeOS doesn't yet have a NetworkChangeManager
// implementation. OSX uses a separate binary for service processes and
// browser test fixture doesn't have NetworkServiceTest mojo code.
- return;
-#endif
+#if !defined(OS_CHROMEOS) && !defined(OS_MACOSX)
network::NetworkConnectionTracker* tracker =
content::GetNetworkConnectionTracker();
EXPECT_NE(nullptr, tracker);
@@ -141,6 +139,7 @@ IN_PROC_BROWSER_TEST_F(NetworkConnectionTrackerBrowserTest,
network_connection_observer.connection_type());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1u, network_connection_observer.num_notifications());
+#endif
}
// Simulates a network service crash, and ensures that network change manager
diff --git a/chromium/chrome/browser/net/network_context_configuration_browsertest.cc b/chromium/chrome/browser/net/network_context_configuration_browsertest.cc
index 957ea1c6b3d..a86aa822a9f 100644
--- a/chromium/chrome/browser/net/network_context_configuration_browsertest.cc
+++ b/chromium/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -14,6 +14,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/guid.h"
#include "base/location.h"
+#include "base/optional.h"
#include "base/path_service.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
@@ -21,6 +22,7 @@
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_restrictions.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
@@ -51,6 +53,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/network_service_util.h"
#include "content/public/common/url_constants.h"
@@ -58,6 +61,7 @@
#include "content/public/test/simple_url_loader_test_helper.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "net/base/address_list.h"
#include "net/base/filename_util.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
@@ -66,6 +70,7 @@
#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_util.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/dns/public/resolve_error_info.h"
#include "net/http/http_response_headers.h"
#include "net/reporting/reporting_policy.h"
#include "net/ssl/ssl_config.h"
@@ -82,13 +87,13 @@
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_connection_tracker.h"
-#include "services/network/public/cpp/resource_response.h"
-#include "services/network/public/cpp/resource_response_info.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "services/network/public/mojom/host_resolver.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/test/test_dns_util.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -105,6 +110,9 @@
namespace {
+constexpr char kHostname[] = "foo.test";
+constexpr char kAddress[] = "5.8.13.21";
+
const char kCacheRandomPath[] = "/cacherandom";
// Path using a ControllableHttpResponse that's part of the test fixture.
@@ -237,6 +245,8 @@ class NetworkContextConfigurationBrowserTest
// Used in a bunch of proxy tests. Should not resolve.
host_resolver()->AddSimulatedFailure("does.not.resolve.test");
+ host_resolver()->AddRule(kHostname, kAddress);
+
controllable_http_response_ =
std::make_unique<net::test_server::ControllableHttpResponse>(
embedded_test_server(), kControllablePath);
@@ -549,12 +559,13 @@ class NetworkContextConfigurationBrowserTest
if (cookie_type == CookieType::kThirdParty)
cookie_line += ";SameSite=None;Secure";
request->url = server->GetURL("/set-cookie?" + cookie_line);
+ url::Origin origin;
if (cookie_type == CookieType::kThirdParty)
- request->site_for_cookies = GURL("http://example.com");
+ origin = url::Origin::Create(GURL("http://example.com"));
else
- request->site_for_cookies = server->base_url();
+ origin = url::Origin::Create(server->base_url());
+ request->site_for_cookies = net::SiteForCookies::FromOrigin(origin);
- url::Origin origin = url::Origin::Create(request->site_for_cookies);
request->trusted_params = network::ResourceRequest::TrustedParams();
request->trusted_params->network_isolation_key =
net::NetworkIsolationKey(origin, origin);
@@ -788,8 +799,8 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
std::unique_ptr<network::ResourceRequest> request =
std::make_unique<network::ResourceRequest>();
request->url = https_server.GetURL("/echoheader?Cookie");
- request->site_for_cookies = GURL(chrome::kChromeUIPrintURL);
- url::Origin origin = url::Origin::Create(request->site_for_cookies);
+ url::Origin origin = url::Origin::Create(GURL(chrome::kChromeUIPrintURL));
+ request->site_for_cookies = net::SiteForCookies::FromOrigin(origin);
request->trusted_params = network::ResourceRequest::TrustedParams();
request->trusted_params->network_isolation_key =
net::NetworkIsolationKey(origin, origin);
@@ -1109,6 +1120,60 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, DiskCache) {
}
}
+// Make sure that NetworkContexts have separate DNS caches.
+IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
+ DnsCacheIsolation) {
+ net::NetworkIsolationKey network_isolation_key =
+ net::NetworkIsolationKey::CreateTransient();
+ net::HostPortPair host_port_pair(kHostname, 0);
+ network::mojom::ResolveHostParametersPtr params =
+ network::mojom::ResolveHostParameters::New();
+ // Use A queries, to avoid running into issues with the IPv6 probe, the
+ // results of which can change during runtime, and can affect the DNS cache
+ // key.
+ params->dns_query_type = net::DnsQueryType ::A;
+ // Resolve |host_port_pair|, which should succeed and put it in the
+ // NetworkContext's cache.
+ network::DnsLookupResult result =
+ network::BlockingDnsLookup(network_context(), host_port_pair,
+ std::move(params), network_isolation_key);
+ EXPECT_EQ(net::OK, result.error);
+ ASSERT_TRUE(result.resolved_addresses.has_value());
+ ASSERT_EQ(1u, result.resolved_addresses->size());
+ EXPECT_EQ(kAddress,
+ result.resolved_addresses.value()[0].ToStringWithoutPort());
+ // Make a cache-only request for the same hostname, for each other network
+ // context, and make sure no result is returned.
+ ForEachOtherContext(
+ base::BindLambdaForTesting([&](NetworkContextType network_context_type) {
+ params = network::mojom::ResolveHostParameters::New();
+ params->dns_query_type = net::DnsQueryType ::A;
+ // Cache only lookup.
+ params->cache_usage =
+ network::mojom::ResolveHostParameters::CacheUsage::STALE_ALLOWED;
+ params->source = net::HostResolverSource::LOCAL_ONLY;
+ network::DnsLookupResult result = network::BlockingDnsLookup(
+ GetNetworkContextForContextType(network_context_type),
+ host_port_pair, std::move(params), network_isolation_key);
+ EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, result.error);
+ }));
+ // Do a cache-only lookup using the original network context, which should
+ // return the same result it initially did.
+ params = network::mojom::ResolveHostParameters::New();
+ // Cache only lookup.
+ params->dns_query_type = net::DnsQueryType ::A;
+ params->source = net::HostResolverSource::LOCAL_ONLY;
+ params->cache_usage =
+ network::mojom::ResolveHostParameters::CacheUsage::STALE_ALLOWED;
+ result = network::BlockingDnsLookup(network_context(), host_port_pair,
+ std::move(params), network_isolation_key);
+ EXPECT_EQ(net::OK, result.error);
+ ASSERT_TRUE(result.resolved_addresses.has_value());
+ ASSERT_EQ(1u, result.resolved_addresses->size());
+ EXPECT_EQ(kAddress,
+ result.resolved_addresses.value()[0].ToStringWithoutPort());
+}
+
// Visits a URL with an HSTS header, and makes sure it is respected.
IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, PRE_Hsts) {
if (IsRestartStateWithInProcessNetworkService())
@@ -1777,11 +1842,15 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationDataPacBrowserTest, DataPac) {
// results in an error, since the spawned test server is designed so that it can
// run remotely (So can't just write a script to a local file and have the
// server serve it).
+//
+// TODO(https://crbug.com/333943): Remove these tests when FTP support is
+// removed.
class NetworkContextConfigurationFtpPacBrowserTest
: public NetworkContextConfigurationBrowserTest {
public:
NetworkContextConfigurationFtpPacBrowserTest()
: ftp_server_(net::SpawnedTestServer::TYPE_FTP, GetChromeTestDataDir()) {
+ scoped_feature_list_.InitAndEnableFeature(features::kFtpProtocol);
EXPECT_TRUE(ftp_server_.Start());
}
~NetworkContextConfigurationFtpPacBrowserTest() override {}
@@ -1794,6 +1863,7 @@ class NetworkContextConfigurationFtpPacBrowserTest
private:
net::SpawnedTestServer ftp_server_;
+ base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(NetworkContextConfigurationFtpPacBrowserTest);
};
@@ -1818,54 +1888,6 @@ IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationFtpPacBrowserTest, FtpPac) {
EXPECT_EQ(net::ERR_PROXY_CONNECTION_FAILED, simple_loader->NetError());
}
-// Used to test that PAC HTTPS URL stripping works. A different test server is
-// used as the "proxy" based on whether the PAC script sees the full path or
-// not. The servers aren't correctly set up to mimic HTTP proxies that tunnel
-// to an HTTPS test server, so the test fixture just watches for any incoming
-// connection.
-class NetworkContextConfigurationHttpsStrippingPacBrowserTest
- : public NetworkContextConfigurationBrowserTest {
- public:
- NetworkContextConfigurationHttpsStrippingPacBrowserTest() {}
-
- ~NetworkContextConfigurationHttpsStrippingPacBrowserTest() override {}
-
- void SetUpCommandLine(base::CommandLine* command_line) override {
- // Test server HostPortPair, as a string.
- std::string test_server_host_port_pair =
- net::HostPortPair::FromURL(embedded_test_server()->base_url())
- .ToString();
- // Set up a PAC file that directs to different servers based on the URL it
- // sees.
- std::string pac_script = base::StringPrintf(
- "function FindProxyForURL(url, host) {"
- // With the test URL stripped of the path, try to use the embedded test
- // server to establish a an SSL tunnel over an HTTP proxy. The request
- // will fail with ERR_TUNNEL_CONNECTION_FAILED.
- " if (url == 'https://does.not.resolve.test:1872/')"
- " return 'PROXY %s';"
- // With the full test URL, try to use a domain that does not resolve as
- // a proxy. Errors connecting to the proxy result in
- // ERR_PROXY_CONNECTION_FAILED.
- " if (url == 'https://does.not.resolve.test:1872/foo')"
- " return 'PROXY does.not.resolve.test';"
- // Otherwise, use direct. If a connection to "does.not.resolve.test"
- // tries to use a direction connection, it will fail with
- // ERR_NAME_NOT_RESOLVED. This path will also
- // be used by the initial request in NetworkServiceState::kRestarted
- // tests to make sure the network service process is fully started
- // before it's crashed and restarted. Using direct in this case avoids
- // that request failing with an unexpeced error when being directed to a
- // bogus proxy.
- " return 'DIRECT';"
- "}",
- test_server_host_port_pair.c_str());
-
- command_line->AppendSwitchASCII(switches::kProxyPacUrl,
- "data:," + pac_script);
- }
-};
-
class NetworkContextConfigurationProxySettingsBrowserTest
: public NetworkContextConfigurationHttpPacBrowserTest {
public:
@@ -1947,12 +1969,11 @@ class NetworkContextConfigurationProxySettingsBrowserTest
expected_connections_run_loop.Run();
// Then wait for any remaining connections that we should NOT get.
- base::RunLoop unexpected_connections_run_loop;
- base::RunLoop::ScopedRunTimeoutForTest run_timeout(
- base::TimeDelta::FromMilliseconds(100),
- base::BindLambdaForTesting(
- [&]() { unexpected_connections_run_loop.Quit(); }));
- unexpected_connections_run_loop.Run();
+ base::RunLoop ugly_100ms_wait;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, ugly_100ms_wait.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(100));
+ ugly_100ms_wait.Run();
// Stop the server.
ASSERT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
@@ -2272,8 +2293,6 @@ INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationFtpPacBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
- NetworkContextConfigurationHttpsStrippingPacBrowserTest);
-INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationProxySettingsBrowserTest);
INSTANTIATE_TEST_CASES_FOR_TEST_FIXTURE(
NetworkContextConfigurationManagedProxySettingsBrowserTest);
diff --git a/chromium/chrome/browser/net/network_request_metrics_browsertest.cc b/chromium/chrome/browser/net/network_request_metrics_browsertest.cc
index cdd09f54fa8..3034b1467ce 100644
--- a/chromium/chrome/browser/net/network_request_metrics_browsertest.cc
+++ b/chromium/chrome/browser/net/network_request_metrics_browsertest.cc
@@ -28,8 +28,6 @@
#include "chrome/test/base/ui_test_utils.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/web_contents_observer.h"
-#include "content/public/common/resource_load_info.mojom.h"
-#include "content/public/common/resource_type.h"
#include "content/public/test/download_test_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/base/filename_util.h"
@@ -38,6 +36,7 @@
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"
@@ -83,8 +82,9 @@ class WaitForMainFrameResourceObserver : public content::WebContentsObserver {
void ResourceLoadComplete(
RenderFrameHost* render_frame_host,
const content::GlobalRequestID& request_id,
- const content::mojom::ResourceLoadInfo& resource_load_info) override {
- EXPECT_EQ(ResourceType::kMainFrame, resource_load_info.resource_type);
+ const blink::mojom::ResourceLoadInfo& resource_load_info) override {
+ EXPECT_EQ(network::mojom::RequestDestination::kDocument,
+ resource_load_info.request_destination);
EXPECT_EQ(net::OK, resource_load_info.net_error);
run_loop_.Quit();
}
diff --git a/chromium/chrome/browser/net/nss_context_chromeos_browsertest.cc b/chromium/chrome/browser/net/nss_context_chromeos_browsertest.cc
index d17dfc90ac2..67db1777d36 100644
--- a/chromium/chrome/browser/net/nss_context_chromeos_browsertest.cc
+++ b/chromium/chrome/browser/net/nss_context_chromeos_browsertest.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/chromeos/login/startup_utils.h"
#include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_task_traits.h"
diff --git a/chromium/chrome/browser/net/profile_network_context_service.cc b/chromium/chrome/browser/net/profile_network_context_service.cc
index 3adf99a4527..44ce8ba980a 100644
--- a/chromium/chrome/browser/net/profile_network_context_service.cc
+++ b/chromium/chrome/browser/net/profile_network_context_service.cc
@@ -12,10 +12,12 @@
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/logging.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
@@ -94,6 +96,9 @@ namespace {
bool* g_discard_domain_reliability_uploads_for_testing = nullptr;
+const char kHttpCacheFinchExperimentGroups[] =
+ "profile_network_context_service.http_cache_finch_experiment_groups";
+
std::vector<std::string> TranslateStringArray(const base::ListValue* list) {
std::vector<std::string> strings;
for (const base::Value& value : *list) {
@@ -165,7 +170,9 @@ void InitializeCorsExtraSafelistedRequestHeaderNamesForProfile(
// We trust and append |pref|'s values only when they are set by the managed
// policy. Chrome does not have any interface to set this preference manually.
- if (has_managed_mitigation_list) {
+ if (!base::FeatureList::IsEnabled(
+ features::kHideCorsMitigationListPolicySupport) &&
+ has_managed_mitigation_list) {
for (const auto& header_name_value :
*pref->GetList(prefs::kCorsMitigationList)) {
extra_safelisted_request_header_names->push_back(
@@ -294,11 +301,14 @@ ProfileNetworkContextService::CreateNetworkContext(
if ((!in_memory && !profile_->IsOffTheRecord())) {
// TODO(jam): delete this code 1 year after Network Service shipped to all
// stable users, which would be after M83 branches.
- base::FilePath media_cache_path = GetPartitionPath(relative_partition_path)
- .Append(chrome::kMediaCacheDirname);
- base::PostTask(
+ base::FilePath base_cache_path;
+ chrome::GetUserCacheDirectory(GetPartitionPath(relative_partition_path),
+ &base_cache_path);
+ base::FilePath media_cache_path =
+ base_cache_path.Append(chrome::kMediaCacheDirname);
+ base::ThreadPool::PostTask(
FROM_HERE,
- {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, base::MayBlock(),
+ {base::TaskPriority::BEST_EFFORT, base::MayBlock(),
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(base::IgnoreResult(&base::DeleteFile), media_cache_path,
true /* recursive */));
@@ -344,6 +354,10 @@ void ProfileNetworkContextService::RegisterLocalStatePrefs(
registry->RegisterIntegerPref(
prefs::kAmbientAuthenticationInPrivateModesEnabled,
static_cast<int>(net::AmbientAuthAllowedProfileTypes::REGULAR_ONLY));
+
+ // For information about whether to reset the HTTP Cache or not, defaults
+ // to the empty string, which does not prompt a reset.
+ registry->RegisterStringPref(kHttpCacheFinchExperimentGroups, "");
}
void ProfileNetworkContextService::DisableQuicIfNotAllowed() {
@@ -592,6 +606,31 @@ ProfileNetworkContextService::CreateClientCertStore() {
#endif
}
+bool GetHttpCacheBackendResetParam(PrefService* local_state) {
+ // Get the field trial groups. If the server cannot be reached, then
+ // this corresponds to "None" for each experiment.
+ base::FieldTrial* field_trial = base::FeatureList::GetFieldTrial(
+ net::features::kSplitCacheByNetworkIsolationKey);
+ std::string current_field_trial_status =
+ (field_trial ? field_trial->group_name() : "None") + " ";
+ field_trial = base::FeatureList::GetFieldTrial(
+ net::features::kAppendFrameOriginToNetworkIsolationKey);
+ current_field_trial_status +=
+ (field_trial ? field_trial->group_name() : "None") + " ";
+ field_trial = base::FeatureList::GetFieldTrial(
+ net::features::kUseRegistrableDomainInNetworkIsolationKey);
+ current_field_trial_status +=
+ (field_trial ? field_trial->group_name() : "None");
+
+ std::string previous_field_trial_status =
+ local_state->GetString(kHttpCacheFinchExperimentGroups);
+ local_state->SetString(kHttpCacheFinchExperimentGroups,
+ current_field_trial_status);
+
+ return !previous_field_trial_status.empty() &&
+ current_field_trial_status != previous_field_trial_status;
+}
+
network::mojom::NetworkContextParamsPtr
ProfileNetworkContextService::CreateNetworkContextParams(
bool in_memory,
@@ -667,6 +706,10 @@ ProfileNetworkContextService::CreateNetworkContextParams(
cookie_path = cookie_path.Append(chrome::kCookieFilename);
network_context_params->cookie_path = cookie_path;
+ base::FilePath trust_token_path = path;
+ trust_token_path = trust_token_path.Append(chrome::kTrustTokenFilename);
+ network_context_params->trust_token_path = std::move(trust_token_path);
+
#if BUILDFLAG(ENABLE_REPORTING)
base::FilePath reporting_and_nel_store_path = path;
reporting_and_nel_store_path = reporting_and_nel_store_path.Append(
@@ -713,7 +756,14 @@ ProfileNetworkContextService::CreateNetworkContextParams(
network_context_params->enable_expect_ct_reporting = true;
#if BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED)
- if (!in_memory && !network_context_params->use_builtin_cert_verifier &&
+ // Require the use_builtin_cert_verifier to be explicitly initialized, as
+ // using the TrialComparisonCertVerifier requires knowing whether Chrome is
+ // using the system verifier.
+ DCHECK_NE(network_context_params->use_builtin_cert_verifier,
+ network::mojom::NetworkContextParams::CertVerifierImpl::kDefault);
+ if (!in_memory &&
+ network_context_params->use_builtin_cert_verifier ==
+ network::mojom::NetworkContextParams::CertVerifierImpl::kSystem &&
TrialComparisonCertVerifierController::MaybeAllowedForProfile(profile_)) {
mojo::PendingRemote<network::mojom::TrialComparisonCertVerifierConfigClient>
config_client;
@@ -767,7 +817,9 @@ ProfileNetworkContextService::CreateNetworkContextParams(
// Note: On non-ChromeOS platforms, the |use_builtin_cert_verifier| param
// value is inherited from CreateDefaultNetworkContextParams.
network_context_params->use_builtin_cert_verifier =
- using_builtin_cert_verifier_;
+ using_builtin_cert_verifier_
+ ? network::mojom::NetworkContextParams::CertVerifierImpl::kBuiltin
+ : network::mojom::NetworkContextParams::CertVerifierImpl::kSystem;
bool profile_supports_policy_certs = false;
if (chromeos::ProfileHelper::IsSigninProfile(profile_))
@@ -803,6 +855,9 @@ ProfileNetworkContextService::CreateNetworkContextParams(
->GetOriginAccessList()
.CreateCorsOriginAccessPatternsList();
+ network_context_params->reset_http_cache_backend =
+ GetHttpCacheBackendResetParam(g_browser_process->local_state());
+
return network_context_params;
}
diff --git a/chromium/chrome/browser/net/profile_network_context_service.h b/chromium/chrome/browser/net/profile_network_context_service.h
index f7e5a3b7325..82941477e64 100644
--- a/chromium/chrome/browser/net/profile_network_context_service.h
+++ b/chromium/chrome/browser/net/profile_network_context_service.h
@@ -104,7 +104,7 @@ class ProfileNetworkContextService
ProfileNetworkContextServiceCertVerifierBuiltinFeaturePolicyTest,
Test);
- friend class AmbientAuthenticationTestWithPolicy;
+ friend class AmbientAuthenticationTestHelper;
// Checks |quic_allowed_|, and disables QUIC if needed.
void DisableQuicIfNotAllowed();
@@ -113,9 +113,6 @@ class ProfileNetworkContextService
// formatting them as appropriate.
void UpdateAcceptLanguage();
- // Forwards changes to |block_third_party_cookies_| to the NetworkContext.
- void UpdateBlockThirdPartyCookies();
-
// Computes appropriate value of Accept-Language header based on
// |pref_accept_language_|
std::string ComputeAcceptLanguage() const;
diff --git a/chromium/chrome/browser/net/profile_network_context_service_browsertest.cc b/chromium/chrome/browser/net/profile_network_context_service_browsertest.cc
index 514f05d31d4..a72b0b8ad0b 100644
--- a/chromium/chrome/browser/net/profile_network_context_service_browsertest.cc
+++ b/chromium/chrome/browser/net/profile_network_context_service_browsertest.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/net/profile_network_context_service.h"
-
#include <algorithm>
#include <string>
#include <vector>
@@ -16,33 +14,34 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/thread_pool/thread_pool_instance.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/threading/platform_thread.h" // For |Sleep()|.
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/metrics/subprocess_metrics_provider.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/profile_network_context_service_factory.h"
+#include "chrome/browser/net/profile_network_context_service_test_utils.h"
#include "chrome/browser/policy/policy_test_utils.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_window.h"
-#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_list.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
-#include "chrome/test/base/search_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
-#include "components/search_engines/template_url_service.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_features.h"
#include "content/public/test/simple_url_loader_test_helper.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "net/base/features.h"
#include "net/base/load_flags.h"
#include "net/http/http_auth_preferences.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -57,7 +56,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_CHROMEOS)
-#include "base/test/scoped_feature_list.h"
#include "chrome/browser/chromeos/policy/login_policy_test_base.h"
#include "chrome/browser/chromeos/policy/user_policy_test_helper.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
@@ -75,13 +73,12 @@
// Most tests for this class are in NetworkContextConfigurationBrowserTest.
class ProfileNetworkContextServiceBrowsertest : public InProcessBrowserTest {
public:
- ProfileNetworkContextServiceBrowsertest() {
- EXPECT_TRUE(embedded_test_server()->Start());
- }
+ ProfileNetworkContextServiceBrowsertest() = default;
- ~ProfileNetworkContextServiceBrowsertest() override {}
+ ~ProfileNetworkContextServiceBrowsertest() override = default;
void SetUpOnMainThread() override {
+ EXPECT_TRUE(embedded_test_server()->Start());
loader_factory_ = content::BrowserContext::GetDefaultStoragePartition(
browser()->profile())
->GetURLLoaderFactoryForBrowserProcess()
@@ -92,6 +89,14 @@ class ProfileNetworkContextServiceBrowsertest : public InProcessBrowserTest {
return loader_factory_;
}
+ protected:
+ // The HttpCache is only created when a request is issued, thus we perform a
+ // navigation to ensure that the http cache is initialized.
+ void NavigateToCreateHttpCache() {
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/createbackend"));
+ }
+
private:
network::mojom::URLLoaderFactory* loader_factory_ = nullptr;
};
@@ -160,28 +165,139 @@ IN_PROC_BROWSER_TEST_F(ProfileNetworkContextServiceBrowsertest, BrotliEnabled) {
EXPECT_TRUE(base::Contains(encodings, "br"));
}
-enum class AmbientAuthProfileBit {
- INCOGNITO = 1,
- GUEST = 2,
+void CheckCacheResetStatus(base::HistogramTester* histograms, bool reset) {
+ // TODO(crbug/1041810): The failure case, here, is to time out. Since Chrome
+ // doesn't synchronize cache loading, there's no guarantee that this is
+ // complete and it's merely available at earliest convenience. If shutdown
+ // occurs prior to the cache being loaded, then nothing is reported. This
+ // should probably be fixed to avoid the use of the sleep function, but that
+ // will require synchronizing in some meaningful way to guarantee the cache
+ // has been loaded prior to testing the histograms.
+ while (!histograms->GetBucketCount("HttpCache.HardReset", reset)) {
+ content::FetchHistogramsFromChildProcesses();
+ SubprocessMetricsProvider::MergeHistogramDeltasForTesting();
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(5));
+ }
+
+ if (reset) {
+ // Some tests load the cache multiple times, but should only be reset once.
+ EXPECT_EQ(histograms->GetBucketCount("HttpCache.HardReset", true), 1);
+ } else {
+ // Make sure it's never reset.
+ EXPECT_EQ(histograms->GetBucketCount("HttpCache.HardReset", true), 0);
+ }
+}
+
+class ProfileNetworkContextServiceCacheSameBrowsertest
+ : public ProfileNetworkContextServiceBrowsertest {
+ public:
+ ProfileNetworkContextServiceCacheSameBrowsertest() = default;
+ ~ProfileNetworkContextServiceCacheSameBrowsertest() override = default;
+
+ void SetUp() override {
+ scoped_feature_list_.InitWithFeatures(
+ {}, {net::features::kSplitCacheByNetworkIsolationKey,
+ net::features::kAppendFrameOriginToNetworkIsolationKey,
+ net::features::kUseRegistrableDomainInNetworkIsolationKey});
+ ProfileNetworkContextServiceBrowsertest::SetUp();
+ }
+
+ base::HistogramTester histograms_;
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
};
-// Indicates the state of the feature flags
-// |kEnableAmbientAuthenticationInIncognito| and
-// |kEnableAmbientAuthenticationInGuestSession|
-enum class AmbientAuthenticationFeatureState {
- GUEST_OFF_INCOGNITO_OFF = 0, // 00
- GUEST_OFF_INCOGNITO_ON = 1, // 01
- GUEST_ON_INCOGNITO_OFF = 2, // 10
- GUEST_ON_INCOGNITO_ON = 3, // 11
+IN_PROC_BROWSER_TEST_F(ProfileNetworkContextServiceCacheSameBrowsertest,
+ PRE_TestCacheResetParameter) {
+ NavigateToCreateHttpCache();
+ CheckCacheResetStatus(&histograms_, false);
+
+ // At this point, we have already called the initialization.
+ // Verify that we have the correct values in the local_state.
+ PrefService* local_state = g_browser_process->local_state();
+ DCHECK_EQ(
+ local_state->GetString(
+ "profile_network_context_service.http_cache_finch_experiment_groups"),
+ "None None None");
+}
+
+IN_PROC_BROWSER_TEST_F(ProfileNetworkContextServiceCacheSameBrowsertest,
+ TestCacheResetParameter) {
+ NavigateToCreateHttpCache();
+ CheckCacheResetStatus(&histograms_, false);
+
+ // At this point, we have already called the initialization.
+ // Verify that we have the correct values in the local_state.
+ PrefService* local_state = g_browser_process->local_state();
+ DCHECK_EQ(
+ local_state->GetString(
+ "profile_network_context_service.http_cache_finch_experiment_groups"),
+ "None None None");
+}
+
+class ProfileNetworkContextServiceCacheChangeBrowsertest
+ : public ProfileNetworkContextServiceBrowsertest {
+ public:
+ ProfileNetworkContextServiceCacheChangeBrowsertest() {
+ scoped_feature_list_.InitWithFeaturesAndParameters(
+ {{net::features::kAppendFrameOriginToNetworkIsolationKey, {}}},
+ {net::features::kSplitCacheByNetworkIsolationKey,
+ net::features::kUseRegistrableDomainInNetworkIsolationKey});
+ }
+ ~ProfileNetworkContextServiceCacheChangeBrowsertest() override = default;
+
+ base::HistogramTester histograms_;
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
};
+// Flaky on Linux and Mac: https://crbug.com/1041810
+// The first time we load, even if we're in an experiment there's no reset
+// from the unknown state.
+IN_PROC_BROWSER_TEST_F(ProfileNetworkContextServiceCacheChangeBrowsertest,
+ PRE_TestCacheResetParameter) {
+ NavigateToCreateHttpCache();
+ CheckCacheResetStatus(&histograms_, false);
+
+ // At this point, we have already called the initialization.
+ // Verify that we have the correct values in the local_state.
+ PrefService* local_state = g_browser_process->local_state();
+ DCHECK_EQ(
+ local_state->GetString(
+ "profile_network_context_service.http_cache_finch_experiment_groups"),
+ "None scoped_feature_list_trial_group None");
+ // Set the local state for the next test.
+ local_state->SetString(
+ "profile_network_context_service.http_cache_finch_experiment_groups",
+ "None None None");
+}
+
+// The second time we load we know the state, which was "None None None" for the
+// previous test, so we should see a reset being in an experiment.
+IN_PROC_BROWSER_TEST_F(ProfileNetworkContextServiceCacheChangeBrowsertest,
+ TestCacheResetParameter) {
+ NavigateToCreateHttpCache();
+ CheckCacheResetStatus(&histograms_, true);
+
+ // At this point, we have already called the initialization once.
+ // Verify that we have the correct values in the local_state.
+ PrefService* local_state = g_browser_process->local_state();
+ DCHECK_EQ(
+ local_state->GetString(
+ "profile_network_context_service.http_cache_finch_experiment_groups"),
+ "None scoped_feature_list_trial_group None");
+}
+
class AmbientAuthenticationTestWithPolicy
: public policy::PolicyTest,
public testing::WithParamInterface<AmbientAuthenticationFeatureState> {
public:
AmbientAuthenticationTestWithPolicy() {
feature_state_ = GetParam();
- CookTheFeatureList();
+ AmbientAuthenticationTestHelper::CookTheFeatureList(scoped_feature_list_,
+ feature_state_);
policy::PolicyTest::SetUpInProcessBrowserTestFixture();
}
@@ -190,115 +306,29 @@ class AmbientAuthenticationTestWithPolicy
int policy_value =
service->GetInteger(prefs::kAmbientAuthenticationInPrivateModesEnabled);
- EXPECT_TRUE(IsAmbientAuthAllowedForProfile(GetRegularProfile()));
- EXPECT_EQ(IsAmbientAuthAllowedForProfile(GetIncognitoProfile()),
- IsIncognitoAllowedInFeature() ||
- IsIncognitoAllowedInPolicy(policy_value));
-// TODO(crbug.com/1030624): Adapt this test for chromeos guest sessions too once
-// we have device level policy for guests
+ Profile* regular_profile = browser()->profile();
+ Profile* incognito_profile = regular_profile->GetOffTheRecordProfile();
+
+ EXPECT_TRUE(AmbientAuthenticationTestHelper::IsAmbientAuthAllowedForProfile(
+ regular_profile));
+ EXPECT_EQ(AmbientAuthenticationTestHelper::IsAmbientAuthAllowedForProfile(
+ incognito_profile),
+ AmbientAuthenticationTestHelper::IsIncognitoAllowedInFeature(
+ feature_state_) ||
+ AmbientAuthenticationTestHelper::IsIncognitoAllowedInPolicy(
+ policy_value));
+// ChromeOS guest sessions don't have the capability to
+// do ambient authentications.
#if !defined(OS_CHROMEOS)
- EXPECT_EQ(
- IsAmbientAuthAllowedForProfile(GetGuestProfile()),
- IsGuestAllowedInFeature() || IsGuestAllowedInPolicy(policy_value));
+ EXPECT_EQ(AmbientAuthenticationTestHelper::IsAmbientAuthAllowedForProfile(
+ AmbientAuthenticationTestHelper::GetGuestProfile()),
+ AmbientAuthenticationTestHelper::IsGuestAllowedInFeature(
+ feature_state_) ||
+ AmbientAuthenticationTestHelper::IsGuestAllowedInPolicy(
+ policy_value));
#endif
}
- protected:
- inline bool IsIncognitoAllowedInFeature() const {
- return static_cast<int>(feature_state_) &
- static_cast<int>(AmbientAuthProfileBit::INCOGNITO);
- }
-
- inline bool IsGuestAllowedInFeature() const {
- return static_cast<int>(feature_state_) &
- static_cast<int>(AmbientAuthProfileBit::GUEST);
- }
-
- inline bool IsIncognitoAllowedInPolicy(int policy_value) const {
- return policy_value & static_cast<int>(AmbientAuthProfileBit::INCOGNITO);
- }
-
- inline bool IsGuestAllowedInPolicy(int policy_value) const {
- return policy_value & static_cast<int>(AmbientAuthProfileBit::GUEST);
- }
-
- void CookTheFeatureList() {
- std::vector<base::Feature> enabled_feature_list;
- std::vector<base::Feature> disabled_feature_list;
-
- if (IsIncognitoAllowedInFeature())
- enabled_feature_list.push_back(
- features::kEnableAmbientAuthenticationInIncognito);
- else
- disabled_feature_list.push_back(
- features::kEnableAmbientAuthenticationInIncognito);
-
- if (IsGuestAllowedInFeature())
- enabled_feature_list.push_back(
- features::kEnableAmbientAuthenticationInGuestSession);
- else
- disabled_feature_list.push_back(
- features::kEnableAmbientAuthenticationInGuestSession);
-
- scoped_feature_list_.InitWithFeatures(enabled_feature_list,
- disabled_feature_list);
- }
-
- Profile* GetIncognitoProfile() {
- Profile* regular_profile = browser()->profile();
- Profile* off_the_record_profile = regular_profile->GetOffTheRecordProfile();
- EXPECT_TRUE(regular_profile->HasOffTheRecordProfile());
- return off_the_record_profile;
- }
-
- Profile* GetGuestProfile() {
- Profile* guest_profile = OpenGuestBrowser()->profile();
- return guest_profile;
- }
-
- Profile* GetRegularProfile() { return browser()->profile(); }
-
- bool IsAmbientAuthAllowedForProfile(Profile* profile) {
- ProfileNetworkContextService* profile_network_context_service =
- ProfileNetworkContextServiceFactory::GetForContext(profile);
- base::FilePath empty_relative_partition_path;
- network::mojom::NetworkContextParamsPtr network_context_params_ptr =
- profile_network_context_service->CreateNetworkContextParams(
- /*in_memory=*/false, empty_relative_partition_path);
- return network_context_params_ptr->http_auth_static_network_context_params
- ->allow_default_credentials ==
- net::HttpAuthPreferences::ALLOW_DEFAULT_CREDENTIALS;
- }
- // OpenGuestBrowser method code borrowed from
- // chrome/browser/profiles/profile_window_browsertest.cc
- Browser* OpenGuestBrowser() {
- size_t num_browsers = BrowserList::GetInstance()->size();
-
- // Create a guest browser nicely. Using CreateProfile() and CreateBrowser()
- // does incomplete initialization that would lead to
- // SystemUrlRequestContextGetter being leaked.
- profiles::SwitchToGuestProfile(ProfileManager::CreateCallback());
- ui_test_utils::WaitForBrowserToOpen();
-
- DCHECK_NE(static_cast<Profile*>(nullptr),
- g_browser_process->profile_manager()->GetProfileByPath(
- ProfileManager::GetGuestProfilePath()));
- EXPECT_EQ(num_browsers + 1, BrowserList::GetInstance()->size());
-
- Profile* guest = g_browser_process->profile_manager()->GetProfileByPath(
- ProfileManager::GetGuestProfilePath());
- Browser* browser = chrome::FindAnyBrowser(guest, true);
- EXPECT_TRUE(browser);
-
- // When |browser| closes a BrowsingDataRemover will be created and executed.
- // It needs a loaded TemplateUrlService or else it hangs on to a
- // CallbackList::Subscription forever.
- search_test_utils::WaitForTemplateURLServiceToLoad(
- TemplateURLServiceFactory::GetForProfile(guest));
-
- return browser;
- }
-
void EnablePolicyWithValue(net::AmbientAuthAllowedProfileTypes value) {
SetPolicy(&policies_,
policy::key::kAmbientAuthenticationInPrivateModesEnabled,
@@ -313,7 +343,7 @@ class AmbientAuthenticationTestWithPolicy
};
INSTANTIATE_TEST_CASE_P(
- ,
+ AmbientAuthAllFeatureValuesTest,
AmbientAuthenticationTestWithPolicy,
testing::Values(AmbientAuthenticationFeatureState::GUEST_OFF_INCOGNITO_OFF,
AmbientAuthenticationFeatureState::GUEST_OFF_INCOGNITO_ON,
@@ -579,7 +609,11 @@ IN_PROC_BROWSER_TEST_P(
network::mojom::NetworkContextParamsPtr network_context_params_ptr =
profile_network_context_service->CreateNetworkContextParams(
/*in_memory=*/false, empty_relative_partition_path);
- EXPECT_EQ(GetParam(), network_context_params_ptr->use_builtin_cert_verifier);
+ EXPECT_EQ(
+ GetParam()
+ ? network::mojom::NetworkContextParams::CertVerifierImpl::kBuiltin
+ : network::mojom::NetworkContextParams::CertVerifierImpl::kSystem,
+ network_context_params_ptr->use_builtin_cert_verifier);
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
// If the BuiltinCertificateVerifierEnabled policy is set it should override
@@ -592,7 +626,8 @@ IN_PROC_BROWSER_TEST_P(
network_context_params_ptr =
profile_network_context_service->CreateNetworkContextParams(
/*in_memory=*/false, empty_relative_partition_path);
- EXPECT_TRUE(network_context_params_ptr->use_builtin_cert_verifier);
+ EXPECT_EQ(network::mojom::NetworkContextParams::CertVerifierImpl::kBuiltin,
+ network_context_params_ptr->use_builtin_cert_verifier);
SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
std::make_unique<base::Value>(false));
@@ -601,7 +636,8 @@ IN_PROC_BROWSER_TEST_P(
network_context_params_ptr =
profile_network_context_service->CreateNetworkContextParams(
/*in_memory=*/false, empty_relative_partition_path);
- EXPECT_FALSE(network_context_params_ptr->use_builtin_cert_verifier);
+ EXPECT_EQ(network::mojom::NetworkContextParams::CertVerifierImpl::kSystem,
+ network_context_params_ptr->use_builtin_cert_verifier);
#endif
}
@@ -614,6 +650,7 @@ INSTANTIATE_TEST_SUITE_P(
enum class CorsTestMode {
kWithCorsMitigationListPolicy,
kWithoutCorsMitigationListPolicy,
+ kWithHiddenCorsMitigationListPolicy,
};
class CorsExtraSafelistedHeaderNamesTest
@@ -622,21 +659,14 @@ class CorsExtraSafelistedHeaderNamesTest
public:
CorsExtraSafelistedHeaderNamesTest() {
switch (GetParam()) {
- case CorsTestMode::kWithCorsMitigationListPolicy: {
- auto list = std::make_unique<base::ListValue>();
- list->AppendString("bar");
- policy::PolicyMap policies;
- policies.Set(policy::key::kCorsMitigationList,
- policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
- policy::POLICY_SOURCE_CLOUD, std::move(list), nullptr);
- provider_.UpdateChromePolicy(policies);
+ case CorsTestMode::kWithCorsMitigationListPolicy:
+ SetUpPolicy();
scoped_feature_list_.InitWithFeaturesAndParameters(
{{network::features::kOutOfBlinkCors, {}},
{features::kExtraSafelistedRequestHeadersForOutOfBlinkCors,
{{"extra-safelisted-request-headers-for-enterprise", "foo"}}}},
- {});
+ {{features::kHideCorsMitigationListPolicySupport}, {}});
break;
- }
case CorsTestMode::kWithoutCorsMitigationListPolicy:
scoped_feature_list_.InitWithFeaturesAndParameters(
{{network::features::kOutOfBlinkCors, {}},
@@ -644,6 +674,16 @@ class CorsExtraSafelistedHeaderNamesTest
{{"extra-safelisted-request-headers", "foo,bar"}}}},
{});
break;
+ case CorsTestMode::kWithHiddenCorsMitigationListPolicy:
+ SetUpPolicy();
+ scoped_feature_list_.InitWithFeaturesAndParameters(
+ {{network::features::kOutOfBlinkCors, {}},
+ {features::kHideCorsMitigationListPolicySupport, {}},
+ {features::kExtraSafelistedRequestHeadersForOutOfBlinkCors,
+ {{"extra-safelisted-request-headers-for-enterprise",
+ "foo,bar"}}}},
+ {});
+ break;
}
}
@@ -693,6 +733,16 @@ class CorsExtraSafelistedHeaderNamesTest
"/cors-extra-safelisted-header-names.html";
private:
+ void SetUpPolicy() {
+ auto list = std::make_unique<base::ListValue>();
+ list->AppendString("bar");
+ policy::PolicyMap policies;
+ policies.Set(policy::key::kCorsMitigationList,
+ policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+ policy::POLICY_SOURCE_CLOUD, std::move(list), nullptr);
+ provider_.UpdateChromePolicy(policies);
+ }
+
std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
const net::test_server::HttpRequest& request) {
std::unique_ptr<net::test_server::BasicHttpResponse> response =
@@ -776,3 +826,8 @@ INSTANTIATE_TEST_SUITE_P(
WithoutCorsMitigationListPolicy,
CorsExtraSafelistedHeaderNamesTest,
testing::Values(CorsTestMode::kWithoutCorsMitigationListPolicy));
+
+INSTANTIATE_TEST_SUITE_P(
+ WithHiddenCorsMitigationListPolicy,
+ CorsExtraSafelistedHeaderNamesTest,
+ testing::Values(CorsTestMode::kWithHiddenCorsMitigationListPolicy));
diff --git a/chromium/chrome/browser/net/profile_network_context_service_test_utils.cc b/chromium/chrome/browser/net/profile_network_context_service_test_utils.cc
new file mode 100644
index 00000000000..b768aac1687
--- /dev/null
+++ b/chromium/chrome/browser/net/profile_network_context_service_test_utils.cc
@@ -0,0 +1,119 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/net/profile_network_context_service_test_utils.h"
+
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/net/profile_network_context_service.h"
+#include "chrome/browser/net/profile_network_context_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_window.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/test/base/search_test_utils.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+enum class AmbientAuthProfileBit {
+ INCOGNITO = 1 << 0,
+ GUEST = 1 << 1,
+};
+
+bool AmbientAuthenticationTestHelper::IsIncognitoAllowedInFeature(
+ const AmbientAuthenticationFeatureState& feature_state) {
+ return static_cast<int>(feature_state) &
+ static_cast<int>(AmbientAuthProfileBit::INCOGNITO);
+}
+
+bool AmbientAuthenticationTestHelper::IsGuestAllowedInFeature(
+ const AmbientAuthenticationFeatureState& feature_state) {
+ return static_cast<int>(feature_state) &
+ static_cast<int>(AmbientAuthProfileBit::GUEST);
+}
+
+bool AmbientAuthenticationTestHelper::IsIncognitoAllowedInPolicy(
+ int policy_value) {
+ return policy_value & static_cast<int>(AmbientAuthProfileBit::INCOGNITO);
+}
+
+bool AmbientAuthenticationTestHelper::IsGuestAllowedInPolicy(int policy_value) {
+ return policy_value & static_cast<int>(AmbientAuthProfileBit::GUEST);
+}
+
+void AmbientAuthenticationTestHelper::CookTheFeatureList(
+ base::test::ScopedFeatureList& scoped_feature_list,
+ const AmbientAuthenticationFeatureState& feature_state) {
+ std::vector<base::Feature> enabled_feature_list;
+ std::vector<base::Feature> disabled_feature_list;
+
+ if (IsIncognitoAllowedInFeature(feature_state)) {
+ enabled_feature_list.push_back(
+ features::kEnableAmbientAuthenticationInIncognito);
+ } else {
+ disabled_feature_list.push_back(
+ features::kEnableAmbientAuthenticationInIncognito);
+ }
+
+ if (IsGuestAllowedInFeature(feature_state)) {
+ enabled_feature_list.push_back(
+ features::kEnableAmbientAuthenticationInGuestSession);
+ } else {
+ disabled_feature_list.push_back(
+ features::kEnableAmbientAuthenticationInGuestSession);
+ }
+ scoped_feature_list.InitWithFeatures(enabled_feature_list,
+ disabled_feature_list);
+}
+
+Profile* AmbientAuthenticationTestHelper::GetGuestProfile() {
+ Profile* guest_profile = OpenGuestBrowser()->profile();
+ return guest_profile;
+}
+
+bool AmbientAuthenticationTestHelper::IsAmbientAuthAllowedForProfile(
+ Profile* profile) {
+ ProfileNetworkContextService* profile_network_context_service =
+ ProfileNetworkContextServiceFactory::GetForContext(profile);
+ base::FilePath empty_relative_partition_path;
+ network::mojom::NetworkContextParamsPtr network_context_params_ptr =
+ profile_network_context_service->CreateNetworkContextParams(
+ /*in_memory=*/false, empty_relative_partition_path);
+ return network_context_params_ptr->http_auth_static_network_context_params
+ ->allow_default_credentials ==
+ net::HttpAuthPreferences::ALLOW_DEFAULT_CREDENTIALS;
+}
+
+// OpenGuestBrowser method code borrowed from
+// chrome/browser/profiles/profile_window_browsertest.cc
+Browser* AmbientAuthenticationTestHelper::OpenGuestBrowser() {
+ size_t num_browsers = BrowserList::GetInstance()->size();
+
+ // Create a guest browser nicely. Using CreateProfile() and CreateBrowser()
+ // does incomplete initialization that would lead to
+ // SystemUrlRequestContextGetter being leaked.
+ profiles::SwitchToGuestProfile(ProfileManager::CreateCallback());
+ ui_test_utils::WaitForBrowserToOpen();
+
+ DCHECK_NE(static_cast<Profile*>(nullptr),
+ g_browser_process->profile_manager()->GetProfileByPath(
+ ProfileManager::GetGuestProfilePath()));
+ EXPECT_EQ(num_browsers + 1, BrowserList::GetInstance()->size());
+
+ Profile* guest = g_browser_process->profile_manager()->GetProfileByPath(
+ ProfileManager::GetGuestProfilePath());
+ Browser* browser = chrome::FindAnyBrowser(guest, true);
+ EXPECT_TRUE(browser);
+
+ // When |browser| closes a BrowsingDataRemover will be created and executed.
+ // It needs a loaded TemplateUrlService or else it hangs on to a
+ // CallbackList::Subscription forever.
+ search_test_utils::WaitForTemplateURLServiceToLoad(
+ TemplateURLServiceFactory::GetForProfile(guest));
+
+ return browser;
+}
diff --git a/chromium/chrome/browser/net/profile_network_context_service_test_utils.h b/chromium/chrome/browser/net/profile_network_context_service_test_utils.h
new file mode 100644
index 00000000000..71cab960fe4
--- /dev/null
+++ b/chromium/chrome/browser/net/profile_network_context_service_test_utils.h
@@ -0,0 +1,45 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NET_PROFILE_NETWORK_CONTEXT_SERVICE_TEST_UTILS_H_
+#define CHROME_BROWSER_NET_PROFILE_NETWORK_CONTEXT_SERVICE_TEST_UTILS_H_
+
+#include "base/test/scoped_feature_list.h"
+#include "chrome/browser/ui/browser.h"
+
+// Indicates the state of the feature flags
+// |kEnableAmbientAuthenticationInIncognito| and
+// |kEnableAmbientAuthenticationInGuestSession|
+enum class AmbientAuthenticationFeatureState {
+ GUEST_OFF_INCOGNITO_OFF = 0, // 00
+ GUEST_OFF_INCOGNITO_ON = 1, // 01
+ GUEST_ON_INCOGNITO_OFF = 2, // 10
+ GUEST_ON_INCOGNITO_ON = 3, // 11
+};
+
+class AmbientAuthenticationTestHelper {
+ public:
+ AmbientAuthenticationTestHelper() = default;
+
+ static bool IsAmbientAuthAllowedForProfile(Profile* profile);
+
+ static bool IsIncognitoAllowedInFeature(
+ const AmbientAuthenticationFeatureState& feature_state);
+ static bool IsIncognitoAllowedInPolicy(int policy_value);
+
+ static bool IsGuestAllowedInFeature(
+ const AmbientAuthenticationFeatureState& feature_state);
+ static bool IsGuestAllowedInPolicy(int policy_value);
+
+ static Profile* GetGuestProfile();
+ // OpenGuestBrowser method code borrowed from
+ // chrome/browser/profiles/profile_window_browsertest.cc
+ static Browser* OpenGuestBrowser();
+
+ static void CookTheFeatureList(
+ base::test::ScopedFeatureList& scoped_feature_list,
+ const AmbientAuthenticationFeatureState& feature_state);
+};
+
+#endif // CHROME_BROWSER_NET_PROFILE_NETWORK_CONTEXT_SERVICE_TEST_UTILS_H_
diff --git a/chromium/chrome/browser/net/proxy_service_factory.cc b/chromium/chrome/browser/net/proxy_service_factory.cc
index 5b436ce90ee..5284a68b640 100644
--- a/chromium/chrome/browser/net/proxy_service_factory.cc
+++ b/chromium/chrome/browser/net/proxy_service_factory.cc
@@ -12,8 +12,8 @@
#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
+#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/proxy_resolution/proxy_config_service.h"
-#include "net/proxy_resolution/proxy_resolution_service.h"
#if defined(OS_CHROMEOS)
#include "chromeos/network/proxy/proxy_config_service_impl.h"
@@ -41,8 +41,9 @@ ProxyServiceFactory::CreateProxyConfigService(PrefProxyConfigTracker* tracker) {
// configuration in case nothing is configured through prefs (Note: prefs
// include command line and configuration policy).
- base_service = net::ProxyResolutionService::CreateSystemProxyConfigService(
- base::ThreadTaskRunnerHandle::Get());
+ base_service =
+ net::ConfiguredProxyResolutionService::CreateSystemProxyConfigService(
+ base::ThreadTaskRunnerHandle::Get());
#endif // !defined(OS_CHROMEOS)
return tracker->CreateTrackingProxyConfigService(std::move(base_service));
diff --git a/chromium/chrome/browser/net/samesite_cookies_policy_browsertest.cc b/chromium/chrome/browser/net/samesite_cookies_policy_browsertest.cc
index f11897c39fe..5028e155e2b 100644
--- a/chromium/chrome/browser/net/samesite_cookies_policy_browsertest.cc
+++ b/chromium/chrome/browser/net/samesite_cookies_policy_browsertest.cc
@@ -67,9 +67,10 @@ IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
// Set a cookie from a same-site context. The cookie does not specify
// SameSite, so it may default to Lax if the SameSite features are enabled.
// Since the context used is same-site, it should always work.
- EXPECT_TRUE(content::SetCookie(
- profile, url, "samesite-unspecified=1",
- net::CookieOptions::SameSiteCookieContext::SAME_SITE_LAX));
+ EXPECT_TRUE(content::SetCookie(profile, url, "samesite-unspecified=1",
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::SAME_SITE_LAX)));
EXPECT_EQ("samesite-unspecified=1", content::GetCookies(profile, url));
// Overwrite the cookie from a cross-site context. Because we have a policy
@@ -77,15 +78,17 @@ IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
// SameSite features are enabled. (It works regardless, if they are disabled.)
EXPECT_TRUE(content::SetCookie(
profile, url, "samesite-unspecified=2",
- net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE)));
// Cookie has the new value because we were able to successfully overwrite it.
EXPECT_EQ("samesite-unspecified=2", content::GetCookies(profile, url));
// Fetching the cookies from a cross-site context also works because of the
// policy.
- EXPECT_EQ(
- "samesite-unspecified=2",
- content::GetCookies(
- profile, url, net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ EXPECT_EQ("samesite-unspecified=2",
+ content::GetCookies(profile, url,
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::CROSS_SITE)));
}
IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
@@ -105,9 +108,10 @@ IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
// Set a cookie from a same-site context. The cookie does not specify
// SameSite, so it may default to Lax if the SameSite features are enabled.
// Since the context used is same-site, it should always work.
- EXPECT_TRUE(content::SetCookie(
- profile, url, "samesite-unspecified=1",
- net::CookieOptions::SameSiteCookieContext::SAME_SITE_LAX));
+ EXPECT_TRUE(content::SetCookie(profile, url, "samesite-unspecified=1",
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::SAME_SITE_LAX)));
EXPECT_EQ("samesite-unspecified=1", content::GetCookies(profile, url));
// Overwrite the cookie from a cross-site context. Because we have a policy
@@ -116,14 +120,17 @@ IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
// enabled.)
EXPECT_FALSE(content::SetCookie(
profile, url, "samesite-unspecified=2",
- net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE)));
// Cookie still has the previous value because re-setting it failed.
EXPECT_EQ("samesite-unspecified=1", content::GetCookies(profile, url));
// Fetching the unspecified-samesite cookie from a cross-site context does not
// work because of the policy.
- EXPECT_EQ("", content::GetCookies(
- profile, url,
- net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ EXPECT_EQ("",
+ content::GetCookies(profile, url,
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::CROSS_SITE)));
}
IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
@@ -150,15 +157,19 @@ IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
// Set a cookie from a same-site context. The cookie does not specify
// SameSite, so it may default to Lax if the SameSite features are enabled.
// Since the context used is same-site, it should always work.
- EXPECT_TRUE(content::SetCookie(
- profile, legacy_allowed_domain_url, "samesite-unspecified=1",
- net::CookieOptions::SameSiteCookieContext::SAME_SITE_LAX));
+ EXPECT_TRUE(content::SetCookie(profile, legacy_allowed_domain_url,
+ "samesite-unspecified=1",
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::SAME_SITE_LAX)));
EXPECT_EQ("samesite-unspecified=1",
content::GetCookies(profile, legacy_allowed_domain_url));
// Do the same on the other domain...
- EXPECT_TRUE(content::SetCookie(
- profile, other_domain_url, "samesite-unspecified=1",
- net::CookieOptions::SameSiteCookieContext::SAME_SITE_LAX));
+ EXPECT_TRUE(content::SetCookie(profile, other_domain_url,
+ "samesite-unspecified=1",
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::SAME_SITE_LAX)));
EXPECT_EQ("samesite-unspecified=1",
content::GetCookies(profile, other_domain_url));
@@ -169,38 +180,48 @@ IN_PROC_BROWSER_TEST_P(SameSiteCookiesPolicyTest,
// disabled.)
EXPECT_TRUE(content::SetCookie(
profile, legacy_allowed_domain_url, "samesite-unspecified=2",
- net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE)));
EXPECT_EQ("samesite-unspecified=2",
content::GetCookies(profile, legacy_allowed_domain_url));
EXPECT_EQ("samesite-unspecified=2",
- content::GetCookies(
- profile, legacy_allowed_domain_url,
- net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ content::GetCookies(profile, legacy_allowed_domain_url,
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::CROSS_SITE)));
// For the domain that is not Legacy by policy, we expect it to work only if
// the SameSite features are disabled.
if (AreSameSiteFeaturesEnabled()) {
- EXPECT_FALSE(content::SetCookie(
- profile, other_domain_url, "samesite-unspecified=2",
- net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ EXPECT_FALSE(
+ content::SetCookie(profile, other_domain_url, "samesite-unspecified=2",
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::CROSS_SITE)));
EXPECT_EQ("samesite-unspecified=1",
content::GetCookies(profile, other_domain_url));
- EXPECT_EQ("", content::GetCookies(
- profile, other_domain_url,
- net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ EXPECT_EQ(
+ "", content::GetCookies(profile, other_domain_url,
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::CROSS_SITE)));
} else {
- EXPECT_TRUE(content::SetCookie(
- profile, other_domain_url, "samesite-unspecified=2",
- net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ EXPECT_TRUE(
+ content::SetCookie(profile, other_domain_url, "samesite-unspecified=2",
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::CROSS_SITE)));
EXPECT_EQ("samesite-unspecified=2",
content::GetCookies(profile, other_domain_url));
- EXPECT_EQ("samesite-unspecified=2",
- content::GetCookies(
- profile, other_domain_url,
- net::CookieOptions::SameSiteCookieContext::CROSS_SITE));
+ EXPECT_EQ(
+ "samesite-unspecified=2",
+ content::GetCookies(profile, other_domain_url,
+ net::CookieOptions::SameSiteCookieContext(
+ net::CookieOptions::SameSiteCookieContext::
+ ContextType::CROSS_SITE)));
}
}
-INSTANTIATE_TEST_SUITE_P(/* no label */,
+INSTANTIATE_TEST_SUITE_P(All,
SameSiteCookiesPolicyTest,
::testing::Bool());
diff --git a/chromium/chrome/browser/net/secure_dns_policy_handler.cc b/chromium/chrome/browser/net/secure_dns_policy_handler.cc
index 879d2724e6e..db21b9f4747 100644
--- a/chromium/chrome/browser/net/secure_dns_policy_handler.cc
+++ b/chromium/chrome/browser/net/secure_dns_policy_handler.cc
@@ -4,9 +4,10 @@
#include "chrome/browser/net/secure_dns_policy_handler.h"
+#include <string>
+
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
#include "base/values.h"
#include "chrome/browser/net/dns_util.h"
#include "chrome/browser/prefs/session_startup_pref.h"
@@ -16,6 +17,7 @@
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_value_map.h"
#include "components/strings/grit/components_strings.h"
+#include "net/dns/public/util.h"
namespace policy {
@@ -43,11 +45,9 @@ bool SecureDnsPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
if (mode_str.size() == 0) {
errors->AddError(key::kDnsOverHttpsMode, IDS_POLICY_NOT_SPECIFIED_ERROR);
mode_is_applicable = false;
- } else if (mode_str == chrome_browser_net::kDnsOverHttpsModeSecure) {
- errors->AddError(key::kDnsOverHttpsMode,
- IDS_POLICY_SECURE_DNS_MODE_NOT_SUPPORTED_ERROR);
} else if (mode_str != chrome_browser_net::kDnsOverHttpsModeOff &&
- mode_str != chrome_browser_net::kDnsOverHttpsModeAutomatic) {
+ mode_str != chrome_browser_net::kDnsOverHttpsModeAutomatic &&
+ mode_str != chrome_browser_net::kDnsOverHttpsModeSecure) {
errors->AddError(key::kDnsOverHttpsMode,
IDS_POLICY_INVALID_SECURE_DNS_MODE_ERROR);
mode_is_applicable = false;
@@ -66,7 +66,7 @@ bool SecureDnsPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
templates_is_applicable = false;
} else {
// Templates is set and is a string.
- base::StringPiece templates_str = templates->GetString();
+ const std::string& templates_str = templates->GetString();
if (templates_str.size() != 0 && !mode) {
errors->AddError(key::kDnsOverHttpsTemplates,
@@ -78,7 +78,7 @@ bool SecureDnsPolicyHandler::CheckPolicySettings(const PolicyMap& policies,
mode_str == chrome_browser_net::kDnsOverHttpsModeOff) {
errors->AddError(key::kDnsOverHttpsTemplates,
IDS_POLICY_SECURE_DNS_TEMPLATES_IRRELEVANT_MODE_ERROR);
- } else if (IsTemplatesPolicyInvalid(templates_str)) {
+ } else if (!chrome_browser_net::IsValidDohTemplateGroup(templates_str)) {
errors->AddError(key::kDnsOverHttpsTemplates,
IDS_POLICY_SECURE_DNS_TEMPLATES_INVALID_ERROR);
}
@@ -93,12 +93,11 @@ void SecureDnsPolicyHandler::ApplyPolicySettings(const PolicyMap& policies,
base::StringPiece mode_str;
if (mode && mode->is_string()) {
mode_str = mode->GetString();
- // TODO(http://crbug.com/955454): Include secure in conditional when
- // support is implemented.
- if (mode_str == chrome_browser_net::kDnsOverHttpsModeAutomatic) {
+ if (mode_str == chrome_browser_net::kDnsOverHttpsModeAutomatic ||
+ mode_str == chrome_browser_net::kDnsOverHttpsModeSecure) {
prefs->SetString(prefs::kDnsOverHttpsMode, mode_str.as_string());
} else {
- // Captures "off" and "secure".
+ // Captures "off".
prefs->SetString(prefs::kDnsOverHttpsMode,
chrome_browser_net::kDnsOverHttpsModeOff);
}
@@ -132,23 +131,6 @@ bool SecureDnsPolicyHandler::IsTemplatesPolicyNotSpecified(
return false;
}
-bool SecureDnsPolicyHandler::IsTemplatesPolicyInvalid(
- const base::StringPiece templates_str) {
- // server_method is unused, it's just to satisfy IsValidDohTemplate()'s
- // function signature
- std::string server_method;
- for (const std::string& server_template :
- SplitString(templates_str, " ", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY)) {
- if (!chrome_browser_net::IsValidDohTemplate(server_template,
- &server_method)) {
- return true;
- }
- }
-
- return false;
-}
-
bool SecureDnsPolicyHandler::ShouldSetTemplatesPref(
const base::Value* templates) {
if (!templates)
diff --git a/chromium/chrome/browser/net/secure_dns_policy_handler.h b/chromium/chrome/browser/net/secure_dns_policy_handler.h
index 8684d896057..c7becd17696 100644
--- a/chromium/chrome/browser/net/secure_dns_policy_handler.h
+++ b/chromium/chrome/browser/net/secure_dns_policy_handler.h
@@ -13,7 +13,7 @@ class PrefValueMap;
namespace policy {
-// Handles DnsOverHttpsMode policy.
+// Handles DnsOverHttpsMode and DnsOverHttpsTemplates policies.
class SecureDnsPolicyHandler : public ConfigurationPolicyHandler {
public:
SecureDnsPolicyHandler();
@@ -28,7 +28,6 @@ class SecureDnsPolicyHandler : public ConfigurationPolicyHandler {
private:
bool IsTemplatesPolicyNotSpecified(const base::Value* templates,
const base::StringPiece mode_str);
- bool IsTemplatesPolicyInvalid(const base::StringPiece templates_str);
bool ShouldSetTemplatesPref(const base::Value* templates);
diff --git a/chromium/chrome/browser/net/secure_dns_policy_handler_unittest.cc b/chromium/chrome/browser/net/secure_dns_policy_handler_unittest.cc
index 2507f53f4d5..08ab428f9e7 100644
--- a/chromium/chrome/browser/net/secure_dns_policy_handler_unittest.cc
+++ b/chromium/chrome/browser/net/secure_dns_policy_handler_unittest.cc
@@ -180,30 +180,27 @@ TEST_F(SecureDnsPolicyHandlerTest, ValidModePolicyValueAutomatic) {
EXPECT_EQ(mode, test_policy_value);
}
-// TODO(http://crbug.com/955454) This test should be modified once secure is a
-// valid policy value for DnsOverHttpsMode.
-TEST_F(SecureDnsPolicyHandlerTest, ModePolicySecureShouldError) {
- // Secure will eventually be a valid option, but for the moment it should
- // error.
+TEST_F(SecureDnsPolicyHandlerTest, ValidModePolicySecure) {
+ const std::string test_policy_value =
+ chrome_browser_net::kDnsOverHttpsModeSecure;
+
SetPolicyValue(key::kDnsOverHttpsMode,
- std::make_unique<base::Value>(
- chrome_browser_net::kDnsOverHttpsModeSecure));
+ std::make_unique<base::Value>(test_policy_value));
+
+ // The template policy requires a value if the mode is set to secure, so set
+ // it to anything.
+ SetPolicyValue(key::kDnsOverHttpsTemplates,
+ std::make_unique<base::Value>("https://foo.test/"));
CheckAndApplyPolicySettings();
- // Should have errors.
- auto expected_error =
- l10n_util::GetStringUTF16(IDS_POLICY_SECURE_DNS_MODE_NOT_SUPPORTED_ERROR);
- // The templates policy will also throw an error but we're not interested in
- // it for this test. Check the total count, but only look at the error we
- // want.
- EXPECT_EQ(errors().size(), 2U);
- EXPECT_EQ(errors().begin()->second, expected_error);
+ // Shouldn't error.
+ EXPECT_EQ(errors().size(), 0U);
std::string mode;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsMode, &mode));
- // Pref should have changed to "off."
- EXPECT_EQ(mode, chrome_browser_net::kDnsOverHttpsModeOff);
+ // Pref should now be the test value.
+ EXPECT_EQ(mode, test_policy_value);
}
TEST_F(SecureDnsPolicyHandlerTest, InvalidTemplatesPolicyValue) {
@@ -332,8 +329,6 @@ TEST_F(SecureDnsPolicyHandlerTest, TemplatesWithModeInvalid) {
EXPECT_EQ(templates, test_policy_value);
}
-// TODO(http://crbug.com/955454) These tests should be modified once secure is a
-// valid policy value for DnsOverHttpsMode.
TEST_F(SecureDnsPolicyHandlerTest, TemplatesNotSetWithModeSecure) {
SetPolicyValue(key::kDnsOverHttpsMode,
std::make_unique<base::Value>(
@@ -341,17 +336,12 @@ TEST_F(SecureDnsPolicyHandlerTest, TemplatesNotSetWithModeSecure) {
CheckAndApplyPolicySettings();
- // Should have errors.
- // TODO(http://crbug.com/955454) Secure will eventually be a valid option, but
- // for the moment it should error.
- auto expected_error1 =
- l10n_util::GetStringUTF16(IDS_POLICY_SECURE_DNS_MODE_NOT_SUPPORTED_ERROR);
- auto expected_error2 = l10n_util::GetStringUTF16(
+ // Should have an error.
+ auto expected_error = l10n_util::GetStringUTF16(
IDS_POLICY_SECURE_DNS_TEMPLATES_NOT_SPECIFIED_ERROR);
- ASSERT_EQ(errors().size(), 2U);
+ ASSERT_EQ(errors().size(), 1U);
auto it = errors().begin();
- EXPECT_EQ(it++->second, expected_error1);
- EXPECT_EQ(it->second, expected_error2);
+ EXPECT_EQ(it->second, expected_error);
// Pref should be set.
std::string templates;
@@ -369,17 +359,12 @@ TEST_F(SecureDnsPolicyHandlerTest, TemplatesNotStringWithModeSecure) {
CheckAndApplyPolicySettings();
- // Should have errors.
- // TODO(http://crbug.com/955454) Secure will eventually be a valid option, but
- // for the moment it should error.
- auto expected_error1 =
- l10n_util::GetStringUTF16(IDS_POLICY_SECURE_DNS_MODE_NOT_SUPPORTED_ERROR);
- auto expected_error2 = l10n_util::GetStringUTF16(
+ // Should have an error.
+ auto expected_error = l10n_util::GetStringUTF16(
IDS_POLICY_SECURE_DNS_TEMPLATES_NOT_SPECIFIED_ERROR);
- ASSERT_EQ(errors().size(), 2U);
+ ASSERT_EQ(errors().size(), 1U);
auto it = errors().begin();
- EXPECT_EQ(it++->second, expected_error1);
- EXPECT_EQ(it->second, expected_error2);
+ EXPECT_EQ(it->second, expected_error);
// Pref should be set.
std::string templates;
@@ -398,16 +383,11 @@ TEST_F(SecureDnsPolicyHandlerTest, TemplatesEmptyWithModeSecure) {
CheckAndApplyPolicySettings();
- // Should have errors.
- // TODO(http://crbug.com/955454) For now the value "secure" for the mode
- // policy will throw an error but we're not interested in it for this test.
- // Check the total count but only look at the error we want. Modify this test
- // when "secure" becomes valid.
+ // Should have an error.
auto expected_error = l10n_util::GetStringUTF16(
IDS_POLICY_SECURE_DNS_TEMPLATES_NOT_SPECIFIED_ERROR);
- ASSERT_EQ(errors().size(), 2U);
+ ASSERT_EQ(errors().size(), 1U);
auto it = errors().begin();
- ++it;
EXPECT_EQ(it->second, expected_error);
// Pref should be set.
@@ -461,8 +441,6 @@ TEST_F(SecureDnsPolicyHandlerTest, TemplatesPolicyWithModeAutomatic) {
EXPECT_EQ(templates, test_policy_value);
}
-// TODO(http://crbug.com/955454) This test should be modified once secure is a
-// valid policy value for DnsOverHttpsMode.
TEST_F(SecureDnsPolicyHandlerTest, TemplatesPolicyWithModeSecure) {
// The templates policy requires a valid Mode policy or it will give an error
// we're not testing for.
@@ -477,11 +455,8 @@ TEST_F(SecureDnsPolicyHandlerTest, TemplatesPolicyWithModeSecure) {
CheckAndApplyPolicySettings();
- // Should have an error
- auto expected_error =
- l10n_util::GetStringUTF16(IDS_POLICY_SECURE_DNS_MODE_NOT_SUPPORTED_ERROR);
- EXPECT_EQ(errors().size(), 1U);
- EXPECT_EQ(errors().begin()->second, expected_error);
+ // Shouldn't error.
+ EXPECT_EQ(errors().size(), 0U);
std::string templates;
EXPECT_TRUE(prefs().GetString(prefs::kDnsOverHttpsTemplates, &templates));
diff --git a/chromium/chrome/browser/net/stub_resolver_config_reader.cc b/chromium/chrome/browser/net/stub_resolver_config_reader.cc
new file mode 100644
index 00000000000..a7ecf47d1be
--- /dev/null
+++ b/chromium/chrome/browser/net/stub_resolver_config_reader.cc
@@ -0,0 +1,388 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/net/stub_resolver_config_reader.h"
+
+#include <set>
+#include <string>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_piece.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/net/dns_util.h"
+#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/pref_names.h"
+#include "components/flags_ui/pref_service_flags_storage.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/network_service_instance.h"
+#include "net/dns/public/util.h"
+#include "services/network/public/mojom/host_resolver.mojom.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+
+#if defined(OS_ANDROID)
+#include "base/android/build_info.h"
+#endif
+
+#if defined(OS_WIN)
+#include "base/enterprise_util.h"
+#include "base/win/windows_version.h"
+#include "chrome/browser/win/parental_controls.h"
+#endif
+
+namespace {
+
+// Detailed descriptions of the secure DNS mode. These values are logged to UMA.
+// Entries should not be renumbered and numeric values should never be reused.
+// Please keep in sync with "SecureDnsModeDetails" in
+// src/tools/metrics/histograms/enums.xml.
+enum class SecureDnsModeDetailsForHistogram {
+ // The mode is controlled by the user and is set to 'off'.
+ kOffByUser = 0,
+ // The mode is controlled via enterprise policy and is set to 'off'.
+ kOffByEnterprisePolicy = 1,
+ // Chrome detected a managed environment and forced the mode to 'off'.
+ kOffByDetectedManagedEnvironment = 2,
+ // Chrome detected parental controls and forced the mode to 'off'.
+ kOffByDetectedParentalControls = 3,
+ // The mode is controlled by the user and is set to 'automatic' (the default
+ // mode).
+ kAutomaticByUser = 4,
+ // The mode is controlled via enterprise policy and is set to 'automatic'.
+ kAutomaticByEnterprisePolicy = 5,
+ // The mode is controlled by the user and is set to 'secure'.
+ kSecureByUser = 6,
+ // The mode is controlled via enterprise policy and is set to 'secure'.
+ kSecureByEnterprisePolicy = 7,
+ kMaxValue = kSecureByEnterprisePolicy,
+};
+
+#if defined(OS_WIN)
+bool ShouldDisableDohForWindowsParentalControls() {
+ const WinParentalControls& parental_controls = GetWinParentalControls();
+ if (parental_controls.web_filter)
+ return true;
+
+ // Some versions before Windows 8 may not fully support |web_filter|, so
+ // conservatively disable doh for any recognized parental controls.
+ if (parental_controls.any_restrictions &&
+ base::win::GetVersion() < base::win::Version::WIN8) {
+ return true;
+ }
+
+ return false;
+}
+#endif // defined(OS_WIN)
+
+// Check the AsyncDns field trial and return true if it should be enabled. On
+// Android this includes checking the Android version in the field trial.
+bool ShouldEnableAsyncDns() {
+ bool feature_can_be_enabled = true;
+#if defined(OS_ANDROID)
+ int min_sdk =
+ base::GetFieldTrialParamByFeatureAsInt(features::kAsyncDns, "min_sdk", 0);
+ if (base::android::BuildInfo::GetInstance()->sdk_int() < min_sdk)
+ feature_can_be_enabled = false;
+#endif
+ return feature_can_be_enabled &&
+ base::FeatureList::IsEnabled(features::kAsyncDns);
+}
+
+} // namespace
+
+// static
+constexpr base::TimeDelta StubResolverConfigReader::kParentalControlsCheckDelay;
+
+StubResolverConfigReader::StubResolverConfigReader(PrefService* local_state,
+ bool set_up_pref_defaults)
+ : local_state_(local_state) {
+ base::RepeatingClosure pref_callback =
+ base::BindRepeating(&StubResolverConfigReader::UpdateNetworkService,
+ base::Unretained(this), false /* record_metrics */);
+
+ pref_change_registrar_.Init(local_state_);
+
+ // Update the DnsClient and DoH default preferences based on the corresponding
+ // features before registering change callbacks for these preferences.
+ // Changing prefs or defaults after registering change callbacks could result
+ // in reentrancy and mess up registration between this code and NetworkService
+ // creation.
+ if (set_up_pref_defaults) {
+ local_state_->SetDefaultPrefValue(prefs::kBuiltInDnsClientEnabled,
+ base::Value(ShouldEnableAsyncDns()));
+ std::string default_doh_mode = chrome_browser_net::kDnsOverHttpsModeOff;
+ std::string default_doh_templates;
+ if (base::FeatureList::IsEnabled(features::kDnsOverHttps)) {
+ if (features::kDnsOverHttpsFallbackParam.Get()) {
+ default_doh_mode = chrome_browser_net::kDnsOverHttpsModeAutomatic;
+ } else {
+ default_doh_mode = chrome_browser_net::kDnsOverHttpsModeSecure;
+ }
+ default_doh_templates = features::kDnsOverHttpsTemplatesParam.Get();
+ }
+ local_state_->SetDefaultPrefValue(prefs::kDnsOverHttpsMode,
+ base::Value(default_doh_mode));
+ local_state_->SetDefaultPrefValue(prefs::kDnsOverHttpsTemplates,
+ base::Value(default_doh_templates));
+
+ // If the user has explicitly enabled or disabled the DoH experiment in
+ // chrome://flags and the DoH UI setting is not visible, store that choice
+ // in the user prefs so that it can be persisted after the experiment ends.
+ // Also make sure to remove the stored prefs value if the user has changed
+ // their chrome://flags selection to the default.
+ if (!features::kDnsOverHttpsShowUiParam.Get()) {
+ flags_ui::PrefServiceFlagsStorage flags_storage(local_state_);
+ std::set<std::string> entries = flags_storage.GetFlags();
+ if (entries.count("dns-over-https@1")) {
+ // The user has "Enabled" selected.
+ local_state_->SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeAutomatic);
+ } else if (entries.count("dns-over-https@2")) {
+ // The user has "Disabled" selected.
+ local_state_->SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeOff);
+ } else {
+ // The user has "Default" selected.
+ local_state_->ClearPref(prefs::kDnsOverHttpsMode);
+ }
+ }
+ }
+
+ pref_change_registrar_.Add(prefs::kBuiltInDnsClientEnabled, pref_callback);
+ pref_change_registrar_.Add(prefs::kDnsOverHttpsMode, pref_callback);
+ pref_change_registrar_.Add(prefs::kDnsOverHttpsTemplates, pref_callback);
+
+ parental_controls_delay_timer_.Start(
+ FROM_HERE, kParentalControlsCheckDelay,
+ base::BindOnce(&StubResolverConfigReader::OnParentalControlsDelayTimer,
+ base::Unretained(this)));
+}
+
+// static
+void StubResolverConfigReader::RegisterPrefs(PrefRegistrySimple* registry) {
+ // Register the DnsClient and DoH preferences. The feature list has not been
+ // initialized yet, so setting the preference defaults here to reflect the
+ // corresponding features will only cause the preference defaults to reflect
+ // the feature defaults (feature values set via the command line will not be
+ // captured). Thus, the preference defaults are updated in the constructor
+ // for SystemNetworkContextManager, at which point the feature list is ready.
+ registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, false);
+ registry->RegisterStringPref(prefs::kDnsOverHttpsMode, std::string());
+ registry->RegisterStringPref(prefs::kDnsOverHttpsTemplates, std::string());
+}
+
+void StubResolverConfigReader::GetConfiguration(
+ bool force_check_parental_controls_for_automatic_mode,
+ bool* insecure_stub_resolver_enabled,
+ net::DnsConfig::SecureDnsMode* secure_dns_mode,
+ std::vector<net::DnsOverHttpsServerConfig>* dns_over_https_servers,
+ chrome_browser_net::SecureDnsUiManagementMode* forced_management_mode) {
+ GetAndUpdateConfiguration(force_check_parental_controls_for_automatic_mode,
+ false /* record_metrics */,
+ false /* update_network_service */,
+ insecure_stub_resolver_enabled, secure_dns_mode,
+ dns_over_https_servers, forced_management_mode);
+}
+
+void StubResolverConfigReader::UpdateNetworkService(bool record_metrics) {
+ GetAndUpdateConfiguration(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ record_metrics, true /* update_network_service */,
+ nullptr /* insecure_stub_resolver_enabled */,
+ nullptr /* secure_dns_mode */, nullptr /* dns_over_https_servers */,
+ nullptr /* forced_management_mode */);
+}
+
+bool StubResolverConfigReader::ShouldDisableDohForManaged() {
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+ if (g_browser_process->browser_policy_connector()->HasMachineLevelPolicies())
+ return true;
+#endif
+#if defined(OS_WIN)
+ if (base::IsMachineExternallyManaged())
+ return true;
+#endif
+ return false;
+}
+
+bool StubResolverConfigReader::ShouldDisableDohForParentalControls() {
+#if defined(OS_WIN)
+ return ShouldDisableDohForWindowsParentalControls();
+#endif
+
+ return false;
+}
+
+void StubResolverConfigReader::OnParentalControlsDelayTimer() {
+ DCHECK(!parental_controls_delay_timer_.IsRunning());
+
+ // No need to act if parental controls were checked early.
+ if (parental_controls_checked_)
+ return;
+ parental_controls_checked_ = true;
+
+ // If parental controls are enabled, force a config change so secure DNS can
+ // be disabled.
+ if (ShouldDisableDohForParentalControls())
+ UpdateNetworkService(false /* record_metrics */);
+}
+
+void StubResolverConfigReader::GetAndUpdateConfiguration(
+ bool force_check_parental_controls_for_automatic_mode,
+ bool record_metrics,
+ bool update_network_service,
+ bool* out_insecure_stub_resolver_enabled,
+ net::DnsConfig::SecureDnsMode* out_secure_dns_mode,
+ std::vector<net::DnsOverHttpsServerConfig>* out_dns_over_https_servers,
+ chrome_browser_net::SecureDnsUiManagementMode* out_forced_management_mode) {
+ DCHECK(!out_dns_over_https_servers || out_dns_over_https_servers->empty());
+
+ bool insecure_stub_resolver_enabled =
+ local_state_->GetBoolean(prefs::kBuiltInDnsClientEnabled);
+
+ std::string doh_mode;
+ SecureDnsModeDetailsForHistogram mode_details;
+ chrome_browser_net::SecureDnsUiManagementMode forced_management_mode =
+ chrome_browser_net::SecureDnsUiManagementMode::kNoOverride;
+ bool is_managed =
+ local_state_->FindPreference(prefs::kDnsOverHttpsMode)->IsManaged();
+ if (!is_managed && ShouldDisableDohForManaged()) {
+ doh_mode = chrome_browser_net::kDnsOverHttpsModeOff;
+ forced_management_mode =
+ chrome_browser_net::SecureDnsUiManagementMode::kDisabledManaged;
+ } else {
+ doh_mode = local_state_->GetString(prefs::kDnsOverHttpsMode);
+ }
+
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ bool check_parental_controls = false;
+ if (doh_mode == chrome_browser_net::kDnsOverHttpsModeSecure) {
+ secure_dns_mode = net::DnsConfig::SecureDnsMode::SECURE;
+ mode_details =
+ is_managed ? SecureDnsModeDetailsForHistogram::kSecureByEnterprisePolicy
+ : SecureDnsModeDetailsForHistogram::kSecureByUser;
+
+ // SECURE mode must always check for parental controls immediately (unless
+ // enabled through policy, which takes precedence over parental controls)
+ // because the mode allows sending DoH requests immediately.
+ check_parental_controls = !is_managed;
+ } else if (doh_mode == chrome_browser_net::kDnsOverHttpsModeAutomatic) {
+ secure_dns_mode = net::DnsConfig::SecureDnsMode::AUTOMATIC;
+ mode_details =
+ is_managed
+ ? SecureDnsModeDetailsForHistogram::kAutomaticByEnterprisePolicy
+ : SecureDnsModeDetailsForHistogram::kAutomaticByUser;
+
+ // To avoid impacting startup performance, AUTOMATIC mode should defer
+ // checking parental for a short period. This delay should have no practical
+ // effect on DoH queries because DoH enabling probes do not start until a
+ // longer period after startup.
+ bool allow_check_parental_controls =
+ force_check_parental_controls_for_automatic_mode ||
+ parental_controls_checked_;
+ check_parental_controls = !is_managed && allow_check_parental_controls;
+ } else {
+ secure_dns_mode = net::DnsConfig::SecureDnsMode::OFF;
+ switch (forced_management_mode) {
+ case chrome_browser_net::SecureDnsUiManagementMode::kNoOverride:
+ mode_details =
+ is_managed
+ ? SecureDnsModeDetailsForHistogram::kOffByEnterprisePolicy
+ : SecureDnsModeDetailsForHistogram::kOffByUser;
+ break;
+ case chrome_browser_net::SecureDnsUiManagementMode::kDisabledManaged:
+ mode_details =
+ SecureDnsModeDetailsForHistogram::kOffByDetectedManagedEnvironment;
+ break;
+ case chrome_browser_net::SecureDnsUiManagementMode::
+ kDisabledParentalControls:
+ NOTREACHED();
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ // No need to check for parental controls if DoH is already disabled.
+ check_parental_controls = false;
+ }
+
+ // Check parental controls last because it can be expensive and should only be
+ // checked if necessary for the otherwise-determined mode.
+ if (check_parental_controls) {
+ if (ShouldDisableDohForParentalControls()) {
+ forced_management_mode = chrome_browser_net::SecureDnsUiManagementMode::
+ kDisabledParentalControls;
+ secure_dns_mode = net::DnsConfig::SecureDnsMode::OFF;
+ mode_details =
+ SecureDnsModeDetailsForHistogram::kOffByDetectedParentalControls;
+
+ // If parental controls had not previously been checked, need to update
+ // network service.
+ if (!parental_controls_checked_)
+ update_network_service = true;
+ }
+
+ parental_controls_checked_ = true;
+ }
+
+ if (record_metrics) {
+ UMA_HISTOGRAM_ENUMERATION("Net.DNS.DnsConfig.SecureDnsMode", mode_details);
+ }
+
+ std::string doh_templates =
+ local_state_->GetString(prefs::kDnsOverHttpsTemplates);
+ std::string server_method;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+ base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>
+ servers_mojo;
+ if (!doh_templates.empty() &&
+ secure_dns_mode != net::DnsConfig::SecureDnsMode::OFF) {
+ for (base::StringPiece server_template :
+ chrome_browser_net::SplitDohTemplateGroup(doh_templates)) {
+ if (!net::dns_util::IsValidDohTemplate(server_template, &server_method)) {
+ continue;
+ }
+
+ bool use_post = server_method == "POST";
+ dns_over_https_servers.emplace_back(std::string(server_template),
+ use_post);
+
+ if (!servers_mojo.has_value()) {
+ servers_mojo = base::make_optional<
+ std::vector<network::mojom::DnsOverHttpsServerPtr>>();
+ }
+
+ network::mojom::DnsOverHttpsServerPtr server_mojo =
+ network::mojom::DnsOverHttpsServer::New();
+ server_mojo->server_template = std::string(server_template);
+ server_mojo->use_post = use_post;
+ servers_mojo->emplace_back(std::move(server_mojo));
+ }
+ }
+
+ if (update_network_service) {
+ content::GetNetworkService()->ConfigureStubHostResolver(
+ insecure_stub_resolver_enabled, secure_dns_mode,
+ std::move(servers_mojo));
+ }
+
+ if (out_insecure_stub_resolver_enabled)
+ *out_insecure_stub_resolver_enabled = insecure_stub_resolver_enabled;
+ if (out_secure_dns_mode)
+ *out_secure_dns_mode = secure_dns_mode;
+ if (out_dns_over_https_servers)
+ *out_dns_over_https_servers = std::move(dns_over_https_servers);
+ if (out_forced_management_mode)
+ *out_forced_management_mode = forced_management_mode;
+}
diff --git a/chromium/chrome/browser/net/stub_resolver_config_reader.h b/chromium/chrome/browser/net/stub_resolver_config_reader.h
new file mode 100644
index 00000000000..14289873c0d
--- /dev/null
+++ b/chromium/chrome/browser/net/stub_resolver_config_reader.h
@@ -0,0 +1,104 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NET_STUB_RESOLVER_CONFIG_READER_H_
+#define CHROME_BROWSER_NET_STUB_RESOLVER_CONFIG_READER_H_
+
+#include <vector>
+
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "components/prefs/pref_change_registrar.h"
+#include "net/dns/dns_config.h"
+#include "net/dns/public/dns_over_https_server_config.h"
+#include "services/network/public/mojom/host_resolver.mojom-forward.h"
+
+class PrefRegistrySimple;
+class PrefService;
+
+namespace chrome_browser_net {
+enum class SecureDnsUiManagementMode;
+} // namespace chrome_browser_net
+
+// Retriever for Chrome configuration for the built-in DNS stub resolver.
+class StubResolverConfigReader {
+ public:
+ static constexpr base::TimeDelta kParentalControlsCheckDelay =
+ base::TimeDelta::FromSeconds(2);
+
+ // |local_state| must outlive the created reader.
+ explicit StubResolverConfigReader(PrefService* local_state,
+ bool set_up_pref_defaults = true);
+
+ StubResolverConfigReader(const StubResolverConfigReader&) = delete;
+ StubResolverConfigReader& operator=(const StubResolverConfigReader&) = delete;
+
+ virtual ~StubResolverConfigReader() = default;
+
+ static void RegisterPrefs(PrefRegistrySimple* registry);
+
+ // Returns the current host resolver configuration.
+ //
+ // Initial checks for parental controls (which cause DoH to be disabled) may
+ // be deferred for performance if called early during startup, if the
+ // configuration is otherwise in AUTOMATIC mode. If this is undesirable, e.g.
+ // because this is being called to populate the config UI, set
+ // |force_check_parental_controls_for_automatic_mode| to force always waiting
+ // for the parental controls check. If forcing the check when it had
+ // previously been deferred, and the check discovers that DoH should be
+ // disabled, the network service will be updated to disable DoH and ensure the
+ // service behavior matches the config returned by this method.
+ //
+ // |forced_management_mode| is an optional param that will be set to indicate
+ // the type of override applied by Chrome if provided.
+ void GetConfiguration(
+ bool force_check_parental_controls_for_automatic_mode,
+ bool* insecure_stub_resolver_enabled,
+ net::DnsConfig::SecureDnsMode* secure_dns_mode,
+ std::vector<net::DnsOverHttpsServerConfig>* dns_over_https_servers,
+ chrome_browser_net::SecureDnsUiManagementMode* forced_management_mode =
+ nullptr);
+
+ // Updates the network service with the current configuration.
+ void UpdateNetworkService(bool record_metrics);
+
+ // Returns true if there are any active machine level policies or if the
+ // machine is domain joined. This special logic is used to disable DoH by
+ // default for Desktop platforms (the enterprise policy field
+ // default_for_enterprise_users only applies to ChromeOS). We don't attempt
+ // enterprise detection on Android at this time.
+ virtual bool ShouldDisableDohForManaged();
+
+ // Returns true if there are parental controls detected on the device.
+ virtual bool ShouldDisableDohForParentalControls();
+
+ private:
+ void OnParentalControlsDelayTimer();
+
+ // Updates network service if |update_network_service| or if necessary due to
+ // first read of parental controls.
+ void GetAndUpdateConfiguration(
+ bool force_check_parental_controls_for_automatic_mode,
+ bool record_metrics,
+ bool update_network_service,
+ bool* insecure_stub_resolver_enabled,
+ net::DnsConfig::SecureDnsMode* secure_dns_mode,
+ std::vector<net::DnsOverHttpsServerConfig>* dns_over_https_servers,
+ chrome_browser_net::SecureDnsUiManagementMode* forced_management_mode);
+
+ PrefService* const local_state_;
+
+ // Timer for deferred running of parental controls checks. Underling API calls
+ // may be slow and run off-thread. Calling for the result is delayed to avoid
+ // blocking during startup.
+ base::OneShotTimer parental_controls_delay_timer_;
+ // Whether or not parental controls have already been checked, either due to
+ // expiration of the delay timer or because of a forced check.
+ bool parental_controls_checked_ = false;
+
+ PrefChangeRegistrar pref_change_registrar_;
+};
+
+#endif // CHROME_BROWSER_NET_STUB_RESOLVER_CONFIG_READER_H_
diff --git a/chromium/chrome/browser/net/stub_resolver_config_reader_unittest.cc b/chromium/chrome/browser/net/stub_resolver_config_reader_unittest.cc
new file mode 100644
index 00000000000..731c9e1161e
--- /dev/null
+++ b/chromium/chrome/browser/net/stub_resolver_config_reader_unittest.cc
@@ -0,0 +1,356 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/net/stub_resolver_config_reader.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/test/task_environment.h"
+#include "base/values.h"
+#include "chrome/browser/net/dns_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/scoped_testing_local_state.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_service.h"
+#include "content/public/test/browser_task_environment.h"
+#include "net/dns/dns_config.h"
+#include "net/dns/public/dns_over_https_server_config.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+constexpr char kDohServerTemplate[] =
+ "https://doh1.test https://doh2.test/query{?dns}";
+
+// Override the reader to mock out the ShouldDisableDohFor...() methods.
+class MockedStubResolverConfigReader : public StubResolverConfigReader {
+ public:
+ explicit MockedStubResolverConfigReader(PrefService* local_state)
+ : StubResolverConfigReader(local_state,
+ false /* set_up_pref_defaults */) {}
+
+ bool ShouldDisableDohForManaged() override { return disable_for_managed_; }
+
+ bool ShouldDisableDohForParentalControls() override {
+ parental_controls_checked_ = true;
+ return disable_for_parental_controls_;
+ }
+
+ void set_disable_for_managed() { disable_for_managed_ = true; }
+
+ void set_disable_for_parental_controls() {
+ disable_for_parental_controls_ = true;
+ }
+
+ bool parental_controls_checked() { return parental_controls_checked_; }
+
+ private:
+ bool disable_for_managed_ = false;
+ bool disable_for_parental_controls_ = false;
+
+ bool parental_controls_checked_ = false;
+};
+
+class StubResolverConfigReaderTest : public testing::Test {
+ public:
+ StubResolverConfigReaderTest() {
+ StubResolverConfigReader::RegisterPrefs(local_state_.registry());
+ }
+
+ protected:
+ content::BrowserTaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ TestingPrefServiceSimple local_state_;
+ std::unique_ptr<MockedStubResolverConfigReader> config_reader_ =
+ std::make_unique<MockedStubResolverConfigReader>(&local_state_);
+};
+
+TEST_F(StubResolverConfigReaderTest, GetConfiguration) {
+ bool insecure_stub_resolver_enabled;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+
+ // |force_check_parental_controls_for_automatic_mode = true| is not the main
+ // default case, but the specific behavior involved is tested separately.
+ config_reader_->GetConfiguration(
+ true /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ EXPECT_FALSE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::OFF);
+ EXPECT_TRUE(dns_over_https_servers.empty());
+
+ // Parental controls should not be checked when DoH otherwise disabled.
+ EXPECT_FALSE(config_reader_->parental_controls_checked());
+}
+
+TEST_F(StubResolverConfigReaderTest, DohEnabled) {
+ local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true);
+ local_state_.SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeAutomatic);
+ local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate);
+
+ bool insecure_stub_resolver_enabled;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+
+ // |force_check_parental_controls_for_automatic_mode = true| is not the main
+ // default case, but the specific behavior involved is tested separately.
+ config_reader_->GetConfiguration(
+ true /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::AUTOMATIC);
+ EXPECT_THAT(dns_over_https_servers,
+ testing::ElementsAre(
+ net::DnsOverHttpsServerConfig("https://doh1.test",
+ true /* use_post */),
+ net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}",
+ false /* use_post */)));
+
+ EXPECT_TRUE(config_reader_->parental_controls_checked());
+}
+
+TEST_F(StubResolverConfigReaderTest, DohEnabled_Secure) {
+ local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true);
+ local_state_.SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeSecure);
+ local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate);
+
+ bool insecure_stub_resolver_enabled;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+
+ // |force_check_parental_controls_for_automatic_mode| should have no effect on
+ // SECURE mode, so set to false to ensure check is not deferred.
+ config_reader_->GetConfiguration(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::SECURE);
+ EXPECT_THAT(dns_over_https_servers,
+ testing::ElementsAre(
+ net::DnsOverHttpsServerConfig("https://doh1.test",
+ true /* use_post */),
+ net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}",
+ false /* use_post */)));
+
+ EXPECT_TRUE(config_reader_->parental_controls_checked());
+}
+
+TEST_F(StubResolverConfigReaderTest, DisabledForManaged) {
+ config_reader_->set_disable_for_managed();
+
+ local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true);
+ local_state_.SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeAutomatic);
+ local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate);
+
+ bool insecure_stub_resolver_enabled;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+
+ // |force_check_parental_controls_for_automatic_mode = true| is not the main
+ // default case, but the specific behavior involved is tested separately.
+ config_reader_->GetConfiguration(
+ true /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::OFF);
+ EXPECT_TRUE(dns_over_https_servers.empty());
+
+ // Parental controls should not be checked when DoH otherwise disabled.
+ EXPECT_FALSE(config_reader_->parental_controls_checked());
+}
+
+TEST_F(StubResolverConfigReaderTest, DisabledForManaged_Secure) {
+ config_reader_->set_disable_for_managed();
+
+ local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true);
+ local_state_.SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeSecure);
+ local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate);
+
+ bool insecure_stub_resolver_enabled;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+
+ config_reader_->GetConfiguration(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::OFF);
+ EXPECT_TRUE(dns_over_https_servers.empty());
+
+ // Parental controls should not be checked when DoH otherwise disabled.
+ EXPECT_FALSE(config_reader_->parental_controls_checked());
+}
+
+TEST_F(StubResolverConfigReaderTest, DisabledForParentalControls) {
+ config_reader_->set_disable_for_parental_controls();
+
+ local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true);
+ local_state_.SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeAutomatic);
+ local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate);
+
+ bool insecure_stub_resolver_enabled;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+
+ // |force_check_parental_controls_for_automatic_mode = true| is not the main
+ // default case, but the specific behavior involved is tested separately.
+ config_reader_->GetConfiguration(
+ true /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::OFF);
+ EXPECT_TRUE(dns_over_https_servers.empty());
+
+ EXPECT_TRUE(config_reader_->parental_controls_checked());
+}
+
+TEST_F(StubResolverConfigReaderTest, DisabledForParentalControls_Secure) {
+ config_reader_->set_disable_for_parental_controls();
+
+ local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true);
+ local_state_.SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeSecure);
+ local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate);
+
+ bool insecure_stub_resolver_enabled;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+
+ // |force_check_parental_controls_for_automatic_mode| should have no effect on
+ // SECURE mode, so set to false to ensure check is not deferred.
+ config_reader_->GetConfiguration(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::OFF);
+ EXPECT_TRUE(dns_over_https_servers.empty());
+
+ EXPECT_TRUE(config_reader_->parental_controls_checked());
+}
+
+TEST_F(StubResolverConfigReaderTest, DeferredParentalControlsCheck) {
+ config_reader_->set_disable_for_parental_controls();
+
+ local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true);
+ local_state_.SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeAutomatic);
+ local_state_.SetString(prefs::kDnsOverHttpsTemplates, kDohServerTemplate);
+
+ bool insecure_stub_resolver_enabled;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+
+ config_reader_->GetConfiguration(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ // Parental controls check initially skipped.
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::AUTOMATIC);
+ EXPECT_THAT(dns_over_https_servers,
+ testing::ElementsAre(
+ net::DnsOverHttpsServerConfig("https://doh1.test",
+ true /* use_post */),
+ net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}",
+ false /* use_post */)));
+ EXPECT_FALSE(config_reader_->parental_controls_checked());
+
+ task_environment_.AdvanceClock(
+ StubResolverConfigReader::kParentalControlsCheckDelay);
+ task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(config_reader_->parental_controls_checked());
+
+ dns_over_https_servers.clear();
+ config_reader_->GetConfiguration(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::OFF);
+ EXPECT_TRUE(dns_over_https_servers.empty());
+}
+
+TEST_F(StubResolverConfigReaderTest, DeferredParentalControlsCheck_Managed) {
+ config_reader_->set_disable_for_managed();
+ config_reader_->set_disable_for_parental_controls();
+
+ local_state_.SetBoolean(prefs::kBuiltInDnsClientEnabled, true);
+ local_state_.SetManagedPref(
+ prefs::kDnsOverHttpsMode,
+ std::make_unique<base::Value>(
+ chrome_browser_net::kDnsOverHttpsModeAutomatic));
+ local_state_.SetManagedPref(
+ prefs::kDnsOverHttpsTemplates,
+ std::make_unique<base::Value>(kDohServerTemplate));
+
+ bool insecure_stub_resolver_enabled;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+
+ config_reader_->GetConfiguration(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ // Parental controls check initially skipped, and managed prefs take
+ // precedence over disables.
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::AUTOMATIC);
+ EXPECT_THAT(dns_over_https_servers,
+ testing::ElementsAre(
+ net::DnsOverHttpsServerConfig("https://doh1.test",
+ true /* use_post */),
+ net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}",
+ false /* use_post */)));
+ EXPECT_FALSE(config_reader_->parental_controls_checked());
+
+ task_environment_.AdvanceClock(
+ StubResolverConfigReader::kParentalControlsCheckDelay);
+ task_environment_.RunUntilIdle();
+
+ EXPECT_TRUE(config_reader_->parental_controls_checked());
+
+ dns_over_https_servers.clear();
+ config_reader_->GetConfiguration(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
+
+ // Expect DoH still enabled after parental controls check because managed
+ // prefs have precedence.
+ EXPECT_TRUE(insecure_stub_resolver_enabled);
+ EXPECT_EQ(secure_dns_mode, net::DnsConfig::SecureDnsMode::AUTOMATIC);
+ EXPECT_THAT(dns_over_https_servers,
+ testing::ElementsAre(
+ net::DnsOverHttpsServerConfig("https://doh1.test",
+ true /* use_post */),
+ net::DnsOverHttpsServerConfig("https://doh2.test/query{?dns}",
+ false /* use_post */)));
+}
+
+} // namespace
diff --git a/chromium/chrome/browser/net/system_network_context_manager.cc b/chromium/chrome/browser/net/system_network_context_manager.cc
index f862945871a..11e4953a792 100644
--- a/chromium/chrome/browser/net/system_network_context_manager.cc
+++ b/chromium/chrome/browser/net/system_network_context_manager.cc
@@ -5,7 +5,6 @@
#include "chrome/browser/net/system_network_context_manager.h"
#include <algorithm>
-#include <set>
#include <unordered_map>
#include <utility>
@@ -14,7 +13,6 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/logging.h"
-#include "base/metrics/field_trial_params.h"
#include "base/process/process_handle.h"
#include "base/sequence_checker.h"
#include "base/strings/string_split.h"
@@ -24,6 +22,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/component_updater/crl_set_component_installer.h"
+#include "chrome/browser/component_updater/tls_deprecation_config_component_installer.h"
#include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h"
#include "chrome/browser/net/dns_util.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
@@ -33,8 +32,8 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/certificate_transparency/ct_known_logs.h"
-#include "components/flags_ui/pref_service_flags_storage.h"
#include "components/net_log/net_export_file_writer.h"
+#include "components/net_log/net_log_proxy_source.h"
#include "components/network_session_configurator/common/network_features.h"
#include "components/os_crypt/os_crypt.h"
#include "components/policy/core/common/policy_namespace.h"
@@ -52,6 +51,7 @@
#include "content/public/browser/network_service_instance.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/network_service_util.h"
#include "content/public/common/service_names.mojom.h"
#include "content/public/common/user_agent.h"
#include "crypto/sha2.h"
@@ -64,15 +64,10 @@
#include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "services/network/public/mojom/host_resolver.mojom.h"
#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "url/gurl.h"
-#if defined(OS_ANDROID)
-#include "base/android/build_info.h"
-#endif // defined(OS_ANDROID)
-
#if defined(OS_CHROMEOS)
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/chromeos/net/dhcp_wpad_url_client.h"
@@ -85,10 +80,6 @@
#include "ui/base/l10n/l10n_util.h"
#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
-#if defined(OS_WIN) || defined(OS_MACOSX)
-#include "content/public/common/network_service_util.h"
-#endif
-
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/common/constants.h"
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
@@ -112,71 +103,6 @@ bool g_enable_certificate_transparency = kCertificateTransparencyEnabled;
// The global instance of the SystemNetworkContextmanager.
SystemNetworkContextManager* g_system_network_context_manager = nullptr;
-void GetStubResolverConfig(
- PrefService* local_state,
- bool* insecure_stub_resolver_enabled,
- net::DnsConfig::SecureDnsMode* secure_dns_mode,
- base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>*
- dns_over_https_servers) {
- DCHECK(!dns_over_https_servers->has_value());
-
- *insecure_stub_resolver_enabled =
- local_state->GetBoolean(prefs::kBuiltInDnsClientEnabled);
-
- std::string doh_mode;
- if (!local_state->FindPreference(prefs::kDnsOverHttpsMode)->IsManaged() &&
- chrome_browser_net::ShouldDisableDohForManaged())
- doh_mode = chrome_browser_net::kDnsOverHttpsModeOff;
- else
- doh_mode = local_state->GetString(prefs::kDnsOverHttpsMode);
-
- if (doh_mode == chrome_browser_net::kDnsOverHttpsModeSecure)
- *secure_dns_mode = net::DnsConfig::SecureDnsMode::SECURE;
- else if (doh_mode == chrome_browser_net::kDnsOverHttpsModeAutomatic)
- *secure_dns_mode = net::DnsConfig::SecureDnsMode::AUTOMATIC;
- else
- *secure_dns_mode = net::DnsConfig::SecureDnsMode::OFF;
-
- std::string doh_templates =
- local_state->GetString(prefs::kDnsOverHttpsTemplates);
- std::string server_method;
- if (!doh_templates.empty() &&
- *secure_dns_mode != net::DnsConfig::SecureDnsMode::OFF) {
- for (const std::string& server_template :
- SplitString(doh_templates, " ", base::TRIM_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY)) {
- if (!chrome_browser_net::IsValidDohTemplate(server_template,
- &server_method)) {
- continue;
- }
-
- if (!dns_over_https_servers->has_value()) {
- *dns_over_https_servers = base::make_optional<
- std::vector<network::mojom::DnsOverHttpsServerPtr>>();
- }
-
- network::mojom::DnsOverHttpsServerPtr dns_over_https_server =
- network::mojom::DnsOverHttpsServer::New();
- dns_over_https_server->server_template = server_template;
- dns_over_https_server->use_post = (server_method == "POST");
- (*dns_over_https_servers)->emplace_back(std::move(dns_over_https_server));
- }
- }
-}
-
-void OnStubResolverConfigChanged(PrefService* local_state,
- const std::string& pref_name) {
- bool insecure_stub_resolver_enabled;
- net::DnsConfig::SecureDnsMode secure_dns_mode;
- base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>
- dns_over_https_servers;
- GetStubResolverConfig(local_state, &insecure_stub_resolver_enabled,
- &secure_dns_mode, &dns_over_https_servers);
- content::GetNetworkService()->ConfigureStubHostResolver(
- insecure_stub_resolver_enabled, secure_dns_mode,
- std::move(dns_over_https_servers));
-}
-
// Constructs HttpAuthStaticParams based on |local_state|.
network::mojom::HttpAuthStaticParamsPtr CreateHttpAuthStaticParams(
PrefService* local_state) {
@@ -243,20 +169,6 @@ void OnAuthPrefsChanged(PrefService* local_state,
CreateHttpAuthDynamicParams(local_state));
}
-// Check the AsyncDns field trial and return true if it should be enabled. On
-// Android this includes checking the Android version in the field trial.
-bool ShouldEnableAsyncDns() {
- bool feature_can_be_enabled = true;
-#if defined(OS_ANDROID)
- int min_sdk =
- base::GetFieldTrialParamByFeatureAsInt(features::kAsyncDns, "min_sdk", 0);
- if (base::android::BuildInfo::GetInstance()->sdk_int() < min_sdk)
- feature_can_be_enabled = false;
-#endif
- return feature_can_be_enabled &&
- base::FeatureList::IsEnabled(features::kAsyncDns);
-}
-
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
bool ShouldUseBuiltinCertVerifier(PrefService* local_state) {
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
@@ -265,7 +177,10 @@ bool ShouldUseBuiltinCertVerifier(PrefService* local_state) {
if (builtin_cert_verifier_enabled_pref->IsManaged())
return builtin_cert_verifier_enabled_pref->GetValue()->GetBool();
#endif
-
+ // Note: intentionally checking the feature state here rather than falling
+ // back to CertVerifierImpl::kDefault, as browser-side network context
+ // initializition for TrialComparisonCertVerifier depends on knowing which
+ // verifier will be used.
return base::FeatureList::IsEnabled(
net::features::kCertVerifierBuiltinFeature);
}
@@ -408,7 +323,8 @@ SystemNetworkContextManager::SystemNetworkContextManager(
: local_state_(local_state),
ssl_config_service_manager_(
SSLConfigServiceManager::CreateDefaultManager(local_state_)),
- proxy_config_monitor_(local_state_) {
+ proxy_config_monitor_(local_state_),
+ stub_resolver_config_reader_(local_state_) {
#if !defined(OS_ANDROID)
// QuicAllowed was not part of Android policy.
const base::Value* value =
@@ -423,53 +339,6 @@ SystemNetworkContextManager::SystemNetworkContextManager(
pref_change_registrar_.Init(local_state_);
- // Update the DnsClient and DoH default preferences based on the corresponding
- // features before registering change callbacks for these preferences.
- local_state_->SetDefaultPrefValue(prefs::kBuiltInDnsClientEnabled,
- base::Value(ShouldEnableAsyncDns()));
- std::string default_doh_mode = chrome_browser_net::kDnsOverHttpsModeOff;
- std::string default_doh_templates = "";
- if (base::FeatureList::IsEnabled(features::kDnsOverHttps)) {
- if (features::kDnsOverHttpsFallbackParam.Get()) {
- default_doh_mode = chrome_browser_net::kDnsOverHttpsModeAutomatic;
- } else {
- default_doh_mode = chrome_browser_net::kDnsOverHttpsModeSecure;
- }
- default_doh_templates = features::kDnsOverHttpsTemplatesParam.Get();
- }
- local_state_->SetDefaultPrefValue(prefs::kDnsOverHttpsMode,
- base::Value(default_doh_mode));
- local_state_->SetDefaultPrefValue(prefs::kDnsOverHttpsTemplates,
- base::Value(default_doh_templates));
-
- // If the user has explicitly enabled or disabled the DoH experiment in
- // chrome://flags, store that choice in the user prefs so that it can be
- // persisted after the experiment ends. Also make sure to remove the stored
- // prefs value if the user has changed their chrome://flags selection to the
- // default.
- flags_ui::PrefServiceFlagsStorage flags_storage(local_state_);
- std::set<std::string> entries = flags_storage.GetFlags();
- if (entries.count("dns-over-https@1")) {
- // The user has "Enabled" selected.
- local_state_->SetString(prefs::kDnsOverHttpsMode,
- chrome_browser_net::kDnsOverHttpsModeAutomatic);
- } else if (entries.count("dns-over-https@2")) {
- // The user has "Disabled" selected.
- local_state_->SetString(prefs::kDnsOverHttpsMode,
- chrome_browser_net::kDnsOverHttpsModeOff);
- } else {
- // The user has "Default" selected.
- local_state_->ClearPref(prefs::kDnsOverHttpsMode);
- }
-
- PrefChangeRegistrar::NamedChangeCallback dns_pref_callback =
- base::BindRepeating(&OnStubResolverConfigChanged,
- base::Unretained(local_state_));
- pref_change_registrar_.Add(prefs::kBuiltInDnsClientEnabled,
- dns_pref_callback);
- pref_change_registrar_.Add(prefs::kDnsOverHttpsMode, dns_pref_callback);
- pref_change_registrar_.Add(prefs::kDnsOverHttpsTemplates, dns_pref_callback);
-
PrefChangeRegistrar::NamedChangeCallback auth_pref_callback =
base::BindRepeating(&OnAuthPrefsChanged, base::Unretained(local_state_));
pref_change_registrar_.Add(prefs::kAuthServerWhitelist, auth_pref_callback);
@@ -511,16 +380,9 @@ SystemNetworkContextManager::~SystemNetworkContextManager() {
shared_url_loader_factory_->Shutdown();
}
+// static
void SystemNetworkContextManager::RegisterPrefs(PrefRegistrySimple* registry) {
- // Register the DnsClient and DoH preferences. The feature list has not been
- // initialized yet, so setting the preference defaults here to reflect the
- // corresponding features will only cause the preference defaults to reflect
- // the feature defaults (feature values set via the command line will not be
- // captured). Thus, the preference defaults are updated in the constructor
- // for SystemNetworkContextManager, at which point the feature list is ready.
- registry->RegisterBooleanPref(prefs::kBuiltInDnsClientEnabled, false);
- registry->RegisterStringPref(prefs::kDnsOverHttpsMode, std::string());
- registry->RegisterStringPref(prefs::kDnsOverHttpsTemplates, std::string());
+ StubResolverConfigReader::RegisterPrefs(registry);
// Static auth params
registry->RegisterStringPref(prefs::kAuthSchemes,
@@ -567,52 +429,40 @@ void SystemNetworkContextManager::RegisterPrefs(PrefRegistrySimple* registry) {
#endif
}
+// static
+StubResolverConfigReader*
+SystemNetworkContextManager::GetStubResolverConfigReader() {
+ if (stub_resolver_config_reader_for_testing_)
+ return stub_resolver_config_reader_for_testing_;
+
+ return &GetInstance()->stub_resolver_config_reader_;
+}
+
void SystemNetworkContextManager::OnNetworkServiceCreated(
network::mojom::NetworkService* network_service) {
// Disable QUIC globally, if needed.
if (!is_quic_allowed_)
network_service->DisableQuic();
+ if (content::IsOutOfProcessNetworkService()) {
+ mojo::PendingRemote<network::mojom::NetLogProxySource> proxy_source_remote;
+ mojo::PendingReceiver<network::mojom::NetLogProxySource>
+ proxy_source_receiver =
+ proxy_source_remote.InitWithNewPipeAndPassReceiver();
+ mojo::Remote<network::mojom::NetLogProxySink> proxy_sink_remote;
+ network_service->AttachNetLogProxy(
+ std::move(proxy_source_remote),
+ proxy_sink_remote.BindNewPipeAndPassReceiver());
+ if (net_log_proxy_source_)
+ net_log_proxy_source_->ShutDown();
+ net_log_proxy_source_ = std::make_unique<net_log::NetLogProxySource>(
+ std::move(proxy_source_receiver), std::move(proxy_sink_remote));
+ }
+
network_service->SetUpHttpAuth(CreateHttpAuthStaticParams(local_state_));
network_service->ConfigureHttpAuthPrefs(
CreateHttpAuthDynamicParams(local_state_));
- // TODO(lukasza): https://crbug.com/944162: Unconditionally include
- // the MIME types below in GetNeverSniffedMimeTypes in
- // services/network/cross_origin_read_blocking.cc.
- network_service->AddExtraMimeTypesForCorb(
- {"application/msexcel",
- "application/mspowerpoint",
- "application/msword",
- "application/msword-template",
- "application/pdf",
- "application/vnd.ces-quickpoint",
- "application/vnd.ces-quicksheet",
- "application/vnd.ces-quickword",
- "application/vnd.ms-excel",
- "application/vnd.ms-excel.sheet.macroenabled.12",
- "application/vnd.ms-powerpoint",
- "application/vnd.ms-powerpoint.presentation.macroenabled.12",
- "application/vnd.ms-word",
- "application/vnd.ms-word.document.12",
- "application/vnd.ms-word.document.macroenabled.12",
- "application/vnd.msword",
- "application/"
- "vnd.openxmlformats-officedocument.presentationml.presentation",
- "application/"
- "vnd.openxmlformats-officedocument.presentationml.template",
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
- "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
- "application/"
- "vnd.openxmlformats-officedocument.wordprocessingml.document",
- "application/"
- "vnd.openxmlformats-officedocument.wordprocessingml.template",
- "application/vnd.presentation-openxml",
- "application/vnd.presentation-openxmlm",
- "application/vnd.spreadsheet-openxml",
- "application/vnd.wordprocessing-openxml",
- "text/csv"});
-
int max_connections_per_proxy =
local_state_->GetInteger(prefs::kMaxConnectionsPerProxy);
if (max_connections_per_proxy != -1)
@@ -633,15 +483,7 @@ void SystemNetworkContextManager::OnNetworkServiceCreated(
// Configure the stub resolver. This must be done after the system
// NetworkContext is created, but before anything has the chance to use it.
- bool insecure_stub_resolver_enabled;
- net::DnsConfig::SecureDnsMode secure_dns_mode;
- base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>
- dns_over_https_servers;
- GetStubResolverConfig(local_state_, &insecure_stub_resolver_enabled,
- &secure_dns_mode, &dns_over_https_servers);
- content::GetNetworkService()->ConfigureStubHostResolver(
- insecure_stub_resolver_enabled, secure_dns_mode,
- std::move(dns_over_https_servers));
+ stub_resolver_config_reader_.UpdateNetworkService(true /* record_metrics */);
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
const base::CommandLine& command_line =
@@ -668,6 +510,10 @@ void SystemNetworkContextManager::OnNetworkServiceCreated(
// Asynchronously reapply the most recently received CRLSet (if any).
component_updater::CRLSetPolicy::ReconfigureAfterNetworkRestart();
+
+ // Asynchronously reapply the most recently received TLS deprecation config.
+ component_updater::TLSDeprecationConfigComponentInstallerPolicy::
+ ReconfigureAfterNetworkRestart();
}
void SystemNetworkContextManager::DisableQuic() {
@@ -780,7 +626,9 @@ SystemNetworkContextManager::CreateDefaultNetworkContextParams() {
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
network_context_params->use_builtin_cert_verifier =
- ShouldUseBuiltinCertVerifier(local_state_);
+ ShouldUseBuiltinCertVerifier(local_state_)
+ ? network::mojom::NetworkContextParams::CertVerifierImpl::kBuiltin
+ : network::mojom::NetworkContextParams::CertVerifierImpl::kSystem;
#endif
return network_context_params;
@@ -809,16 +657,6 @@ void SystemNetworkContextManager::FlushNetworkInterfaceForTesting() {
url_loader_factory_.FlushForTesting();
}
-void SystemNetworkContextManager::GetStubResolverConfigForTesting(
- bool* insecure_stub_resolver_enabled,
- net::DnsConfig::SecureDnsMode* secure_dns_mode,
- base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>*
- dns_over_https_servers) {
- GetStubResolverConfig(g_browser_process->local_state(),
- insecure_stub_resolver_enabled, secure_dns_mode,
- dns_over_https_servers);
-}
-
network::mojom::HttpAuthStaticParamsPtr
SystemNetworkContextManager::GetHttpAuthStaticParamsForTesting() {
return CreateHttpAuthStaticParams(g_browser_process->local_state());
@@ -863,3 +701,7 @@ SystemNetworkContextManager::CreateNetworkContextParams() {
void SystemNetworkContextManager::UpdateReferrersEnabled() {
GetContext()->SetEnableReferrers(enable_referrers_.GetValue());
}
+
+// static
+StubResolverConfigReader*
+SystemNetworkContextManager::stub_resolver_config_reader_for_testing_ = nullptr;
diff --git a/chromium/chrome/browser/net/system_network_context_manager.h b/chromium/chrome/browser/net/system_network_context_manager.h
index be3f37dbaa1..755ef5a9e3d 100644
--- a/chromium/chrome/browser/net/system_network_context_manager.h
+++ b/chromium/chrome/browser/net/system_network_context_manager.h
@@ -12,16 +12,18 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
+#include "chrome/browser/net/dns_util.h"
#include "chrome/browser/net/proxy_config_monitor.h"
+#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_member.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "net/dns/dns_config.h"
#include "services/network/public/mojom/host_resolver.mojom-forward.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom-forward.h"
#include "services/network/public/mojom/ssl_config.mojom-forward.h"
-#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
class PrefRegistrySimple;
class PrefService;
@@ -36,6 +38,7 @@ class SharedURLLoaderFactory;
namespace net_log {
class NetExportFileWriter;
+class NetLogProxySource;
}
// Responsible for creating and managing access to the system NetworkContext.
@@ -78,6 +81,8 @@ class SystemNetworkContextManager {
static void RegisterPrefs(PrefRegistrySimple* registry);
+ static StubResolverConfigReader* GetStubResolverConfigReader();
+
// Returns the System NetworkContext. May only be called after SetUp(). Does
// any initialization of the NetworkService that may be needed when first
// called.
@@ -131,13 +136,6 @@ class SystemNetworkContextManager {
// use only.
void FlushNetworkInterfaceForTesting();
- // Returns configuration that would be sent to the stub DNS resolver.
- static void GetStubResolverConfigForTesting(
- bool* insecure_stub_resolver_enabled,
- net::DnsConfig::SecureDnsMode* secure_dns_mode,
- base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>*
- dns_over_https_servers);
-
static network::mojom::HttpAuthStaticParamsPtr
GetHttpAuthStaticParamsForTesting();
static network::mojom::HttpAuthDynamicParamsPtr
@@ -149,6 +147,11 @@ class SystemNetworkContextManager {
static void SetEnableCertificateTransparencyForTesting(
base::Optional<bool> enabled);
+ static void set_stub_resolver_config_reader_for_testing(
+ StubResolverConfigReader* reader) {
+ stub_resolver_config_reader_for_testing_ = reader;
+ }
+
private:
class URLLoaderFactoryForSystem;
@@ -186,9 +189,17 @@ class SystemNetworkContextManager {
BooleanPrefMember enable_referrers_;
+ // Copies NetLog events from the browser process to the Network Service, if
+ // the network service is running in a separate process. It will be destroyed
+ // and re-created on Network Service crash.
+ std::unique_ptr<net_log::NetLogProxySource> net_log_proxy_source_;
+
// Initialized on first access.
std::unique_ptr<net_log::NetExportFileWriter> net_export_file_writer_;
+ StubResolverConfigReader stub_resolver_config_reader_;
+ static StubResolverConfigReader* stub_resolver_config_reader_for_testing_;
+
DISALLOW_COPY_AND_ASSIGN(SystemNetworkContextManager);
};
diff --git a/chromium/chrome/browser/net/system_network_context_manager_browsertest.cc b/chromium/chrome/browser/net/system_network_context_manager_browsertest.cc
index 1ca38b62775..742b72003f8 100644
--- a/chromium/chrome/browser/net/system_network_context_manager_browsertest.cc
+++ b/chromium/chrome/browser/net/system_network_context_manager_browsertest.cc
@@ -14,6 +14,7 @@
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/net/dns_util.h"
+#include "chrome/browser/net/stub_resolver_config_reader.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
@@ -42,13 +43,14 @@
namespace {
void GetStubResolverConfig(
+ bool force_check_parental_controls_for_automatic_mode,
bool* insecure_stub_resolver_enabled,
net::DnsConfig::SecureDnsMode* secure_dns_mode,
- base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>*
- dns_over_https_servers) {
- dns_over_https_servers->reset();
+ std::vector<net::DnsOverHttpsServerConfig>* dns_over_https_servers) {
+ dns_over_https_servers->clear();
- SystemNetworkContextManager::GetStubResolverConfigForTesting(
+ SystemNetworkContextManager::GetStubResolverConfigReader()->GetConfiguration(
+ force_check_parental_controls_for_automatic_mode,
insecure_stub_resolver_enabled, secure_dns_mode, dns_over_https_servers);
}
@@ -64,17 +66,18 @@ void RunStubResolverConfigTests(bool async_dns_feature_enabled) {
// Check initial state.
bool insecure_stub_resolver_enabled = !async_dns_feature_enabled;
net::DnsConfig::SecureDnsMode secure_dns_mode;
- base::Optional<std::vector<network::mojom::DnsOverHttpsServerPtr>>
- dns_over_https_servers;
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(async_dns_feature_enabled, insecure_stub_resolver_enabled);
if (base::FeatureList::IsEnabled(features::kDnsOverHttps)) {
EXPECT_EQ(net::DnsConfig::SecureDnsMode::AUTOMATIC, secure_dns_mode);
} else {
EXPECT_EQ(net::DnsConfig::SecureDnsMode::OFF, secure_dns_mode);
}
- EXPECT_FALSE(dns_over_https_servers.has_value());
+ EXPECT_TRUE(dns_over_https_servers.empty());
std::string good_post_template = "https://foo.test/";
std::string good_get_template = "https://bar.test/dns-query{?dns}";
@@ -88,89 +91,103 @@ void RunStubResolverConfigTests(bool async_dns_feature_enabled) {
local_state->SetString(prefs::kDnsOverHttpsMode,
chrome_browser_net::kDnsOverHttpsModeSecure);
local_state->SetString(prefs::kDnsOverHttpsTemplates, bad_template);
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(async_dns_feature_enabled, insecure_stub_resolver_enabled);
EXPECT_EQ(net::DnsConfig::SecureDnsMode::SECURE, secure_dns_mode);
- EXPECT_FALSE(dns_over_https_servers.has_value());
+ EXPECT_TRUE(dns_over_https_servers.empty());
local_state->SetString(prefs::kDnsOverHttpsTemplates, good_post_template);
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(async_dns_feature_enabled, insecure_stub_resolver_enabled);
EXPECT_EQ(net::DnsConfig::SecureDnsMode::SECURE, secure_dns_mode);
- ASSERT_TRUE(dns_over_https_servers.has_value());
- ASSERT_EQ(1u, dns_over_https_servers->size());
- EXPECT_EQ(good_post_template, dns_over_https_servers->at(0)->server_template);
- EXPECT_EQ(true, dns_over_https_servers->at(0)->use_post);
+ ASSERT_EQ(1u, dns_over_https_servers.size());
+ EXPECT_EQ(good_post_template, dns_over_https_servers.at(0).server_template);
+ EXPECT_EQ(true, dns_over_https_servers.at(0).use_post);
local_state->SetString(prefs::kDnsOverHttpsMode,
chrome_browser_net::kDnsOverHttpsModeAutomatic);
local_state->SetString(prefs::kDnsOverHttpsTemplates, bad_template);
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(async_dns_feature_enabled, insecure_stub_resolver_enabled);
EXPECT_EQ(net::DnsConfig::SecureDnsMode::AUTOMATIC, secure_dns_mode);
- EXPECT_FALSE(dns_over_https_servers.has_value());
+ EXPECT_TRUE(dns_over_https_servers.empty());
local_state->SetString(prefs::kDnsOverHttpsTemplates, good_then_bad_template);
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(async_dns_feature_enabled, insecure_stub_resolver_enabled);
EXPECT_EQ(net::DnsConfig::SecureDnsMode::AUTOMATIC, secure_dns_mode);
- ASSERT_TRUE(dns_over_https_servers.has_value());
- ASSERT_EQ(1u, dns_over_https_servers->size());
- EXPECT_EQ(good_get_template, dns_over_https_servers->at(0)->server_template);
- EXPECT_FALSE(dns_over_https_servers->at(0)->use_post);
+ ASSERT_EQ(1u, dns_over_https_servers.size());
+ EXPECT_EQ(good_get_template, dns_over_https_servers.at(0).server_template);
+ EXPECT_FALSE(dns_over_https_servers.at(0).use_post);
local_state->SetString(prefs::kDnsOverHttpsTemplates, bad_then_good_template);
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(async_dns_feature_enabled, insecure_stub_resolver_enabled);
EXPECT_EQ(net::DnsConfig::SecureDnsMode::AUTOMATIC, secure_dns_mode);
- ASSERT_TRUE(dns_over_https_servers.has_value());
- ASSERT_EQ(1u, dns_over_https_servers->size());
- EXPECT_EQ(good_get_template, dns_over_https_servers->at(0)->server_template);
- EXPECT_FALSE(dns_over_https_servers->at(0)->use_post);
+ ASSERT_EQ(1u, dns_over_https_servers.size());
+ EXPECT_EQ(good_get_template, dns_over_https_servers.at(0).server_template);
+ EXPECT_FALSE(dns_over_https_servers.at(0).use_post);
local_state->SetString(prefs::kDnsOverHttpsTemplates,
multiple_good_templates);
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(async_dns_feature_enabled, insecure_stub_resolver_enabled);
EXPECT_EQ(net::DnsConfig::SecureDnsMode::AUTOMATIC, secure_dns_mode);
- ASSERT_TRUE(dns_over_https_servers.has_value());
- ASSERT_EQ(2u, dns_over_https_servers->size());
- EXPECT_EQ(good_get_template, dns_over_https_servers->at(0)->server_template);
- EXPECT_FALSE(dns_over_https_servers->at(0)->use_post);
- EXPECT_EQ(good_post_template, dns_over_https_servers->at(1)->server_template);
- EXPECT_TRUE(dns_over_https_servers->at(1)->use_post);
+ ASSERT_EQ(2u, dns_over_https_servers.size());
+ EXPECT_EQ(good_get_template, dns_over_https_servers.at(0).server_template);
+ EXPECT_FALSE(dns_over_https_servers.at(0).use_post);
+ EXPECT_EQ(good_post_template, dns_over_https_servers.at(1).server_template);
+ EXPECT_TRUE(dns_over_https_servers.at(1).use_post);
local_state->SetString(prefs::kDnsOverHttpsMode,
chrome_browser_net::kDnsOverHttpsModeOff);
local_state->SetString(prefs::kDnsOverHttpsTemplates, good_get_template);
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(async_dns_feature_enabled, insecure_stub_resolver_enabled);
EXPECT_EQ(net::DnsConfig::SecureDnsMode::OFF, secure_dns_mode);
- EXPECT_FALSE(dns_over_https_servers.has_value());
+ EXPECT_TRUE(dns_over_https_servers.empty());
local_state->SetString(prefs::kDnsOverHttpsMode, "no_match");
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(async_dns_feature_enabled, insecure_stub_resolver_enabled);
EXPECT_EQ(net::DnsConfig::SecureDnsMode::OFF, secure_dns_mode);
- EXPECT_FALSE(dns_over_https_servers.has_value());
+ EXPECT_TRUE(dns_over_https_servers.empty());
// Test case with policy BuiltInDnsClientEnabled enabled. The DoH fields
// should be unaffected.
local_state->Set(prefs::kBuiltInDnsClientEnabled,
base::Value(!async_dns_feature_enabled));
- GetStubResolverConfig(&insecure_stub_resolver_enabled, &secure_dns_mode,
- &dns_over_https_servers);
+ GetStubResolverConfig(
+ false /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers);
EXPECT_EQ(!async_dns_feature_enabled, insecure_stub_resolver_enabled);
EXPECT_EQ(net::DnsConfig::SecureDnsMode::OFF, secure_dns_mode);
- EXPECT_FALSE(dns_over_https_servers.has_value());
+ EXPECT_TRUE(dns_over_https_servers.empty());
}
} // namespace
@@ -473,9 +490,13 @@ IN_PROC_BROWSER_TEST_P(
Test) {
// If no BuiltinCertificateVerifierEnabled policy is set, the
// use_builtin_cert_verifier param should be set from the feature flag.
- EXPECT_EQ(GetParam(), g_browser_process->system_network_context_manager()
- ->CreateDefaultNetworkContextParams()
- ->use_builtin_cert_verifier);
+ EXPECT_EQ(
+ GetParam()
+ ? network::mojom::NetworkContextParams::CertVerifierImpl::kBuiltin
+ : network::mojom::NetworkContextParams::CertVerifierImpl::kSystem,
+ g_browser_process->system_network_context_manager()
+ ->CreateDefaultNetworkContextParams()
+ ->use_builtin_cert_verifier);
#if BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
// If the BuiltinCertificateVerifierEnabled policy is set it should override
// the feature flag.
@@ -483,16 +504,18 @@ IN_PROC_BROWSER_TEST_P(
SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
std::make_unique<base::Value>(true));
UpdateProviderPolicy(policies);
- EXPECT_TRUE(g_browser_process->system_network_context_manager()
- ->CreateDefaultNetworkContextParams()
- ->use_builtin_cert_verifier);
+ EXPECT_EQ(network::mojom::NetworkContextParams::CertVerifierImpl::kBuiltin,
+ g_browser_process->system_network_context_manager()
+ ->CreateDefaultNetworkContextParams()
+ ->use_builtin_cert_verifier);
SetPolicy(&policies, policy::key::kBuiltinCertificateVerifierEnabled,
std::make_unique<base::Value>(false));
UpdateProviderPolicy(policies);
- EXPECT_FALSE(g_browser_process->system_network_context_manager()
- ->CreateDefaultNetworkContextParams()
- ->use_builtin_cert_verifier);
+ EXPECT_EQ(network::mojom::NetworkContextParams::CertVerifierImpl::kSystem,
+ g_browser_process->system_network_context_manager()
+ ->CreateDefaultNetworkContextParams()
+ ->use_builtin_cert_verifier);
#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_POLICY_SUPPORTED)
}
diff --git a/chromium/chrome/browser/net/trial_comparison_cert_verifier_browsertest.cc b/chromium/chrome/browser/net/trial_comparison_cert_verifier_browsertest.cc
index 05873ef06f9..6d676834b67 100644
--- a/chromium/chrome/browser/net/trial_comparison_cert_verifier_browsertest.cc
+++ b/chromium/chrome/browser/net/trial_comparison_cert_verifier_browsertest.cc
@@ -12,7 +12,7 @@
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "net/base/features.h"
#include "net/cert/trial_comparison_cert_verifier.h"
#include "net/net_buildflags.h"
diff --git a/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.cc b/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.cc
index e86dc48c647..a6a9196252e 100644
--- a/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.cc
+++ b/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.cc
@@ -20,7 +20,7 @@
#include "chrome/browser/safe_browsing/certificate_reporting_service_factory.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_features.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/security_interstitials/content/certificate_error_report.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -106,6 +106,8 @@ void TrialComparisonCertVerifierController::SendTrialReport(
bool require_rev_checking_local_anchors,
bool enable_sha1_local_anchors,
bool disable_symantec_enforcement,
+ const std::vector<uint8_t>& stapled_ocsp,
+ const std::vector<uint8_t>& sct_list,
const net::CertVerifyResult& primary_result,
const net::CertVerifyResult& trial_result,
network::mojom::CertVerifierDebugInfoPtr debug_info) {
@@ -115,11 +117,13 @@ void TrialComparisonCertVerifierController::SendTrialReport(
return;
}
- CertificateErrorReport report(hostname, *unverified_cert, enable_rev_checking,
- require_rev_checking_local_anchors,
- enable_sha1_local_anchors,
- disable_symantec_enforcement, primary_result,
- trial_result, std::move(debug_info));
+ CertificateErrorReport report(
+ hostname, *unverified_cert, enable_rev_checking,
+ require_rev_checking_local_anchors, enable_sha1_local_anchors,
+ disable_symantec_enforcement,
+ std::string(stapled_ocsp.begin(), stapled_ocsp.end()),
+ std::string(sct_list.begin(), sct_list.end()), primary_result,
+ trial_result, std::move(debug_info));
report.AddNetworkTimeInfo(g_browser_process->network_time_tracker());
report.AddChromeChannel(chrome::GetChannel());
diff --git a/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.h b/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.h
index bbe51a8b781..e6e1b1b3b25 100644
--- a/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.h
+++ b/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller.h
@@ -58,6 +58,8 @@ class TrialComparisonCertVerifierController
bool require_rev_checking_local_anchors,
bool enable_sha1_local_anchors,
bool disable_symantec_enforcement,
+ const std::vector<uint8_t>& stapled_ocsp,
+ const std::vector<uint8_t>& sct_list,
const net::CertVerifyResult& primary_result,
const net::CertVerifyResult& trial_result,
network::mojom::CertVerifierDebugInfoPtr debug_info) override;
diff --git a/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller_unittest.cc b/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller_unittest.cc
index eea85574e45..83417a3c335 100644
--- a/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller_unittest.cc
+++ b/chromium/chrome/browser/net/trial_comparison_cert_verifier_controller_unittest.cc
@@ -21,7 +21,7 @@
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/testing_profile_manager.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/security_interstitials/content/cert_logger.pb.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/browser/browser_task_traits.h"
@@ -242,8 +242,9 @@ TEST_F(TrialComparisonCertVerifierControllerTest, NothingEnabled) {
// Attempting to send a report should also do nothing.
report_client()->SendTrialReport(
- "hostname", leaf_cert_1_, false, false, false, false, ok_result_,
- ok_result_, network::mojom::CertVerifierDebugInfo::New());
+ "hostname", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, ok_result_,
+ network::mojom::CertVerifierDebugInfo::New());
// Ensure any in-flight mojo calls get run.
base::RunLoop().RunUntilIdle();
// Expect no report since the trial is not allowed.
@@ -264,8 +265,9 @@ TEST_F(TrialComparisonCertVerifierControllerTest,
// Attempting to send a report should do nothing.
report_client()->SendTrialReport(
- "hostname", leaf_cert_1_, false, false, false, false, ok_result_,
- ok_result_, network::mojom::CertVerifierDebugInfo::New());
+ "hostname", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, ok_result_,
+ network::mojom::CertVerifierDebugInfo::New());
// Ensure any in-flight mojo calls get run.
base::RunLoop().RunUntilIdle();
@@ -300,8 +302,9 @@ TEST_F(TrialComparisonCertVerifierControllerTest,
// Attempting to send a report should do nothing.
report_client()->SendTrialReport(
- "hostname", leaf_cert_1_, false, false, false, false, ok_result_,
- ok_result_, network::mojom::CertVerifierDebugInfo::New());
+ "hostname", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, ok_result_,
+ network::mojom::CertVerifierDebugInfo::New());
// Ensure any in-flight mojo calls get run.
base::RunLoop().RunUntilIdle();
@@ -334,7 +337,8 @@ TEST_F(TrialComparisonCertVerifierControllerTest, OfficialBuildTrialEnabled) {
// Report should be sent.
report_client()->SendTrialReport(
- "127.0.0.1", leaf_cert_1_, false, false, false, false, ok_result_,
+ "127.0.0.1", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>{4, 5, 6}, std::vector<uint8_t>{7, 8, 9}, ok_result_,
bad_result_, network::mojom::CertVerifierDebugInfo::New());
// Ensure any in-flight mojo calls get run.
@@ -366,6 +370,10 @@ TEST_F(TrialComparisonCertVerifierControllerTest, OfficialBuildTrialEnabled) {
EXPECT_THAT(report.unverified_cert_chain(), CertChainMatches(leaf_cert_1_));
EXPECT_THAT(report.cert_chain(), CertChainMatches(cert_chain_1_));
EXPECT_THAT(trial_info.cert_chain(), CertChainMatches(cert_chain_2_));
+ ASSERT_TRUE(trial_info.has_stapled_ocsp());
+ EXPECT_EQ("\x04\x05\x06", trial_info.stapled_ocsp());
+ ASSERT_TRUE(trial_info.has_sct_list());
+ EXPECT_EQ("\x07\x08\x09", trial_info.sct_list());
// Disable the SBER pref again, which should trigger the OnTrialConfigUpdated
// callback.
@@ -377,8 +385,9 @@ TEST_F(TrialComparisonCertVerifierControllerTest, OfficialBuildTrialEnabled) {
// Attempting to send a report should do nothing now.
report_client()->SendTrialReport(
- "hostname", leaf_cert_1_, false, false, false, false, ok_result_,
- bad_result_, network::mojom::CertVerifierDebugInfo::New());
+ "hostname", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, bad_result_,
+ network::mojom::CertVerifierDebugInfo::New());
// Ensure any in-flight mojo calls get run.
base::RunLoop().RunUntilIdle();
// Expect no report since the trial is not allowed.
@@ -425,11 +434,13 @@ TEST_F(TrialComparisonCertVerifierControllerTest,
// Report should be sent.
report_client()->SendTrialReport(
- "127.0.0.1", leaf_cert_1_, false, false, false, false, ok_result_,
- bad_result_, network::mojom::CertVerifierDebugInfo::New());
+ "127.0.0.1", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, bad_result_,
+ network::mojom::CertVerifierDebugInfo::New());
report_client_2->SendTrialReport(
- "127.0.0.2", leaf_cert_1_, false, false, false, false, ok_result_,
- bad_result_, network::mojom::CertVerifierDebugInfo::New());
+ "127.0.0.2", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, bad_result_,
+ network::mojom::CertVerifierDebugInfo::New());
// Ensure any in-flight mojo calls get run.
base::RunLoop().RunUntilIdle();
@@ -462,6 +473,9 @@ TEST_F(TrialComparisonCertVerifierControllerTest,
EXPECT_THAT(report.unverified_cert_chain(), CertChainMatches(leaf_cert_1_));
EXPECT_THAT(report.cert_chain(), CertChainMatches(cert_chain_1_));
EXPECT_THAT(trial_info.cert_chain(), CertChainMatches(cert_chain_2_));
+
+ EXPECT_FALSE(trial_info.has_stapled_ocsp());
+ EXPECT_FALSE(trial_info.has_sct_list());
}
// Disable the SBER pref again, which should trigger the OnTrialConfigUpdated
@@ -475,11 +489,13 @@ TEST_F(TrialComparisonCertVerifierControllerTest,
// Attempting to send a report should do nothing now.
report_client()->SendTrialReport(
- "hostname", leaf_cert_1_, false, false, false, false, ok_result_,
- bad_result_, network::mojom::CertVerifierDebugInfo::New());
+ "hostname", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, bad_result_,
+ network::mojom::CertVerifierDebugInfo::New());
report_client_2->SendTrialReport(
- "hostname2", leaf_cert_1_, false, false, false, false, ok_result_,
- bad_result_, network::mojom::CertVerifierDebugInfo::New());
+ "hostname2", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, bad_result_,
+ network::mojom::CertVerifierDebugInfo::New());
// Ensure any in-flight mojo calls get run.
base::RunLoop().RunUntilIdle();
// Expect no report since the trial is not allowed.
@@ -511,8 +527,9 @@ TEST_F(TrialComparisonCertVerifierControllerTest,
// In uma_only mode, the network service will generate a report, but the
// trial controller will not send it to the reporting service.
report_client()->SendTrialReport(
- "127.0.0.1", leaf_cert_1_, false, false, false, false, ok_result_,
- bad_result_, network::mojom::CertVerifierDebugInfo::New());
+ "127.0.0.1", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, bad_result_,
+ network::mojom::CertVerifierDebugInfo::New());
// Ensure any in-flight mojo calls get run.
base::RunLoop().RunUntilIdle();
@@ -540,8 +557,9 @@ TEST_F(TrialComparisonCertVerifierControllerTest,
// Attempting to send a report should also do nothing.
report_client()->SendTrialReport(
- "hostname", leaf_cert_1_, false, false, false, false, ok_result_,
- ok_result_, network::mojom::CertVerifierDebugInfo::New());
+ "hostname", leaf_cert_1_, false, false, false, false,
+ std::vector<uint8_t>(), std::vector<uint8_t>(), ok_result_, ok_result_,
+ network::mojom::CertVerifierDebugInfo::New());
// Ensure any in-flight mojo calls get run.
base::RunLoop().RunUntilIdle();
// Expect no report since the trial is not allowed.
diff --git a/chromium/chrome/browser/net/variations_http_headers_browsertest.cc b/chromium/chrome/browser/net/variations_http_headers_browsertest.cc
index 65b41240a37..485626d43c8 100644
--- a/chromium/chrome/browser/net/variations_http_headers_browsertest.cc
+++ b/chromium/chrome/browser/net/variations_http_headers_browsertest.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
@@ -18,11 +19,13 @@
#include "chrome/browser/chrome_browser_main_extra_parts.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/network_session_configurator/common/network_switches.h"
+#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/variations/net/variations_http_headers.h"
#include "components/variations/variations_http_header_provider.h"
#include "content/public/browser/browser_context.h"
@@ -120,6 +123,10 @@ class VariationsHttpHeadersBrowserTest : public InProcessBrowserTest {
return GetGoogleUrlWithPath("/redirect2");
}
+ GURL GetGoogleSubresourceUrl() const {
+ return GetGoogleUrlWithPath("/logo.png");
+ }
+
GURL GetExampleUrlWithPath(const std::string& path) const {
return server()->GetURL("www.example.com", path);
}
@@ -136,9 +143,24 @@ class VariationsHttpHeadersBrowserTest : public InProcessBrowserTest {
return it->second.find(header) != it->second.end();
}
+ // Returns the |header| recievced by |url| or nullopt if it hasn't been
+ // received. Fails an EXPECT if |url| hasn't been observed.
+ base::Optional<std::string> GetReceivedHeader(
+ const GURL& url,
+ const std::string& header) const {
+ auto it = received_headers_.find(url);
+ EXPECT_TRUE(it != received_headers_.end());
+ if (it == received_headers_.end())
+ return base::nullopt;
+ auto it2 = it->second.find(header);
+ if (it2 == it->second.end())
+ return base::nullopt;
+ return it2->second;
+ }
+
void ClearReceivedHeaders() { received_headers_.clear(); }
- bool FetchResource(const GURL& url) {
+ bool FetchResource(Browser* browser, const GURL& url) {
if (!url.is_valid())
return false;
std::string script(
@@ -155,11 +177,13 @@ class VariationsHttpHeadersBrowserTest : public InProcessBrowserTest {
" window.domAutomationController.send(false);"
"};"
"xhr.send(null)";
- return ExecuteScript(script);
+ return ExecuteScript(browser, script);
}
- content::WebContents* GetWebContents() {
- return browser()->tab_strip_model()->GetActiveWebContents();
+ content::WebContents* GetWebContents() { return GetWebContents(browser()); }
+
+ content::WebContents* GetWebContents(Browser* browser) {
+ return browser->tab_strip_model()->GetActiveWebContents();
}
// Registers a service worker for google.com root scope.
@@ -239,11 +263,11 @@ class VariationsHttpHeadersBrowserTest : public InProcessBrowserTest {
}
private:
- bool ExecuteScript(const std::string& script) {
+ bool ExecuteScript(Browser* browser, const std::string& script) {
bool xhr_result = false;
// The JS call will fail if disallowed because the process will be killed.
- bool execute_result =
- ExecuteScriptAndExtractBool(GetWebContents(), script, &xhr_result);
+ bool execute_result = ExecuteScriptAndExtractBool(GetWebContents(browser),
+ script, &xhr_result);
return xhr_result && execute_result;
}
@@ -297,12 +321,47 @@ VariationsHttpHeadersBrowserTest::RequestHandler(
http_response->set_code(net::HTTP_OK);
http_response->set_content("hello");
http_response->set_content_type("text/plain");
+ } else if (request.relative_url == GetGoogleSubresourceUrl().path()) {
+ http_response->set_code(net::HTTP_OK);
+ http_response->set_content("");
+ http_response->set_content_type("image/png");
} else {
return nullptr;
}
return http_response;
}
+scoped_refptr<base::FieldTrial> CreateTrialAndAssociateId(
+ const std::string& trial_name,
+ const std::string& default_group_name,
+ variations::IDCollectionKey key,
+ variations::VariationID id) {
+ AssociateGoogleVariationID(key, trial_name, default_group_name, id);
+ scoped_refptr<base::FieldTrial> trial(
+ base::FieldTrialList::CreateFieldTrial(trial_name, default_group_name));
+ EXPECT_TRUE(trial);
+
+ if (trial) {
+ // Ensure the trial is registered under the correct key so we can look it
+ // up.
+ trial->group();
+ }
+
+ return trial;
+}
+
+// Sets up a FieldTrial for Google properites when signed in.
+void CreateGoogleSignedInFieldTrial() {
+ const std::string default_name = "default";
+ scoped_refptr<base::FieldTrial> trial_1(CreateTrialAndAssociateId(
+ "t1", default_name, variations::GOOGLE_WEB_PROPERTIES_SIGNED_IN, 123));
+
+ auto* variations_http_header_provider =
+ variations::VariationsHttpHeaderProvider::GetInstance();
+ EXPECT_NE(variations_http_header_provider->GetClientDataHeader(true),
+ variations_http_header_provider->GetClientDataHeader(false));
+}
+
} // namespace
// Verify in an integration test that the variations header (X-Client-Data) is
@@ -323,13 +382,57 @@ IN_PROC_BROWSER_TEST_F(VariationsHttpHeadersBrowserTest,
TestStrippingHeadersFromSubresourceRequest) {
GURL url = server()->GetURL("/simple_page.html");
ui_test_utils::NavigateToURL(browser(), url);
- EXPECT_TRUE(FetchResource(GetGoogleRedirectUrl1()));
+ EXPECT_TRUE(FetchResource(browser(), GetGoogleRedirectUrl1()));
EXPECT_TRUE(HasReceivedHeader(GetGoogleRedirectUrl1(), "X-Client-Data"));
EXPECT_TRUE(HasReceivedHeader(GetGoogleRedirectUrl2(), "X-Client-Data"));
EXPECT_TRUE(HasReceivedHeader(GetExampleUrl(), "Host"));
EXPECT_FALSE(HasReceivedHeader(GetExampleUrl(), "X-Client-Data"));
}
+IN_PROC_BROWSER_TEST_F(VariationsHttpHeadersBrowserTest, Incognito) {
+ Browser* incognito = CreateIncognitoBrowser();
+ ui_test_utils::NavigateToURL(incognito, GetGoogleUrl());
+
+ EXPECT_FALSE(HasReceivedHeader(GetGoogleUrl(), "X-Client-Data"));
+
+ EXPECT_TRUE(FetchResource(incognito, GetGoogleSubresourceUrl()));
+ EXPECT_FALSE(HasReceivedHeader(GetGoogleSubresourceUrl(), "X-Client-Data"));
+}
+
+IN_PROC_BROWSER_TEST_F(VariationsHttpHeadersBrowserTest, UserSignedIn) {
+ // Ensure GetClientDataHeader() returns different values when signed in vs
+ // not signed in.
+ CreateGoogleSignedInFieldTrial();
+
+ // Sign the user in.
+ signin::MakePrimaryAccountAvailable(
+ IdentityManagerFactory::GetForProfile(browser()->profile()),
+ "main_email@gmail.com");
+
+ ui_test_utils::NavigateToURL(browser(), GetGoogleUrl());
+
+ base::Optional<std::string> header =
+ GetReceivedHeader(GetGoogleUrl(), "X-Client-Data");
+ ASSERT_TRUE(header);
+ EXPECT_EQ(*header, variations::VariationsHttpHeaderProvider::GetInstance()
+ ->GetClientDataHeader(true));
+}
+
+IN_PROC_BROWSER_TEST_F(VariationsHttpHeadersBrowserTest, UserNotSignedIn) {
+ // Ensure GetClientDataHeader() returns different values when signed in vs
+ // not signed in.
+ CreateGoogleSignedInFieldTrial();
+
+ // By default the user is not signed in.
+ ui_test_utils::NavigateToURL(browser(), GetGoogleUrl());
+
+ base::Optional<std::string> header =
+ GetReceivedHeader(GetGoogleUrl(), "X-Client-Data");
+ ASSERT_TRUE(header);
+ EXPECT_EQ(*header, variations::VariationsHttpHeaderProvider::GetInstance()
+ ->GetClientDataHeader(false));
+}
+
IN_PROC_BROWSER_TEST_F(
VariationsHttpHeadersBrowserTest,
TestStrippingHeadersFromRequestUsingSimpleURLLoaderWithProfileNetworkContext) {
diff --git a/chromium/chrome/browser/notifications/BUILD.gn b/chromium/chrome/browser/notifications/BUILD.gn
index 1390b7f4c6b..2ebbde7975f 100644
--- a/chromium/chrome/browser/notifications/BUILD.gn
+++ b/chromium/chrome/browser/notifications/BUILD.gn
@@ -11,7 +11,5 @@ group("notifications") {
group("unit_tests") {
testonly = true
- deps = [
- "//chrome/browser/notifications/scheduler:unit_tests",
- ]
+ deps = [ "//chrome/browser/notifications/scheduler:unit_tests" ]
}
diff --git a/chromium/chrome/browser/notifications/chime/android/BUILD.gn b/chromium/chrome/browser/notifications/chime/android/BUILD.gn
index 53fe51cab77..4e47c14ff4c 100644
--- a/chromium/chrome/browser/notifications/chime/android/BUILD.gn
+++ b/chromium/chrome/browser/notifications/chime/android/BUILD.gn
@@ -5,7 +5,7 @@
import("//build/config/android/rules.gni")
android_library("java") {
- java_files = [ "java/src/org/chromium/chrome/browser/notifications/chime/ChimeSession.java" ]
+ sources = [ "java/src/org/chromium/chrome/browser/notifications/chime/ChimeSession.java" ]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
@@ -31,7 +31,5 @@ source_set("android") {
generate_jni("jni_headers") {
visibility = [ ":*" ]
- sources = [
- "java/src/org/chromium/chrome/browser/notifications/chime/ChimeSession.java",
- ]
+ sources = [ "java/src/org/chromium/chrome/browser/notifications/chime/ChimeSession.java" ]
}
diff --git a/chromium/chrome/browser/notifications/scheduler/BUILD.gn b/chromium/chrome/browser/notifications/scheduler/BUILD.gn
index 02f3321e230..b500b3d42f8 100644
--- a/chromium/chrome/browser/notifications/scheduler/BUILD.gn
+++ b/chromium/chrome/browser/notifications/scheduler/BUILD.gn
@@ -3,13 +3,9 @@
# found in the LICENSE file.
group("scheduler") {
- deps = [
- ":factory",
- ]
+ deps = [ ":factory" ]
- public_deps = [
- "//chrome/browser/notifications/scheduler/public",
- ]
+ public_deps = [ "//chrome/browser/notifications/scheduler/public" ]
}
# The embedder can depend on this target to get the internal library.
diff --git a/chromium/chrome/browser/notifications/scheduler/public/BUILD.gn b/chromium/chrome/browser/notifications/scheduler/public/BUILD.gn
index 020c9a7b894..31ce353abbc 100644
--- a/chromium/chrome/browser/notifications/scheduler/public/BUILD.gn
+++ b/chromium/chrome/browser/notifications/scheduler/public/BUILD.gn
@@ -34,6 +34,8 @@ source_set("public") {
"schedule_params.h",
"schedule_service_utils.cc",
"schedule_service_utils.h",
+ "throttle_config.cc",
+ "throttle_config.h",
"user_action_handler.h",
]
@@ -46,17 +48,13 @@ source_set("public") {
if (is_android) {
java_cpp_enum("jni_enums") {
- sources = [
- "notification_scheduler_types.h",
- ]
+ sources = [ "notification_scheduler_types.h" ]
}
}
source_set("unit_tests") {
testonly = true
- sources = [
- "schedule_service_utils_unittest.cc",
- ]
+ sources = [ "schedule_service_utils_unittest.cc" ]
deps = [
"//chrome/browser/notifications/scheduler/public",
diff --git a/chromium/chrome/browser/notifications/scheduler/test/BUILD.gn b/chromium/chrome/browser/notifications/scheduler/test/BUILD.gn
index 183b609d283..20ff21b5013 100644
--- a/chromium/chrome/browser/notifications/scheduler/test/BUILD.gn
+++ b/chromium/chrome/browser/notifications/scheduler/test/BUILD.gn
@@ -11,6 +11,8 @@ source_set("test_support") {
"mock_display_agent.h",
"mock_notification_background_task_scheduler.cc",
"mock_notification_background_task_scheduler.h",
+ "mock_notification_schedule_service.cc",
+ "mock_notification_schedule_service.h",
"mock_notification_scheduler_client.cc",
"mock_notification_scheduler_client.h",
]
diff --git a/chromium/chrome/browser/offline_pages/prefetch/notifications/BUILD.gn b/chromium/chrome/browser/offline_pages/prefetch/notifications/BUILD.gn
new file mode 100644
index 00000000000..c6b99d11266
--- /dev/null
+++ b/chromium/chrome/browser/offline_pages/prefetch/notifications/BUILD.gn
@@ -0,0 +1,26 @@
+# Copyright 2020 The Chromium Authors.All rights reserved.
+# Use of this source code is governed by a BSD - style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+ import("//build/config/android/rules.gni")
+}
+
+source_set("notifications") {
+ sources = [
+ "prefetch_notification_client.cc",
+ "prefetch_notification_client.h",
+ "prefetch_notification_service.h",
+ "prefetch_notification_service_bridge.h",
+ "prefetch_notification_service_impl.cc",
+ "prefetch_notification_service_impl.h",
+ ]
+
+ deps = [
+ "//base",
+ "//chrome/browser/notifications/scheduler/public",
+ "//components/keyed_service/content",
+ "//components/keyed_service/core",
+ "//skia",
+ ]
+}
diff --git a/chromium/chrome/browser/optimization_guide/android/BUILD.gn b/chromium/chrome/browser/optimization_guide/android/BUILD.gn
new file mode 100644
index 00000000000..2fecfe2845d
--- /dev/null
+++ b/chromium/chrome/browser/optimization_guide/android/BUILD.gn
@@ -0,0 +1,66 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+generate_jni("jni_headers") {
+ sources = [ "java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridge.java" ]
+}
+
+android_library("java") {
+ sources = [
+ "java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridge.java",
+ "java/src/org/chromium/chrome/browser/optimization_guide/OptimizationMetadata.java",
+ ]
+
+ deps = [
+ "//base:base_java",
+ "//base:jni_java",
+ "//components/optimization_guide/proto:optimization_guide_proto_java",
+ "//content/public/android:content_java",
+ "//third_party/android_deps:androidx_annotation_annotation_java",
+ "//third_party/android_deps:com_google_protobuf_protobuf_javalite_java",
+ ]
+
+ srcjar_deps =
+ [ "//components/optimization_guide:optimization_guide_generated_enums" ]
+
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+}
+
+generate_jni("native_j_unittests_jni_headers") {
+ testonly = true
+
+ sources = [ "java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeNativeUnitTest.java" ]
+}
+
+android_library("native_java_unittests") {
+ testonly = true
+
+ deps = [
+ ":java",
+ "//components/optimization_guide/proto:optimization_guide_proto_java",
+ "//content/public/android:content_java",
+ "//third_party/junit",
+ ]
+
+ sources = [ "java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeNativeUnitTest.java" ]
+}
+
+java_library("junit_tests") {
+ # Skip platform checks since Robolectric depends on require_android targets.
+ bypass_platform_checks = true
+ testonly = true
+
+ sources = [ "java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuideBridgeUnitTest.java" ]
+
+ deps = [
+ ":java",
+ "//base:base_java_test_support",
+ "//base:base_junit_test_support",
+ "//chrome/android:chrome_test_util_java",
+ "//third_party/junit",
+ "//third_party/mockito:mockito_java",
+ ]
+}
diff --git a/chromium/chrome/browser/page_load_metrics/integration_tests/jsdeps.gni b/chromium/chrome/browser/page_load_metrics/integration_tests/jsdeps.gni
new file mode 100644
index 00000000000..8b2c5abb261
--- /dev/null
+++ b/chromium/chrome/browser/page_load_metrics/integration_tests/jsdeps.gni
@@ -0,0 +1,8 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+metric_integration_jsdeps = [
+ "//third_party/blink/web_tests/external/wpt/layout-instability/resources/util.js",
+ "//third_party/blink/web_tests/external/wpt/resources/testharness.js",
+]
diff --git a/chromium/chrome/browser/page_load_metrics/integration_tests/sources.gni b/chromium/chrome/browser/page_load_metrics/integration_tests/sources.gni
new file mode 100644
index 00000000000..c6be3a5b357
--- /dev/null
+++ b/chromium/chrome/browser/page_load_metrics/integration_tests/sources.gni
@@ -0,0 +1,11 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+metric_integration_sources = [
+ "//chrome/browser/page_load_metrics/integration_tests/first_input_delay_browsertest.cc",
+ "//chrome/browser/page_load_metrics/integration_tests/layout_instability_browsertest.cc",
+ "//chrome/browser/page_load_metrics/integration_tests/metric_integration_test.cc",
+ "//chrome/browser/page_load_metrics/integration_tests/metric_integration_test.h",
+ "//chrome/browser/page_load_metrics/integration_tests/total_input_delay_browsertest.cc",
+]
diff --git a/chromium/chrome/browser/password_manager/android_test_helpers/BUILD.gn b/chromium/chrome/browser/password_manager/android_test_helpers/BUILD.gn
new file mode 100644
index 00000000000..66106e9e2c8
--- /dev/null
+++ b/chromium/chrome/browser/password_manager/android_test_helpers/BUILD.gn
@@ -0,0 +1,32 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+static_library("android_wrappers") {
+ testonly = true
+ sources = [ "chrome_password_manager_client_android_wrapper.cc" ]
+ deps = [
+ "//base",
+ "//chrome/browser:browser",
+ "//chrome/browser/password_manager/android_test_helpers:jni_headers",
+ "//content/public/browser",
+ ]
+}
+
+generate_jni("jni_headers") {
+ testonly = true
+ sources = [ "javatests/src/org/chromium/chrome/browser/password_manager/PasswordManagerClientBridgeForTesting.java" ]
+}
+
+android_library("test_support_java") {
+ testonly = true
+ sources = [ "javatests/src/org/chromium/chrome/browser/password_manager/PasswordManagerClientBridgeForTesting.java" ]
+ deps = [
+ "//base:base_jni_headers",
+ "//base:jni_java",
+ "//content/public/android:content_java",
+ ]
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+}
diff --git a/chromium/chrome/browser/payments/BUILD.gn b/chromium/chrome/browser/payments/BUILD.gn
new file mode 100644
index 00000000000..3d238407557
--- /dev/null
+++ b/chromium/chrome/browser/payments/BUILD.gn
@@ -0,0 +1,81 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("browsertests") {
+ testonly = true
+
+ sources = [
+ "empty_parameters_browsertest.cc",
+ "has_enrolled_instrument_browsertest.cc",
+ "has_enrolled_instrument_query_quota_browsertest.cc",
+ "iframe_csp_browsertest.cc",
+ "ignore_payment_method_browsertest.cc",
+ "journey_logger_browsertest.cc",
+ "payment_handler_change_shipping_address_option_browsertest.cc",
+ "payment_handler_enable_delegations_browsertest.cc",
+ "payment_handler_exploit_browsertest.cc",
+ "payment_handler_just_in_time_installation_browsertest.cc",
+ "payment_request_can_make_payment_browsertest.cc",
+ "payment_request_can_make_payment_event_browsertest.cc",
+ "payment_request_minimal_ui_browsertest.cc",
+ "sec_fetch_site_browsertest.cc",
+ ]
+
+ defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
+
+ deps = [
+ "//base/test:test_support",
+ "//chrome/test:test_support",
+ "//chrome/test/payments:test_support",
+ "//components/payments/content",
+ "//components/payments/content:utils",
+ "//components/payments/core:test_support",
+ "//components/ukm:test_support",
+ ]
+
+ if (is_android) {
+ sources += [
+ "expandable_payment_handler_browsertest.cc",
+ "hybrid_request_skip_ui_browsertest.cc",
+ ]
+ }
+
+ if (!is_android) {
+ sources += [
+ "manifest_verifier_browsertest.cc",
+ "payment_manifest_parser_browsertest.cc",
+ "service_worker_payment_app_finder_browsertest.cc",
+ "site_per_process_payments_browsertest.cc",
+ ]
+
+ deps += [
+ "//chrome/test:test_support_ui",
+ "//components/payments/content:utils",
+ "//components/payments/content/utility",
+ "//components/permissions:permissions",
+ ]
+ }
+}
+
+source_set("unittests") {
+ testonly = true
+
+ sources = [ "payment_handler_permission_context_unittest.cc" ]
+
+ deps = [
+ "//chrome/test:test_support",
+ "//components/content_settings/core/test:test_support",
+ "//components/permissions:permissions",
+ ]
+
+ if (is_android) {
+ sources += [
+ "android/android_payment_app_finder_unittest.cc",
+ "android/android_payment_app_unittest.cc",
+ "android/payment_manifest_verifier_unittest.cc",
+ ]
+
+ deps += [ "//chrome/android:native_j_unittests_jni_headers" ]
+ }
+}
diff --git a/chromium/chrome/browser/payments/android/BUILD.gn b/chromium/chrome/browser/payments/android/BUILD.gn
new file mode 100644
index 00000000000..49e98d56274
--- /dev/null
+++ b/chromium/chrome/browser/payments/android/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/config.gni")
+import("//build/config/android/rules.gni")
+
+# TODO(crbug.com/1066269): Extract //chrome/browser/payments/android source files
+# from //chrome/browser/BUILD.gn into an independent build target here.
+
+generate_jni("jni_headers") {
+ sources = [
+ "../../../android/java/src/org/chromium/chrome/browser/payments/CanMakePaymentQuery.java",
+ "../../../android/java/src/org/chromium/chrome/browser/payments/JourneyLogger.java",
+ "../../../android/java/src/org/chromium/chrome/browser/payments/PaymentManifestWebDataService.java",
+ "../../../android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java",
+ "../../../android/java/src/org/chromium/chrome/browser/payments/SslValidityChecker.java",
+ ]
+}
diff --git a/chromium/chrome/browser/performance_hints/android/BUILD.gn b/chromium/chrome/browser/performance_hints/android/BUILD.gn
new file mode 100644
index 00000000000..e1c44ea6c67
--- /dev/null
+++ b/chromium/chrome/browser/performance_hints/android/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+generate_jni("jni_headers") {
+ sources = [ "java/src/org/chromium/chrome/browser/performance_hints/PerformanceHintsObserver.java" ]
+}
+
+android_library("java") {
+ sources = [ "java/src/org/chromium/chrome/browser/performance_hints/PerformanceHintsObserver.java" ]
+
+ deps = [
+ "//base:base_java",
+ "//base:jni_java",
+ "//content/public/android:content_java",
+ ]
+
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+}
diff --git a/chromium/chrome/browser/performance_manager/BUILD.gn b/chromium/chrome/browser/performance_manager/BUILD.gn
index ab1114ae8b4..a0a384385da 100644
--- a/chromium/chrome/browser/performance_manager/BUILD.gn
+++ b/chromium/chrome/browser/performance_manager/BUILD.gn
@@ -6,7 +6,5 @@ import("//chrome/common/features.gni")
import("//third_party/protobuf/proto_library.gni")
proto_library("site_data_proto") {
- sources = [
- "persistence/site_data/site_data.proto",
- ]
+ sources = [ "persistence/site_data/site_data.proto" ]
}
diff --git a/chromium/chrome/browser/preferences/BUILD.gn b/chromium/chrome/browser/preferences/BUILD.gn
index 2af39ba0c5b..5491897b9e5 100644
--- a/chromium/chrome/browser/preferences/BUILD.gn
+++ b/chromium/chrome/browser/preferences/BUILD.gn
@@ -5,8 +5,12 @@
import("//build/config/android/rules.gni")
android_library("java") {
- java_files = [
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/preferences/BaseChromePreferenceKeyChecker.java",
+ "android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyChecker.java",
"android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java",
+ "android/java/src/org/chromium/chrome/browser/preferences/DeprecatedChromePreferenceKeys.java",
+ "android/java/src/org/chromium/chrome/browser/preferences/GrandfatheredChromePreferenceKeys.java",
"android/java/src/org/chromium/chrome/browser/preferences/KeyPrefix.java",
"android/java/src/org/chromium/chrome/browser/preferences/PrefChangeRegistrar.java",
"android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java",
@@ -28,18 +32,18 @@ generate_jni("jni_headers") {
}
java_cpp_enum("java_enums_srcjar") {
- sources = [
- "//chrome/browser/android/preferences/prefs.h",
- ]
+ sources = [ "//chrome/browser/android/preferences/prefs.h" ]
}
java_library("preferences_junit_tests") {
# Skip platform checks since Robolectric depends on requires_android targets.
bypass_platform_checks = true
testonly = true
- java_files = [
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeyCheckerTest.java",
"android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeysTest.java",
"android/java/src/org/chromium/chrome/browser/preferences/KeyPrefixTest.java",
+ "android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManagerTest.java",
]
deps = [
":java",
diff --git a/chromium/chrome/browser/prefs/browser_prefs.cc b/chromium/chrome/browser/prefs/browser_prefs.cc
index 32f0c22512c..b40d5bc7482 100644
--- a/chromium/chrome/browser/prefs/browser_prefs.cc
+++ b/chromium/chrome/browser/prefs/browser_prefs.cc
@@ -37,14 +37,15 @@
#include "chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.h"
#include "chrome/browser/memory/enterprise_memory_limit_pref_observer.h"
#include "chrome/browser/metrics/chrome_metrics_service_client.h"
+#include "chrome/browser/net/dns_util.h"
#include "chrome/browser/net/net_error_tab_helper.h"
#include "chrome/browser/net/prediction_options.h"
#include "chrome/browser/net/profile_network_context_service.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/notifications/notification_channels_provider_android.h"
+#include "chrome/browser/notifications/notification_display_service_impl.h"
#include "chrome/browser/notifications/notifier_state_tracker.h"
#include "chrome/browser/notifications/platform_notification_service_impl.h"
-#include "chrome/browser/pepper_flash_settings_manager.h"
#include "chrome/browser/permissions/quiet_notification_permission_ui_state.h"
#include "chrome/browser/policy/developer_tools_policy_handler.h"
#include "chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h"
@@ -62,11 +63,9 @@
#include "chrome/browser/profiles/profile_info_cache.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
-#include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
#include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/sharing/sharing_sync_preference.h"
-#include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
#include "chrome/browser/ssl/ssl_config_service_manager.h"
#include "chrome/browser/task_manager/task_manager_interface.h"
#include "chrome/browser/tracing/chrome_tracing_delegate.h"
@@ -77,7 +76,9 @@
#include "chrome/browser/ui/network_profile_bubble.h"
#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
#include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
+#include "chrome/browser/ui/send_tab_to_self/send_tab_to_self_bubble_controller.h"
#include "chrome/browser/ui/tabs/pinned_tab_codec.h"
+#include "chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h"
#include "chrome/browser/ui/webui/flags_ui.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/browser/ui/webui/print_preview/policy_settings.h"
@@ -85,6 +86,7 @@
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h"
#include "chrome/common/buildflags.h"
+#include "chrome/common/chrome_ui_features_prefs.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/secure_origin_whitelist.h"
#include "chrome/common/web_components_prefs.h"
@@ -94,12 +96,13 @@
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
#include "components/dom_distiller/core/distilled_page_prefs.h"
+#include "components/dom_distiller/core/dom_distiller_features.h"
+#include "components/dom_distiller/core/pref_names.h"
#include "components/feature_engagement/buildflags.h"
#include "components/flags_ui/pref_service_flags_storage.h"
-#include "components/gcm_driver/gcm_channel_status_syncer.h"
#include "components/image_fetcher/core/cache/image_cache.h"
#include "components/invalidation/impl/invalidator_registrar_with_memory.h"
-#include "components/invalidation/impl/per_user_topic_registration_manager.h"
+#include "components/invalidation/impl/per_user_topic_subscription_manager.h"
#include "components/language/content/browser/geo_language_provider.h"
#include "components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.h"
#include "components/language/core/browser/language_prefs.h"
@@ -121,14 +124,17 @@
#include "components/payments/core/payment_prefs.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/browser/url_blacklist_manager.h"
+#include "components/policy/core/common/policy_pref_names.h"
#include "components/policy/core/common/policy_statistics_collector.h"
#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_registry.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
#include "components/rappor/rappor_service_impl.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/search_engines/template_url_prepopulate_data.h"
+#include "components/security_interstitials/content/stateful_ssl_host_state_delegate.h"
#include "components/security_state/core/security_state.h"
#include "components/sessions/core/session_id_generator.h"
#include "components/signin/public/identity_manager/identity_manager.h"
@@ -166,16 +172,23 @@
#include "extensions/browser/api/runtime/runtime_api.h"
#include "extensions/browser/extension_prefs.h"
#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/extensions/extensions_permissions_tracker.h"
#include "chrome/browser/chromeos/guest_os/guest_os_share_path.h"
#include "chrome/browser/chromeos/kerberos/kerberos_credentials_manager.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h"
+#include "chrome/browser/chromeos/login/existing_user_controller.h"
+#include "chrome/browser/chromeos/policy/system_features_disable_list_policy_handler.h"
#include "chrome/browser/chromeos/settings/stats_reporting_controller.h"
#include "chrome/browser/component_updater/metadata_table_chromeos.h"
#else
#include "chrome/browser/extensions/api/enterprise_reporting_private/prefs.h"
-#endif
+#endif // defined(OS_CHROMEOS)
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
+#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
+#include "chrome/browser/feature_engagement/session_duration_updater.h"
+#endif
+
#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
#include "chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h"
#include "chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.h"
@@ -183,22 +196,20 @@
#endif
#if BUILDFLAG(ENABLE_PLUGINS)
+#include "chrome/browser/pepper_flash_settings_manager.h"
#include "chrome/browser/plugins/plugin_info_host_impl.h"
#include "chrome/browser/plugins/plugins_resource_service.h"
-#endif
-
-#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
-#include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
-#include "chrome/browser/supervised_user/supervised_user_service.h"
-#include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
+#include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
#endif
#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY)
#include "chrome/browser/ui/webui/local_discovery/local_discovery_ui.h"
#endif
-#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
-#include "chrome/browser/feature_engagement/session_duration_updater.h"
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+#include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
+#include "chrome/browser/supervised_user/supervised_user_service.h"
+#include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
#endif
#if defined(OS_ANDROID)
@@ -208,20 +219,23 @@
#include "chrome/browser/android/oom_intervention/oom_intervention_decider.h"
#include "chrome/browser/android/preferences/browser_prefs_android.h"
#include "chrome/browser/android/usage_stats/usage_stats_bridge.h"
-#include "chrome/browser/geolocation/geolocation_permission_context_android.h"
#include "chrome/browser/media/android/cdm/media_drm_origin_id_manager.h"
#include "chrome/browser/ssl/known_interception_disclosure_infobar_delegate.h"
#include "components/cdm/browser/media_drm_storage_impl.h"
#include "components/feed/buildflags.h"
+#include "components/feed/core/shared_prefs/pref_names.h"
+#include "components/games/core/games_prefs.h"
#include "components/ntp_snippets/category_rankers/click_based_category_ranker.h"
#include "components/ntp_tiles/popular_sites_impl.h"
+#include "components/permissions/contexts/geolocation_permission_context_android.h"
#if BUILDFLAG(ENABLE_FEED_IN_CHROME)
-#include "components/feed/core/pref_names.h"
+#include "components/feed/core/common/pref_names.h"
#endif // BUILDFLAG(ENABLE_FEED_IN_CHROME)
#else // defined(OS_ANDROID)
#include "chrome/browser/apps/app_service/app_service_proxy.h"
-#include "chrome/browser/enterprise_reporting/prefs.h"
+#include "chrome/browser/enterprise/reporting/prefs.h"
#include "chrome/browser/gcm/gcm_product_util.h"
+#include "chrome/browser/media/unified_autoplay_config.h"
#include "chrome/browser/metrics/tab_stats_tracker.h"
#include "chrome/browser/search/instant_service.h"
#include "chrome/browser/search/promos/promo_service.h"
@@ -232,6 +246,7 @@
#include "chrome/browser/ui/webui/history/history_ui.h"
#include "chrome/browser/ui/webui/settings/settings_ui.h"
#include "chrome/browser/upgrade_detector/upgrade_detector.h"
+#include "components/ntp_tiles/custom_links_manager_impl.h"
#endif // defined(OS_ANDROID)
#if defined(OS_CHROMEOS)
@@ -245,14 +260,19 @@
#include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h"
#include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
#include "chrome/browser/chromeos/bluetooth/debug_logs_manager.h"
+#include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h"
#include "chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service.h"
#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_activity_registry.h"
+#include "chrome/browser/chromeos/child_accounts/time_limits/app_time_controller.h"
#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
-#include "chrome/browser/chromeos/crostini/crostini_registry_service.h"
#include "chrome/browser/chromeos/cryptauth/cryptauth_device_id_provider_impl.h"
#include "chrome/browser/chromeos/customization/customization_document.h"
#include "chrome/browser/chromeos/extensions/echo_private_api.h"
#include "chrome/browser/chromeos/extensions/login_screen/login/login_api.h"
+#if defined(USE_CUPS)
+#include "chrome/browser/chromeos/extensions/printing/printing_api_handler.h"
+#endif
#include "chrome/browser/chromeos/file_system_provider/registry.h"
#include "chrome/browser/chromeos/first_run/first_run.h"
#include "chrome/browser/chromeos/guest_os/guest_os_pref_names.h"
@@ -290,18 +310,19 @@
#include "chrome/browser/chromeos/power/power_metrics_reporter.h"
#include "chrome/browser/chromeos/preferences.h"
#include "chrome/browser/chromeos/printing/cups_printers_manager.h"
+#include "chrome/browser/chromeos/printing/enterprise_printers_provider.h"
#include "chrome/browser/chromeos/printing/history/print_job_history_service.h"
-#include "chrome/browser/chromeos/printing/synced_printers_manager.h"
#include "chrome/browser/chromeos/release_notes/release_notes_storage.h"
#include "chrome/browser/chromeos/resource_reporter/resource_reporter.h"
-#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
#include "chrome/browser/chromeos/settings/device_settings_cache.h"
#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
#include "chrome/browser/chromeos/system/input_device_settings.h"
+#include "chrome/browser/device_identity/chromeos/device_oauth2_token_store_chromeos.h"
#include "chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h"
#include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
#include "chrome/browser/media/protected_media_identifier_permission_context.h"
#include "chrome/browser/metrics/chromeos_metrics_provider.h"
+#include "chrome/browser/supervised_user/child_accounts/secondary_account_consent_logger.h"
#include "chrome/browser/ui/app_list/app_list_syncable_service.h"
#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h"
@@ -310,11 +331,14 @@
#include "chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h"
#include "chrome/browser/upgrade_detector/upgrade_detector_chromeos.h"
#include "chromeos/audio/audio_devices_pref_handler_impl.h"
#include "chromeos/components/account_manager/account_manager.h"
+#include "chromeos/components/quick_answers/public/cpp/quick_answers_prefs.h"
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/network/fast_transition_observer.h"
+#include "chromeos/network/network_metadata_store.h"
#include "chromeos/network/proxy/proxy_config_handler.h"
#include "chromeos/services/assistant/public/cpp/assistant_prefs.h"
#include "chromeos/services/device_sync/device_sync_impl.h"
@@ -322,7 +346,6 @@
#include "chromeos/timezone/timezone_resolver.h"
#include "components/arc/arc_prefs.h"
#include "components/invalidation/impl/fcm_invalidation_service.h"
-#include "components/invalidation/impl/invalidator_storage.h"
#include "components/onc/onc_pref_names.h"
#include "components/quirks/quirks_manager.h"
#include "extensions/browser/api/lock_screen_data/lock_screen_item_storage.h"
@@ -331,9 +354,9 @@
#endif
#if defined(OS_MACOSX)
-#include "chrome/browser/apps/platform_apps/app_shim_registry_mac.h"
#include "chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.h"
#include "chrome/browser/ui/cocoa/confirm_quit.h"
+#include "chrome/browser/web_applications/components/app_shim_registry_mac.h"
#endif
#if defined(OS_WIN)
@@ -357,22 +380,16 @@
#endif
#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#include "chrome/browser/device_identity//device_oauth2_token_store_desktop.h"
+#include "chrome/browser/downgrade/downgrade_prefs.h"
#include "chrome/browser/ui/startup/default_browser_prompt.h"
+
#endif
#if defined(TOOLKIT_VIEWS)
#include "chrome/browser/ui/browser_view_prefs.h"
#endif
-#if !defined(OS_ANDROID)
-#include "chrome/browser/media/unified_autoplay_config.h"
-#include "components/ntp_tiles/custom_links_manager_impl.h"
-#endif
-
-#if defined(OS_ANDROID) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
-#include "components/games/core/games_prefs.h"
-#endif
-
namespace {
// Deprecated 8/2018.
@@ -511,6 +528,8 @@ const char kGoogleServicesUsername[] = "google.services.username";
const char kGoogleServicesUserAccountId[] = "google.services.user_account_id";
const char kDataReductionProxySavingsClearedNegativeSystemClock[] =
"data_reduction.savings_cleared_negative_system_clock";
+const char kDataReductionNetworkProperties[] =
+ "data_reduction.network_properties";
#if defined(OS_CHROMEOS)
// Deprecated 10/2019
@@ -522,6 +541,20 @@ const char kDisplayRotationAcceleratorDialogHasBeenAccepted[] =
const char kBlacklistedCredentialsNormalized[] =
"profile.blacklisted_credentials_normalized";
+// Deprecated 1/2020
+#if defined(OS_MACOSX)
+const char kKeyCreated[] = "os_crypt.key_created";
+#endif // defined(OS_MACOSX)
+
+const char kGCMChannelStatus[] = "gcm.channel_status";
+const char kGCMChannelPollIntervalSeconds[] = "gcm.poll_interval";
+const char kGCMChannelLastCheckTime[] = "gcm.check_time";
+
+// Deprecated 2/2020
+const char kInvalidatorClientId[] = "invalidator.client_id";
+const char kInvalidatorInvalidationState[] = "invalidator.invalidation_state";
+const char kInvalidatorSavedInvalidations[] = "invalidator.saved_invalidations";
+
// Register prefs used only for migration (clearing or moving to a new key).
void RegisterProfilePrefsForMigration(
user_prefs::PrefRegistrySyncable* registry) {
@@ -602,6 +635,7 @@ void RegisterProfilePrefsForMigration(
registry->RegisterStringPref(kGoogleServicesUserAccountId, std::string());
registry->RegisterInt64Pref(
kDataReductionProxySavingsClearedNegativeSystemClock, 0);
+ registry->RegisterDictionaryPref(kDataReductionNetworkProperties);
#if defined(OS_CHROMEOS)
registry->RegisterBooleanPref(
@@ -609,6 +643,16 @@ void RegisterProfilePrefsForMigration(
#endif // defined(OS_CHROMEOS)
registry->RegisterBooleanPref(kBlacklistedCredentialsNormalized, false);
+
+ registry->RegisterBooleanPref(kGCMChannelStatus, true);
+ registry->RegisterIntegerPref(kGCMChannelPollIntervalSeconds, 0);
+ registry->RegisterInt64Pref(kGCMChannelLastCheckTime, 0);
+
+ registry->RegisterListPref(kInvalidatorSavedInvalidations);
+ registry->RegisterStringPref(kInvalidatorInvalidationState, std::string());
+ registry->RegisterStringPref(kInvalidatorClientId, std::string());
+
+ chrome_browser_net::RegisterDNSProbesSettingBackupPref(registry);
}
} // namespace
@@ -633,6 +677,8 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
network_time::NetworkTimeTracker::RegisterPrefs(registry);
OriginTrialPrefs::RegisterPrefs(registry);
password_manager::PasswordManager::RegisterLocalPrefs(registry);
+ policy::BrowserPolicyConnector::RegisterPrefs(registry);
+ policy::PolicyStatisticsCollector::RegisterPrefs(registry);
PrefProxyConfigTrackerImpl::RegisterPrefs(registry);
ProfileAttributesEntry::RegisterLocalStatePrefs(registry);
ProfileInfoCache::RegisterPrefs(registry);
@@ -649,17 +695,10 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
update_client::RegisterPrefs(registry);
variations::VariationsService::RegisterPrefs(registry);
- policy::BrowserPolicyConnector::RegisterPrefs(registry);
- policy::PolicyStatisticsCollector::RegisterPrefs(registry);
-
#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
BackgroundModeManager::RegisterPrefs(registry);
#endif
-#if BUILDFLAG(ENABLE_EXTENSIONS) and defined(OS_CHROMEOS)
- chromeos::EasyUnlockService::RegisterPrefs(registry);
-#endif
-
#if BUILDFLAG(ENABLE_PLUGINS)
PluginsResourceService::RegisterPrefs(registry);
#endif
@@ -667,19 +706,14 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
#if defined(OS_ANDROID)
::android::RegisterPrefs(registry);
#else
- media_router::RegisterLocalStatePrefs(registry);
- // The native GCM is used on Android instead.
- gcm::GCMChannelStatusSyncer::RegisterPrefs(registry);
+ enterprise_reporting::RegisterLocalStatePrefs(registry);
gcm::RegisterPrefs(registry);
+ media_router::RegisterLocalStatePrefs(registry);
metrics::TabStatsTracker::RegisterPrefs(registry);
RegisterBrowserPrefs(registry);
StartupBrowserCreator::RegisterLocalStatePrefs(registry);
task_manager::TaskManagerInterface::RegisterPrefs(registry);
UpgradeDetector::RegisterPrefs(registry);
- enterprise_reporting::RegisterLocalStatePrefs(registry);
-#if !defined(OS_CHROMEOS)
- RegisterDefaultBrowserPromptPrefs(registry);
-#endif // !defined(OS_CHROMEOS)
#endif // !defined(OS_ANDROID)
#if defined(OS_CHROMEOS)
@@ -692,11 +726,13 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
chromeos::DemoModeResourcesRemover::RegisterLocalStatePrefs(registry);
chromeos::DemoSession::RegisterLocalStatePrefs(registry);
chromeos::DemoSetupController::RegisterLocalStatePrefs(registry);
- chromeos::DeviceOAuth2TokenService::RegisterPrefs(registry);
+ chromeos::DeviceOAuth2TokenStoreChromeOS::RegisterPrefs(registry);
chromeos::device_settings_cache::RegisterPrefs(registry);
+ chromeos::EasyUnlockService::RegisterPrefs(registry);
chromeos::echo_offer::RegisterPrefs(registry);
chromeos::EnableAdbSideloadingScreen::RegisterPrefs(registry);
chromeos::EnableDebuggingScreenHandler::RegisterPrefs(registry);
+ chromeos::ExistingUserController::RegisterLocalStatePrefs(registry);
chromeos::FastTransitionObserver::RegisterPrefs(registry);
chromeos::HIDDetectionScreenHandler::RegisterPrefs(registry);
chromeos::KerberosCredentialsManager::RegisterLocalStatePrefs(registry);
@@ -704,6 +740,7 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
chromeos::KioskCryptohomeRemover::RegisterPrefs(registry);
chromeos::language_prefs::RegisterPrefs(registry);
chromeos::MultiProfileUserController::RegisterPrefs(registry);
+ chromeos::NetworkMetadataStore::RegisterPrefs(registry);
chromeos::NetworkThrottlingObserver::RegisterPrefs(registry);
chromeos::PowerMetricsReporter::RegisterLocalStatePrefs(registry);
chromeos::power::auto_screen_brightness::MetricsReporter::
@@ -724,11 +761,11 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
component_updater::MetadataTable::RegisterPrefs(registry);
cryptauth::CryptAuthDeviceIdProviderImpl::RegisterLocalPrefs(registry);
extensions::ExtensionAssetsManagerChromeOS::RegisterPrefs(registry);
+ extensions::ExtensionsPermissionsTracker::RegisterLocalStatePrefs(registry);
extensions::lock_screen_data::LockScreenItemStorage::RegisterLocalState(
registry);
extensions::login_api::RegisterLocalStatePrefs(registry);
invalidation::FCMInvalidationService::RegisterPrefs(registry);
- invalidation::InvalidatorStorage::RegisterPrefs(registry);
::onc::RegisterPrefs(registry);
policy::AutoEnrollmentClientImpl::RegisterPrefs(registry);
policy::BrowserPolicyConnectorChromeOS::RegisterPrefs(registry);
@@ -739,25 +776,30 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
policy::PolicyCertServiceFactory::RegisterPrefs(registry);
policy::TPMAutoUpdateModePolicyHandler::RegisterPrefs(registry);
policy::WebUsbAllowDevicesForUrlsPolicyHandler::RegisterPrefs(registry);
+ policy::SystemFeaturesDisableListPolicyHandler::RegisterPrefs(registry);
quirks::QuirksManager::RegisterPrefs(registry);
UpgradeDetectorChromeos::RegisterPrefs(registry);
- syncer::PerUserTopicRegistrationManager::RegisterPrefs(registry);
+ syncer::PerUserTopicSubscriptionManager::RegisterPrefs(registry);
syncer::InvalidatorRegistrarWithMemory::RegisterPrefs(registry);
-#endif
+ chromeos::cert_provisioning::RegisterLocalStatePrefs(registry);
+#endif // defined(OS_CHROMEOS)
#if defined(OS_MACOSX)
confirm_quit::RegisterLocalState(registry);
QuitWithAppsController::RegisterPrefs(registry);
system_media_permissions::RegisterSystemMediaPermissionStatesPrefs(registry);
AppShimRegistry::Get()->RegisterLocalPrefs(registry);
+ registry->RegisterBooleanPref(kKeyCreated, false);
#endif
-#if defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(OS_WIN)
OSCrypt::RegisterLocalPrefs(registry);
#endif
#if defined(OS_WIN)
registry->RegisterBooleanPref(prefs::kRendererCodeIntegrityEnabled, true);
+ registry->RegisterBooleanPref(
+ policy::policy_prefs::kNativeWindowOcclusionEnabled, true);
component_updater::RegisterPrefsForSwReporter(registry);
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
IncompatibleApplicationsUpdater::RegisterLocalStatePrefs(registry);
@@ -769,6 +811,12 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
registry->RegisterStringPref(kLastWelcomedOSVersion, std::string());
#endif // defined(OS_WIN)
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+ RegisterDefaultBrowserPromptPrefs(registry);
+ downgrade::RegisterPrefs(registry);
+ DeviceOAuth2TokenStoreDesktop::RegisterPrefs(registry);
+#endif
+
// Obsolete. See MigrateObsoleteBrowserPrefs().
registry->RegisterIntegerPref(metrics::prefs::kStabilityExecutionPhase, 0);
#if !defined(OS_ANDROID)
@@ -781,6 +829,16 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
#if defined(TOOLKIT_VIEWS)
RegisterBrowserViewLocalPrefs(registry);
#endif
+
+ // Obsolete. See MigrateObsoleteBrowserPrefs().
+ registry->RegisterBooleanPref(kGCMChannelStatus, true);
+ registry->RegisterIntegerPref(kGCMChannelPollIntervalSeconds, 0);
+ registry->RegisterInt64Pref(kGCMChannelLastCheckTime, 0);
+
+ // Obsolete. See MigrateObsoleteBrowserPrefs().
+ registry->RegisterListPref(kInvalidatorSavedInvalidations);
+ registry->RegisterStringPref(kInvalidatorInvalidationState, std::string());
+ registry->RegisterStringPref(kInvalidatorClientId, std::string());
}
// Register prefs applicable to all profiles.
@@ -796,13 +854,16 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
browsing_data::prefs::RegisterBrowserUserPrefs(registry);
certificate_transparency::prefs::RegisterPrefs(registry);
ChromeContentBrowserClient::RegisterProfilePrefs(registry);
- ChromeSSLHostStateDelegate::RegisterProfilePrefs(registry);
+ ChromeLocationBarModelDelegate::RegisterProfilePrefs(registry);
+ StatefulSSLHostStateDelegate::RegisterProfilePrefs(registry);
ChromeVersionService::RegisterProfilePrefs(registry);
chrome_browser_net::NetErrorTabHelper::RegisterProfilePrefs(registry);
chrome_browser_net::RegisterPredictionOptionsProfilePrefs(registry);
chrome_prefs::RegisterProfilePrefs(registry);
- dom_distiller::DistilledPagePrefs::RegisterProfilePrefs(registry);
+ chrome_ui_features_prefs::RegisterProfilePrefs(registry);
DocumentProvider::RegisterProfilePrefs(registry);
+ dom_distiller::DistilledPagePrefs::RegisterProfilePrefs(registry);
+ dom_distiller::RegisterProfilePrefs(registry);
DownloadPrefs::RegisterProfilePrefs(registry);
HostContentSettingsMap::RegisterProfilePrefs(registry);
image_fetcher::ImageCache::RegisterProfilePrefs(registry);
@@ -815,6 +876,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
MediaStorageIdSalt::RegisterProfilePrefs(registry);
MediaStreamDevicesController::RegisterProfilePrefs(registry);
NavigationCorrectionTabObserver::RegisterProfilePrefs(registry);
+ NotificationDisplayServiceImpl::RegisterProfilePrefs(registry);
NotifierStateTracker::RegisterProfilePrefs(registry);
ntp_snippets::ContentSuggestionsService::RegisterProfilePrefs(registry);
ntp_snippets::RemoteSuggestionsProviderImpl::RegisterProfilePrefs(registry);
@@ -848,7 +910,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
sync_sessions::SessionSyncPrefs::RegisterProfilePrefs(registry);
syncer::DeviceInfoPrefs::RegisterProfilePrefs(registry);
syncer::SyncPrefs::RegisterProfilePrefs(registry);
- syncer::PerUserTopicRegistrationManager::RegisterProfilePrefs(registry);
+ syncer::PerUserTopicSubscriptionManager::RegisterProfilePrefs(registry);
syncer::InvalidatorRegistrarWithMemory::RegisterProfilePrefs(registry);
web_components_prefs::RegisterProfilePrefs(registry);
TemplateURLPrepopulateData::RegisterProfilePrefs(registry);
@@ -874,7 +936,14 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
feature_engagement::SessionDurationUpdater::RegisterProfilePrefs(registry);
#endif
+#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
+ offline_pages::OfflineMetricsCollectorImpl::RegisterPrefs(registry);
+ offline_pages::prefetch_prefs::RegisterPrefs(registry);
+#endif
+
#if BUILDFLAG(ENABLE_PLUGINS)
+ DeviceIDFetcher::RegisterProfilePrefs(registry);
+ PepperFlashSettingsManager::RegisterProfilePrefs(registry);
PluginInfoHostImpl::RegisterUserPrefs(registry);
#endif
@@ -883,6 +952,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
printing::PrintPreviewStickySettings::RegisterProfilePrefs(registry);
#endif
+#if BUILDFLAG(ENABLE_RLZ)
+ ChromeRLZTrackerDelegate::RegisterProfilePrefs(registry);
+#endif
+
#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY)
LocalDiscoveryUI::RegisterProfilePrefs(registry);
#endif
@@ -894,59 +967,52 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
#endif
#if defined(OS_ANDROID)
- ntp_tiles::PopularSitesImpl::RegisterProfilePrefs(registry);
- variations::VariationsService::RegisterProfilePrefs(registry);
- GeolocationPermissionContextAndroid::RegisterProfilePrefs(registry);
+ cdm::MediaDrmStorageImpl::RegisterProfilePrefs(registry);
+ explore_sites::HistoryStatisticsReporter::RegisterPrefs(registry);
+ games::prefs::RegisterProfilePrefs(registry);
+ permissions::GeolocationPermissionContextAndroid::RegisterProfilePrefs(
+ registry);
KnownInterceptionDisclosureInfoBarDelegate::RegisterProfilePrefs(registry);
+ MediaDrmOriginIdManager::RegisterProfilePrefs(registry);
+ NotificationChannelsProviderAndroid::RegisterProfilePrefs(registry);
+ ntp_snippets::ClickBasedCategoryRanker::RegisterProfilePrefs(registry);
+ ntp_tiles::PopularSitesImpl::RegisterProfilePrefs(registry);
+ OomInterventionDecider::RegisterProfilePrefs(registry);
PartnerBookmarksShim::RegisterProfilePrefs(registry);
RecentTabsPagePrefs::RegisterProfilePrefs(registry);
usage_stats::UsageStatsBridge::RegisterProfilePrefs(registry);
+ variations::VariationsService::RegisterProfilePrefs(registry);
+ feed::prefs::RegisterFeedSharedProfilePrefs(registry);
#if BUILDFLAG(ENABLE_FEED_IN_CHROME)
feed::RegisterProfilePrefs(registry);
#endif // BUILDFLAG(ENABLE_FEED_IN_CHROME)
-#else
+#else // defined(OS_ANDROID)
apps::AppServiceProxy::RegisterProfilePrefs(registry);
AppShortcutManager::RegisterProfilePrefs(registry);
- DeviceIDFetcher::RegisterProfilePrefs(registry);
+ browser_sync::ForeignSessionHandler::RegisterProfilePrefs(registry);
+ ChromeAuthenticatorRequestDelegate::RegisterProfilePrefs(registry);
DevToolsWindow::RegisterProfilePrefs(registry);
+ enterprise_reporting::RegisterProfilePrefs(registry);
extensions::CommandService::RegisterProfilePrefs(registry);
extensions::TabsCaptureVisibleTabFunction::RegisterProfilePrefs(registry);
- NewTabUI::RegisterProfilePrefs(registry);
- PepperFlashSettingsManager::RegisterProfilePrefs(registry);
- PinnedTabCodec::RegisterProfilePrefs(registry);
- signin::RegisterProfilePrefs(registry);
-#endif
-
-#if defined(OS_ANDROID)
- cdm::MediaDrmStorageImpl::RegisterProfilePrefs(registry);
- MediaDrmOriginIdManager::RegisterProfilePrefs(registry);
- explore_sites::HistoryStatisticsReporter::RegisterPrefs(registry);
- ntp_snippets::ClickBasedCategoryRanker::RegisterProfilePrefs(registry);
- OomInterventionDecider::RegisterProfilePrefs(registry);
-
-#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
- games::prefs::RegisterProfilePrefs(registry);
-#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
-#endif // defined(OS_ANDROID)
-
-#if !defined(OS_ANDROID)
- browser_sync::ForeignSessionHandler::RegisterProfilePrefs(registry);
- ChromeAuthenticatorRequestDelegate::RegisterProfilePrefs(registry);
first_run::RegisterProfilePrefs(registry);
+ gcm::RegisterProfilePrefs(registry);
HatsService::RegisterProfilePrefs(registry);
+ HistoryUI::RegisterProfilePrefs(registry);
InstantService::RegisterProfilePrefs(registry);
- PromoService::RegisterProfilePrefs(registry);
- SearchSuggestService::RegisterProfilePrefs(registry);
- gcm::GCMChannelStatusSyncer::RegisterProfilePrefs(registry);
- gcm::RegisterProfilePrefs(registry);
media_router::RegisterProfilePrefs(registry);
+ NewTabUI::RegisterProfilePrefs(registry);
ntp_tiles::CustomLinksManagerImpl::RegisterProfilePrefs(registry);
+ PinnedTabCodec::RegisterProfilePrefs(registry);
+ PromoService::RegisterProfilePrefs(registry);
+ SearchSuggestService::RegisterProfilePrefs(registry);
+ settings::SettingsUI::RegisterProfilePrefs(registry);
+ send_tab_to_self::SendTabToSelfBubbleController::RegisterProfilePrefs(
+ registry);
+ signin::RegisterProfilePrefs(registry);
StartupBrowserCreator::RegisterProfilePrefs(registry);
-#endif
-
-#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
- default_apps::RegisterProfilePrefs(registry);
-#endif
+ UnifiedAutoplayConfig::RegisterProfilePrefs(registry);
+#endif // defined(OS_ANDROID)
#if defined(OS_CHROMEOS)
app_list::AppListSyncableService::RegisterProfilePrefs(registry);
@@ -956,6 +1022,8 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
certificate_manager::CertificatesHandler::RegisterProfilePrefs(registry);
chromeos::AccountManager::RegisterPrefs(registry);
chromeos::ApkWebAppService::RegisterProfilePrefs(registry);
+ chromeos::app_time::AppActivityRegistry::RegisterProfilePrefs(registry);
+ chromeos::app_time::AppTimeController::RegisterProfilePrefs(registry);
chromeos::assistant::prefs::RegisterProfilePrefs(registry);
chromeos::bluetooth::DebugLogsManager::RegisterPrefs(registry);
chromeos::CupsPrintersManager::RegisterProfilePrefs(registry);
@@ -967,21 +1035,28 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
chromeos::multidevice_setup::MultiDeviceSetupService::RegisterProfilePrefs(
registry);
chromeos::MultiProfileUserController::RegisterProfilePrefs(registry);
+ chromeos::NetworkMetadataStore::RegisterPrefs(registry);
chromeos::ReleaseNotesStorage::RegisterProfilePrefs(registry);
chromeos::quick_unlock::FingerprintStorage::RegisterProfilePrefs(registry);
chromeos::quick_unlock::PinStoragePrefs::RegisterProfilePrefs(registry);
chromeos::Preferences::RegisterProfilePrefs(registry);
chromeos::PrintJobHistoryService::RegisterProfilePrefs(registry);
- chromeos::SyncedPrintersManager::RegisterProfilePrefs(registry);
+ chromeos::EnterprisePrintersProvider::RegisterProfilePrefs(registry);
chromeos::parent_access::ParentAccessService::RegisterProfilePrefs(registry);
+ chromeos::quick_answers::prefs::RegisterProfilePrefs(registry);
chromeos::quick_unlock::RegisterProfilePrefs(registry);
chromeos::RegisterSamlProfilePrefs(registry);
chromeos::ScreenTimeController::RegisterProfilePrefs(registry);
+ SecondaryAccountConsentLogger::RegisterPrefs(registry);
chromeos::ServicesCustomizationDocument::RegisterProfilePrefs(registry);
+ chromeos::settings::OSSettingsUI::RegisterProfilePrefs(registry);
chromeos::UserImageSyncObserver::RegisterProfilePrefs(registry);
crostini::prefs::RegisterProfilePrefs(registry);
chromeos::attestation::TpmChallengeKey::RegisterProfilePrefs(registry);
extensions::EPKPChallengeKey::RegisterProfilePrefs(registry);
+#if defined(USE_CUPS)
+ extensions::PrintingAPIHandler::RegisterProfilePrefs(registry);
+#endif
flags_ui::PrefServiceFlagsStorage::RegisterProfilePrefs(registry);
guest_os::prefs::RegisterProfilePrefs(registry);
lock_screen_apps::StateController::RegisterProfilePrefs(registry);
@@ -989,12 +1064,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
policy::AppInstallEventLogger::RegisterProfilePrefs(registry);
policy::AppInstallEventLogManagerWrapper::RegisterProfilePrefs(registry);
policy::StatusCollector::RegisterProfilePrefs(registry);
+ RegisterChromeLauncherUserPrefs(registry);
::onc::RegisterProfilePrefs(registry);
-#endif
-
-#if BUILDFLAG(ENABLE_RLZ)
- ChromeRLZTrackerDelegate::RegisterProfilePrefs(registry);
-#endif
+ chromeos::cert_provisioning::RegisterProfilePrefs(registry);
+#endif // defined(OS_CHROMEOS)
#if defined(OS_WIN)
component_updater::RegisterProfilePrefsForSwReporter(registry);
@@ -1009,39 +1082,17 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
browser_switcher::BrowserSwitcherPrefs::RegisterProfilePrefs(registry);
#endif
-#if defined(TOOLKIT_VIEWS)
- accessibility_prefs::RegisterInvertBubbleUserPrefs(registry);
- RegisterBrowserViewProfilePrefs(registry);
-#endif
-
-#if defined(OS_CHROMEOS)
- RegisterChromeLauncherUserPrefs(registry);
-#endif
-
-#if !defined(OS_ANDROID)
- HistoryUI::RegisterProfilePrefs(registry);
- settings::SettingsUI::RegisterProfilePrefs(registry);
-#endif
-
-#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
- offline_pages::OfflineMetricsCollectorImpl::RegisterPrefs(registry);
- offline_pages::prefetch_prefs::RegisterPrefs(registry);
-#endif
-
-#if defined(OS_ANDROID)
- NotificationChannelsProviderAndroid::RegisterProfilePrefs(registry);
-#endif
-
-#if !defined(OS_ANDROID)
- UnifiedAutoplayConfig::RegisterProfilePrefs(registry);
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+ default_apps::RegisterProfilePrefs(registry);
#endif
#if !defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_EXTENSIONS)
extensions::enterprise_reporting::RegisterProfilePrefs(registry);
#endif
-#if !defined(OS_ANDROID)
- enterprise_reporting::RegisterProfilePrefs(registry);
+#if defined(TOOLKIT_VIEWS)
+ accessibility_prefs::RegisterInvertBubbleUserPrefs(registry);
+ RegisterBrowserViewProfilePrefs(registry);
#endif
RegisterProfilePrefsForMigration(registry);
@@ -1109,6 +1160,22 @@ void MigrateObsoleteBrowserPrefs(Profile* profile, PrefService* local_state) {
local_state->ClearPref(kLastStartupTimestamp);
local_state->ClearPref(kLastStartupVersion);
local_state->ClearPref(kSameVersionStartupCount);
+
+ // Added 1/2019
+ local_state->ClearPref(kLastStartupTimestamp);
+
+ // Added 1/2020
+#if defined(OS_MACOSX)
+ local_state->ClearPref(kKeyCreated);
+#endif // defined(OS_MACOSX)
+ local_state->ClearPref(kGCMChannelStatus);
+ local_state->ClearPref(kGCMChannelPollIntervalSeconds);
+ local_state->ClearPref(kGCMChannelLastCheckTime);
+
+ // Added 2/2020.
+ local_state->ClearPref(kInvalidatorSavedInvalidations);
+ local_state->ClearPref(kInvalidatorInvalidationState);
+ local_state->ClearPref(kInvalidatorClientId);
}
// This method should be periodically pruned of year+ old migrations.
@@ -1143,9 +1210,6 @@ void MigrateObsoleteProfilePrefs(Profile* profile) {
#if defined(OS_CHROMEOS)
// Added 12/2018.
profile_prefs->ClearPref(prefs::kDataSaverPromptsShown);
-
- // Added 4/2019
- guest_os::GuestOsSharePath::MigratePersistedPathsToMultiVM(profile_prefs);
#endif
// Added 1/2019.
@@ -1250,4 +1314,18 @@ void MigrateObsoleteProfilePrefs(Profile* profile) {
// Added 11/2019.
profile_prefs->ClearPref(kBlacklistedCredentialsNormalized);
+
+ // Added 1/2020.
+ profile_prefs->ClearPref(kGCMChannelStatus);
+ profile_prefs->ClearPref(kGCMChannelPollIntervalSeconds);
+ profile_prefs->ClearPref(kGCMChannelLastCheckTime);
+
+ // Added 2/2020.
+ profile_prefs->ClearPref(kInvalidatorSavedInvalidations);
+ profile_prefs->ClearPref(kInvalidatorInvalidationState);
+ profile_prefs->ClearPref(kInvalidatorClientId);
+
+ // Added 3/2020.
+ profile_prefs->ClearPref(kDataReductionNetworkProperties);
+ chrome_browser_net::MigrateDNSProbesSettingToOrFromBackup(profile_prefs);
}
diff --git a/chromium/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chromium/chrome/browser/prefs/chrome_command_line_pref_store.cc
index 60cd72cedbb..782d368081b 100644
--- a/chromium/chrome/browser/prefs/chrome_command_line_pref_store.cc
+++ b/chromium/chrome/browser/prefs/chrome_command_line_pref_store.cc
@@ -27,6 +27,8 @@
#include "components/language/core/browser/pref_names.h"
#include "components/proxy_config/proxy_config_dictionary.h"
#include "components/proxy_config/proxy_config_pref_names.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safebrowsing_switches.h"
#include "components/sync/base/pref_names.h"
#include "content/public/common/content_switches.h"
#include "services/network/public/cpp/network_switches.h"
@@ -72,6 +74,8 @@ const CommandLinePrefStore::BooleanSwitchToPreferenceMapEntry
{switches::kAllowCrossOriginAuthPrompt,
prefs::kAllowCrossOriginAuthPrompt, true},
{switches::kDisablePrintPreview, prefs::kPrintPreviewDisabled, true},
+ {safe_browsing::switches::kSbEnableEnhancedProtection,
+ prefs::kSafeBrowsingEnhanced, true},
#if defined(OS_CHROMEOS)
{chromeos::switches::kEnableTouchpadThreeFingerClick,
prefs::kEnableTouchpadThreeFingerClick, true},
diff --git a/chromium/chrome/browser/prefs/chrome_command_line_pref_store_proxy_unittest.cc b/chromium/chrome/browser/prefs/chrome_command_line_pref_store_proxy_unittest.cc
index 62e885a16b5..991c79bac75 100644
--- a/chromium/chrome/browser/prefs/chrome_command_line_pref_store_proxy_unittest.cc
+++ b/chromium/chrome/browser/prefs/chrome_command_line_pref_store_proxy_unittest.cc
@@ -35,7 +35,7 @@ struct CommandLineTestParams {
// Expected outputs (fields of the ProxyConfig).
bool is_null;
bool auto_detect;
- GURL pac_url;
+ std::string pac_url;
net::ProxyRulesExpectation proxy_rules;
};
@@ -49,9 +49,9 @@ static const CommandLineTestParams kCommandLineTestParams[] = {
// Input
{},
// Expected result
- true, // is_null
- false, // auto_detect
- GURL(), // pac_url
+ true, // is_null
+ false, // auto_detect
+ "", // pac_url
net::ProxyRulesExpectation::Empty(),
},
{
@@ -61,9 +61,9 @@ static const CommandLineTestParams kCommandLineTestParams[] = {
{switches::kNoProxyServer, NULL},
},
// Expected result
- false, // is_null
- false, // auto_detect
- GURL(), // pac_url
+ false, // is_null
+ false, // auto_detect
+ "", // pac_url
net::ProxyRulesExpectation::Empty(),
},
{
@@ -74,9 +74,9 @@ static const CommandLineTestParams kCommandLineTestParams[] = {
{switches::kProxyServer, "http://proxy:8888"},
},
// Expected result
- false, // is_null
- false, // auto_detect
- GURL(), // pac_url
+ false, // is_null
+ false, // auto_detect
+ "", // pac_url
net::ProxyRulesExpectation::Empty(),
},
{
@@ -88,7 +88,7 @@ static const CommandLineTestParams kCommandLineTestParams[] = {
// Expected result
false, // is_null
false, // auto_detect
- GURL(), // pac_url
+ "", // pac_url
net::ProxyRulesExpectation::Single("proxy:8888", // single proxy
""), // bypass rules
},
@@ -101,7 +101,7 @@ static const CommandLineTestParams kCommandLineTestParams[] = {
// Expected result
false, // is_null
false, // auto_detect
- GURL(), // pac_url
+ "", // pac_url
net::ProxyRulesExpectation::PerScheme("httpproxy:8888", // http
"", // https
"ftpproxy:8889", // ftp
@@ -116,9 +116,9 @@ static const CommandLineTestParams kCommandLineTestParams[] = {
".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8"},
},
// Expected result
- false, // is_null
- false, // auto_detect
- GURL(), // pac_url
+ false, // is_null
+ false, // auto_detect
+ "", // pac_url
net::ProxyRulesExpectation::PerScheme(
"httpproxy:8888", // http
"", // https
@@ -132,9 +132,9 @@ static const CommandLineTestParams kCommandLineTestParams[] = {
{switches::kProxyPacUrl, "http://wpad/wpad.dat"},
},
// Expected result
- false, // is_null
- false, // auto_detect
- GURL("http://wpad/wpad.dat"), // pac_url
+ false, // is_null
+ false, // auto_detect
+ "http://wpad/wpad.dat", // pac_url
net::ProxyRulesExpectation::Empty(),
},
{
@@ -144,9 +144,9 @@ static const CommandLineTestParams kCommandLineTestParams[] = {
{switches::kProxyAutoDetect, NULL},
},
// Expected result
- false, // is_null
- true, // auto_detect
- GURL(), // pac_url
+ false, // is_null
+ true, // auto_detect
+ "", // pac_url
net::ProxyRulesExpectation::Empty(),
},
};
@@ -188,7 +188,7 @@ class ChromeCommandLinePrefStoreProxyTest
TEST_P(ChromeCommandLinePrefStoreProxyTest, CommandLine) {
EXPECT_EQ(GetParam().auto_detect, proxy_config()->value().auto_detect());
- EXPECT_EQ(GetParam().pac_url, proxy_config()->value().pac_url());
+ EXPECT_EQ(GURL(GetParam().pac_url), proxy_config()->value().pac_url());
EXPECT_TRUE(
GetParam().proxy_rules.Matches(proxy_config()->value().proxy_rules()));
}
diff --git a/chromium/chrome/browser/prefs/chrome_pref_service_factory.cc b/chromium/chrome/browser/prefs/chrome_pref_service_factory.cc
index ce49583f5c3..6186da7ed18 100644
--- a/chromium/chrome/browser/prefs/chrome_pref_service_factory.cc
+++ b/chromium/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -47,7 +47,7 @@
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_store.h"
#include "components/prefs/pref_value_store.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/search_engines/default_search_manager.h"
#include "components/search_engines/search_engines_pref_names.h"
#include "components/signin/public/base/signin_pref_names.h"
diff --git a/chromium/chrome/browser/prefs/incognito_mode_prefs.cc b/chromium/chrome/browser/prefs/incognito_mode_prefs.cc
index 881d7e6934a..203efcee12a 100644
--- a/chromium/chrome/browser/prefs/incognito_mode_prefs.cc
+++ b/chromium/chrome/browser/prefs/incognito_mode_prefs.cc
@@ -8,121 +8,21 @@
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/task/post_task.h"
-#include "base/threading/scoped_blocking_call.h"
-#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
-#include "content/public/browser/browser_thread.h"
#if defined(OS_WIN)
-#include <windows.h>
-#include <objbase.h>
-#include <wpcapi.h>
-#include <wrl/client.h>
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/memory/singleton.h"
+#include "chrome/browser/win/parental_controls.h"
#endif // OS_WIN
#if defined(OS_ANDROID)
#include "chrome/browser/android/partner_browser_customizations.h"
#endif // defined(OS_ANDROID)
-using content::BrowserThread;
-
-#if defined(OS_WIN)
-namespace {
-
-// This singleton allows us to attempt to calculate the Platform Parental
-// Controls enabled value on a worker thread before the UI thread needs the
-// value. If the UI thread finishes sooner than we expect, that's no worse than
-// today where we block.
-class PlatformParentalControlsValue {
- public:
- static PlatformParentalControlsValue* GetInstance() {
- return base::Singleton<PlatformParentalControlsValue>::get();
- }
-
- bool is_enabled() const {
- return is_enabled_;
- }
-
- private:
- friend struct base::DefaultSingletonTraits<PlatformParentalControlsValue>;
-
- // Histogram enum for tracking the thread that checked parental controls.
- enum class ThreadType {
- UI = 0,
- BLOCKING,
- COUNT,
- };
-
- PlatformParentalControlsValue()
- : is_enabled_(IsParentalControlActivityLoggingOn()) {}
-
- ~PlatformParentalControlsValue() = default;
-
- // Returns true if Windows Parental control activity logging is enabled. This
- // feature is available on Windows 7 and beyond. This function should be
- // called on a COM Initialized thread and is potentially blocking.
- static bool IsParentalControlActivityLoggingOn() {
- ThreadType thread_type = ThreadType::BLOCKING;
- if (BrowserThread::IsThreadInitialized(BrowserThread::UI) &&
- content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- thread_type = ThreadType::UI;
- }
-
- UMA_HISTOGRAM_ENUMERATION(
- "IncognitoModePrefs.WindowsParentalControlsInitThread",
- static_cast<int32_t>(thread_type),
- static_cast<int32_t>(ThreadType::COUNT));
-
- base::Time begin_time = base::Time::Now();
- bool result = IsParentalControlActivityLoggingOnImpl();
- UMA_HISTOGRAM_TIMES("IncognitoModePrefs.WindowsParentalControlsInitTime",
- base::Time::Now() - begin_time);
- return result;
- }
-
- // Does the work of determining if Windows Parental control activity logging
- // is enabled.
- static bool IsParentalControlActivityLoggingOnImpl() {
- // Since we can potentially block, make sure the thread is okay with this.
- base::ScopedBlockingCall scoped_blocking_call(
- FROM_HERE, base::BlockingType::MAY_BLOCK);
- Microsoft::WRL::ComPtr<IWindowsParentalControlsCore> parent_controls;
- HRESULT hr = ::CoCreateInstance(__uuidof(WindowsParentalControls), nullptr,
- CLSCTX_ALL, IID_PPV_ARGS(&parent_controls));
- if (FAILED(hr))
- return false;
-
- Microsoft::WRL::ComPtr<IWPCSettings> settings;
- hr = parent_controls->GetUserSettings(nullptr, settings.GetAddressOf());
- if (FAILED(hr))
- return false;
-
- unsigned long restrictions = 0;
- settings->GetRestrictions(&restrictions);
-
- return (restrictions & WPCFLAG_LOGGING_REQUIRED) ==
- WPCFLAG_LOGGING_REQUIRED;
- }
-
- const bool is_enabled_;
-
- DISALLOW_COPY_AND_ASSIGN(PlatformParentalControlsValue);
-};
-
-} // namespace
-#endif // OS_WIN
-
// static
// Sadly, this is required until c++17.
constexpr IncognitoModePrefs::Availability
@@ -196,20 +96,10 @@ bool IncognitoModePrefs::CanOpenBrowser(Profile* profile) {
}
}
-#if defined(OS_WIN)
-// static
-void IncognitoModePrefs::InitializePlatformParentalControls() {
- base::CreateCOMSTATaskRunner(
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE})
- ->PostTask(FROM_HERE, base::BindOnce(base::IgnoreResult(
- &PlatformParentalControlsValue::GetInstance)));
-}
-#endif
-
// static
bool IncognitoModePrefs::ArePlatformParentalControlsEnabled() {
#if defined(OS_WIN)
- return PlatformParentalControlsValue::GetInstance()->is_enabled();
+ return GetWinParentalControls().logging_required;
#elif defined(OS_ANDROID)
return chrome::android::PartnerBrowserCustomizations::IsIncognitoDisabled();
#else
diff --git a/chromium/chrome/browser/prefs/incognito_mode_prefs.h b/chromium/chrome/browser/prefs/incognito_mode_prefs.h
index 03ad9282af7..b80d29529e7 100644
--- a/chromium/chrome/browser/prefs/incognito_mode_prefs.h
+++ b/chromium/chrome/browser/prefs/incognito_mode_prefs.h
@@ -7,7 +7,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "build/build_config.h"
class PrefService;
class Profile;
@@ -67,12 +66,6 @@ class IncognitoModePrefs {
// open new windows.
static bool CanOpenBrowser(Profile* profile);
-#if defined(OS_WIN)
- // Calculates and caches the platform parental controls enable value on a
- // worker thread.
- static void InitializePlatformParentalControls();
-#endif
-
// Returns whether parental controls have been enabled on the platform. This
// method evaluates and caches if the platform controls have been enabled on
// the first call, which must be on the UI thread when IO and blocking are
diff --git a/chromium/chrome/browser/prefs/pref_functional_browsertest.cc b/chromium/chrome/browser/prefs/pref_functional_browsertest.cc
index 29a9b4edfbf..9c0624e57ab 100644
--- a/chromium/chrome/browser/prefs/pref_functional_browsertest.cc
+++ b/chromium/chrome/browser/prefs/pref_functional_browsertest.cc
@@ -22,7 +22,8 @@
#include "components/content_settings/core/browser/website_settings_registry.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/content_settings/core/common/pref_names.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/embedder_support/pref_names.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
@@ -220,8 +221,8 @@ IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, PRE_TestPrivacySecurityPrefs) {
EXPECT_TRUE(prefs->GetBoolean(prefs::kSafeBrowsingEnabled));
prefs->SetBoolean(prefs::kSafeBrowsingEnabled, false);
- EXPECT_TRUE(prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled));
- prefs->SetBoolean(prefs::kAlternateErrorPagesEnabled, false);
+ EXPECT_TRUE(prefs->GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
+ prefs->SetBoolean(embedder_support::kAlternateErrorPagesEnabled, false);
EXPECT_TRUE(prefs->GetBoolean(prefs::kSearchSuggestEnabled));
prefs->SetBoolean(prefs::kSearchSuggestEnabled, false);
@@ -234,7 +235,8 @@ IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, TestPrivacySecurityPrefs) {
EXPECT_EQ(chrome_browser_net::NETWORK_PREDICTION_NEVER,
prefs->GetInteger(prefs::kNetworkPredictionOptions));
EXPECT_FALSE(prefs->GetBoolean(prefs::kSafeBrowsingEnabled));
- EXPECT_FALSE(prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled));
+ EXPECT_FALSE(
+ prefs->GetBoolean(embedder_support::kAlternateErrorPagesEnabled));
EXPECT_FALSE(prefs->GetBoolean(prefs::kSearchSuggestEnabled));
}
diff --git a/chromium/chrome/browser/prefs/pref_metrics_service.cc b/chromium/chrome/browser/prefs/pref_metrics_service.cc
index 8d2283b1b42..4d98dc65b0e 100644
--- a/chromium/chrome/browser/prefs/pref_metrics_service.cc
+++ b/chromium/chrome/browser/prefs/pref_metrics_service.cc
@@ -142,10 +142,6 @@ bool PrefMetricsService::Factory::ServiceIsCreatedWithBrowserContext() const {
return true;
}
-bool PrefMetricsService::Factory::ServiceIsNULLWhileTesting() const {
- return false;
-}
-
content::BrowserContext* PrefMetricsService::Factory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return chrome::GetBrowserContextRedirectedInIncognito(context);
diff --git a/chromium/chrome/browser/prefs/pref_metrics_service.h b/chromium/chrome/browser/prefs/pref_metrics_service.h
index a1864def73f..5d7616e28b5 100644
--- a/chromium/chrome/browser/prefs/pref_metrics_service.h
+++ b/chromium/chrome/browser/prefs/pref_metrics_service.h
@@ -40,7 +40,6 @@ class PrefMetricsService : public KeyedService {
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* profile) const override;
bool ServiceIsCreatedWithBrowserContext() const override;
- bool ServiceIsNULLWhileTesting() const override;
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
};
diff --git a/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.cc b/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.cc
index 0206ea78562..3cfc0bc885b 100644
--- a/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.cc
+++ b/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.cc
@@ -91,60 +91,6 @@ const char* const kPersistentPrefNames[] = {
prefs::kPartnerBookmarkMappings,
#endif // defined(OS_ANDROID)
- // Metrics preferences are out of profile scope and are merged between
- // incognito and regular modes.
- metrics::prefs::kInstallDate,
- metrics::prefs::kMetricsClientID,
- metrics::prefs::kMetricsDefaultOptIn,
- metrics::prefs::kMetricsInitialLogs,
- metrics::prefs::kMetricsLowEntropySource,
- metrics::prefs::kMetricsMachineId,
- metrics::prefs::kMetricsOngoingLogs,
- metrics::prefs::kMetricsResetIds,
-
- metrics::prefs::kMetricsReportingEnabled,
- metrics::prefs::kMetricsReportingEnabledTimestamp,
- metrics::prefs::kMetricsSessionID,
- metrics::prefs::kMetricsLastSeenPrefix,
- metrics::prefs::kStabilityBreakpadRegistrationFail,
- metrics::prefs::kStabilityBreakpadRegistrationSuccess,
- metrics::prefs::kStabilityBrowserLastLiveTimeStamp,
- metrics::prefs::kStabilityChildProcessCrashCount,
- metrics::prefs::kStabilityCrashCount,
- metrics::prefs::kStabilityCrashCountDueToGmsCoreUpdate,
- metrics::prefs::kStabilityCrashCountWithoutGmsCoreUpdateObsolete,
- metrics::prefs::kStabilityDebuggerNotPresent,
- metrics::prefs::kStabilityDebuggerPresent,
- metrics::prefs::kStabilityDeferredCount,
- metrics::prefs::kStabilityDiscardCount,
- metrics::prefs::kStabilityExecutionPhase,
- metrics::prefs::kStabilityExitedCleanly,
- metrics::prefs::kStabilityExtensionRendererCrashCount,
- metrics::prefs::kStabilityExtensionRendererFailedLaunchCount,
- metrics::prefs::kStabilityExtensionRendererLaunchCount,
- metrics::prefs::kStabilityGmsCoreVersion,
- metrics::prefs::kStabilityGpuCrashCount,
- metrics::prefs::kStabilityIncompleteSessionEndCount,
- metrics::prefs::kStabilityLaunchCount,
- metrics::prefs::kStabilityPageLoadCount,
- metrics::prefs::kStabilityRendererCrashCount,
- metrics::prefs::kStabilityRendererFailedLaunchCount,
- metrics::prefs::kStabilityRendererHangCount,
- metrics::prefs::kStabilityRendererLaunchCount,
- metrics::prefs::kStabilitySavedSystemProfile,
- metrics::prefs::kStabilitySavedSystemProfileHash,
- metrics::prefs::kStabilitySessionEndCompleted,
- metrics::prefs::kStabilityStatsBuildTime,
- metrics::prefs::kStabilityStatsVersion,
- metrics::prefs::kStabilitySystemCrashCount,
- metrics::prefs::kStabilityVersionMismatchCount,
- metrics::prefs::kUninstallLaunchCount,
- metrics::prefs::kUninstallMetricsPageLoadCount,
- metrics::prefs::kUninstallMetricsUptimeSec,
- metrics::prefs::kUkmCellDataUse,
- metrics::prefs::kUmaCellDataUse,
- metrics::prefs::kUserCellDataUse,
-
#if defined(OS_ANDROID)
// Clipboard modification state is updated over all profiles.
prefs::kClipboardLastModifiedTime,
diff --git a/chromium/chrome/browser/prefs/profile_pref_store_manager.h b/chromium/chrome/browser/prefs/profile_pref_store_manager.h
index 94dadd4953d..229a755a937 100644
--- a/chromium/chrome/browser/prefs/profile_pref_store_manager.h
+++ b/chromium/chrome/browser/prefs/profile_pref_store_manager.h
@@ -16,8 +16,8 @@
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "services/preferences/public/mojom/preferences.mojom.h"
-#include "services/preferences/public/mojom/tracked_preference_validation_delegate.mojom.h"
+#include "services/preferences/public/mojom/preferences.mojom-forward.h"
+#include "services/preferences/public/mojom/tracked_preference_validation_delegate.mojom-forward.h"
class PersistentPrefStore;
class PrefService;
diff --git a/chromium/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chromium/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
index 67913e7e49d..061c2442bfc 100644
--- a/chromium/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
+++ b/chromium/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
@@ -129,6 +129,7 @@ int GetTrackedPrefHistogramCount(const char* histogram_name,
return GetTrackedPrefHistogramCount(histogram_name, "", allowed_buckets);
}
+#if !defined(OS_CHROMEOS)
std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary(
const base::FilePath& pref_file) {
JSONFileValueDeserializer deserializer(pref_file);
@@ -147,6 +148,7 @@ std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary(
return std::unique_ptr<base::DictionaryValue>(
static_cast<base::DictionaryValue*>(prefs.release()));
}
+#endif
// Returns whether external validation is supported on the platform through
// storing MACs in the registry.
@@ -227,8 +229,7 @@ class PrefHashBrowserTestBase
// below).
EXPECT_EQ(PROTECTION_DISABLED_ON_PLATFORM, protection_level_);
return true;
-#endif
-
+#else
base::FilePath profile_dir;
EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &profile_dir));
profile_dir = profile_dir.AppendASCII(TestingProfile::kTestUserProfileDir);
@@ -277,6 +278,7 @@ class PrefHashBrowserTestBase
}
return true;
+#endif
}
void SetUpInProcessBrowserTestFixture() override {
diff --git a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc
index 55fc976539c..a2bdf7fb98f 100644
--- a/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc
+++ b/chromium/chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc
@@ -20,6 +20,7 @@
#include "components/cloud_devices/common/cloud_devices_urls.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
+#include "components/signin/public/identity_manager/scope_set.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/base/load_flags.h"
#include "net/base/url_util.h"
@@ -100,7 +101,7 @@ GCDApiFlowImpl::~GCDApiFlowImpl() {}
void GCDApiFlowImpl::Start(std::unique_ptr<Request> request) {
request_ = std::move(request);
- identity::ScopeSet oauth_scopes;
+ signin::ScopeSet oauth_scopes;
oauth_scopes.insert(request_->GetOAuthScope());
DCHECK(identity_manager_);
token_fetcher_ = std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
diff --git a/chromium/chrome/browser/printing/cloud_print/privet_notifications.cc b/chromium/chrome/browser/printing/cloud_print/privet_notifications.cc
index 92f43abc1f0..5e16ab98978 100644
--- a/chromium/chrome/browser/printing/cloud_print/privet_notifications.cc
+++ b/chromium/chrome/browser/printing/cloud_print/privet_notifications.cc
@@ -33,6 +33,7 @@
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/theme_resources.h"
#include "components/prefs/pref_service.h"
+#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_controller.h"
@@ -57,7 +58,6 @@ const int kTenMinutesInSeconds = 600;
const char kPrivetInfoKeyUptime[] = "uptime";
const char kPrivetNotificationID[] = "privet_notification";
const char kPrivetNotificationOriginUrl[] = "chrome://devices";
-const int kStartDelaySeconds = 5;
} // namespace
@@ -179,13 +179,15 @@ PrivetNotificationsListener::DeviceContext::DeviceContext() {
PrivetNotificationsListener::DeviceContext::~DeviceContext() {
}
+// static
+constexpr base::TimeDelta PrivetNotificationService::kStartDelay;
+
PrivetNotificationService::PrivetNotificationService(
content::BrowserContext* profile)
: profile_(profile) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::BindOnce(&PrivetNotificationService::Start, AsWeakPtr()),
- base::TimeDelta::FromSeconds(kStartDelaySeconds +
- base::RandInt(0, kStartDelaySeconds / 4)));
+ kStartDelay + base::TimeDelta::FromMilliseconds(base::RandInt(0, 1000)));
}
PrivetNotificationService::~PrivetNotificationService() {
@@ -287,8 +289,11 @@ void PrivetNotificationService::Start() {
auto* identity_manager = IdentityManagerFactory::GetForProfileIfExists(
Profile::FromBrowserContext(profile_));
- if (!identity_manager || !identity_manager->HasPrimaryAccount())
+ // Only show notifications for signed-in accounts. https://crbug.com/349098
+ if (!identity_manager || !identity_manager->HasPrimaryAccount(
+ signin::ConsentLevel::kNotRequired)) {
return;
+ }
#endif // defined(OS_CHROMEOS)
enable_privet_notification_member_.Init(
diff --git a/chromium/chrome/browser/printing/cloud_print/privet_notifications.h b/chromium/chrome/browser/printing/cloud_print/privet_notifications.h
index 6e5b84da305..325cfc81326 100644
--- a/chromium/chrome/browser/printing/cloud_print/privet_notifications.h
+++ b/chromium/chrome/browser/printing/cloud_print/privet_notifications.h
@@ -10,6 +10,7 @@
#include <set>
#include <string>
+#include "base/time/time.h"
#include "chrome/browser/printing/cloud_print/privet_device_lister.h"
#include "chrome/browser/printing/cloud_print/privet_http.h"
#include "components/keyed_service/core/keyed_service.h"
@@ -101,6 +102,10 @@ class PrivetNotificationService
public PrivetNotificationsListener::Delegate,
public base::SupportsWeakPtr<PrivetNotificationService> {
public:
+ // Visible for testing.
+ static constexpr base::TimeDelta kStartDelay =
+ base::TimeDelta::FromSeconds(5);
+
explicit PrivetNotificationService(content::BrowserContext* profile);
~PrivetNotificationService() override;
@@ -117,6 +122,11 @@ class PrivetNotificationService
static bool IsEnabled();
static bool IsForced();
+ PrivetDeviceLister* device_lister_for_test() { return device_lister_.get(); }
+ PrivetTrafficDetector* traffic_detector_for_test() {
+ return traffic_detector_.get();
+ }
+
private:
void Start();
void OnNotificationsEnabledChanged();
diff --git a/chromium/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc b/chromium/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc
index 7086c4b66f0..afa2682fe23 100644
--- a/chromium/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc
+++ b/chromium/chrome/browser/printing/cloud_print/privet_notifications_unittest.cc
@@ -320,6 +320,24 @@ TEST_F(PrivetNotificationsNotificationTest, DontShowAgain) {
.size());
}
+#if defined(OS_CHROMEOS)
+TEST(PrivetNotificationServiceTest, NoNotificationsInGuestMode) {
+ content::BrowserTaskEnvironment task_environment{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ TestingProfileManager profile_manager(TestingBrowserProcess::GetGlobal());
+ ASSERT_TRUE(profile_manager.SetUp());
+ Profile* profile = profile_manager.CreateGuestProfile();
+
+ TestPrivetNotificationService service(profile);
+ // Wait for delayed initialization.
+ task_environment.FastForwardBy(PrivetNotificationService::kStartDelay * 2);
+
+ // We're not watching for printers.
+ EXPECT_FALSE(service.device_lister_for_test());
+ EXPECT_FALSE(service.traffic_detector_for_test());
+}
+#endif // defined(OS_CHROMEOS)
+
} // namespace
} // namespace cloud_print
diff --git a/chromium/chrome/browser/printing/pdf_to_emf_converter.cc b/chromium/chrome/browser/printing/pdf_to_emf_converter.cc
index 3a9141aaebe..79e5971f6b4 100644
--- a/chromium/chrome/browser/printing/pdf_to_emf_converter.cc
+++ b/chromium/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -219,7 +219,7 @@ std::unique_ptr<MetafilePlayer> PdfConverterImpl::GetMetaFileFromMapping(
} else {
metafile = std::make_unique<Emf>();
}
- if (!metafile->InitFromData(mapping.memory(), mapping.size()))
+ if (!metafile->InitFromData(mapping.GetMemoryAsSpan<const uint8_t>()))
metafile.reset();
return metafile;
}
@@ -265,7 +265,7 @@ void PdfConverterImpl::Initialize(scoped_refptr<base::RefCountedMemory> data) {
base::MappedReadOnlyRegion memory =
base::ReadOnlySharedMemoryRegion::Create(data->size());
- if (!memory.region.IsValid() || !memory.mapping.IsValid()) {
+ if (!memory.IsValid()) {
OnFailed(std::string("Failed to create PDF data mapping."));
return;
}
diff --git a/chromium/chrome/browser/printing/pdf_to_emf_converter_browsertest.cc b/chromium/chrome/browser/printing/pdf_to_emf_converter_browsertest.cc
index e912e01e8c8..0eec97e7519 100644
--- a/chromium/chrome/browser/printing/pdf_to_emf_converter_browsertest.cc
+++ b/chromium/chrome/browser/printing/pdf_to_emf_converter_browsertest.cc
@@ -59,7 +59,7 @@ std::string GetFileNameForPageNumber(const std::string& name, int page_number) {
std::unique_ptr<ENHMETAHEADER> GetEmfHeader(const std::string& emf_data) {
Emf emf;
- if (!emf.InitFromData(emf_data.data(), emf_data.size()))
+ if (!emf.InitFromData(base::as_bytes(base::make_span(emf_data))))
return nullptr;
auto meta_header = std::make_unique<ENHMETAHEADER>();
@@ -361,4 +361,24 @@ IN_PROC_BROWSER_TEST_F(PdfToEmfConverterBrowserTest,
"bug_806746.emf");
}
+IN_PROC_BROWSER_TEST_F(PdfToEmfConverterBrowserTest,
+ PostScriptLevel2WithLineCapLineJoin) {
+ const PdfRenderSettings pdf_settings(
+ kLetter200DpiRect, gfx::Point(0, 0), k200DpiSize,
+ /*autorotate=*/false, /*use_color=*/true,
+ PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2);
+ RunSinglePagePdfToPostScriptConverterTest(pdf_settings, "bug_1030689.pdf",
+ "bug_1030689.emf");
+}
+
+IN_PROC_BROWSER_TEST_F(PdfToEmfConverterBrowserTest,
+ PostScriptLevel3WithLineCapLineJoin) {
+ const PdfRenderSettings pdf_settings(
+ kLetter200DpiRect, gfx::Point(0, 0), k200DpiSize,
+ /*autorotate=*/false, /*use_color=*/true,
+ PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3);
+ RunSinglePagePdfToPostScriptConverterTest(pdf_settings, "bug_1030689.pdf",
+ "bug_1030689.emf");
+}
+
} // namespace printing
diff --git a/chromium/chrome/browser/printing/print_browsertest.cc b/chromium/chrome/browser/printing/print_browsertest.cc
index 4d210459a3f..0af8ae0aeda 100644
--- a/chromium/chrome/browser/printing/print_browsertest.cc
+++ b/chromium/chrome/browser/printing/print_browsertest.cc
@@ -28,6 +28,7 @@
#include "components/printing/browser/features.h"
#include "components/printing/browser/print_composite_client.h"
#include "components/printing/browser/print_manager_utils.h"
+#include "components/printing/common/print.mojom.h"
#include "components/printing/common/print_messages.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/render_frame_host.h"
@@ -39,6 +40,7 @@
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
namespace printing {
@@ -260,11 +262,16 @@ class PrintBrowserTest : public InProcessBrowserTest {
frame_host->GetProcess()->AddFilter(filter.get());
}
- static PrintMsg_PrintFrame_Params GetDefaultPrintFrameParams() {
- PrintMsg_PrintFrame_Params params;
- params.printable_area = gfx::Rect(800, 600);
- params.document_cookie = kDefaultDocumentCookie;
- return params;
+ static mojom::PrintFrameContentParamsPtr GetDefaultPrintFrameParams() {
+ return mojom::PrintFrameContentParams::New(gfx::Rect(800, 600),
+ kDefaultDocumentCookie);
+ }
+
+ static const mojo::AssociatedRemote<mojom::PrintRenderFrame>
+ GetPrintRenderFrame(content::RenderFrameHost* rfh) {
+ mojo::AssociatedRemote<mojom::PrintRenderFrame> remote;
+ rfh->GetRemoteAssociatedInterfaces()->GetInterface(&remote);
+ return remote;
}
private:
@@ -377,8 +384,7 @@ IN_PROC_BROWSER_TEST_F(PrintBrowserTest, PrintFrameContent) {
content::RenderFrameHost* rfh = original_contents->GetMainFrame();
AddFilterForFrame(rfh);
- rfh->Send(new PrintMsg_PrintFrameContent(rfh->GetRoutingID(),
- GetDefaultPrintFrameParams()));
+ GetPrintRenderFrame(rfh)->PrintFrameContent(GetDefaultPrintFrameParams());
// The printed result will be received and checked in
// TestPrintFrameContentMsgFilter.
@@ -402,8 +408,8 @@ IN_PROC_BROWSER_TEST_F(PrintBrowserTest, PrintSubframeContent) {
AddFilterForFrame(test_frame);
- test_frame->Send(new PrintMsg_PrintFrameContent(
- test_frame->GetRoutingID(), GetDefaultPrintFrameParams()));
+ GetPrintRenderFrame(test_frame)
+ ->PrintFrameContent(GetDefaultPrintFrameParams());
// The printed result will be received and checked in
// TestPrintFrameContentMsgFilter.
@@ -447,8 +453,8 @@ IN_PROC_BROWSER_TEST_F(PrintBrowserTest, PrintSubframeChain) {
AddFilterForFrame(grandchild_frame);
}
- main_frame->Send(new PrintMsg_PrintFrameContent(
- main_frame->GetRoutingID(), GetDefaultPrintFrameParams()));
+ GetPrintRenderFrame(main_frame)
+ ->PrintFrameContent(GetDefaultPrintFrameParams());
// The printed result will be received and checked in
// TestPrintFrameContentMsgFilter.
@@ -491,8 +497,8 @@ IN_PROC_BROWSER_TEST_F(PrintBrowserTest, PrintSubframeABA) {
if (oopif_enabled)
AddFilterForFrame(child_frame);
- main_frame->Send(new PrintMsg_PrintFrameContent(
- main_frame->GetRoutingID(), GetDefaultPrintFrameParams()));
+ GetPrintRenderFrame(main_frame)
+ ->PrintFrameContent(GetDefaultPrintFrameParams());
// The printed result will be received and checked in
// TestPrintFrameContentMsgFilter.
diff --git a/chromium/chrome/browser/printing/print_dialog_cloud_win.cc b/chromium/chrome/browser/printing/print_dialog_cloud_win.cc
index 250d420e9e2..42181f7590d 100644
--- a/chromium/chrome/browser/printing/print_dialog_cloud_win.cc
+++ b/chromium/chrome/browser/printing/print_dialog_cloud_win.cc
@@ -18,6 +18,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
@@ -129,9 +130,8 @@ void CreatePrintDialogForFile(content::BrowserContext* browser_context,
const base::string16& print_ticket,
const std::string& file_type) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(&ReadFile, path_to_file),
base::BindOnce(&CreatePrintDialog, browser_context, print_job_title,
print_ticket, file_type));
diff --git a/chromium/chrome/browser/printing/print_job.cc b/chromium/chrome/browser/printing/print_job.cc
index 7a90438438b..0cfd89165ad 100644
--- a/chromium/chrome/browser/printing/print_job.cc
+++ b/chromium/chrome/browser/printing/print_job.cc
@@ -12,6 +12,7 @@
#include "base/location.h"
#include "base/run_loop.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_notification_types.h"
@@ -317,7 +318,7 @@ void PrintJob::StartPdfToEmfConversion(
const PrintSettings& settings = document()->settings();
bool print_text_with_gdi =
settings.print_text_with_gdi() && !settings.printer_is_xps() &&
- base::FeatureList::IsEnabled(features::kGdiTextPrinting);
+ base::FeatureList::IsEnabled(::features::kGdiTextPrinting);
PdfRenderSettings render_settings(
content_area, gfx::Point(0, 0), settings.dpi_size(),
/*autorotate=*/true, settings.color() == COLOR,
@@ -475,6 +476,7 @@ void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
pdf_conversion_state_->OnPageProcessed(
base::BindRepeating(&PrintJob::OnPdfPageConverted, this));
}
+ document_->DropPage(event_details.page());
break;
#endif // defined(OS_WIN)
default: {
@@ -532,9 +534,9 @@ void PrintJob::ControlledWorkerShutdown() {
// Now make sure the thread object is cleaned up. Do this on a worker
// thread because it may block.
- base::PostTaskAndReply(
+ base::ThreadPool::PostTaskAndReply(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::WithBaseSyncPrimitives(),
+ {base::MayBlock(), base::WithBaseSyncPrimitives(),
base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(&PrintJobWorker::Stop, base::Unretained(worker_.get())),
diff --git a/chromium/chrome/browser/printing/print_job_worker.cc b/chromium/chrome/browser/printing/print_job_worker.cc
index aacffd44658..33e17f0df35 100644
--- a/chromium/chrome/browser/printing/print_job_worker.cc
+++ b/chromium/chrome/browser/printing/print_job_worker.cc
@@ -43,6 +43,7 @@
#if defined(OS_WIN)
#include "base/threading/thread_restrictions.h"
#include "printing/printed_page_win.h"
+#include "printing/printing_features.h"
#endif
using content::BrowserThread;
@@ -350,13 +351,39 @@ void PrintJobWorker::OnNewPage() {
if (!document_)
return;
+ bool do_spool_job = true;
#if defined(OS_WIN)
+ const bool source_is_pdf =
+ !print_job_->document()->settings().is_modifiable();
+ if (!printing::features::ShouldPrintUsingXps(source_is_pdf)) {
+ // Using the Windows GDI print API.
+ if (!OnNewPageHelperGdi())
+ return;
+
+ do_spool_job = false;
+ }
+#endif // defined(OS_WIN)
+
+ if (do_spool_job) {
+ if (!document_->GetMetafile()) {
+ PostWaitForPage();
+ return;
+ }
+ SpoolJob();
+ }
+
+ OnDocumentDone();
+ // Don't touch |this| anymore since the instance could be destroyed.
+}
+
+#if defined(OS_WIN)
+bool PrintJobWorker::OnNewPageHelperGdi() {
if (page_number_ == PageNumber::npos()) {
// Find first page to print.
int page_count = document_->page_count();
if (!page_count) {
// We still don't know how many pages the document contains.
- return;
+ return false;
}
// We have enough information to initialize |page_number_|.
page_number_.Init(document_->settings(), page_count);
@@ -366,7 +393,7 @@ void PrintJobWorker::OnNewPage() {
scoped_refptr<PrintedPage> page = document_->GetPage(page_number_.ToInt());
if (!page) {
PostWaitForPage();
- return;
+ return false;
}
// The page is there, print it.
SpoolPage(page.get());
@@ -374,17 +401,9 @@ void PrintJobWorker::OnNewPage() {
if (page_number_ == PageNumber::npos())
break;
}
-#else
- if (!document_->GetMetafile()) {
- PostWaitForPage();
- return;
- }
- SpoolJob();
-#endif // defined(OS_WIN)
-
- OnDocumentDone();
- // Don't touch |this| anymore since the instance could be destroyed.
+ return true;
}
+#endif // defined(OS_WIN)
void PrintJobWorker::Cancel() {
// This is the only function that can be called from any thread.
@@ -467,13 +486,13 @@ void PrintJobWorker::SpoolPage(PrintedPage* page) {
JobEventDetails::PAGE_DONE, printing_context_->job_id(),
base::RetainedRef(document_), base::RetainedRef(page)));
}
-#else
+#endif // defined(OS_WIN)
+
void PrintJobWorker::SpoolJob() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!document_->RenderPrintedDocument(printing_context_.get()))
OnFailure();
}
-#endif
void PrintJobWorker::OnFailure() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
diff --git a/chromium/chrome/browser/printing/print_job_worker.h b/chromium/chrome/browser/printing/print_job_worker.h
index 4b3557e5941..8541347f5a3 100644
--- a/chromium/chrome/browser/printing/print_job_worker.h
+++ b/chromium/chrome/browser/printing/print_job_worker.h
@@ -114,12 +114,16 @@ class PrintJobWorker {
void PostWaitForPage();
#if defined(OS_WIN)
+ // Windows print GDI-specific handling for OnNewPage().
+ bool OnNewPageHelperGdi();
+
// Renders a page in the printer.
+ // This is applicable when using the Windows GDI print API.
void SpoolPage(PrintedPage* page);
-#else
+#endif // defined(OS_WIN)
+
// Renders the document to the printer.
void SpoolJob();
-#endif
// Closes the job since spooling is done.
void OnDocumentDone();
diff --git a/chromium/chrome/browser/printing/print_preview_dialog_controller.cc b/chromium/chrome/browser/printing/print_preview_dialog_controller.cc
index ba6cbab2e2e..84818167bce 100644
--- a/chromium/chrome/browser/printing/print_preview_dialog_controller.cc
+++ b/chromium/chrome/browser/printing/print_preview_dialog_controller.cc
@@ -39,6 +39,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_ui.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/web_dialogs/web_dialog_delegate.h"
@@ -155,7 +156,11 @@ void PrintPreviewDialogDelegate::GetDialogSize(gfx::Size* size) const {
size->Enlarge(-2 * kBorder, -kBorder);
static const gfx::Size kMaxDialogSize(1000, 660);
- size->SetToMin(kMaxDialogSize);
+ int max_width = std::max(size->width() * 7 / 10, kMaxDialogSize.width());
+ int max_height =
+ std::max(max_width * kMaxDialogSize.height() / kMaxDialogSize.width(),
+ kMaxDialogSize.height());
+ size->SetToMin(gfx::Size(max_width, max_height));
}
std::string PrintPreviewDialogDelegate::GetDialogArgs() const {
@@ -248,7 +253,7 @@ PrintPreviewDialogController* PrintPreviewDialogController::GetInstance() {
// static
void PrintPreviewDialogController::PrintPreview(WebContents* initiator) {
#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
- ModuleDatabase::GetInstance()->DisableThirdPartyBlocking();
+ ModuleDatabase::DisableThirdPartyBlocking();
#endif
if (initiator->ShowingInterstitialPage() || initiator->IsCrashed())
diff --git a/chromium/chrome/browser/printing/print_preview_dialog_controller_unittest.cc b/chromium/chrome/browser/printing/print_preview_dialog_controller_unittest.cc
index 8c1ad0e1f88..9b95dfaacf8 100644
--- a/chromium/chrome/browser/printing/print_preview_dialog_controller_unittest.cc
+++ b/chromium/chrome/browser/printing/print_preview_dialog_controller_unittest.cc
@@ -211,9 +211,10 @@ TEST_F(PrintPreviewDialogControllerUnitTest, ClearInitiatorDetails) {
// (typed + address bar) to an existing page as occurs in gmail does not cause
// the dialogs to close.
TEST_F(PrintPreviewDialogControllerUnitTest, CloseDialogOnNavigation) {
- // Two similar URLs (same webpage, different URL fragments)
- GURL tiger_barb("https://www.google.com/#q=tiger+barb");
+ // Two similar URLs (same webpage, different URL fragment/query)
+ // Gmail navigates from fragment to query when opening an email to print.
GURL tiger("https://www.google.com/#q=tiger");
+ GURL tiger_barb("https://www.google.com/?q=tiger+barb");
// Set up by opening a new tab and getting web contents
EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
diff --git a/chromium/chrome/browser/printing/print_preview_message_handler.cc b/chromium/chrome/browser/printing/print_preview_message_handler.cc
index 2cd76f14157..38bc7246be8 100644
--- a/chromium/chrome/browser/printing/print_preview_message_handler.cc
+++ b/chromium/chrome/browser/printing/print_preview_message_handler.cc
@@ -145,10 +145,10 @@ void PrintPreviewMessageHandler::OnDidPrepareForDocumentToPdf(
if (!print_preview_ui)
return;
- // Determine if document composition from individual pages is desired
- // configuration. Issue a preparation call to client if that hasn't
- // been done yet.
- if (!print_preview_ui->ShouldCompositeDocumentUsingIndividualPages())
+ // Determine if document composition from individual pages with the print
+ // compositor is the desired configuration. Issue a preparation call to the
+ // PrintCompositeClient if that hasn't been done yet. Otherwise, return early.
+ if (!ShouldUseCompositor(print_preview_ui))
return;
// For case of print preview, page metafile is used to composite into
@@ -165,7 +165,7 @@ void PrintPreviewMessageHandler::OnDidPrepareForDocumentToPdf(
base::BindOnce(
&PrintPreviewMessageHandler::OnPrepareForDocumentToPdfDone,
weak_ptr_factory_.GetWeakPtr(), ids),
- mojom::PdfCompositor::Status::kCompositingFailure));
+ mojom::PrintCompositor::Status::kCompositingFailure));
}
void PrintPreviewMessageHandler::OnDidPreviewPage(
@@ -201,7 +201,7 @@ void PrintPreviewMessageHandler::OnDidPreviewPage(
base::BindOnce(&PrintPreviewMessageHandler::OnCompositePdfPageDone,
weak_ptr_factory_.GetWeakPtr(), page_number,
params.document_cookie, ids),
- mojom::PdfCompositor::Status::kCompositingFailure,
+ mojom::PrintCompositor::Status::kCompositingFailure,
base::ReadOnlySharedMemoryRegion()));
} else {
NotifyUIPreviewPageReady(
@@ -222,14 +222,16 @@ void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
if (!print_preview_ui)
return;
- const PrintHostMsg_DidPrintContent_Params& content = params.content;
const bool composite_document_using_individual_pages =
- print_preview_ui->ShouldCompositeDocumentUsingIndividualPages();
- // Concern about valid |metafile_data_region| is only relevant if full
- // document is provided on this call. When document is compiled together
- // from prior individual pages then there is no content required here.
- if (!composite_document_using_individual_pages &&
- !content.metafile_data_region.IsValid())
+ ShouldUseCompositor(print_preview_ui);
+ const base::ReadOnlySharedMemoryRegion& metafile =
+ params.content.metafile_data_region;
+
+ // When the Print Compositor is active, the print document is composed from
+ // the individual pages, so |metafile| should be invalid.
+ // When it is inactive, the print document is composed from |metafile|.
+ // So if this comparison succeeds, that means the renderer sent bad data.
+ if (composite_document_using_individual_pages == metafile.IsValid())
return;
if (params.expected_pages_count <= 0) {
@@ -237,41 +239,29 @@ void PrintPreviewMessageHandler::OnMetafileReadyForPrinting(
return;
}
- if (ShouldUseCompositor(print_preview_ui)) {
+ if (composite_document_using_individual_pages) {
// Don't bother compositing if this request has been cancelled already.
if (PrintPreviewUI::ShouldCancelRequest(ids))
return;
- auto* client = PrintCompositeClient::FromWebContents(web_contents());
- DCHECK(client);
auto callback = base::BindOnce(
- &PrintPreviewMessageHandler::OnCompositeOrCompleteDocumentToPdfDone,
- weak_ptr_factory_.GetWeakPtr(),
- composite_document_using_individual_pages, params.expected_pages_count,
- params.document_cookie, ids);
- if (composite_document_using_individual_pages) {
- // Page metafile is used to composite into the document at same time.
- // Need to provide particulars of how many pages are required before
- // document will be completed.
- client->DoCompleteDocumentToPdf(
- params.document_cookie, params.expected_pages_count,
- mojo::WrapCallbackWithDefaultInvokeIfNotRun(
- std::move(callback),
- mojom::PdfCompositor::Status::kCompositingFailure,
- base::ReadOnlySharedMemoryRegion()));
- } else {
- client->DoCompositeDocumentToPdf(
- params.document_cookie, render_frame_host, content,
- mojo::WrapCallbackWithDefaultInvokeIfNotRun(
- std::move(callback),
- mojom::PdfCompositor::Status::kCompositingFailure,
- base::ReadOnlySharedMemoryRegion()));
- }
+ &PrintPreviewMessageHandler::OnCompositeToPdfDone,
+ weak_ptr_factory_.GetWeakPtr(), params.document_cookie, ids);
+
+ // Page metafile is used to composite into the document at same time.
+ // Need to provide particulars of how many pages are required before
+ // document will be completed.
+ auto* client = PrintCompositeClient::FromWebContents(web_contents());
+ client->DoCompleteDocumentToPdf(
+ params.document_cookie, params.expected_pages_count,
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(
+ std::move(callback),
+ mojom::PrintCompositor::Status::kCompositingFailure,
+ base::ReadOnlySharedMemoryRegion()));
} else {
NotifyUIPreviewDocumentReady(
- print_preview_ui, params.expected_pages_count, ids,
- base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(
- content.metafile_data_region));
+ print_preview_ui, ids,
+ base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(metafile));
}
}
@@ -350,7 +340,6 @@ void PrintPreviewMessageHandler::NotifyUIPreviewPageReady(
void PrintPreviewMessageHandler::NotifyUIPreviewDocumentReady(
PrintPreviewUI* print_preview_ui,
- int page_count,
const PrintHostMsg_PreviewIds& ids,
scoped_refptr<base::RefCountedMemory> data_bytes) {
if (!data_bytes || !data_bytes->size())
@@ -360,7 +349,7 @@ void PrintPreviewMessageHandler::NotifyUIPreviewDocumentReady(
if (PrintPreviewUI::ShouldCancelRequest(ids))
return;
- print_preview_ui->OnPreviewDataIsAvailable(page_count, std::move(data_bytes),
+ print_preview_ui->OnPreviewDataIsAvailable(std::move(data_bytes),
ids.request_id);
}
@@ -368,11 +357,11 @@ void PrintPreviewMessageHandler::OnCompositePdfPageDone(
int page_number,
int document_cookie,
const PrintHostMsg_PreviewIds& ids,
- mojom::PdfCompositor::Status status,
+ mojom::PrintCompositor::Status status,
base::ReadOnlySharedMemoryRegion region) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PrintPreviewUI* print_preview_ui = GetPrintPreviewUI(ids.ui_id);
- if (status != mojom::PdfCompositor::Status::kSuccess) {
+ if (status != mojom::PrintCompositor::Status::kSuccess) {
DLOG(ERROR) << "Compositing pdf failed with error " << status;
if (print_preview_ui)
print_preview_ui->OnPrintPreviewFailed(ids.request_id);
@@ -443,20 +432,15 @@ void PrintPreviewMessageHandler::OnNupPdfConvertDone(
base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region));
}
-void PrintPreviewMessageHandler::OnCompositeOrCompleteDocumentToPdfDone(
- bool composite_document_using_individual_pages,
- int page_count,
+void PrintPreviewMessageHandler::OnCompositeToPdfDone(
int document_cookie,
const PrintHostMsg_PreviewIds& ids,
- mojom::PdfCompositor::Status status,
+ mojom::PrintCompositor::Status status,
base::ReadOnlySharedMemoryRegion region) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PrintPreviewUI* print_preview_ui = GetPrintPreviewUI(ids.ui_id);
- if (status != mojom::PdfCompositor::Status::kSuccess) {
- DLOG(ERROR) << (composite_document_using_individual_pages
- ? "Completion of document to"
- : "Compositing")
- << " pdf failed with error " << status;
+ if (status != mojom::PrintCompositor::Status::kSuccess) {
+ DLOG(ERROR) << "Completion of document to pdf failed with error " << status;
if (print_preview_ui)
print_preview_ui->OnPrintPreviewFailed(ids.request_id);
return;
@@ -467,7 +451,7 @@ void PrintPreviewMessageHandler::OnCompositeOrCompleteDocumentToPdfDone(
int pages_per_sheet = print_preview_ui->pages_per_sheet();
if (pages_per_sheet == 1) {
NotifyUIPreviewDocumentReady(
- print_preview_ui, page_count, ids,
+ print_preview_ui, ids,
base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region));
} else {
auto* client = PdfNupConverterClient::FromWebContents(web_contents());
@@ -484,8 +468,7 @@ void PrintPreviewMessageHandler::OnCompositeOrCompleteDocumentToPdfDone(
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
base::BindOnce(
&PrintPreviewMessageHandler::OnNupPdfDocumentConvertDone,
- weak_ptr_factory_.GetWeakPtr(),
- (page_count + pages_per_sheet - 1) / pages_per_sheet, ids),
+ weak_ptr_factory_.GetWeakPtr(), ids),
mojom::PdfNupConverter::Status::CONVERSION_FAILURE,
base::ReadOnlySharedMemoryRegion()));
}
@@ -493,9 +476,9 @@ void PrintPreviewMessageHandler::OnCompositeOrCompleteDocumentToPdfDone(
void PrintPreviewMessageHandler::OnPrepareForDocumentToPdfDone(
const PrintHostMsg_PreviewIds& ids,
- mojom::PdfCompositor::Status status) {
+ mojom::PrintCompositor::Status status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (status != mojom::PdfCompositor::Status::kSuccess) {
+ if (status != mojom::PrintCompositor::Status::kSuccess) {
PrintPreviewUI* print_preview_ui = GetPrintPreviewUI(ids.ui_id);
if (print_preview_ui)
print_preview_ui->OnPrintPreviewFailed(ids.request_id);
@@ -503,7 +486,6 @@ void PrintPreviewMessageHandler::OnPrepareForDocumentToPdfDone(
}
void PrintPreviewMessageHandler::OnNupPdfDocumentConvertDone(
- int page_count,
const PrintHostMsg_PreviewIds& ids,
mojom::PdfNupConverter::Status status,
base::ReadOnlySharedMemoryRegion region) {
@@ -520,7 +502,7 @@ void PrintPreviewMessageHandler::OnNupPdfDocumentConvertDone(
return;
NotifyUIPreviewDocumentReady(
- print_preview_ui, page_count, ids,
+ print_preview_ui, ids,
base::RefCountedSharedMemoryMapping::CreateFromWholeRegion(region));
}
diff --git a/chromium/chrome/browser/printing/print_preview_message_handler.h b/chromium/chrome/browser/printing/print_preview_message_handler.h
index afecc1a7515..70f3385dbf9 100644
--- a/chromium/chrome/browser/printing/print_preview_message_handler.h
+++ b/chromium/chrome/browser/printing/print_preview_message_handler.h
@@ -9,7 +9,7 @@
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/weak_ptr.h"
#include "chrome/services/printing/public/mojom/pdf_nup_converter.mojom.h"
-#include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
+#include "components/services/print_compositor/public/mojom/print_compositor.mojom.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
@@ -98,32 +98,27 @@ class PrintPreviewMessageHandler
scoped_refptr<base::RefCountedMemory> data_bytes);
void NotifyUIPreviewDocumentReady(
PrintPreviewUI* print_preview_ui,
- int page_count,
const PrintHostMsg_PreviewIds& ids,
scoped_refptr<base::RefCountedMemory> data_bytes);
- // Callbacks for pdf compositor client.
+ // Callbacks for print compositor client.
void OnCompositePdfPageDone(int page_number,
int document_cookie,
const PrintHostMsg_PreviewIds& ids,
- mojom::PdfCompositor::Status status,
+ mojom::PrintCompositor::Status status,
base::ReadOnlySharedMemoryRegion region);
- void OnCompositeOrCompleteDocumentToPdfDone(
- bool composite_document_using_individual_pages,
- int page_count,
- int document_cookie,
- const PrintHostMsg_PreviewIds& ids,
- mojom::PdfCompositor::Status status,
- base::ReadOnlySharedMemoryRegion region);
+ void OnCompositeToPdfDone(int document_cookie,
+ const PrintHostMsg_PreviewIds& ids,
+ mojom::PrintCompositor::Status status,
+ base::ReadOnlySharedMemoryRegion region);
void OnPrepareForDocumentToPdfDone(const PrintHostMsg_PreviewIds& ids,
- mojom::PdfCompositor::Status status);
+ mojom::PrintCompositor::Status status);
void OnNupPdfConvertDone(int page_number,
const PrintHostMsg_PreviewIds& ids,
mojom::PdfNupConverter::Status status,
base::ReadOnlySharedMemoryRegion region);
- void OnNupPdfDocumentConvertDone(int page_count,
- const PrintHostMsg_PreviewIds& ids,
+ void OnNupPdfDocumentConvertDone(const PrintHostMsg_PreviewIds& ids,
mojom::PdfNupConverter::Status status,
base::ReadOnlySharedMemoryRegion region);
diff --git a/chromium/chrome/browser/printing/print_preview_sticky_settings.cc b/chromium/chrome/browser/printing/print_preview_sticky_settings.cc
index 7059e69ff04..dc3dd487c8b 100644
--- a/chromium/chrome/browser/printing/print_preview_sticky_settings.cc
+++ b/chromium/chrome/browser/printing/print_preview_sticky_settings.cc
@@ -71,10 +71,9 @@ PrintPreviewStickySettings::GetPrinterRecentlyUsedRanks() {
if (!recent_destinations)
return {};
- auto& recent_destinations_list = recent_destinations->GetList();
base::flat_map<std::string, int> recently_used_ranks;
int current_rank = 0;
- for (const auto& recent_destination : recent_destinations_list) {
+ for (const auto& recent_destination : recent_destinations->GetList()) {
const std::string* printer_id = recent_destination.FindStringKey(kId);
if (!printer_id)
continue;
diff --git a/chromium/chrome/browser/printing/print_view_manager.h b/chromium/chrome/browser/printing/print_view_manager.h
index ee5b0b2f5f4..4030f940e4d 100644
--- a/chromium/chrome/browser/printing/print_view_manager.h
+++ b/chromium/chrome/browser/printing/print_view_manager.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "chrome/browser/printing/print_view_manager_base.h"
-#include "components/printing/common/print.mojom.h"
+#include "components/printing/common/print.mojom-forward.h"
#include "content/public/browser/web_contents_user_data.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "printing/buildflags/buildflags.h"
diff --git a/chromium/chrome/browser/printing/print_view_manager_base.cc b/chromium/chrome/browser/printing/print_view_manager_base.cc
index 3d026cd11aa..3378f34bd8e 100644
--- a/chromium/chrome/browser/printing/print_view_manager_base.cc
+++ b/chromium/chrome/browser/printing/print_view_manager_base.cc
@@ -35,7 +35,7 @@
#include "components/printing/browser/print_composite_client.h"
#include "components/printing/browser/print_manager_utils.h"
#include "components/printing/common/print_messages.h"
-#include "components/services/pdf_compositor/public/cpp/pdf_service_mojo_types.h"
+#include "components/services/print_compositor/public/cpp/print_service_mojo_types.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
@@ -52,6 +52,10 @@
#include "printing/printed_document.h"
#include "ui/base/l10n/l10n_util.h"
+#if defined(OS_WIN)
+#include "printing/printing_features.h"
+#endif
+
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
#include "chrome/browser/printing/print_error_dialog.h"
#endif
@@ -161,17 +165,23 @@ void PrintViewManagerBase::PrintDocument(
const gfx::Rect& content_area,
const gfx::Point& offsets) {
#if defined(OS_WIN)
- print_job_->StartConversionToNativeFormat(print_data, page_size, content_area,
- offsets);
-#else
+ const bool source_is_pdf =
+ !print_job_->document()->settings().is_modifiable();
+ if (!printing::features::ShouldPrintUsingXps(source_is_pdf)) {
+ // Print using GDI, which first requires conversion to EMF.
+ print_job_->StartConversionToNativeFormat(print_data, page_size,
+ content_area, offsets);
+ return;
+ }
+#endif
+
std::unique_ptr<MetafileSkia> metafile = std::make_unique<MetafileSkia>();
- CHECK(metafile->InitFromData(print_data->front(), print_data->size()));
+ CHECK(metafile->InitFromData(*print_data));
// Update the rendered document. It will send notifications to the listener.
PrintedDocument* document = print_job_->document();
document->SetDocument(std::move(metafile), page_size, content_area);
ShouldQuitFromInnerMessageLoop();
-#endif
}
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
@@ -284,10 +294,10 @@ void PrintViewManagerBase::OnComposePdfDone(
const gfx::Rect& content_area,
const gfx::Point& physical_offsets,
std::unique_ptr<DelayedFrameDispatchHelper> helper,
- mojom::PdfCompositor::Status status,
+ mojom::PrintCompositor::Status status,
base::ReadOnlySharedMemoryRegion region) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- if (status != mojom::PdfCompositor::Status::kSuccess) {
+ if (status != mojom::PrintCompositor::Status::kSuccess) {
DLOG(ERROR) << "Compositing pdf failed with error " << status;
return;
}
diff --git a/chromium/chrome/browser/printing/print_view_manager_base.h b/chromium/chrome/browser/printing/print_view_manager_base.h
index af49d3e2f8a..3d434244927 100644
--- a/chromium/chrome/browser/printing/print_view_manager_base.h
+++ b/chromium/chrome/browser/printing/print_view_manager_base.h
@@ -17,7 +17,7 @@
#include "chrome/browser/ui/webui/print_preview/printer_handler.h"
#include "components/prefs/pref_member.h"
#include "components/printing/browser/print_manager.h"
-#include "components/services/pdf_compositor/public/mojom/pdf_compositor.mojom.h"
+#include "components/services/print_compositor/public/mojom/print_compositor.mojom.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "printing/buildflags/buildflags.h"
@@ -133,7 +133,7 @@ class PrintViewManagerBase : public content::NotificationObserver,
const gfx::Rect& content_area,
const gfx::Point& physical_offsets,
std::unique_ptr<DelayedFrameDispatchHelper> helper,
- mojom::PdfCompositor::Status status,
+ mojom::PrintCompositor::Status status,
base::ReadOnlySharedMemoryRegion region);
// Helpers for PrintForPrintPreview();
diff --git a/chromium/chrome/browser/printing/print_view_manager_common.h b/chromium/chrome/browser/printing/print_view_manager_common.h
index 4240d2465c7..bf67ddba35b 100644
--- a/chromium/chrome/browser/printing/print_view_manager_common.h
+++ b/chromium/chrome/browser/printing/print_view_manager_common.h
@@ -5,7 +5,7 @@
#ifndef CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_COMMON_H_
#define CHROME_BROWSER_PRINTING_PRINT_VIEW_MANAGER_COMMON_H_
-#include "components/printing/common/print.mojom.h"
+#include "components/printing/common/print.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "printing/buildflags/buildflags.h"
diff --git a/chromium/chrome/browser/printing/printer_manager_dialog_linux.cc b/chromium/chrome/browser/printing/printer_manager_dialog_linux.cc
index f236c055c16..07d9dee216a 100644
--- a/chromium/chrome/browser/printing/printer_manager_dialog_linux.cc
+++ b/chromium/chrome/browser/printing/printer_manager_dialog_linux.cc
@@ -13,6 +13,7 @@
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
namespace {
@@ -88,9 +89,8 @@ void DetectAndOpenPrinterConfigDialog() {
namespace printing {
void PrinterManagerDialog::ShowPrinterManagerDialog(Profile* profile) {
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(&DetectAndOpenPrinterConfigDialog));
}
diff --git a/chromium/chrome/browser/printing/printer_manager_dialog_win.cc b/chromium/chrome/browser/printing/printer_manager_dialog_win.cc
index a6a4e9c1800..7da88909891 100644
--- a/chromium/chrome/browser/printing/printer_manager_dialog_win.cc
+++ b/chromium/chrome/browser/printing/printer_manager_dialog_win.cc
@@ -11,6 +11,7 @@
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread.h"
#include "base/win/windows_version.h"
#include "chrome/browser/platform_util.h"
@@ -39,10 +40,9 @@ void PrinterManagerDialog::ShowPrinterManagerDialog(Profile* profile) {
if (base::win::GetVersion() >= base::win::Version::WIN10_RS1) {
platform_util::OpenExternal(profile, GURL("ms-settings:printers"));
} else {
- base::PostTask(FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_BLOCKING},
- base::BindOnce(OpenPrintersDialogCallback));
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::BindOnce(OpenPrintersDialogCallback));
}
}
diff --git a/chromium/chrome/browser/printing/printing_service.cc b/chromium/chrome/browser/printing/printing_service.cc
index 9b0f43d94ac..1c9e0853250 100644
--- a/chromium/chrome/browser/printing/printing_service.cc
+++ b/chromium/chrome/browser/printing/printing_service.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/printing/printing_service.h"
#include "base/no_destructor.h"
+#include "build/build_config.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/service_process_host.h"
@@ -16,7 +17,9 @@ const mojo::Remote<printing::mojom::PrintingService>& GetPrintingService() {
remote->BindNewPipeAndPassReceiver(),
content::ServiceProcessHost::Options()
.WithDisplayName(IDS_UTILITY_PROCESS_PRINTING_SERVICE_NAME)
- .WithSandboxType(service_manager::SANDBOX_TYPE_UTILITY)
+#if defined(OS_WIN)
+ .WithSandboxType(service_manager::SandboxType::kPdfConversion)
+#endif
.Pass());
// Ensure that if the interface is ever disconnected (e.g. the service
diff --git a/chromium/chrome/browser/profile_resetter/BUILD.gn b/chromium/chrome/browser/profile_resetter/BUILD.gn
index 4b02da468db..752218df9dd 100644
--- a/chromium/chrome/browser/profile_resetter/BUILD.gn
+++ b/chromium/chrome/browser/profile_resetter/BUILD.gn
@@ -5,7 +5,5 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("profile_reset_report_proto") {
- sources = [
- "profile_reset_report.proto",
- ]
+ sources = [ "profile_reset_report.proto" ]
}
diff --git a/chromium/chrome/browser/profiles/android/BUILD.gn b/chromium/chrome/browser/profiles/android/BUILD.gn
new file mode 100644
index 00000000000..a8308d038a1
--- /dev/null
+++ b/chromium/chrome/browser/profiles/android/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+# Keep profiles and cookies in the same target due to bi-directional dependency
+# between Profile and CookiesFetcher.
+android_library("java") {
+ deps = [
+ "//base:base_java",
+ "//base:jni_java",
+ "//chrome/browser/android/crypto:java",
+ "//chrome/browser/preferences:java",
+ "//content/public/android:content_java",
+ ]
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+ sources = [
+ "java/src/org/chromium/chrome/browser/cookies/CanonicalCookie.java",
+ "java/src/org/chromium/chrome/browser/cookies/CookiesFetcher.java",
+ "java/src/org/chromium/chrome/browser/profiles/OriginalProfileSupplier.java",
+ "java/src/org/chromium/chrome/browser/profiles/Profile.java",
+ "java/src/org/chromium/chrome/browser/profiles/ProfileKey.java",
+ "java/src/org/chromium/chrome/browser/profiles/ProfileManager.java",
+ "java/src/org/chromium/chrome/browser/profiles/ProfileManagerUtils.java",
+ ]
+}
+
+generate_jni("jni_headers") {
+ sources = [
+ "java/src/org/chromium/chrome/browser/cookies/CookiesFetcher.java",
+ "java/src/org/chromium/chrome/browser/profiles/Profile.java",
+ "java/src/org/chromium/chrome/browser/profiles/ProfileKey.java",
+ "java/src/org/chromium/chrome/browser/profiles/ProfileManager.java",
+ "java/src/org/chromium/chrome/browser/profiles/ProfileManagerUtils.java",
+ ]
+}
diff --git a/chromium/chrome/browser/profiling_host/BUILD.gn b/chromium/chrome/browser/profiling_host/BUILD.gn
index f92dd2636ec..ea427aa14f1 100644
--- a/chromium/chrome/browser/profiling_host/BUILD.gn
+++ b/chromium/chrome/browser/profiling_host/BUILD.gn
@@ -28,51 +28,21 @@ static_library("profiling_host") {
]
}
-if (!is_android) {
- source_set("profiling_browsertests") {
- testonly = true
+source_set("profiling_browsertests") {
+ testonly = true
- sources = [
- "memlog_browsertest.cc",
- ]
+ sources = [ "memlog_browsertest.cc" ]
- defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
+ defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
- deps = [
- "//base",
- "//base/allocator:buildflags",
- "//chrome/test:test_support_ui",
- "//components/heap_profiling:test_support",
- "//components/services/heap_profiling/public/cpp",
- "//testing/gmock",
- "//testing/gtest",
- ]
- }
-} else {
- import("//build/config/android/rules.gni")
-
- # In-process browser tests aren't supported on Android. The tests are run as
- # instrumentation tests.
- group("profiling_browsertests") {
- }
-
- # This library must be included by the instrumentation_test. It must not be
- # included by the apk_under_test, since in debug builds, java classes that
- # appear in the apk_under_test are stripped from the instrumentation_test.
- # This library contains dependencies that must not be stripped from the
- # instrumentation_test.
- android_library("profiling_host_javatests") {
- testonly = true
- java_files = [ "../../android/javatests/src/org/chromium/chrome/browser/profiling_host/ProfilingProcessHostAndroidTest.java" ]
- deps = [
- "//base:base_java",
- "//base:base_java_test_support",
- "//chrome/android:chrome_java",
- "//chrome/test/android:chrome_java_test_support",
- "//components/heap_profiling:heap_profiling_java_test_support",
- "//third_party/android_support_test_runner:rules_java",
- "//third_party/android_support_test_runner:runner_java",
- "//third_party/junit",
- ]
- }
+ deps = [
+ "//base",
+ "//base/allocator:buildflags",
+ "//chrome/common:non_code_constants",
+ "//components/heap_profiling:test_support",
+ "//components/services/heap_profiling/public/cpp",
+ "//content/public/common",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
}
diff --git a/chromium/chrome/browser/push_messaging/BUILD.gn b/chromium/chrome/browser/push_messaging/BUILD.gn
index 7f63e2f1ec6..01e9512773e 100644
--- a/chromium/chrome/browser/push_messaging/BUILD.gn
+++ b/chromium/chrome/browser/push_messaging/BUILD.gn
@@ -5,7 +5,5 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("budget_proto") {
- sources = [
- "budget.proto",
- ]
+ sources = [ "budget.proto" ]
}
diff --git a/chromium/chrome/browser/renderer_host/chrome_extension_message_filter.cc b/chromium/chrome/browser/renderer_host/chrome_extension_message_filter.cc
index e758df9391d..79fcca57e9f 100644
--- a/chromium/chrome/browser/renderer_host/chrome_extension_message_filter.cc
+++ b/chromium/chrome/browser/renderer_host/chrome_extension_message_filter.cc
@@ -14,6 +14,7 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
#include "chrome/browser/extensions/activity_log/activity_actions.h"
@@ -159,21 +160,25 @@ void ChromeExtensionMessageFilter::OnGetExtMessageBundle(
}
// This blocks tab loading. Priority is inherited from the calling context.
- base::PostTask(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
- base::BindOnce(&ChromeExtensionMessageFilter::OnGetExtMessageBundleAsync,
- this, paths_to_load, extension_id, default_locale,
- reply_msg));
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock()},
+ base::BindOnce(
+ &ChromeExtensionMessageFilter::OnGetExtMessageBundleAsync, this,
+ paths_to_load, extension_id, default_locale,
+ extension_l10n_util::GetGzippedMessagesPermissionForExtension(
+ extension),
+ reply_msg));
}
void ChromeExtensionMessageFilter::OnGetExtMessageBundleAsync(
const std::vector<base::FilePath>& extension_paths,
const std::string& main_extension_id,
const std::string& default_locale,
+ extension_l10n_util::GzippedMessagesPermission gzip_permission,
IPC::Message* reply_msg) {
std::unique_ptr<extensions::MessageBundle::SubstitutionMap> dictionary_map(
extensions::file_util::LoadMessageBundleSubstitutionMapFromPaths(
- extension_paths, main_extension_id, default_locale));
+ extension_paths, main_extension_id, default_locale, gzip_permission));
ExtensionHostMsg_GetMessageBundle::WriteReplyParams(reply_msg,
*dictionary_map);
diff --git a/chromium/chrome/browser/renderer_host/chrome_extension_message_filter.h b/chromium/chrome/browser/renderer_host/chrome_extension_message_filter.h
index 430fb226fc9..6ac981533ec 100644
--- a/chromium/chrome/browser/renderer_host/chrome_extension_message_filter.h
+++ b/chromium/chrome/browser/renderer_host/chrome_extension_message_filter.h
@@ -15,6 +15,7 @@
#include "chrome/browser/profiles/profile_observer.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
+#include "extensions/common/extension_l10n_util.h"
struct ExtensionHostMsg_APIActionOrEvent_Params;
struct ExtensionHostMsg_DOMAction_Params;
@@ -54,6 +55,7 @@ class ChromeExtensionMessageFilter : public content::BrowserMessageFilter,
const std::vector<base::FilePath>& extension_paths,
const std::string& main_extension_id,
const std::string& default_locale,
+ extension_l10n_util::GzippedMessagesPermission gzip_permission,
IPC::Message* reply_msg);
void OnAddAPIActionToExtensionActivityLog(
const std::string& extension_id,
diff --git a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h
index 86bdd502ce2..acd9a2061d4 100644
--- a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h
+++ b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.h
@@ -20,10 +20,10 @@ class RenderWidgetHost;
@interface ChromeRenderWidgetHostViewMacDelegate
: NSObject<RenderWidgetHostViewMacDelegate> {
@private
- content::RenderWidgetHost* renderWidgetHost_; // weak
+ content::RenderWidgetHost* _renderWidgetHost; // weak
// Responsible for 2-finger swipes history navigation.
- base::scoped_nsobject<HistorySwiper> historySwiper_;
+ base::scoped_nsobject<HistorySwiper> _historySwiper;
}
- (id)initWithRenderWidgetHost:(content::RenderWidgetHost*)renderWidgetHost;
diff --git a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm
index d64cd0beecc..f54c77051fd 100644
--- a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm
+++ b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm
@@ -35,20 +35,20 @@ using content::RenderViewHost;
@end
@implementation ChromeRenderWidgetHostViewMacDelegate {
- BOOL resigningFirstResponder_;
+ BOOL _resigningFirstResponder;
}
- (id)initWithRenderWidgetHost:(content::RenderWidgetHost*)renderWidgetHost {
self = [super init];
if (self) {
- renderWidgetHost_ = renderWidgetHost;
- historySwiper_.reset([[HistorySwiper alloc] initWithDelegate:self]);
+ _renderWidgetHost = renderWidgetHost;
+ _historySwiper.reset([[HistorySwiper alloc] initWithDelegate:self]);
}
return self;
}
- (void)dealloc {
- [historySwiper_ setDelegate:nil];
+ [_historySwiper setDelegate:nil];
[super dealloc];
}
@@ -56,44 +56,44 @@ using content::RenderViewHost;
// delegate method if implemented. Return YES if the event is fully handled, or
// NO if normal processing should take place.
- (BOOL)handleEvent:(NSEvent*)event {
- return [historySwiper_ handleEvent:event];
+ return [_historySwiper handleEvent:event];
}
// NSWindow events.
- (void)beginGestureWithEvent:(NSEvent*)event {
- [historySwiper_ beginGestureWithEvent:event];
+ [_historySwiper beginGestureWithEvent:event];
}
- (void)endGestureWithEvent:(NSEvent*)event {
- [historySwiper_ endGestureWithEvent:event];
+ [_historySwiper endGestureWithEvent:event];
}
// This is a low level API which provides touches associated with an event.
// It is used in conjunction with gestures to determine finger placement
// on the trackpad.
- (void)touchesMovedWithEvent:(NSEvent*)event {
- [historySwiper_ touchesMovedWithEvent:event];
+ [_historySwiper touchesMovedWithEvent:event];
}
- (void)touchesBeganWithEvent:(NSEvent*)event {
- [historySwiper_ touchesBeganWithEvent:event];
+ [_historySwiper touchesBeganWithEvent:event];
}
- (void)touchesCancelledWithEvent:(NSEvent*)event {
- [historySwiper_ touchesCancelledWithEvent:event];
+ [_historySwiper touchesCancelledWithEvent:event];
}
- (void)touchesEndedWithEvent:(NSEvent*)event {
- [historySwiper_ touchesEndedWithEvent:event];
+ [_historySwiper touchesEndedWithEvent:event];
}
// HistorySwiperDelegate methods
- (BOOL)shouldAllowHistorySwiping {
- if (!renderWidgetHost_)
+ if (!_renderWidgetHost)
return NO;
- RenderViewHost* renderViewHost = RenderViewHost::From(renderWidgetHost_);
+ RenderViewHost* renderViewHost = RenderViewHost::From(_renderWidgetHost);
if (!renderViewHost)
return NO;
content::WebContents* webContents =
@@ -106,7 +106,7 @@ using content::RenderViewHost;
}
- (NSView*)viewThatWantsHistoryOverlay {
- return renderWidgetHost_->GetView()->GetNativeView().GetNativeNSView();
+ return _renderWidgetHost->GetView()->GetNativeView().GetNativeNSView();
}
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item
@@ -114,7 +114,7 @@ using content::RenderViewHost;
SEL action = [item action];
Profile* profile = Profile::FromBrowserContext(
- renderWidgetHost_->GetProcess()->GetBrowserContext());
+ _renderWidgetHost->GetProcess()->GetBrowserContext());
DCHECK(profile);
PrefService* pref = profile->GetPrefs();
const PrefService::Preference* spellCheckEnablePreference =
@@ -128,7 +128,7 @@ using content::RenderViewHost;
// TODO(suzhe): Plumb the "can*" methods up from WebCore.
if (action == @selector(checkSpelling:)) {
*valid = spellCheckUserModifiable &&
- (RenderViewHost::From(renderWidgetHost_) != nullptr);
+ (RenderViewHost::From(_renderWidgetHost) != nullptr);
return YES;
}
@@ -156,16 +156,16 @@ using content::RenderViewHost;
- (void)rendererHandledWheelEvent:(const blink::WebMouseWheelEvent&)event
consumed:(BOOL)consumed {
- [historySwiper_ rendererHandledWheelEvent:event consumed:consumed];
+ [_historySwiper rendererHandledWheelEvent:event consumed:consumed];
}
- (void)rendererHandledGestureScrollEvent:(const blink::WebGestureEvent&)event
consumed:(BOOL)consumed {
- [historySwiper_ rendererHandledGestureScrollEvent:event consumed:consumed];
+ [_historySwiper rendererHandledGestureScrollEvent:event consumed:consumed];
}
- (void)rendererHandledOverscrollEvent:(const ui::DidOverscrollParams&)params {
- [historySwiper_ onOverscrolled:params];
+ [_historySwiper onOverscrolled:params];
}
// Spellchecking methods
@@ -181,7 +181,7 @@ using content::RenderViewHost;
if (newWord != nil) {
content::WebContents* webContents =
content::WebContents::FromRenderViewHost(
- RenderViewHost::From(renderWidgetHost_));
+ RenderViewHost::From(_renderWidgetHost));
webContents->ReplaceMisspelling(base::SysNSStringToUTF16(newWord));
}
}
@@ -195,14 +195,14 @@ using content::RenderViewHost;
// This is also called from the Edit -> Spelling -> Check Spelling menu item.
- (void)checkSpelling:(id)sender {
content::WebContents* webContents = content::WebContents::FromRenderViewHost(
- RenderViewHost::From(renderWidgetHost_));
- DCHECK(webContents && webContents->GetFocusedFrame());
-
- mojo::Remote<spellcheck::mojom::SpellCheckPanel>
- focused_spell_check_panel_client;
- webContents->GetFocusedFrame()->GetRemoteInterfaces()->GetInterface(
- focused_spell_check_panel_client.BindNewPipeAndPassReceiver());
- focused_spell_check_panel_client->AdvanceToNextMisspelling();
+ RenderViewHost::From(_renderWidgetHost));
+ if (webContents && webContents->GetFocusedFrame()) {
+ mojo::Remote<spellcheck::mojom::SpellCheckPanel>
+ focused_spell_check_panel_client;
+ webContents->GetFocusedFrame()->GetRemoteInterfaces()->GetInterface(
+ focused_spell_check_panel_client.BindNewPipeAndPassReceiver());
+ focused_spell_check_panel_client->AdvanceToNextMisspelling();
+ }
}
// This message is sent by the spelling panel whenever a word is ignored.
@@ -213,14 +213,15 @@ using content::RenderViewHost;
// spellcheck_platform::IgnoreWord assumes that is the correct tag.
NSString* wordToIgnore = [sender stringValue];
if (wordToIgnore != nil)
- spellcheck_platform::IgnoreWord(base::SysNSStringToUTF16(wordToIgnore));
+ spellcheck_platform::IgnoreWord(nullptr,
+ base::SysNSStringToUTF16(wordToIgnore));
}
- (void)showGuessPanel:(id)sender {
const bool visible = spellcheck_platform::SpellingPanelVisible();
content::WebContents* webContents = content::WebContents::FromRenderViewHost(
- RenderViewHost::From(renderWidgetHost_));
+ RenderViewHost::From(_renderWidgetHost));
DCHECK(webContents && webContents->GetFocusedFrame());
mojo::Remote<spellcheck::mojom::SpellCheckPanel>
@@ -231,7 +232,7 @@ using content::RenderViewHost;
}
- (void)toggleContinuousSpellChecking:(id)sender {
- content::RenderProcessHost* host = renderWidgetHost_->GetProcess();
+ content::RenderProcessHost* host = _renderWidgetHost->GetProcess();
Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
DCHECK(profile);
PrefService* pref = profile->GetPrefs();
@@ -244,7 +245,7 @@ using content::RenderViewHost;
// If a dialog is visible, make its window key. See becomeFirstResponder.
- (void)makeAnyDialogKey {
if (const auto* contents = content::WebContents::FromRenderViewHost(
- RenderViewHost::From(renderWidgetHost_))) {
+ RenderViewHost::From(_renderWidgetHost))) {
if (const auto* manager =
web_modal::WebContentsModalDialogManager::FromWebContents(
contents)) {
@@ -269,7 +270,7 @@ using content::RenderViewHost;
// window should become key.
- (void)resignFirstResponder {
NSWindow* browserWindow =
- [renderWidgetHost_->GetView()->GetNativeView().GetNativeNSView() window];
+ [_renderWidgetHost->GetView()->GetNativeView().GetNativeNSView() window];
DCHECK(browserWindow);
// If the browser window is already key, there's nothing to do.
@@ -287,7 +288,7 @@ using content::RenderViewHost;
// Otherwise, temporarily set an ivar so that -windowDidBecomeKey, below,
// doesn't immediately make the dialog key.
- base::AutoReset<BOOL> scoped(&resigningFirstResponder_, YES);
+ base::AutoReset<BOOL> scoped(&_resigningFirstResponder, YES);
// …then make the browser window key.
[browserWindow makeKeyWindow];
@@ -296,10 +297,10 @@ using content::RenderViewHost;
// If the browser window becomes key while the RenderWidgetHostView is first
// responder, make the dialog key (if there is one).
- (void)windowDidBecomeKey {
- if (resigningFirstResponder_)
+ if (_resigningFirstResponder)
return;
NSView* view =
- renderWidgetHost_->GetView()->GetNativeView().GetNativeNSView();
+ _renderWidgetHost->GetView()->GetNativeView().GetNativeNSView();
if (view.window.firstResponder == view)
[self makeAnyDialogKey];
}
diff --git a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h
index f925c6109d8..968648e7746 100644
--- a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h
+++ b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h
@@ -134,29 +134,29 @@ enum RecognitionState {
@interface HistorySwiper : NSObject {
@private
// This controller will exist if and only if the UI is in history swipe mode.
- HistoryOverlayController* historyOverlay_;
+ HistoryOverlayController* _historyOverlay;
// The location of the fingers when the gesture started.
- NSPoint gestureStartPoint_;
+ NSPoint _gestureStartPoint;
// The current location of the fingers in the gesture.
- NSPoint gestureCurrentPoint_;
+ NSPoint _gestureCurrentPoint;
// The total Y distance moved since the beginning of the gesture.
- CGFloat gestureTotalY_;
+ CGFloat _gestureTotalY;
// A flag that indicates that there is an ongoing gesture. Only used to
// determine whether swipe events are coming from a Magic Mouse.
- BOOL inGesture_;
+ BOOL _inGesture;
// A flag that indicates that Chrome is receiving a series of touch events.
- BOOL receivingTouches_;
+ BOOL _receivingTouches;
// Each time a new gesture begins, we must get a new start point.
// This ivar determines whether the start point is valid.
- int gestureStartPointValid_;
+ int _gestureStartPointValid;
// The user's intended direction with the history swipe. Set during the
// transition from kPending -> kPotential.
- history_swiper::NavigationDirection historySwipeDirection_;
+ history_swiper::NavigationDirection _historySwipeDirection;
// Whether the history swipe gesture has its direction inverted. Set during
// the transition from kPending -> kPotential.
- BOOL historySwipeDirectionInverted_;
+ BOOL _historySwipeDirectionInverted;
// Whether:
// 1) When wheel gestures are disabled if the wheel event with phase
@@ -164,24 +164,24 @@ enum RecognitionState {
// 2) When wheel gestures are enabled and if the first gesture
// scroll was not consumed by the renderer.
// This variables defaults to NO for new gestures.
- BOOL firstScrollUnconsumed_;
+ BOOL _firstScrollUnconsumed;
// Whether the overscroll has been triggered by renderer and is not disabled
// by CSSOverscrollBehavior.
- BOOL overscrollTriggeredByRenderer_;
+ BOOL _overscrollTriggeredByRenderer;
// Whether we have received a gesture scroll begin and are awiting on the
// first gesture scroll update to deteremine of the event was consumed by
// the renderer.
- BOOL waitingForFirstGestureScroll_;
+ BOOL _waitingForFirstGestureScroll;
- history_swiper::RecognitionState recognitionState_;
+ history_swiper::RecognitionState _recognitionState;
- id<HistorySwiperDelegate> delegate_;
+ id<HistorySwiperDelegate> _delegate;
// Cumulative scroll delta since scroll gesture start. Only valid during
// scroll gesture handling. Only used to trigger Magic Mouse history swiping.
- NSSize mouseScrollDelta_;
+ NSSize _mouseScrollDelta;
}
// Many event types are passed in, but the only one we care about is
diff --git a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
index 1ec08fbf586..724458d0e08 100644
--- a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
+++ b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.mm
@@ -4,14 +4,13 @@
#import "chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h"
-#import "base/mac/sdk_forward_declarations.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#import "chrome/browser/ui/cocoa/history_overlay_controller.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "third_party/blink/public/platform/web_gesture_event.h"
-#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
+#include "third_party/blink/public/common/input/web_gesture_event.h"
+#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
#include "ui/events/blink/did_overscroll_params.h"
namespace {
@@ -94,12 +93,12 @@ BOOL forceMagicMouse = NO;
@end
@implementation HistorySwiper
-@synthesize delegate = delegate_;
+@synthesize delegate = _delegate;
- (id)initWithDelegate:(id<HistorySwiperDelegate>)delegate {
self = [super init];
if (self) {
- delegate_ = delegate;
+ _delegate = delegate;
}
return self;
}
@@ -120,7 +119,7 @@ BOOL forceMagicMouse = NO;
consumed:(BOOL)consumed {
if (event.phase != NSEventPhaseBegan)
return;
- firstScrollUnconsumed_ = !consumed;
+ _firstScrollUnconsumed = !consumed;
}
- (void)rendererHandledGestureScrollEvent:(const blink::WebGestureEvent&)event
@@ -132,12 +131,12 @@ BOOL forceMagicMouse = NO;
blink::WebGestureEvent::InertialPhaseState::kMomentum) {
return;
}
- waitingForFirstGestureScroll_ = YES;
+ _waitingForFirstGestureScroll = YES;
break;
case blink::WebInputEvent::kGestureScrollUpdate:
- if (waitingForFirstGestureScroll_)
- firstScrollUnconsumed_ = !consumed;
- waitingForFirstGestureScroll_ = NO;
+ if (_waitingForFirstGestureScroll)
+ _firstScrollUnconsumed = !consumed;
+ _waitingForFirstGestureScroll = NO;
break;
default:
break;
@@ -145,21 +144,21 @@ BOOL forceMagicMouse = NO;
}
- (void)onOverscrolled:(const ui::DidOverscrollParams&)params {
- overscrollTriggeredByRenderer_ =
+ _overscrollTriggeredByRenderer =
params.overscroll_behavior.x ==
cc::OverscrollBehavior::OverscrollBehaviorType::
kOverscrollBehaviorTypeAuto;
}
- (void)beginGestureWithEvent:(NSEvent*)event {
- inGesture_ = YES;
+ _inGesture = YES;
// Reset state pertaining to Magic Mouse swipe gestures.
- mouseScrollDelta_ = NSZeroSize;
+ _mouseScrollDelta = NSZeroSize;
}
- (void)endGestureWithEvent:(NSEvent*)event {
- inGesture_ = NO;
+ _inGesture = NO;
}
// This method assumes that there is at least 1 touch in the event.
@@ -187,16 +186,16 @@ BOOL forceMagicMouse = NO;
NSPoint averagePosition = [self averagePositionInEvent:event];
// If the start point is valid, then so is the current point.
- if (gestureStartPointValid_)
- gestureTotalY_ += fabs(averagePosition.y - gestureCurrentPoint_.y);
+ if (_gestureStartPointValid)
+ _gestureTotalY += fabs(averagePosition.y - _gestureCurrentPoint.y);
// Update the current point of the gesture.
- gestureCurrentPoint_ = averagePosition;
+ _gestureCurrentPoint = averagePosition;
// If the gesture doesn't have a start point, set one.
- if (!gestureStartPointValid_) {
- gestureStartPointValid_ = YES;
- gestureStartPoint_ = gestureCurrentPoint_;
+ if (!_gestureStartPointValid) {
+ _gestureStartPointValid = YES;
+ _gestureStartPoint = _gestureCurrentPoint;
}
}
@@ -204,15 +203,15 @@ BOOL forceMagicMouse = NO;
// called before the gesture begins, and the touches in an event are only
// available after the gesture begins.
- (void)touchesBeganWithEvent:(NSEvent*)event {
- receivingTouches_ = YES;
+ _receivingTouches = YES;
// Reset state pertaining to previous trackpad gestures.
- gestureStartPointValid_ = NO;
- gestureTotalY_ = 0;
- firstScrollUnconsumed_ = NO;
- overscrollTriggeredByRenderer_ = NO;
- waitingForFirstGestureScroll_ = NO;
- recognitionState_ = history_swiper::kPending;
+ _gestureStartPointValid = NO;
+ _gestureTotalY = 0;
+ _firstScrollUnconsumed = NO;
+ _overscrollTriggeredByRenderer = NO;
+ _waitingForFirstGestureScroll = NO;
+ _recognitionState = history_swiper::kPending;
}
- (void)touchesMovedWithEvent:(NSEvent*)event {
@@ -220,7 +219,7 @@ BOOL forceMagicMouse = NO;
}
- (void)touchesCancelledWithEvent:(NSEvent*)event {
- receivingTouches_ = NO;
+ _receivingTouches = NO;
if (![self processTouchEventForHistorySwiping:event])
return;
@@ -229,21 +228,21 @@ BOOL forceMagicMouse = NO;
}
- (void)touchesEndedWithEvent:(NSEvent*)event {
- receivingTouches_ = NO;
+ _receivingTouches = NO;
if (![self processTouchEventForHistorySwiping:event])
return;
- if (historyOverlay_) {
+ if (_historyOverlay) {
BOOL finished = [self updateProgressBar];
// If the gesture was completed, perform a navigation.
if (finished)
- [self navigateBrowserInDirection:historySwipeDirection_];
+ [self navigateBrowserInDirection:_historySwipeDirection];
[self removeHistoryOverlay];
// The gesture was completed.
- recognitionState_ = history_swiper::kCompleted;
+ _recognitionState = history_swiper::kCompleted;
}
}
@@ -254,7 +253,7 @@ BOOL forceMagicMouse = NO;
return NO;
}
- switch (recognitionState_) {
+ switch (_recognitionState) {
case history_swiper::kCancelled:
case history_swiper::kCompleted:
return NO;
@@ -267,27 +266,27 @@ BOOL forceMagicMouse = NO;
[self updateGestureCurrentPointFromEvent:event];
// Consider cancelling the history swipe gesture.
- if ([self shouldCancelHorizontalSwipeWithCurrentPoint:gestureCurrentPoint_
- startPoint:gestureStartPoint_]) {
+ if ([self shouldCancelHorizontalSwipeWithCurrentPoint:_gestureCurrentPoint
+ startPoint:_gestureStartPoint]) {
[self cancelHistorySwipe];
return NO;
}
// Don't do any more processing if the state machine is in the pending state.
- if (recognitionState_ == history_swiper::kPending)
+ if (_recognitionState == history_swiper::kPending)
return NO;
- if (recognitionState_ == history_swiper::kPotential) {
+ if (_recognitionState == history_swiper::kPotential) {
// The user is in the process of doing history swiping. If the history
// swipe has progressed sufficiently far, stop sending events to the
// renderer.
- BOOL sufficientlyFar = fabs(gestureCurrentPoint_.x - gestureStartPoint_.x) >
+ BOOL sufficientlyFar = fabs(_gestureCurrentPoint.x - _gestureStartPoint.x) >
kConsumeEventThreshold;
if (sufficientlyFar)
- recognitionState_ = history_swiper::kTracking;
+ _recognitionState = history_swiper::kTracking;
}
- if (historyOverlay_)
+ if (_historyOverlay)
[self updateProgressBar];
return YES;
}
@@ -296,7 +295,7 @@ BOOL forceMagicMouse = NO;
// vertical swipe.
- (BOOL)shouldCancelHorizontalSwipeWithCurrentPoint:(NSPoint)currentPoint
startPoint:(NSPoint)startPoint {
- CGFloat yDelta = gestureTotalY_;
+ CGFloat yDelta = _gestureTotalY;
CGFloat xDelta = fabs(currentPoint.x - startPoint.x);
// The gesture is pretty clearly more vertical than horizontal.
@@ -316,30 +315,30 @@ BOOL forceMagicMouse = NO;
- (void)cancelHistorySwipe {
[self removeHistoryOverlay];
- recognitionState_ = history_swiper::kCancelled;
+ _recognitionState = history_swiper::kCancelled;
}
- (void)removeHistoryOverlay {
- [historyOverlay_ dismiss];
- [historyOverlay_ release];
- historyOverlay_ = nil;
+ [_historyOverlay dismiss];
+ [_historyOverlay release];
+ _historyOverlay = nil;
}
// Returns whether the progress bar has been 100% filled.
- (BOOL)updateProgressBar {
- NSPoint currentPoint = gestureCurrentPoint_;
- NSPoint startPoint = gestureStartPoint_;
+ NSPoint currentPoint = _gestureCurrentPoint;
+ NSPoint startPoint = _gestureStartPoint;
float progress = 0;
BOOL finished = NO;
progress = (currentPoint.x - startPoint.x) / kHistorySwipeThreshold;
// If the swipe is a backwards gesture, we need to invert progress.
- if (historySwipeDirection_ == history_swiper::kBackwards)
+ if (_historySwipeDirection == history_swiper::kBackwards)
progress *= -1;
// If the user has directions reversed, we need to invert progress.
- if (historySwipeDirectionInverted_)
+ if (_historySwipeDirectionInverted)
progress *= -1;
if (progress >= 1.0)
@@ -349,7 +348,7 @@ BOOL forceMagicMouse = NO;
progress = MAX(0.0, progress);
progress = MIN(1.0, progress);
- [historyOverlay_ setProgress:progress finished:finished];
+ [_historyOverlay setProgress:progress finished:finished];
return finished;
}
@@ -370,8 +369,8 @@ BOOL forceMagicMouse = NO;
initForMode:(direction == history_swiper::kForwards)
? kHistoryOverlayModeForward
: kHistoryOverlayModeBack];
- [historyOverlay showPanelForView:[delegate_ viewThatWantsHistoryOverlay]];
- historyOverlay_ = historyOverlay;
+ [historyOverlay showPanelForView:[_delegate viewThatWantsHistoryOverlay]];
+ _historyOverlay = historyOverlay;
}
- (BOOL)systemSettingsAllowHistorySwiping:(NSEvent*)event {
@@ -384,7 +383,7 @@ BOOL forceMagicMouse = NO;
- (void)navigateBrowserInDirection:
(history_swiper::NavigationDirection)direction {
Browser* browser = chrome::FindBrowserWithWindow(
- historyOverlay_.view.window);
+ _historyOverlay.view.window);
if (browser) {
if (direction == history_swiper::kForwards)
chrome::GoForward(browser, WindowOpenDisposition::CURRENT_TAB);
@@ -412,11 +411,11 @@ BOOL forceMagicMouse = NO;
if ([theEvent phase] == NSEventPhaseNone)
return NO;
- mouseScrollDelta_.width += [theEvent scrollingDeltaX];
- mouseScrollDelta_.height += [theEvent scrollingDeltaY];
+ _mouseScrollDelta.width += [theEvent scrollingDeltaX];
+ _mouseScrollDelta.height += [theEvent scrollingDeltaY];
BOOL isHorizontalGesture =
- std::abs(mouseScrollDelta_.width) > std::abs(mouseScrollDelta_.height);
+ std::abs(_mouseScrollDelta.width) > std::abs(_mouseScrollDelta.height);
if (!isHorizontalGesture)
return NO;
@@ -473,7 +472,7 @@ BOOL forceMagicMouse = NO;
BOOL* stop) {
if (phase == NSEventPhaseBegan) {
[historyOverlay
- showPanelForView:[delegate_ viewThatWantsHistoryOverlay]];
+ showPanelForView:[_delegate viewThatWantsHistoryOverlay]];
return;
}
@@ -518,7 +517,7 @@ BOOL forceMagicMouse = NO;
}
// We've already processed this gesture.
- if (recognitionState_ != history_swiper::kPending) {
+ if (_recognitionState != history_swiper::kPending) {
return [self shouldConsumeWheelEvent:theEvent];
}
@@ -530,35 +529,35 @@ BOOL forceMagicMouse = NO;
if (!systemSettingsValid)
return NO;
- if (![delegate_ shouldAllowHistorySwiping])
+ if (![_delegate shouldAllowHistorySwiping])
return NO;
// Don't enable history swiping until the renderer has decided to not consume
// the event with phase NSEventPhaseBegan.
- if (!firstScrollUnconsumed_)
+ if (!_firstScrollUnconsumed)
return NO;
// History swiping should be prevented if the renderer hasn't triggered it.
- if (!overscrollTriggeredByRenderer_)
+ if (!_overscrollTriggeredByRenderer)
return NO;
// Magic mouse and touchpad swipe events are identical except magic mouse
// events do not generate NSTouch callbacks. Since we rely on NSTouch
// callbacks to perform history swiping, magic mouse swipe events use an
// entirely different set of logic.
- if ((inGesture_ && !receivingTouches_) || forceMagicMouse)
+ if ((_inGesture && !_receivingTouches) || forceMagicMouse)
return [self handleMagicMouseWheelEvent:theEvent];
// The scrollWheel: callback is only relevant if it happens while the user is
// still actively using the touchpad.
- if (!receivingTouches_)
+ if (!_receivingTouches)
return NO;
// TODO(erikchen): Ideally, the direction of history swiping should not be
// determined this early in a gesture, when it's unclear what the user is
// intending to do. Since it is determined this early, make sure that there
// is at least a minimal amount of horizontal motion.
- CGFloat xDelta = gestureCurrentPoint_.x - gestureStartPoint_.x;
+ CGFloat xDelta = _gestureCurrentPoint.x - _gestureStartPoint.x;
if (fabs(xDelta) < 0.001)
return NO;
@@ -574,15 +573,15 @@ BOOL forceMagicMouse = NO;
if (!browserCanMove)
return NO;
- historySwipeDirection_ = direction;
- historySwipeDirectionInverted_ = [self isEventDirectionInverted:theEvent];
- recognitionState_ = history_swiper::kPotential;
+ _historySwipeDirection = direction;
+ _historySwipeDirectionInverted = [self isEventDirectionInverted:theEvent];
+ _recognitionState = history_swiper::kPotential;
[self showHistoryOverlay:direction];
return [self shouldConsumeWheelEvent:theEvent];
}
- (BOOL)shouldConsumeWheelEvent:(NSEvent*)event {
- switch (recognitionState_) {
+ switch (_recognitionState) {
case history_swiper::kPending:
case history_swiper::kCancelled:
return NO;
diff --git a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm
index 6b92c17c894..9b972bb85c8 100644
--- a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm
+++ b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_browsertest.mm
@@ -8,7 +8,6 @@
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/mac/scoped_nsobject.h"
-#import "base/mac/sdk_forward_declarations.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/test/simple_test_tick_clock.h"
@@ -21,7 +20,7 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
-#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
+#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/ocmock_extensions.h"
#include "ui/events/base_event_utils.h"
diff --git a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm
index 1af449d13a9..76fe7eb08f7 100644
--- a/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm
+++ b/chromium/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper_unit_test.mm
@@ -5,11 +5,10 @@
#import "chrome/browser/renderer_host/chrome_render_widget_host_view_mac_history_swiper.h"
#include "base/mac/scoped_nsobject.h"
-#import "base/mac/sdk_forward_declarations.h"
#import "chrome/browser/ui/cocoa/test/cocoa_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/platform/web_input_event.h"
-#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
+#include "third_party/blink/public/common/input/web_input_event.h"
+#include "third_party/blink/public/common/input/web_mouse_wheel_event.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#import "third_party/ocmock/ocmock_extensions.h"
#include "ui/events/blink/did_overscroll_params.h"
diff --git a/chromium/chrome/browser/renderer_host/pepper/device_id_fetcher.cc b/chromium/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
index 712e0a74b95..93799f8adbf 100644
--- a/chromium/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
+++ b/chromium/chrome/browser/renderer_host/pepper/device_id_fetcher.cc
@@ -9,6 +9,7 @@
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
@@ -124,9 +125,8 @@ void DeviceIDFetcher::CheckPrefsOnUIThread() {
#if defined(OS_CHROMEOS)
// Try the legacy path first for ChromeOS. We pass the new salt in as well
// in case the legacy id doesn't exist.
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&DeviceIDFetcher::LegacyComputeAsync, this,
profile->GetPath(), salt));
#else
diff --git a/chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc b/chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc
index 4bb88c55a82..d72a867594a 100644
--- a/chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc
+++ b/chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.cc
@@ -34,7 +34,7 @@ PepperBrokerMessageFilter::PepperBrokerMessageFilter(PP_Instance instance,
PepperBrokerMessageFilter::~PepperBrokerMessageFilter() {}
-scoped_refptr<base::TaskRunner>
+scoped_refptr<base::SequencedTaskRunner>
PepperBrokerMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& message) {
return base::CreateSingleThreadTaskRunner({BrowserThread::UI});
diff --git a/chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h b/chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h
index d3a01e4249b..fcff906099f 100644
--- a/chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h
+++ b/chromium/chrome/browser/renderer_host/pepper/pepper_broker_message_filter.h
@@ -33,7 +33,7 @@ class PepperBrokerMessageFilter : public ppapi::host::ResourceMessageFilter {
~PepperBrokerMessageFilter() override;
// ppapi::host::ResourceMessageFilter overrides.
- scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ scoped_refptr<base::SequencedTaskRunner> OverrideTaskRunnerForMessage(
const IPC::Message& message) override;
int32_t OnResourceMessageReceived(
const IPC::Message& msg,
diff --git a/chromium/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc b/chromium/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc
index 860c5738d57..c1fdd9dd86e 100644
--- a/chromium/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc
+++ b/chromium/chrome/browser/renderer_host/pepper/pepper_flash_browser_host.cc
@@ -15,8 +15,8 @@
#include "content/public/browser/browser_ppapi_host.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/device_service.h"
#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/system_connector.h"
#include "ipc/ipc_message_macros.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -26,9 +26,7 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/proxy/resource_message_params.h"
#include "ppapi/shared_impl/time_conversion.h"
-#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
#include "url/gurl.h"
#if defined(OS_WIN)
@@ -57,13 +55,10 @@ scoped_refptr<content_settings::CookieSettings> GetCookieSettings(
return nullptr;
}
-void PepperBindConnectorReceiver(
- mojo::PendingReceiver<service_manager::mojom::Connector>
- connector_receiver) {
+void BindWakeLockProviderOnUIThread(
+ mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(content::GetSystemConnector());
- content::GetSystemConnector()->BindConnectorReceiver(
- std::move(connector_receiver));
+ content::GetDeviceService().BindWakeLockProvider(std::move(receiver));
}
} // namespace
@@ -139,11 +134,11 @@ int32_t PepperFlashBrowserHost::OnGetLocalDataRestrictions(
} else {
base::PostTaskAndReplyWithResult(
FROM_HERE, {BrowserThread::UI},
- base::Bind(&GetCookieSettings, render_process_id_),
- base::Bind(&PepperFlashBrowserHost::GetLocalDataRestrictions,
- weak_factory_.GetWeakPtr(),
- context->MakeReplyMessageContext(), document_url,
- plugin_url));
+ base::BindOnce(&GetCookieSettings, render_process_id_),
+ base::BindOnce(&PepperFlashBrowserHost::GetLocalDataRestrictions,
+ weak_factory_.GetWeakPtr(),
+ context->MakeReplyMessageContext(), document_url,
+ plugin_url));
}
return PP_OK_COMPLETIONPENDING;
}
@@ -182,23 +177,11 @@ device::mojom::WakeLock* PepperFlashBrowserHost::GetWakeLock() {
if (wake_lock_)
return wake_lock_.get();
- // The system Connector might be not initialized in some testing environments.
- if (!content::GetSystemConnector())
- return wake_lock_.get();
-
- mojo::PendingReceiver<service_manager::mojom::Connector> connector_receiver;
- auto connector = service_manager::Connector::Create(&connector_receiver);
-
- // The existing connector is bound to the UI thread, the current thread is
- // IO thread. So bind the Connector receiver of IO thread to the connector
- // in UI thread.
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&PepperBindConnectorReceiver,
- std::move(connector_receiver)));
-
mojo::Remote<device::mojom::WakeLockProvider> wake_lock_provider;
- connector->Connect(device::mojom::kServiceName,
- wake_lock_provider.BindNewPipeAndPassReceiver());
+ base::PostTask(
+ FROM_HERE, {BrowserThread::UI},
+ base::BindOnce(&BindWakeLockProviderOnUIThread,
+ wake_lock_provider.BindNewPipeAndPassReceiver()));
wake_lock_provider->GetWakeLockWithoutContext(
device::mojom::WakeLockType::kPreventDisplaySleep,
device::mojom::WakeLockReason::kOther, "Requested By PepperFlash",
diff --git a/chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc b/chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc
index 8a57873a375..8147eb02d87 100644
--- a/chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc
+++ b/chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc
@@ -99,7 +99,7 @@ PepperFlashClipboardMessageFilter::PepperFlashClipboardMessageFilter() {}
PepperFlashClipboardMessageFilter::~PepperFlashClipboardMessageFilter() {}
-scoped_refptr<base::TaskRunner>
+scoped_refptr<base::SequencedTaskRunner>
PepperFlashClipboardMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& msg) {
// Clipboard writes should always occur on the UI thread due to the
@@ -163,11 +163,12 @@ int32_t PepperFlashClipboardMessageFilter::OnMsgIsFormatAvailable(
bool available = false;
switch (format) {
case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: {
- bool plain = clipboard->IsFormatAvailable(
+ available = clipboard->IsFormatAvailable(
ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer);
- bool plainw = clipboard->IsFormatAvailable(
- ui::ClipboardFormatType::GetPlainTextWType(), clipboard_buffer);
- available = plain || plainw;
+#if defined(OS_WIN)
+ available |= clipboard->IsFormatAvailable(
+ ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer);
+#endif
break;
}
case PP_FLASH_CLIPBOARD_FORMAT_HTML:
@@ -212,7 +213,7 @@ int32_t PepperFlashClipboardMessageFilter::OnMsgReadData(
switch (format) {
case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: {
if (clipboard->IsFormatAvailable(
- ui::ClipboardFormatType::GetPlainTextWType(), clipboard_buffer)) {
+ ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer)) {
base::string16 text;
clipboard->ReadText(clipboard_buffer, &text);
if (!text.empty()) {
@@ -221,13 +222,15 @@ int32_t PepperFlashClipboardMessageFilter::OnMsgReadData(
break;
}
}
- // If the PlainTextW format isn't available or is empty, take the
+#if defined(OS_WIN)
+ // If the PlainText format isn't available or is empty, take the
// ASCII text format.
if (clipboard->IsFormatAvailable(
- ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer)) {
+ ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer)) {
result = PP_OK;
clipboard->ReadAsciiText(clipboard_buffer, &clipboard_string);
}
+#endif
break;
}
case PP_FLASH_CLIPBOARD_FORMAT_HTML: {
diff --git a/chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h b/chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h
index 33b4797d5dd..9498c3944a6 100644
--- a/chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h
+++ b/chromium/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.h
@@ -39,7 +39,7 @@ class PepperFlashClipboardMessageFilter
protected:
// ppapi::host::ResourceMessageFilter overrides.
- scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ scoped_refptr<base::SequencedTaskRunner> OverrideTaskRunnerForMessage(
const IPC::Message& msg) override;
int32_t OnResourceMessageReceived(
const IPC::Message& msg,
diff --git a/chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc b/chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc
index 0fa0fa341e9..c94e1947dc1 100644
--- a/chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc
+++ b/chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc
@@ -76,7 +76,7 @@ PepperIsolatedFileSystemMessageFilter::PepperIsolatedFileSystemMessageFilter(
PepperIsolatedFileSystemMessageFilter::
~PepperIsolatedFileSystemMessageFilter() {}
-scoped_refptr<base::TaskRunner>
+scoped_refptr<base::SequencedTaskRunner>
PepperIsolatedFileSystemMessageFilter::OverrideTaskRunnerForMessage(
const IPC::Message& msg) {
// In order to reach ExtensionSystem, we need to get ProfileManager first.
diff --git a/chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h b/chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h
index b36248debee..56a23e8f41b 100644
--- a/chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h
+++ b/chromium/chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h
@@ -40,7 +40,7 @@ class PepperIsolatedFileSystemMessageFilter
content::BrowserPpapiHost* host);
// ppapi::host::ResourceMessageFilter implementation.
- scoped_refptr<base::TaskRunner> OverrideTaskRunnerForMessage(
+ scoped_refptr<base::SequencedTaskRunner> OverrideTaskRunnerForMessage(
const IPC::Message& msg) override;
int32_t OnResourceMessageReceived(
const IPC::Message& msg,
diff --git a/chromium/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chromium/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
index d58b837f47a..dd94a6bbfa1 100644
--- a/chromium/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
+++ b/chromium/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -112,7 +112,7 @@ class ChromeRenderProcessHostTest : public extensions::ExtensionBrowserTest {
WebContents* OpenBackgroundTab(const GURL& page) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), page, WindowOpenDisposition::NEW_BACKGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
TabStripModel* tab_strip = browser()->tab_strip_model();
WebContents* wc =
@@ -320,7 +320,7 @@ IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, ProcessPerTab) {
// WebUI.
ui_test_utils::NavigateToURLWithDisposition(
browser(), omnibox, WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
tab_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
@@ -329,7 +329,7 @@ IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest, ProcessPerTab) {
// WebUI.
ui_test_utils::NavigateToURLWithDisposition(
browser(), omnibox, WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
tab_count++;
EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
EXPECT_EQ(host_count, RenderProcessHostCount());
diff --git a/chromium/chrome/browser/reputation/BUILD.gn b/chromium/chrome/browser/reputation/BUILD.gn
index bbcd9b1bf1d..74fe53b033f 100644
--- a/chromium/chrome/browser/reputation/BUILD.gn
+++ b/chromium/chrome/browser/reputation/BUILD.gn
@@ -5,7 +5,5 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
- sources = [
- "safety_tips.proto",
- ]
+ sources = [ "safety_tips.proto" ]
}
diff --git a/chromium/chrome/browser/resource_coordinator/BUILD.gn b/chromium/chrome/browser/resource_coordinator/BUILD.gn
index c308b7901ac..4d26a150dab 100644
--- a/chromium/chrome/browser/resource_coordinator/BUILD.gn
+++ b/chromium/chrome/browser/resource_coordinator/BUILD.gn
@@ -7,25 +7,21 @@ import("//mojo/public/tools/bindings/mojom.gni")
import("//third_party/protobuf/proto_library.gni")
proto_library("tab_metrics_event_proto") {
- sources = [
- "tab_metrics_event.proto",
- ]
+ sources = [ "tab_metrics_event.proto" ]
}
mojom("mojo_bindings") {
- sources = [
- "lifecycle_unit_state.mojom",
- ]
+ sources = [ "lifecycle_unit_state.mojom" ]
+}
+
+proto_library("intervention_policy_database_proto") {
+ sources = [ "intervention_policy_database.proto" ]
}
source_set("tab_manager_features") {
- public = [
- "tab_manager_features.h",
- ]
+ public = [ "tab_manager_features.h" ]
- sources = [
- "tab_manager_features.cc",
- ]
+ sources = [ "tab_manager_features.cc" ]
deps = [
"//base",
diff --git a/chromium/chrome/browser/resource_coordinator/lifecycle_unit_state.mojom b/chromium/chrome/browser/resource_coordinator/lifecycle_unit_state.mojom
index fc04dae81ec..03e35133825 100644
--- a/chromium/chrome/browser/resource_coordinator/lifecycle_unit_state.mojom
+++ b/chromium/chrome/browser/resource_coordinator/lifecycle_unit_state.mojom
@@ -15,8 +15,9 @@ enum LifecycleUnitState {
PENDING_FREEZE = 2,
// The LifecycleUnit is frozen.
FROZEN = 3,
- // The LifecycleUnit is currently transitioning to a DISCARDED state.
- PENDING_DISCARD = 4,
+ // Deprecated: The LifecycleUnit is currently transitioning to a DISCARDED
+ // state.
+ // PENDING_DISCARD = 4,
// The LifecycleUnit is discarded, and is consuming no system resources.
DISCARDED = 5,
// The LifecycleUnit is currently transitioning from the FROZEN state to the
@@ -55,10 +56,7 @@ enum LifecycleUnitStateChangeReason {
enum LifecycleUnitDiscardReason {
// The discard is requested from outside of TabManager (e.g. by an extension).
EXTERNAL = 0,
- // The discard is requested proactively by TabManager when the system is in a
- // good state.
- PROACTIVE = 1,
// The discard is requested urgently by TabManager when the system is in a
// critical condition.
- URGENT = 2,
+ URGENT = 1,
};
diff --git a/chromium/chrome/browser/resource_coordinator/tab_ranker/BUILD.gn b/chromium/chrome/browser/resource_coordinator/tab_ranker/BUILD.gn
index 23125cc476e..e53fa7a3293 100644
--- a/chromium/chrome/browser/resource_coordinator/tab_ranker/BUILD.gn
+++ b/chromium/chrome/browser/resource_coordinator/tab_ranker/BUILD.gn
@@ -41,7 +41,5 @@ static_library("tab_features_test_helper") {
"tab_features_test_helper.h",
]
- deps = [
- ":tab_ranker",
- ]
+ deps = [ ":tab_ranker" ]
}
diff --git a/chromium/chrome/browser/resources/BUILD.gn b/chromium/chrome/browser/resources/BUILD.gn
index dee22c32836..f4ad27fb62d 100644
--- a/chromium/chrome/browser/resources/BUILD.gn
+++ b/chromium/chrome/browser/resources/BUILD.gn
@@ -4,6 +4,8 @@
import("//chrome/common/features.gni")
import("//chrome/test/base/js2gtest.gni")
+import("//chrome/test/include_js_tests.gni")
+import("//components/nacl/features.gni")
import("//tools/grit/grit_rule.gni")
import("//tools/grit/repack.gni")
@@ -15,6 +17,7 @@ if (closure_compile) {
"components:closure_compile",
"engagement:closure_compile",
"interventions_internals:closure_compile",
+ "media:closure_compile",
"reset_password:closure_compile",
]
if (is_linux || is_win || is_mac) {
@@ -24,6 +27,7 @@ if (closure_compile) {
"discards:closure_compile",
"download_internals:closure_compile",
"downloads:closure_compile",
+ "gaia_auth_host:closure_compile",
"history:closure_compile",
"local_ntp:closure_compile",
"local_state:closure_compile",
@@ -36,6 +40,7 @@ if (closure_compile) {
"print_preview:closure_compile",
"quota_internals:closure_compile",
"settings:closure_compile",
+ "settings:closure_compile_module",
"signin:closure_compile",
"usb_internals:closure_compile",
"user_manager:closure_compile",
@@ -51,6 +56,9 @@ if (closure_compile) {
if (enable_extensions) {
deps += [ "extensions:closure_compile" ]
}
+ if (enable_nacl) {
+ deps += [ "about_nacl:closure_compile" ]
+ }
if (enable_webui_tab_strip) {
deps += [ "tab_strip:closure_compile" ]
}
@@ -66,13 +74,19 @@ if (closure_compile) {
if (is_win || is_mac || is_desktop_linux) {
deps += [ "browser_switch:closure_compile" ]
}
+
+ # Note: The following targets should only be type-checked on Windows builds,
+ # but because Window bots don't depend on Java, |closure_compile| is off on
+ # Windows. Adding |is_linux| so that these targets are type-checked on at
+ # least one platform.
+ if (is_win || is_linux) {
+ deps += [ "conflicts:closure_compile" ]
+ }
}
}
if (!is_android) {
grit("bookmarks_resources") {
- # The .grd contains references to generated files.
- source_is_generated = true
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
@@ -81,15 +95,11 @@ if (!is_android) {
if (optimize_webui) {
source = "bookmarks/bookmarks_resources_vulcanized.grd"
- deps = [
- "//chrome/browser/resources/bookmarks:build",
- ]
+ deps = [ "//chrome/browser/resources/bookmarks:build" ]
} else {
source = "bookmarks/bookmarks_resources.grd"
- deps = [
- "//chrome/browser/resources/bookmarks:polymer3_elements",
- ]
+ deps = [ "//chrome/browser/resources/bookmarks:polymer3_elements" ]
}
defines = chrome_grit_defines
@@ -105,16 +115,12 @@ if (!is_android) {
grit("component_extension_resources") {
source = "component_extension_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
- deps = [
- "//chrome/browser/resources/pdf/elements:polymer3_elements",
- ]
+ deps = [ "//chrome/browser/resources/pdf/elements:polymer3_elements" ]
defines = chrome_grit_defines
if (enable_hangout_services_extension) {
@@ -130,22 +136,39 @@ if (!is_android) {
output_dir = "$root_gen_dir/chrome"
}
+ grit("gaia_auth_host_resources") {
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
+
+ source = "gaia_auth_host/gaia_auth_host_resources.grd"
+ deps = [ "//chrome/browser/resources/gaia_auth_host:modulize" ]
+
+ defines = chrome_grit_defines
+ outputs = [
+ "grit/gaia_auth_host_resources.h",
+ "grit/gaia_auth_host_resources_map.cc",
+ "grit/gaia_auth_host_resources_map.h",
+ "gaia_auth_host_resources.pak",
+ ]
+ output_dir = "$root_gen_dir/chrome"
+ }
+
grit("history_resources") {
- if (optimize_webui) {
- # The .grd contains references to generated files.
- source_is_generated = true
- grit_flags = [
- "-E",
- "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
- ]
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
+ if (optimize_webui) {
source = "history/history_resources_vulcanized.grd"
- deps = [
- "//chrome/browser/resources/history:build",
- ]
+ deps = [ "//chrome/browser/resources/history:build" ]
} else {
source = "history/history_resources.grd"
+
+ deps = [ "//chrome/browser/resources/history:polymer3_elements" ]
}
defines = chrome_grit_defines
@@ -174,11 +197,9 @@ if (!is_android) {
deps = [
"//chrome/browser/resources/new_tab_page:polymer3_elements",
"//chrome/browser/ui/webui/new_tab_page:mojo_bindings_js",
+ "//skia/public/mojom:mojom_js",
]
- # The .grd contains references to generated files.
- source_is_generated = true
-
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
@@ -195,21 +216,21 @@ if (!is_android) {
}
grit("settings_resources") {
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
+
if (optimize_webui) {
source = "settings/settings_resources_vulcanized.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
-
deps = [
"//chrome/browser/resources/settings:build",
- ]
- grit_flags = [
- "-E",
- "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ "//chrome/browser/resources/settings:build_polymer3",
]
} else {
source = "settings/settings_resources.grd"
+ deps = [ "//chrome/browser/resources/settings:polymer3_elements" ]
}
defines = chrome_grit_defines
@@ -226,20 +247,13 @@ if (!is_android) {
if (optimize_webui) {
source = "downloads/downloads_resources_vulcanized.grd"
- deps = [
- "//chrome/browser/resources/downloads:build",
- ]
+ deps = [ "//chrome/browser/resources/downloads:build" ]
} else {
source = "downloads/downloads_resources.grd"
- deps = [
- "//chrome/browser/resources/downloads:polymer3_elements",
- "//chrome/browser/ui/webui/downloads:mojo_bindings_js",
- ]
+ deps = [ "//chrome/browser/resources/downloads:polymer3_elements" ]
}
-
- # The .grd contains references to generated files.
- source_is_generated = true
+ deps += [ "//chrome/browser/ui/webui/downloads:mojo_bindings_js" ]
grit_flags = [
"-E",
@@ -259,24 +273,25 @@ if (!is_android) {
if (is_chromeos) {
grit("os_settings_resources") {
+ deps = [
+ "//chrome/browser/ui/webui/app_management:mojo_bindings_js",
+ "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings_js",
+ ]
if (optimize_webui) {
+ # Required due to flattenhtml="true" on a generated file.
+ enable_input_discovery_for_gn_analyze = false
source = "settings/os_settings_resources_vulcanized.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
-
- deps = [
- "//chrome/browser/resources/settings/chromeos:build",
- ]
-
- grit_flags = [
- "-E",
- "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
- ]
+ deps += [ "//chrome/browser/resources/settings/chromeos:build" ]
} else {
source = "settings/os_settings_resources.grd"
}
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
+
defines = chrome_grit_defines
outputs = [
"grit/os_settings_resources.h",
@@ -292,12 +307,7 @@ if (!is_android && !is_chromeos) {
grit("welcome_resources") {
source = "welcome/welcome_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
-
- deps = [
- "//chrome/browser/resources/welcome:polymer3_elements",
- ]
+ deps = [ "//chrome/browser/resources/welcome:polymer3_elements" ]
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
@@ -316,9 +326,6 @@ if (!is_android && !is_chromeos) {
if (enable_extensions) {
grit("extensions_resources") {
- # The .grd contains references to generated files.
- source_is_generated = true
-
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
@@ -326,15 +333,11 @@ if (enable_extensions) {
if (optimize_webui) {
source = "extensions/extensions_resources_vulcanized.grd"
- deps = [
- "//chrome/browser/resources/extensions:build",
- ]
+ deps = [ "//chrome/browser/resources/extensions:build" ]
} else {
source = "extensions/extensions_resources.grd"
- deps = [
- "//chrome/browser/resources/extensions:polymer3_elements",
- ]
+ deps = [ "//chrome/browser/resources/extensions:polymer3_elements" ]
}
defines = chrome_grit_defines
@@ -361,9 +364,6 @@ if (enable_extensions) {
if (enable_print_preview) {
grit("print_preview_resources") {
- # The .grd contains references to generated files.
- source_is_generated = true
-
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
@@ -371,15 +371,10 @@ if (enable_print_preview) {
if (optimize_webui) {
source = "print_preview/print_preview_resources_vulcanized.grd"
-
- deps = [
- "//chrome/browser/resources/print_preview:build",
- ]
+ deps = [ "//chrome/browser/resources/print_preview:build" ]
} else {
source = "print_preview/print_preview_resources.grd"
- deps = [
- "//chrome/browser/resources/print_preview/ui:polymer3_elements",
- ]
+ deps = [ "//chrome/browser/resources/print_preview/ui:polymer3_elements" ]
}
defines = chrome_grit_defines
@@ -397,10 +392,7 @@ if (enable_webui_tab_strip) {
grit("tab_strip_resources") {
source = "tab_strip/tab_strip_resources.grd"
defines = chrome_grit_defines
- deps = [
- "tab_strip:tab_strip_modules",
- ]
- source_is_generated = true
+ deps = [ "tab_strip:tab_strip_modules" ]
outputs = [
"grit/tab_strip_resources.h",
"grit/tab_strip_resources_map.cc",
@@ -420,17 +412,21 @@ repack("dev_ui_paks") {
sources = [
"$root_gen_dir/chrome/bluetooth_internals_resources.pak",
+ "$root_gen_dir/chrome/dev_ui_browser_resources.pak",
"$root_gen_dir/chrome/invalidations_resources.pak",
"$root_gen_dir/chrome/net_internals_resources.pak",
"$root_gen_dir/chrome/omnibox_resources.pak",
"$root_gen_dir/chrome/quota_internals_resources.pak",
"$root_gen_dir/chrome/usb_internals_resources.pak",
"$root_gen_dir/chrome/webrtc_logs_resources.pak",
+ "$root_gen_dir/components/dev_ui_components_resources.pak",
"$root_gen_dir/components/sync_driver_resources.pak",
"$root_gen_dir/content/browser/resources/media/media_internals_resources.pak",
"$root_gen_dir/content/browser/webrtc/resources/webrtc_internals_resources.pak",
+ "$root_gen_dir/content/dev_ui_content_resources.pak",
]
deps = [
+ "//chrome/browser:dev_ui_browser_resources",
"//chrome/browser/resources/bluetooth_internals:resources",
"//chrome/browser/resources/invalidations:invalidations_resources",
"//chrome/browser/resources/media:webrtc_logs_resources",
@@ -438,7 +434,9 @@ repack("dev_ui_paks") {
"//chrome/browser/resources/omnibox:resources",
"//chrome/browser/resources/quota_internals:quota_internals_resources",
"//chrome/browser/resources/usb_internals:resources",
+ "//components/resources:dev_ui_components_resources",
"//components/sync/driver:resources",
+ "//content:dev_ui_content_resources",
"//content/browser/resources/media:media_internals_resources",
"//content/browser/webrtc/resources",
]
@@ -449,27 +447,32 @@ repack("dev_ui_paks") {
}
}
-js2gtest("resources_unitjs_tests") {
- test_type = "webui"
- sources = [
- "gaia_auth_host/password_change_authenticator_test.unitjs",
- ]
-
- # This has to be a gen_include, so it doesn't collide with other js2gtests
- gen_include_files = [ "//ui/webui/resources/js/cr.js" ]
-
- # But these have to be extra_js_files, since it uses a native object
- # EventTarget, which doesn't work at compile time.
- extra_js_files = [
- "//ui/webui/resources/js/cr/event_target.js",
- "gaia_auth_host/password_change_authenticator.js",
- ]
- defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
-}
+# Some targets in this file are depended on independent of include_js_tests,
+# so this file gets loaded even if !include_js_tests. Since js2gtest()s don't
+# compile in some scenarios when include_js_tests is false, and since this
+# file is loaded even when it's false, we need to make sure the js2gtest()
+# target only exists in this file when it works. (In contrast, most other
+# BUILD.gn files containing js2gtest()s contain nothing else and hence are only
+# loaded when include_js_tests is true.)
+if (!is_android && include_js_tests) {
+ js2gtest("resources_unitjs_tests") {
+ test_type = "webui"
+ sources = [ "gaia_auth_host/password_change_authenticator_test.unitjs" ]
+
+ # This has to be a gen_include, so it doesn't collide with other js2gtests
+ gen_include_files = [ "//ui/webui/resources/js/cr.js" ]
+
+ # But these have to be extra_js_files, since it uses a native object
+ # EventTarget, which doesn't work at compile time.
+ extra_js_files = [
+ "//ui/webui/resources/js/cr/event_target.js",
+ "gaia_auth_host/password_change_authenticator.js",
+ ]
+ defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
+ }
-source_set("browser_tests_js") {
- testonly = true
- deps = [
- ":resources_unitjs_tests",
- ]
+ source_set("browser_tests_js") {
+ testonly = true
+ deps = [ ":resources_unitjs_tests" ]
+ }
}
diff --git a/chromium/chrome/browser/resources/about_nacl/BUILD.gn b/chromium/chrome/browser/resources/about_nacl/BUILD.gn
new file mode 100644
index 00000000000..67a1b9e7bec
--- /dev/null
+++ b/chromium/chrome/browser/resources/about_nacl/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+ uses_js_modules = true
+ deps = [ ":about_nacl" ]
+}
+
+js_library("about_nacl") {
+ deps = [
+ "//third_party/jstemplate:jstemplate",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:util.m",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/about_nacl/about_nacl.html b/chromium/chrome/browser/resources/about_nacl/about_nacl.html
index c8045497cae..9cac928d287 100644
--- a/chromium/chrome/browser/resources/about_nacl/about_nacl.html
+++ b/chromium/chrome/browser/resources/about_nacl/about_nacl.html
@@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
- <link rel="stylesheet" href="chrome://nacl/about_nacl.css">
+ <link rel="stylesheet" href="about_nacl.css">
</head>
<body>
<div id="loading-message">Loading...</div>
@@ -18,10 +18,7 @@
</div>
</div>
</div>
-<script src="chrome://resources/js/promise_resolver.js"></script>
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://nacl/about_nacl.js"></script>
+<script type="module" src="about_nacl.js"></script>
<script src="chrome://resources/js/jstemplate_compiled.js"></script>
-<script src="chrome://resources/js/util.js"></script>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/about_nacl/about_nacl.js b/chromium/chrome/browser/resources/about_nacl/about_nacl.js
index 3ff098ec357..8eab373610b 100644
--- a/chromium/chrome/browser/resources/about_nacl/about_nacl.js
+++ b/chromium/chrome/browser/resources/about_nacl/about_nacl.js
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-(function() {
+import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
+
/**
* Takes the |moduleListData| input argument which represents data about
* the currently available modules and populates the html jstemplate
@@ -21,13 +23,12 @@ function renderTemplate(moduleListData) {
* re-populates the page with the data.
*/
function requestNaClInfo() {
- cr.sendWithPromise('requestNaClInfo').then((moduleListData) => {
- $('loading-message').hidden = 'hidden';
- $('body-container').hidden = '';
+ sendWithPromise('requestNaClInfo').then((moduleListData) => {
+ $('loading-message').hidden = true;
+ $('body-container').hidden = false;
renderTemplate(moduleListData);
});
}
// Get data and have it displayed upon loading.
document.addEventListener('DOMContentLoaded', requestNaClInfo);
-})();
diff --git a/chromium/chrome/browser/resources/accessibility/accessibility.js b/chromium/chrome/browser/resources/accessibility/accessibility.js
index fffc73a334e..16ef356673b 100644
--- a/chromium/chrome/browser/resources/accessibility/accessibility.js
+++ b/chromium/chrome/browser/resources/accessibility/accessibility.js
@@ -263,11 +263,11 @@ cr.define('accessibility', function() {
}
function insertHeadingInline(parentElement, headingText, id) {
- const h4 = document.createElement('h4');
- h4.textContent = headingText;
- h4.style.display = 'inline';
- h4.id = id + ':title';
- parentElement.appendChild(h4);
+ const h3 = document.createElement('h3');
+ h3.textContent = headingText;
+ h3.style.display = 'inline';
+ h3.id = id + ':title';
+ parentElement.appendChild(h3);
}
function formatValue(data, property) {
@@ -480,7 +480,12 @@ cr.define('accessibility', function() {
treeElement = document.createElement('pre');
treeElement.id = id + ':' + type;
}
- treeElement.textContent = data[type];
+ const dataSplitByLine = data[type].split(/\n/);
+ for (let i = 0; i < dataSplitByLine.length; i++) {
+ const lineElement = document.createElement('div');
+ lineElement.textContent = dataSplitByLine[i];
+ treeElement.appendChild(lineElement);
+ }
return treeElement;
}
diff --git a/chromium/chrome/browser/resources/app_management/BUILD.gn b/chromium/chrome/browser/resources/app_management/BUILD.gn
deleted file mode 100644
index 05147eec84f..00000000000
--- a/chromium/chrome/browser/resources/app_management/BUILD.gn
+++ /dev/null
@@ -1,276 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-import("../optimize_webui.gni")
-
-if (!is_android) {
- js_type_check("closure_compile") {
- deps = [
- ":actions",
- ":api_listener",
- ":app",
- ":app_item",
- ":arc_permission_view",
- ":browser_proxy",
- ":chrome_app_permission_view",
- ":constants",
- ":dom_switch",
- ":expandable_app_list",
- ":fake_page_handler",
- ":main_view",
- ":metadata_view",
- ":notifications_view",
- ":permission_item",
- ":permission_toggle",
- ":permission_view_header",
- ":pin_to_shelf_item",
- ":pwa_permission_view",
- ":reducers",
- ":router",
- ":search_view",
- ":store",
- ":store_client",
- ":toggle_row",
- ":types",
- ":util",
- ]
- }
-
- js_library("actions") {
- deps = [
- "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile",
- "//ui/webui/resources/js:cr",
- ]
- }
-
- js_library("api_listener") {
- deps = [
- ":actions",
- ":store",
- ":util",
- "//ui/webui/resources/js:cr",
- ]
- }
-
- js_library("app") {
- deps = [
- ":actions",
- ":arc_permission_view",
- ":browser_proxy",
- ":constants",
- ":dom_switch",
- ":main_view",
- ":metadata_view",
- ":pwa_permission_view",
- ":router",
- ":store",
- ":store_client",
- ":types",
- ":util",
- "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile",
- "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar",
- "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar_search_field",
- ]
- }
-
- js_library("app_item") {
- deps = [
- ":actions",
- ":store_client",
- "//ui/webui/resources/js:load_time_data",
- ]
- }
-
- js_library("arc_permission_view") {
- deps = [
- ":constants",
- ":fake_page_handler",
- ":metadata_view",
- ":permission_item",
- ":permission_view_header",
- ":pin_to_shelf_item",
- ":store_client",
- ]
- }
-
- js_library("browser_proxy") {
- deps = [
- ":fake_page_handler",
- "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile",
- "//ui/webui/resources/js:cr",
- ]
- }
-
- js_library("chrome_app_permission_view") {
- deps = [
- ":fake_page_handler",
- ":metadata_view",
- ":permission_view_header",
- ":pin_to_shelf_item",
- ":store_client",
- ]
- }
-
- js_library("constants") {
- }
-
- js_library("dom_switch") {
- }
-
- js_library("expandable_app_list") {
- deps = [
- ":app_item",
- ":constants",
- ":store_client",
- "//third_party/polymer/v1_0/components-chromium/iron-collapse:iron-collapse-extracted",
- ]
- }
-
- js_library("fake_page_handler") {
- deps = [
- ":constants",
- ":types",
- ":util",
- "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile",
- "//ui/webui/resources/js:cr",
- ]
- }
-
- js_library("main_view") {
- deps = [
- ":app_item",
- ":browser_proxy",
- ":constants",
- ":store_client",
- "//ui/webui/resources/js:load_time_data",
- ]
- }
-
- js_library("metadata_view") {
- deps = [
- ":browser_proxy",
- ":constants",
- ":fake_page_handler",
- ":store_client",
- ":types",
- ]
- }
-
- js_library("notifications_view") {
- deps = [
- ":app_item",
- ":constants",
- ":fake_page_handler",
- ":store_client",
- ":util",
- ]
- }
-
- js_library("permission_item") {
- deps = [
- ":fake_page_handler",
- ":permission_toggle",
- ":store_client",
- ":util",
- ]
- }
-
- js_library("permission_toggle") {
- deps = [
- ":util",
- ]
- }
-
- js_library("permission_view_header") {
- deps = [
- ":browser_proxy",
- ":store_client",
- ]
- }
-
- js_library("pin_to_shelf_item") {
- deps = [
- ":browser_proxy",
- ":toggle_row",
- ":types",
- ]
- }
-
- js_library("pwa_permission_view") {
- deps = [
- ":constants",
- ":fake_page_handler",
- ":metadata_view",
- ":permission_item",
- ":permission_view_header",
- ":pin_to_shelf_item",
- ":store_client",
- ]
- }
-
- js_library("reducers") {
- deps = [
- ":types",
- ":util",
- "//ui/webui/resources/js:cr",
- ]
- }
-
- js_library("router") {
- deps = [
- ":actions",
- ":constants",
- ":store_client",
- ]
- }
-
- js_library("search_view") {
- deps = [
- ":app_item",
- ":store_client",
- "//ui/webui/resources/js:load_time_data",
- ]
- }
-
- js_library("store") {
- deps = [
- ":reducers",
- ":util",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js/cr/ui:store",
- ]
- }
-
- js_library("store_client") {
- deps = [
- ":store",
- ":types",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js/cr/ui:store",
- "//ui/webui/resources/js/cr/ui:store_client",
- ]
- }
-
- js_library("toggle_row") {
- deps = [
- ":types",
- "//ui/webui/resources/cr_elements/cr_toggle:cr_toggle",
- ]
- }
-
- js_library("types") {
- deps = [
- "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile",
- ]
- }
-
- js_library("util") {
- deps = [
- ":constants",
- ":types",
- "//ui/webui/resources/js:cr",
- ]
- }
-}
diff --git a/chromium/chrome/browser/resources/app_management/OWNERS b/chromium/chrome/browser/resources/app_management/OWNERS
deleted file mode 100644
index 94b2e07d850..00000000000
--- a/chromium/chrome/browser/resources/app_management/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-dominickn@chromium.org
-jshikaram@chromium.org
-
-# COMPONENT: Platform>Apps>Foundation
diff --git a/chromium/chrome/browser/resources/app_management/app.html b/chromium/chrome/browser/resources/app_management/app.html
deleted file mode 100644
index c532a44fd23..00000000000
--- a/chromium/chrome/browser/resources/app_management/app.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="actions.html">
-<link rel="import" href="arc_detail_view.html">
-<link rel="import" href="browser_proxy.html">
-<link rel="import" href="chrome_app_detail_view.html">
-<link rel="import" href="dom_switch.html">
-<link rel="import" href="main_view.html">
-<link rel="import" href="notifications_view.html">
-<link rel="import" href="pwa_detail_view.html">
-<link rel="import" href="router.html">
-<link rel="import" href="search_view.html">
-<link rel="import" href="store.html">
-<link rel="import" href="store_client.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
-
-<link rel="import" href="api_listener.html">
-
-<dom-module id="app-management-app">
- <template>
- <style include="app-management-shared-css">
- :host {
- display: flex;
- flex-direction: column;
- font-size: var(--app-management-font-size);
- height: 100%;
- line-height: var(--app-management-line-height);
- overflow: hidden;
- }
-
- #main-container {
- flex: 1;
- overflow: auto;
- padding: 0 40px;
- }
- </style>
- <cr-toolbar
- page-name="$i18n{title}"
- search-prompt="$i18n{searchPrompt}"
- on-search-changed="onSearchChanged_">
- </cr-toolbar>
- <div id="main-container">
- <app-management-dom-switch id="view-selector"
- route="[[selectedRouteId_(currentPage_, searchTerm_)]]">
- <template>
- <app-management-main-view route-id="main-view">
- </app-management-main-view>
- <app-management-notifications-view route-id="notifications-view">
- </app-management-notifications-view>
- <app-management-pwa-detail-view route-id="pwa-detail-view">
- </app-management-pwa-detail-view>
- <app-management-chrome-app-detail-view
- route-id="chrome-app-detail-view">
- </app-management-chrome-app-detail-view>
- <app-management-arc-detail-view route-id="arc-detail-view">
- </app-management-arc-detail-view>
- <app-management-search-view route-id="search-view">
- </app-management-search-view>
- </template>
- </app-management-dom-switch>
- </div>
- <app-management-router></app-management-router>
- </template>
- <script src="app.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/app_management/app.js b/chromium/chrome/browser/resources/app_management/app.js
deleted file mode 100644
index cdb4317219a..00000000000
--- a/chromium/chrome/browser/resources/app_management/app.js
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-Polymer({
- is: 'app-management-app',
-
- behaviors: [
- app_management.StoreClient,
- ],
-
- properties: {
- /** @private */
- searchTerm_: {
- type: String,
- observer: 'onSearchTermChanged_',
- },
-
- /**
- * @private {Page}
- */
- currentPage_: {
- type: Object,
- },
- },
-
- /**
- * @override
- */
- attached: function() {
- this.watch('searchTerm_', function(state) {
- return state.search.term;
- });
- this.watch('currentPage_', state => state.currentPage);
- this.updateFromStore();
- },
-
- /** @return {CrToolbarSearchFieldElement} */
- get searchField() {
- return /** @type {CrToolbarElement} */ (this.$$('cr-toolbar'))
- .getSearchField();
- },
-
-
- /** @private */
- onSearchTermChanged_: function() {
- this.searchField.setValue(this.searchTerm_ || '');
- },
-
- /**
- * @param {Event} e
- * @private
- */
- onSearchChanged_: function(e) {
- const searchTerm = /** @type {string} */ (e.detail);
- if (searchTerm != this.searchTerm_) {
- this.dispatch(app_management.actions.setSearchTerm(searchTerm));
- }
- },
-
- /**
- * @param {Page} currentPage
- * @param {String} searchTerm
- * @private
- */
- selectedRouteId_: function(currentPage, searchTerm) {
- if (searchTerm) {
- return 'search-view';
- }
- // This is to prevent console error caused by currentPage being undefined.
- if (currentPage) {
- switch (currentPage.pageType) {
- case (PageType.MAIN):
- return 'main-view';
-
- case (PageType.NOTIFICATIONS):
- return 'notifications-view';
-
- case (PageType.DETAIL):
- const state = this.getState();
- const selectedAppType =
- state.apps[assert(state.currentPage.selectedAppId)].type;
- switch (selectedAppType) {
- case (AppType.kWeb):
- return 'pwa-detail-view';
- case (AppType.kExtension):
- return 'chrome-app-detail-view';
- case (AppType.kArc):
- return 'arc-detail-view';
- default:
- assertNotReached();
- }
-
- default:
- assertNotReached();
- }
- }
- },
-});
diff --git a/chromium/chrome/browser/resources/app_management/expandable_app_list.html b/chromium/chrome/browser/resources/app_management/expandable_app_list.html
deleted file mode 100644
index 189b4c08822..00000000000
--- a/chromium/chrome/browser/resources/app_management/expandable_app_list.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="app_item.html">
-<link rel="import" href="constants.html">
-<link rel="import" href="shared_style.html">
-<link rel="import" href="store_client.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
-
-<dom-module id="app-management-expandable-app-list">
- <template>
- <style include="app-management-shared-css cr-shared-style">
- #app-list-header {
- align-items: center;
- display: flex;
- padding: 16px 12px;
- }
-
- #app-list-title {
- margin-inline-start: 12px;
- }
-
- #collapse {
- display: block;
- min-height: var(--collapsed-height);
- overflow: hidden;
- }
- </style>
- <div class="card-container">
- <div id="app-list-header">
- <div id="app-list-title" class="cr-title-text header-text">
- [[listTitle]]
- </div>
- </div>
- <iron-collapse id="collapse">
- <slot></slot>
- </iron-collapse>
-
- <div id="expander-row" class="expander-list-row"
- on-click="toggleListExpanded_">
- <span>[[moreAppsString_(apps.length, listExpanded_)]]</span>
- <cr-icon-button class="expand-button"
- iron-icon="[[getCollapsedIcon_(listExpanded_)]]"></cr-icon-button>
- </div>
- </div>
- </template>
- <script src="expandable_app_list.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/app_management/expandable_app_list.js b/chromium/chrome/browser/resources/app_management/expandable_app_list.js
deleted file mode 100644
index c7a6f4b93ac..00000000000
--- a/chromium/chrome/browser/resources/app_management/expandable_app_list.js
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * This is an expanding container for a list of apps that shows some items by
- * default and can be expanded to show more.
- *
- * Note: The implementation assumes children are all the same height.
- *
- * Example usage:
- * <app-management-expandable-app-list apps="[[appsList]]">
- * <template is="dom-repeat" items="[[appsList]]" as="app" notify-dom-change>
- * <app-management-app-item app="[[app]]"></app-management-app-item>
- * </template>
- * </app-management-expandable-app-list>
- */
-Polymer({
- is: 'app-management-expandable-app-list',
-
- properties: {
- /**
- * Title of the expandable list.
- * @type {String}
- */
- listTitle: {
- type: String,
- value: '',
- observer: 'onListTitleChanged_',
- },
-
- /** The number of apps to collapse down to. */
- collapsedSize: {
- type: Number,
- value: NUMBER_OF_APPS_DISPLAYED_DEFAULT,
- },
-
- /** @private {boolean} */
- listExpanded_: {
- type: Boolean,
- observer: 'onListExpandedChanged_',
- },
-
- /** @private {number} */
- numChildrenForTesting_: {
- type: Number,
- value: 0,
- notify: true,
- },
- },
-
- listeners: {
- 'dom-change': 'onDomChange_',
- },
-
- attached: function() {
- // Hide on reattach.
- this.listExpanded_ = false;
- this.$.collapse.hide();
- },
-
- /** @private */
- onAppsChanged_: function(change) {},
-
- /** @private */
- onListTitleChanged_() {
- this.$['app-list-title'].hidden = !this.listTitle;
- },
-
- /** @private */
- onDomChange_: function() {
- let collapsedHeight = 0;
- let numChildren = 0;
- for (const child of this.$.collapse.getContentChildren()) {
- // Wait until we have an actual child element rather than just the
- // dom-repeat.
- if (child.tagName == 'DOM-REPEAT' || child.tagName == 'TEMPLATE') {
- continue;
- }
-
- if (numChildren < this.collapsedSize) {
- collapsedHeight += child.offsetHeight;
- }
-
- numChildren++;
- }
-
- this.style.setProperty(
- '--collapsed-height', String(collapsedHeight) + 'px');
- this.$['expander-row'].hidden = numChildren <= this.collapsedSize;
- this.numChildrenForTesting_ = numChildren;
- },
-
- /** @private */
- toggleListExpanded_: function() {
- this.listExpanded_ = !this.listExpanded_;
- },
-
- /** @private */
- onListExpandedChanged_() {
- // TODO(calamity): Hiding should display:none after the animation to prevent
- // tabbing into hidden items.
- const collapse = this.$.collapse;
- // Since iron-collapse does not support a 'min-height' property, we force it
- // to animate to the collapsed height.
- if (this.listExpanded_) {
- // Reset the opened state, or show won't work.
- collapse.hide();
- collapse.show();
- } else {
- // This technically leaves the collapse open.
- collapse.updateSize('var(--collapsed-height)', true);
- }
- },
-
- /**
- * @param {boolean} listExpanded
- * @return {string}
- * @private
- */
- getCollapsedIcon_: function(listExpanded) {
- return listExpanded ? 'cr:expand-less' : 'cr:expand-more';
- },
-
- /**
- * @param {number} numApps
- * @param {boolean} listExpanded
- * @return {string}
- * @private
- */
- moreAppsString_: function(numApps, listExpanded) {
- return listExpanded ?
- loadTimeData.getString('lessApps') :
- loadTimeData.getStringF('moreApps', numApps - this.collapsedSize);
- },
-});
diff --git a/chromium/chrome/browser/resources/app_management/index.html b/chromium/chrome/browser/resources/app_management/index.html
deleted file mode 100644
index ccdca6ef60c..00000000000
--- a/chromium/chrome/browser/resources/app_management/index.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!doctype html>
-<html dir="$i18n{textdirection}" lang="$i18n{language}">
-<head>
- <meta charset="utf8">
- <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
- <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
- <style>
- html {
- /* Remove 300ms delay for 'click' event, when using touch interface. */
- touch-action: manipulation;
- }
-
- html,
- body {
- background: var(--md-background-color);
- height: 100%;
- margin: 0;
- }
- </style>
-</head>
-<body>
- <app-management-app></app-management-app>
- <script src="chrome://resources/js/load_time_data.js"></script>
- <script src="strings.js"></script>
- <link rel="import" href="app.html">
-</body>
-</html>
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/BUILD.gn b/chromium/chrome/browser/resources/bluetooth_internals/BUILD.gn
index da87186b5e3..ebe9b736436 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/bluetooth_internals/BUILD.gn
@@ -6,9 +6,7 @@ import("//third_party/closure_compiler/compile_js.gni")
import("//tools/grit/grit_rule.gni")
js_type_check("closure_compile") {
- deps = [
- ":bluetooth_internals",
- ]
+ deps = [ ":bluetooth_internals" ]
}
js_library("bluetooth_internals") {
@@ -46,9 +44,7 @@ js_library("bluetooth_internals") {
}
js_library("node_utils") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("page") {
@@ -73,8 +69,6 @@ js_library("page_manager") {
grit("resources") {
source = "resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
outputs = [
"grit/bluetooth_internals_resources.h",
"grit/bluetooth_internals_resources_map.h",
@@ -82,12 +76,9 @@ grit("resources") {
"bluetooth_internals_resources.pak",
]
output_dir = "$root_gen_dir/chrome"
- depfile_dir = target_gen_dir
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
- deps = [
- "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings_js",
- ]
+ deps = [ "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings_js" ]
}
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js b/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js
index e146a8e1746..c3e111afb89 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/bluetooth_internals.js
@@ -52,7 +52,7 @@ cr.define('bluetooth_internals', function() {
PageObserver.prototype = {
__proto__: PageManager.Observer.prototype,
- updateHistory: function(path) {
+ updateHistory(path) {
window.location.hash = '#' + path;
},
@@ -61,7 +61,7 @@ cr.define('bluetooth_internals', function() {
* @override
* @param {string} title
*/
- updateTitle: function(title) {
+ updateTitle(title) {
document.querySelector('.page-title').textContent = title;
},
};
@@ -110,11 +110,6 @@ cr.define('bluetooth_internals', function() {
$('page-container').appendChild(pageSection);
deviceDetailsPage = new DeviceDetailsPage(deviceDetailsPageId, deviceInfo);
- deviceDetailsPage.pageDiv.addEventListener(
- 'connectionchanged', function(event) {
- devices.updateConnectionStatus(
- event.detail.address, event.detail.status);
- });
deviceDetailsPage.pageDiv.addEventListener('infochanged', function(event) {
devices.addOrUpdate(event.detail.info);
@@ -176,7 +171,11 @@ cr.define('bluetooth_internals', function() {
adapterPage.pageDiv.addEventListener('refreshpressed', function() {
adapterBroker.getInfo().then(function(response) {
- adapterPage.setAdapterInfo(response.info);
+ if (response && response.info) {
+ adapterPage.setAdapterInfo(response.info);
+ } else {
+ console.error('Failed to fetch adapter info.');
+ }
});
});
}
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js b/chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js
index 2ae6a000a43..741975b9ac1 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/characteristic_list.js
@@ -73,7 +73,7 @@ cr.define('characteristic_list', function() {
* two fieldsets for displaying property values.
* @override
*/
- decorate: function() {
+ decorate() {
this.classList.add('characteristic-list-item');
/** @private {!object_fieldset.ObjectFieldSet} */
@@ -187,7 +187,7 @@ cr.define('characteristic_list', function() {
},
/** @override */
- onExpandInternal: function(expanded) {
+ onExpandInternal(expanded) {
this.descriptorList_.load(
this.deviceAddress_, this.serviceId_, this.info.id);
},
@@ -204,7 +204,7 @@ cr.define('characteristic_list', function() {
__proto__: ExpandableList.prototype,
/** @override */
- decorate: function() {
+ decorate() {
ExpandableList.prototype.decorate.call(this);
/** @private {?string} */
@@ -218,7 +218,7 @@ cr.define('characteristic_list', function() {
this.setEmptyMessage('No Characteristics Found');
},
- createItem: function(data) {
+ createItem(data) {
return new CharacteristicListItem(
data, assert(this.deviceAddress_), assert(this.serviceId_));
},
@@ -230,7 +230,7 @@ cr.define('characteristic_list', function() {
* @param {string} deviceAddress
* @param {string} serviceId
*/
- load: function(deviceAddress, serviceId) {
+ load(deviceAddress, serviceId) {
if (this.characteristicsRequested_ || !this.isSpinnerShowing()) {
return;
}
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js b/chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js
index c158d38cf0c..84c2ed8fb5b 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/descriptor_list.js
@@ -57,7 +57,7 @@ cr.define('descriptor_list', function() {
* a fieldset for displaying property values.
* @override
*/
- decorate: function() {
+ decorate() {
this.classList.add('descriptor-list-item');
/** @private {!object_fieldset.ObjectFieldSet} */
@@ -122,7 +122,7 @@ cr.define('descriptor_list', function() {
__proto__: ExpandableList.prototype,
/** @override */
- decorate: function() {
+ decorate() {
ExpandableList.prototype.decorate.call(this);
/** @private {?string} */
@@ -138,7 +138,7 @@ cr.define('descriptor_list', function() {
this.setEmptyMessage('No Descriptors Found');
},
- createItem: function(data) {
+ createItem(data) {
return new DescriptorListItem(
data, assert(this.deviceAddress_), assert(this.serviceId_),
assert(this.characteristicId_));
@@ -153,7 +153,7 @@ cr.define('descriptor_list', function() {
* @param {string} serviceId
* @param {string} characteristicId
*/
- load: function(deviceAddress, serviceId, characteristicId) {
+ load(deviceAddress, serviceId, characteristicId) {
if (this.descriptorsRequested_ || !this.isSpinnerShowing()) {
return;
}
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/device_collection.js b/chromium/chrome/browser/resources/bluetooth_internals/device_collection.js
index 15ab49af962..34f06dc7b07 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/device_collection.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/device_collection.js
@@ -9,10 +9,7 @@
cr.define('device_collection', function() {
/**
- * Enum of connection status for a device. Used for
- * DeviceCollection.updateConnectionStatus which sets the connectionStatus
- * on the DeviceInfo object. New DeviceInfo objects have a DISCONNECTED status
- * by default.
+ * Enum of connection status for a device.
* @enum {number}
*/
const ConnectionStatus = {
@@ -32,6 +29,11 @@ cr.define('device_collection', function() {
*/
constructor(array) {
super(array);
+
+ // Keep track of MAC addresses which were previously found via scan, but
+ // are no longer being advertised or nearby. Used to inform isRemoved().
+ /** @private {!Object<string, boolean>} */
+ this.removedDevices_ = {};
}
/**
@@ -53,7 +55,7 @@ cr.define('device_collection', function() {
* @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
addOrUpdate(deviceInfo) {
- deviceInfo.removed = false;
+ this.removedDevices_[deviceInfo.address] = false;
const oldDeviceInfo = this.getByAddress(deviceInfo.address);
if (oldDeviceInfo) {
@@ -61,14 +63,11 @@ cr.define('device_collection', function() {
const rssi = (deviceInfo.rssi && deviceInfo.rssi.value) ||
(oldDeviceInfo.rssi && oldDeviceInfo.rssi.value);
- // The connectionStatus and connectionMessage properties may not exist
- // on |deviceInfo|. The rssi property may be null, so it must be
- // re-assigned.
+ // The rssi property may be null, so it must be re-assigned.
Object.assign(oldDeviceInfo, deviceInfo);
oldDeviceInfo.rssi = {value: rssi};
this.updateIndex(this.indexOf(oldDeviceInfo));
} else {
- deviceInfo.connectionStatus = ConnectionStatus.DISCONNECTED;
this.push(deviceInfo);
}
}
@@ -80,20 +79,17 @@ cr.define('device_collection', function() {
remove(deviceInfo) {
const device = this.getByAddress(deviceInfo.address);
assert(device, 'Device does not exist.');
- device.removed = true;
+ this.removedDevices_[deviceInfo.address] = true;
this.updateIndex(this.indexOf(device));
}
/**
- * Updates the device connection status.
- * @param {string} address The address of the device.
- * @param {number} status The new connection status.
+ * Return true if device was "removed" -- previously found via scan but
+ * either no longer advertising or no longer nearby.
+ * @param {!bluetooth.mojom.DeviceInfo} deviceInfo
*/
- updateConnectionStatus(address, status) {
- const device =
- assert(this.getByAddress(address), 'Device does not exist');
- device.connectionStatus = status;
- this.updateIndex(this.indexOf(device));
+ isRemoved(deviceInfo) {
+ return !!this.removedDevices_[deviceInfo.address];
}
}
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/device_table.js b/chromium/chrome/browser/resources/bluetooth_internals/device_table.js
index 91ca24e220e..704e1de492d 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/device_table.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/device_table.js
@@ -38,7 +38,7 @@ cr.define('device_table', function() {
* Decorates an element as a UI element class. Caches references to the
* table body and headers.
*/
- decorate: function() {
+ decorate() {
/** @private */
this.body_ = this.tBodies[0];
/** @private */
@@ -51,7 +51,7 @@ cr.define('device_table', function() {
* Sets the tables device collection.
* @param {!device_collection.DeviceCollection} deviceCollection
*/
- setDevices: function(deviceCollection) {
+ setDevices(deviceCollection) {
assert(!this.devices_, 'Devices can only be set once.');
this.devices_ = deviceCollection;
@@ -69,7 +69,7 @@ cr.define('device_table', function() {
* @param {!bluetooth.mojom.DeviceInfo} deviceInfo
* @param {boolean} isInspecting
*/
- setInspecting: function(deviceInfo, isInspecting) {
+ setInspecting(deviceInfo, isInspecting) {
this.inspectionMap_.set(deviceInfo, isInspecting);
this.updateRow_(deviceInfo, this.devices_.indexOf(deviceInfo));
},
@@ -79,7 +79,7 @@ cr.define('device_table', function() {
* @param {number} index
* @private
*/
- handleForgetClick_: function(index) {
+ handleForgetClick_(index) {
const event = new CustomEvent('forgetpressed', {
bubbles: true,
detail: {
@@ -94,7 +94,7 @@ cr.define('device_table', function() {
* @param {!Event} event
* @private
*/
- handleChange_: function(event) {
+ handleChange_(event) {
this.updateRow_(this.devices_.item(event.index), event.index);
},
@@ -103,7 +103,7 @@ cr.define('device_table', function() {
* @param {number} index
* @private
*/
- handleInspectClick_: function(index) {
+ handleInspectClick_(index) {
const event = new CustomEvent('inspectpressed', {
bubbles: true,
detail: {
@@ -118,7 +118,7 @@ cr.define('device_table', function() {
* @param {!Event} event
* @private
*/
- handleSplice_: function(event) {
+ handleSplice_(event) {
event.removed.forEach(function() {
this.body_.deleteRow(event.index);
}, this);
@@ -134,7 +134,7 @@ cr.define('device_table', function() {
* @param {?number} index
* @private
*/
- insertRow_: function(device, index) {
+ insertRow_(device, index) {
const row = this.body_.insertRow(index);
row.id = device.address;
@@ -170,7 +170,7 @@ cr.define('device_table', function() {
* Deletes and recreates the table using the cached |devices_|.
* @private
*/
- redraw_: function() {
+ redraw_() {
this.removeChild(this.body_);
this.appendChild(document.createElement('tbody'));
this.body_ = this.tBodies[0];
@@ -187,11 +187,11 @@ cr.define('device_table', function() {
* @param {number} index
* @private
*/
- updateRow_: function(device, index) {
+ updateRow_(device, index) {
const row = this.body_.rows[index];
assert(row, 'Row ' + index + ' is not in the table.');
- row.classList.toggle('removed', device.removed);
+ row.classList.toggle('removed', this.devices_.isRemoved(device));
const forgetLink = row.cells[COLUMNS.LINKS].children[1];
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/expandable_list.js b/chromium/chrome/browser/resources/bluetooth_internals/expandable_list.js
index e9dcc731f97..04dd60af6cd 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/expandable_list.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/expandable_list.js
@@ -27,7 +27,7 @@ cr.define('expandable_list', function() {
* content holders for implementations.
* @override
*/
- decorate: function() {
+ decorate() {
this.classList.add('expandable-list-item');
this.briefContent_ = document.createElement('div');
this.briefContent_.classList.add('brief-content');
@@ -43,13 +43,13 @@ cr.define('expandable_list', function() {
* Called when the list item is expanded or collapsed.
* @param {boolean} expanded
*/
- onExpandInternal: function(expanded) {},
+ onExpandInternal(expanded) {},
/**
* Toggles the expanded class on the item.
* @private
*/
- onExpand_: function() {
+ onExpand_() {
this.onExpandInternal(this.classList.toggle('expanded'));
},
};
@@ -69,7 +69,7 @@ cr.define('expandable_list', function() {
* elements.
* @override
*/
- decorate: function() {
+ decorate() {
List.prototype.decorate.call(this);
this.classList.add('expandable-list');
@@ -91,7 +91,7 @@ cr.define('expandable_list', function() {
* Sets the data model of the list.
* @param {cr.ui.ArrayDataModel} data
*/
- setData: function(data) {
+ setData(data) {
if (this.dataModel) {
this.dataModel.removeEventListener('splice', this.boundUpdateMessage_);
}
@@ -105,7 +105,7 @@ cr.define('expandable_list', function() {
* Sets the empty message text.
* @param {string} message
*/
- setEmptyMessage: function(message) {
+ setEmptyMessage(message) {
this.emptyMessage_.textContent = message;
},
@@ -114,7 +114,7 @@ cr.define('expandable_list', function() {
* spinner is dispayed.
* @param {boolean} showing
*/
- setSpinnerShowing: function(showing) {
+ setSpinnerShowing(showing) {
this.spinner_.hidden = !showing;
},
@@ -122,7 +122,7 @@ cr.define('expandable_list', function() {
* Gets the spinner display state. Returns true if the spinner is showing.
* @return {boolean}
*/
- isSpinnerShowing: function() {
+ isSpinnerShowing() {
return !this.spinner_.hidden;
},
@@ -130,7 +130,7 @@ cr.define('expandable_list', function() {
* Updates the display state of the empty message. If there are no items in
* the data model, the empty message is displayed.
*/
- updateMessageDisplay_: function() {
+ updateMessageDisplay_() {
this.emptyMessage_.hidden = this.dataModel.length > 0;
},
};
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/object_fieldset.js b/chromium/chrome/browser/resources/bluetooth_internals/object_fieldset.js
index baf0f50c719..3e8991c59a0 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/object_fieldset.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/object_fieldset.js
@@ -37,7 +37,7 @@ cr.define('object_fieldset', function() {
/**
* Decorates the element as an ObjectFieldset.
*/
- decorate: function() {
+ decorate() {
this.classList.add('object-fieldset');
/** @type {?Object} */
@@ -51,7 +51,7 @@ cr.define('object_fieldset', function() {
* Sets the object data to be displayed in the fieldset.
* @param {!Object} value
*/
- setObject: function(value) {
+ setObject(value) {
this.value = value;
this.redraw();
},
@@ -61,14 +61,14 @@ cr.define('object_fieldset', function() {
* name is not provided, the default property name will be used.
* @param {!Object<string, string>} nameMap
*/
- setPropertyDisplayNames: function(nameMap) {
+ setPropertyDisplayNames(nameMap) {
this.nameMap_ = nameMap;
},
/**
* Deletes and recreates the table structure with current object data.
*/
- redraw: function() {
+ redraw() {
this.innerHTML = '';
Object.keys(assert(this.value)).forEach(function(propName) {
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/page_manager.js b/chromium/chrome/browser/resources/bluetooth_internals/page_manager.js
index bca2b6dbb76..c09879fb2cb 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/page_manager.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/page_manager.js
@@ -50,7 +50,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {cr.ui.pageManager.Page} defaultPage The page to be shown when no
* page is specified in the path.
*/
- initialize: function(defaultPage) {
+ initialize(defaultPage) {
this.defaultPage_ = defaultPage;
cr.ui.FocusOutlineManager.forDocument(document);
@@ -76,7 +76,7 @@ cr.define('cr.ui.pageManager', function() {
* Registers new page.
* @param {!cr.ui.pageManager.Page} page Page to register.
*/
- register: function(page) {
+ register(page) {
this.registeredPages[page.name.toLowerCase()] = page;
page.initializePage();
},
@@ -85,7 +85,7 @@ cr.define('cr.ui.pageManager', function() {
* Unregisters an existing page.
* @param {!cr.ui.pageManager.Page} page Page to unregister.
*/
- unregister: function(page) {
+ unregister(page) {
delete this.registeredPages[page.name.toLowerCase()];
},
@@ -97,7 +97,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {Array} associatedControls Array of control elements associated
* with this page.
*/
- registerOverlay: function(overlay, parentPage, associatedControls) {
+ registerOverlay(overlay, parentPage, associatedControls) {
this.registeredOverlayPages[overlay.name.toLowerCase()] = overlay;
overlay.parentPage = parentPage;
if (associatedControls) {
@@ -125,7 +125,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {boolean=} opt_updateHistory If we should update the history after
* showing the page (defaults to true).
*/
- showDefaultPage: function(opt_updateHistory) {
+ showDefaultPage(opt_updateHistory) {
assert(
this.defaultPage_ instanceof cr.ui.pageManager.Page,
'PageManager must be initialized with a default page.');
@@ -141,7 +141,7 @@ cr.define('cr.ui.pageManager', function() {
* replaceState (if history state should be replaced instead of pushed).
* hash (a hash state to attach to the page).
*/
- showPageByName: function(pageName, opt_updateHistory, opt_propertyBag) {
+ showPageByName(pageName, opt_updateHistory, opt_propertyBag) {
opt_updateHistory = opt_updateHistory !== false;
opt_propertyBag = opt_propertyBag || {};
@@ -234,7 +234,7 @@ cr.define('cr.ui.pageManager', function() {
* Returns the name of the page from the current path.
* @return {string} Name of the page specified by the current path.
*/
- getPageNameFromPath: function() {
+ getPageNameFromPath() {
const path = location.pathname;
if (path.length <= 1) {
return this.defaultPage_.name;
@@ -249,7 +249,7 @@ cr.define('cr.ui.pageManager', function() {
* level 0.
* @return {number} How far down this page is from the root page.
*/
- getNestingLevel: function(page) {
+ getNestingLevel(page) {
let level = 0;
let parent = page.parentPage;
while (parent) {
@@ -267,7 +267,7 @@ cr.define('cr.ui.pageManager', function() {
* @return {boolean} True if |potentialDescendent| is nested under
* |potentialAncestor|.
*/
- isAncestorOfPage: function(potentialAncestor, potentialDescendent) {
+ isAncestorOfPage(potentialAncestor, potentialDescendent) {
let parent = potentialDescendent.parentPage;
while (parent) {
if (parent == potentialAncestor) {
@@ -284,7 +284,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {cr.ui.pageManager.Page} page Page to check.
* @return {boolean} True if |page| is a top-level overlay.
*/
- isTopLevelOverlay: function(page) {
+ isTopLevelOverlay(page) {
return page.isOverlay &&
(page.alwaysOnTop || this.getNestingLevel(page) == 1);
},
@@ -295,7 +295,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {cr.ui.pageManager.Page} page The page being made visible or
* invisible.
*/
- onPageVisibilityChanged: function(page) {
+ onPageVisibilityChanged(page) {
this.updateRootPageFreezeState();
for (let i = 0; i < this.observers_.length; ++i) {
@@ -312,7 +312,7 @@ cr.define('cr.ui.pageManager', function() {
* page, the history state is updated.
* @param {cr.ui.pageManager.Page} page The page whose hash has changed.
*/
- onPageHashChanged: function(page) {
+ onPageHashChanged(page) {
if (page == this.getTopmostVisiblePage()) {
this.updateHistoryState_(false);
}
@@ -322,7 +322,7 @@ cr.define('cr.ui.pageManager', function() {
* Returns the topmost visible page, or null if no page is visible.
* @return {cr.ui.pageManager.Page} The topmost visible page.
*/
- getTopmostVisiblePage: function() {
+ getTopmostVisiblePage() {
// Check overlays first since they're top-most if visible.
return this.getVisibleOverlay_() ||
this.getTopmostVisibleNonOverlayPage_();
@@ -332,7 +332,7 @@ cr.define('cr.ui.pageManager', function() {
* Closes the visible overlay. Updates the history state after closing the
* overlay.
*/
- closeOverlay: function() {
+ closeOverlay() {
const overlay = this.getVisibleOverlay_();
if (!overlay) {
return;
@@ -350,7 +350,7 @@ cr.define('cr.ui.pageManager', function() {
/**
* Closes all overlays and updates the history after each closed overlay.
*/
- closeAllOverlays: function() {
+ closeAllOverlays() {
while (this.isOverlayVisible_()) {
this.closeOverlay();
}
@@ -359,7 +359,7 @@ cr.define('cr.ui.pageManager', function() {
/**
* Cancels (closes) the overlay, due to the user pressing <Esc>.
*/
- cancelOverlay: function() {
+ cancelOverlay() {
// Blur the active element to ensure any changed pref value is saved.
document.activeElement.blur();
const overlay = this.getVisibleOverlay_();
@@ -385,7 +385,7 @@ cr.define('cr.ui.pageManager', function() {
* added to the DOM.
* @param {cr.ui.ArrowLocation} location The arrow location.
*/
- showBubble: function(content, target, domSibling, location) {
+ showBubble(content, target, domSibling, location) {
this.hideBubble();
const bubble = new cr.ui.AutoCloseBubble;
@@ -400,7 +400,7 @@ cr.define('cr.ui.pageManager', function() {
/**
* Hides the currently visible bubble, if any.
*/
- hideBubble: function() {
+ hideBubble() {
if (this.bubble_) {
this.bubble_.hide();
}
@@ -410,7 +410,7 @@ cr.define('cr.ui.pageManager', function() {
* Returns the currently visible bubble, or null if no bubble is visible.
* @return {cr.ui.AutoCloseBubble} The bubble currently being shown.
*/
- getVisibleBubble: function() {
+ getVisibleBubble() {
const bubble = this.bubble_;
return bubble && !bubble.hidden ? bubble : null;
},
@@ -421,7 +421,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {string} hash The hash to pass into the page.
* @param {Object} data State data pushed into history.
*/
- setState: function(pageName, hash, data) {
+ setState(pageName, hash, data) {
const currentOverlay = this.getVisibleOverlay_();
const lowercaseName = pageName.toLowerCase();
const newPage = this.registeredPages[lowercaseName] ||
@@ -438,7 +438,7 @@ cr.define('cr.ui.pageManager', function() {
* Whether the page is still loading (i.e. onload hasn't finished running).
* @return {boolean} Whether the page is still loading.
*/
- isLoading: function() {
+ isLoading() {
return document.documentElement.classList.contains('loading');
},
@@ -446,7 +446,7 @@ cr.define('cr.ui.pageManager', function() {
* Callback for window.onbeforeunload. Used to notify overlays that they
* will be closed.
*/
- willClose: function() {
+ willClose() {
const overlay = this.getVisibleOverlay_();
if (overlay) {
overlay.didClosePage();
@@ -457,7 +457,7 @@ cr.define('cr.ui.pageManager', function() {
* Freezes/unfreezes the scroll position of the root page based on the
* current page stack.
*/
- updateRootPageFreezeState: function() {
+ updateRootPageFreezeState() {
const topPage = this.getTopmostVisiblePage();
if (topPage) {
this.setRootPageFrozen_(topPage.isOverlay);
@@ -476,7 +476,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {!cr.ui.pageManager.PageManager.Observer} observer The observer to
* register.
*/
- addObserver: function(observer) {
+ addObserver(observer) {
this.observers_.push(observer);
},
@@ -489,7 +489,7 @@ cr.define('cr.ui.pageManager', function() {
* @return {boolean} Whether we showed an overlay.
* @private
*/
- showOverlay_: function(overlayName, hash, rootPage) {
+ showOverlay_(overlayName, hash, rootPage) {
const overlay = this.registeredOverlayPages[overlayName.toLowerCase()];
if (!overlay || !overlay.canShowPage()) {
return false;
@@ -543,7 +543,7 @@ cr.define('cr.ui.pageManager', function() {
* @return {boolean} True if an overlay is visible.
* @private
*/
- isOverlayVisible_: function() {
+ isOverlayVisible_() {
return this.getVisibleOverlay_() != null;
},
@@ -552,7 +552,7 @@ cr.define('cr.ui.pageManager', function() {
* @return {cr.ui.pageManager.Page} The visible overlay.
* @private
*/
- getVisibleOverlay_: function() {
+ getVisibleOverlay_() {
let topmostPage = null;
for (const name in this.registeredOverlayPages) {
const page = this.registeredOverlayPages[name];
@@ -578,7 +578,7 @@ cr.define('cr.ui.pageManager', function() {
* overlays.
* @private
*/
- getTopmostVisibleNonOverlayPage_: function() {
+ getTopmostVisibleNonOverlayPage_() {
for (const name in this.registeredPages) {
const page = this.registeredPages[name];
if (page.visible) {
@@ -595,7 +595,7 @@ cr.define('cr.ui.pageManager', function() {
* becomes visible).
* @private
*/
- updateScrollPosition_: function() {
+ updateScrollPosition_() {
const container = $('page-container');
const scrollTop = container.oldScrollTop || 0;
container.oldScrollTop = undefined;
@@ -607,7 +607,7 @@ cr.define('cr.ui.pageManager', function() {
* visible page with a non-empty title.
* @private
*/
- updateTitle_: function() {
+ updateTitle_() {
let page = this.getTopmostVisiblePage();
while (page) {
if (page.title) {
@@ -627,7 +627,7 @@ cr.define('cr.ui.pageManager', function() {
* history event rather than create new ones.
* @private
*/
- updateHistoryState_: function(replace) {
+ updateHistoryState_(replace) {
if (this.isDialog) {
return;
}
@@ -655,7 +655,7 @@ cr.define('cr.ui.pageManager', function() {
* Restores the last focused element on a given page.
* @private
*/
- restoreLastFocusedElement_: function() {
+ restoreLastFocusedElement_() {
const currentPage = this.getTopmostVisiblePage();
if (!currentPage.lastFocusedElement) {
@@ -675,7 +675,7 @@ cr.define('cr.ui.pageManager', function() {
* @return {Node} The section element, or null.
* @private
*/
- findSectionForNode_: function(node) {
+ findSectionForNode_(node) {
while (node = node.parentNode) {
if (node.nodeName == 'SECTION') {
return node;
@@ -689,7 +689,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {boolean} freeze Whether the page should be frozen.
* @private
*/
- setRootPageFrozen_: function(freeze) {
+ setRootPageFrozen_(freeze) {
const container = $('page-container');
if (container.classList.contains('frozen') == freeze) {
return;
@@ -718,7 +718,7 @@ cr.define('cr.ui.pageManager', function() {
* but should only behave as if they are fixed for vertical scrolling.
* @private
*/
- handleScroll_: function() {
+ handleScroll_() {
this.updateAllFrozenElementPositions_();
},
@@ -726,7 +726,7 @@ cr.define('cr.ui.pageManager', function() {
* Updates all frozen pages to match the horizontal scroll position.
* @private
*/
- updateAllFrozenElementPositions_: function() {
+ updateAllFrozenElementPositions_() {
const frozenElements = document.querySelectorAll('.frozen');
for (let i = 0; i < frozenElements.length; i++) {
this.updateFrozenElementHorizontalPosition_(frozenElements[i]);
@@ -738,7 +738,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {HTMLElement} e The frozen element to update.
* @private
*/
- updateFrozenElementHorizontalPosition_: function(e) {
+ updateFrozenElementHorizontalPosition_(e) {
if (isRTL()) {
e.style.right = this.horizontalOffset + 'px';
} else {
@@ -754,7 +754,7 @@ cr.define('cr.ui.pageManager', function() {
* @param {function(cr.ui.pageManager.Page)} callback The callback.
* @private
*/
- forEachPage_: function(includeRootPages, callback) {
+ forEachPage_(includeRootPages, callback) {
let pageNames = Object.keys(this.registeredOverlayPages);
if (includeRootPages) {
pageNames = Object.keys(this.registeredPages).concat(pageNames);
@@ -779,20 +779,20 @@ cr.define('cr.ui.pageManager', function() {
* Called when a page is being shown or has been hidden.
* @param {cr.ui.pageManager.Page} page The page being shown or hidden.
*/
- onPageVisibilityChanged: function(page) {},
+ onPageVisibilityChanged(page) {},
/**
* Called when a new title should be set.
* @param {string} title The title to set.
*/
- updateTitle: function(title) {},
+ updateTitle(title) {},
/**
* Called when a page is navigated to.
* @param {string} path The path of the page being visited.
* @param {boolean} replace If true, allow no history events to be created.
*/
- updateHistory: function(path, replace) {},
+ updateHistory(path, replace) {},
};
// Export
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/service_list.js b/chromium/chrome/browser/resources/bluetooth_internals/service_list.js
index 3776681f6d5..ad9106d256f 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/service_list.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/service_list.js
@@ -56,7 +56,7 @@ cr.define('service_list', function() {
* references to the created header and fieldset.
* @override
*/
- decorate: function() {
+ decorate() {
this.classList.add('service-list-item');
/** @private {!object_fieldset.ObjectFieldSet} */
@@ -103,7 +103,7 @@ cr.define('service_list', function() {
},
/** @override */
- onExpandInternal: function(expanded) {
+ onExpandInternal(expanded) {
this.characteristicList_.load(this.deviceAddress_, this.info.id);
},
};
@@ -119,7 +119,7 @@ cr.define('service_list', function() {
__proto__: ExpandableList.prototype,
/** @override */
- decorate: function() {
+ decorate() {
ExpandableList.prototype.decorate.call(this);
/** @private {?string} */
@@ -132,7 +132,7 @@ cr.define('service_list', function() {
},
/** @override */
- createItem: function(data) {
+ createItem(data) {
return new ServiceListItem(data, assert(this.deviceAddress_));
},
@@ -142,7 +142,7 @@ cr.define('service_list', function() {
* exists, one is created.
* @param {string} deviceAddress
*/
- load: function(deviceAddress) {
+ load(deviceAddress) {
if (this.servicesRequested_ || !this.isSpinnerShowing()) {
return;
}
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/sidebar.js b/chromium/chrome/browser/resources/bluetooth_internals/sidebar.js
index 1739e717a96..abb3c3112e1 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/sidebar.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/sidebar.js
@@ -51,7 +51,7 @@ cr.define('sidebar', function() {
* Adds a new list item to the sidebar using the given |item|.
* @param {!SidebarItem} item
*/
- addItem: function(item) {
+ addItem(item) {
const sidebarItem = document.createElement('li');
sidebarItem.dataset.pageName = item.pageName.toLowerCase();
@@ -67,7 +67,7 @@ cr.define('sidebar', function() {
/**
* Closes the sidebar. Only applies to layouts with window width <= 600px.
*/
- close: function() {
+ close() {
this.sidebarDiv_.classList.remove('open');
document.body.style.overflow = '';
document.dispatchEvent(new CustomEvent('contentfocus'));
@@ -76,7 +76,7 @@ cr.define('sidebar', function() {
/**
* Opens the sidebar. Only applies to layouts with window width <= 600px.
*/
- open: function() {
+ open() {
document.body.style.overflow = 'hidden';
this.sidebarDiv_.classList.add('open');
document.dispatchEvent(new CustomEvent('contentblur'));
@@ -86,7 +86,7 @@ cr.define('sidebar', function() {
* Removes a sidebar item where |pageName| matches the item's pageName.
* @param {string} pageName
*/
- removeItem: function(pageName) {
+ removeItem(pageName) {
pageName = pageName.toLowerCase();
const query = 'li[data-page-name="' + pageName + '"]';
this.sidebarList_.removeChild(this.sidebarList_.querySelector(query));
@@ -97,7 +97,7 @@ cr.define('sidebar', function() {
* @override
* @param {string} path The path of the page being visited.
*/
- updateHistory: function(path) {
+ updateHistory(path) {
this.sidebarContent_.querySelectorAll('li').forEach(function(item) {
item.classList.toggle('selected', item.dataset.pageName === path);
});
@@ -108,7 +108,7 @@ cr.define('sidebar', function() {
* @param {!Event} event
* @private
*/
- onItemClick_: function(event) {
+ onItemClick_(event) {
this.close();
PageManager.showPageByName(event.target.parentNode.dataset.pageName);
},
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/snackbar.js b/chromium/chrome/browser/resources/bluetooth_internals/snackbar.js
index 988ddd4b038..b20a9eb2a28 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/snackbar.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/snackbar.js
@@ -48,7 +48,7 @@ cr.define('snackbar', function() {
* Decorates an element as a UI element class. Creates the message div and
* action link for the new Snackbar.
*/
- decorate: function() {
+ decorate() {
this.classList.add('snackbar');
this.messageDiv_ = document.createElement('div');
this.appendChild(this.messageDiv_);
@@ -68,7 +68,7 @@ cr.define('snackbar', function() {
* including the message, action link text, and click action of the link.
* @param {!SnackbarOptions} options
*/
- initialize: function(options) {
+ initialize(options) {
this.messageDiv_.textContent = options.message;
this.classList.add(options.type);
this.actionLink_.textContent = options.actionText || 'Dismiss';
@@ -84,7 +84,7 @@ cr.define('snackbar', function() {
/**
* Shows the Snackbar and dispatches the 'showed' event.
*/
- show: function() {
+ show() {
this.classList.add('open');
if (Snackbar.hasContentFocus_) {
this.startTimeout_();
@@ -103,7 +103,7 @@ cr.define('snackbar', function() {
* snackbar is already hidden, a resolved Promise is returned.
* @return {!Promise}
*/
- dismiss: function() {
+ dismiss() {
this.stopTimeout_();
if (!this.classList.contains('open')) {
@@ -128,7 +128,7 @@ cr.define('snackbar', function() {
* Starts the timeout for dismissing the Snackbar.
* @private
*/
- startTimeout_: function() {
+ startTimeout_() {
this.timeoutId_ = setTimeout(function() {
this.dismiss();
}.bind(this), SHOW_DURATION);
@@ -139,7 +139,7 @@ cr.define('snackbar', function() {
* when the Snackbar is open.
* @private
*/
- stopTimeout_: function() {
+ stopTimeout_() {
if (this.classList.contains('open')) {
clearTimeout(this.timeoutId_);
this.timeoutId_ = null;
diff --git a/chromium/chrome/browser/resources/bluetooth_internals/value_control.js b/chromium/chrome/browser/resources/bluetooth_internals/value_control.js
index b942f6d3b06..38def354fcd 100644
--- a/chromium/chrome/browser/resources/bluetooth_internals/value_control.js
+++ b/chromium/chrome/browser/resources/bluetooth_internals/value_control.js
@@ -45,7 +45,7 @@ cr.define('value_control', function() {
* Gets the backing array value.
* @return {!Array<number>}
*/
- getArray: function() {
+ getArray() {
return this.value_;
},
@@ -53,7 +53,7 @@ cr.define('value_control', function() {
* Sets the backing array value.
* @param {!Array<number>} newValue
*/
- setArray: function(newValue) {
+ setArray(newValue) {
this.value_ = newValue;
},
@@ -63,7 +63,7 @@ cr.define('value_control', function() {
* @param {!value_control.ValueDataType} valueDataType
* @param {string} newValue
*/
- setAs: function(valueDataType, newValue) {
+ setAs(valueDataType, newValue) {
switch (valueDataType) {
case ValueDataType.HEXADECIMAL:
this.setValueFromHex_(newValue);
@@ -84,7 +84,7 @@ cr.define('value_control', function() {
* @param {!value_control.ValueDataType} valueDataType
* @return {string}
*/
- getAs: function(valueDataType) {
+ getAs(valueDataType) {
switch (valueDataType) {
case ValueDataType.HEXADECIMAL:
return this.toHex_();
@@ -104,7 +104,7 @@ cr.define('value_control', function() {
* @return {string}
* @private
*/
- toHex_: function() {
+ toHex_() {
if (this.value_.length == 0) {
return '';
}
@@ -119,7 +119,7 @@ cr.define('value_control', function() {
* @param {string} newValue
* @private
*/
- setValueFromHex_: function(newValue) {
+ setValueFromHex_(newValue) {
if (!newValue) {
this.value_ = [];
return;
@@ -142,7 +142,7 @@ cr.define('value_control', function() {
* @return {string}
* @private
*/
- toUTF8_: function() {
+ toUTF8_() {
return this.value_.reduce(function(result, value) {
return result + String.fromCharCode(value);
}, '');
@@ -153,7 +153,7 @@ cr.define('value_control', function() {
* @param {string} newValue
* @private
*/
- setValueFromUTF8_: function(newValue) {
+ setValueFromUTF8_(newValue) {
if (!newValue) {
this.value_ = [];
return;
@@ -169,7 +169,7 @@ cr.define('value_control', function() {
* @return {string}
* @private
*/
- toDecimal_: function() {
+ toDecimal_() {
return this.value_.join('-');
},
@@ -178,7 +178,7 @@ cr.define('value_control', function() {
* @param {string} newValue
* @private
*/
- setValueFromDecimal_: function(newValue) {
+ setValueFromDecimal_(newValue) {
if (!newValue) {
this.value_ = [];
return;
@@ -214,7 +214,7 @@ cr.define('value_control', function() {
* read/write requests. Event handlers are attached and references to these
* elements are stored for later use.
*/
- decorate: function() {
+ decorate() {
this.classList.add('value-control');
/** @private {!Value} */
@@ -281,7 +281,7 @@ cr.define('value_control', function() {
* are not provided, no restrictions on reading/writing are applied.
* @param {!ValueLoadOptions} options
*/
- load: function(options) {
+ load(options) {
this.deviceAddress_ = options.deviceAddress;
this.serviceId_ = options.serviceId;
this.characteristicId_ = options.characteristicId;
@@ -298,7 +298,7 @@ cr.define('value_control', function() {
* Redraws the value control with updated layout depending on the
* availability of reads and writes and the current cached value.
*/
- redraw: function() {
+ redraw() {
this.readBtn_.hidden =
(this.properties_ & bluetooth.mojom.Property.READ) === 0;
this.writeBtn_.hidden =
@@ -322,7 +322,7 @@ cr.define('value_control', function() {
* Sets the value of the control.
* @param {!Array<number>} value
*/
- setValue: function(value) {
+ setValue(value) {
this.value_.setArray(value);
this.redraw();
},
@@ -332,7 +332,7 @@ cr.define('value_control', function() {
* @param {!bluetooth.mojom.GattResult} result
* @private
*/
- getErrorString_: function(result) {
+ getErrorString_(result) {
// TODO(crbug.com/663394): Replace with more descriptive error
// messages.
const GattResult = bluetooth.mojom.GattResult;
@@ -348,7 +348,7 @@ cr.define('value_control', function() {
* descriptor value with |descriptor_id| is read instead.
* @private
*/
- readValue_: function() {
+ readValue_() {
this.readBtn_.disabled = true;
device_broker.connectToDevice(assert(this.deviceAddress_))
@@ -386,7 +386,7 @@ cr.define('value_control', function() {
* the descriptor value with |descriptor_id| is written instead.
* @private
*/
- writeValue_: function() {
+ writeValue_() {
this.writeBtn_.disabled = true;
device_broker.connectToDevice(assert(this.deviceAddress_))
diff --git a/chromium/chrome/browser/resources/bookmarks/.eslintrc.js b/chromium/chrome/browser/resources/bookmarks/.eslintrc.js
new file mode 100644
index 00000000000..9c84e103640
--- /dev/null
+++ b/chromium/chrome/browser/resources/bookmarks/.eslintrc.js
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/bookmarks/BUILD.gn b/chromium/chrome/browser/resources/bookmarks/BUILD.gn
index a0b0f5d230d..b42844e5cd8 100644
--- a/chromium/chrome/browser/resources/bookmarks/BUILD.gn
+++ b/chromium/chrome/browser/resources/bookmarks/BUILD.gn
@@ -29,24 +29,18 @@ if (optimize_webui) {
pak_file = bookmarks_pak_file
out_folder = unpak_folder
- deps = [
- ":flattened_resources",
- ]
+ deps = [ ":flattened_resources" ]
}
grit("flattened_resources") {
source = "bookmarks_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
- deps = [
- ":polymer3_elements",
- ]
+ deps = [ ":polymer3_elements" ]
defines = chrome_grit_defines
outputs = [
"grit/bookmarks_resources.h",
@@ -59,7 +53,7 @@ if (optimize_webui) {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":app_module",
":command_manager_module",
":edit_dialog_module",
@@ -193,7 +187,7 @@ js_library("app") {
":store",
":store_client",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
- "//ui/webui/resources/cr_elements/cr_splitter:cr_splitter.m",
+ "//ui/webui/resources/cr_elements/cr_splitter:cr_splitter",
"//ui/webui/resources/js:find_shortcut_behavior.m",
"//ui/webui/resources/js:load_time_data.m",
]
@@ -240,9 +234,7 @@ js_library("debouncer") {
}
js_library("dialog_focus_manager") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
}
js_library("dnd_manager") {
@@ -381,15 +373,11 @@ js_library("toolbar") {
}
js_library("types") {
- deps = [
- ":constants",
- ]
+ deps = [ ":constants" ]
externs_list = [ "$externs_path/chrome_extensions.js" ]
}
js_library("util") {
- deps = [
- ":types",
- ]
+ deps = [ ":types" ]
externs_list = [ "$externs_path/chrome_extensions.js" ]
}
diff --git a/chromium/chrome/browser/resources/bookmarks/actions.js b/chromium/chrome/browser/resources/bookmarks/actions.js
index 81c62ccb8c7..54cfd79207a 100644
--- a/chromium/chrome/browser/resources/bookmarks/actions.js
+++ b/chromium/chrome/browser/resources/bookmarks/actions.js
@@ -107,7 +107,7 @@ export function refreshNodes(nodeMap) {
* @return {?Action}
*/
export function selectFolder(id, nodes) {
- if (nodes && (id == ROOT_NODE_ID || !nodes[id] || nodes[id].url)) {
+ if (nodes && (id === ROOT_NODE_ID || !nodes[id] || nodes[id].url)) {
console.warn('Tried to select invalid folder: ' + id);
return null;
}
@@ -169,9 +169,9 @@ export function selectItem(id, state, config) {
if (config.range && anchor) {
const displayedList = getDisplayedList(state);
const selectedIndex = displayedList.indexOf(id);
- assert(selectedIndex != -1);
+ assert(selectedIndex !== -1);
let anchorIndex = displayedList.indexOf(anchor);
- if (anchorIndex == -1) {
+ if (anchorIndex === -1) {
anchorIndex = selectedIndex;
}
@@ -256,7 +256,7 @@ export function setSearchResults(ids) {
* @return {!Action}
*/
export function setIncognitoAvailability(availability) {
- assert(availability != IncognitoAvailability.FORCED);
+ assert(availability !== IncognitoAvailability.FORCED);
return {
name: 'set-incognito-availability',
value: availability,
diff --git a/chromium/chrome/browser/resources/bookmarks/app.js b/chromium/chrome/browser/resources/bookmarks/app.js
index 474d2341900..3f90d04cb9f 100644
--- a/chromium/chrome/browser/resources/bookmarks/app.js
+++ b/chromium/chrome/browser/resources/bookmarks/app.js
@@ -6,7 +6,7 @@ import 'chrome://resources/cr_components/managed_footnote/managed_footnote.m.js'
import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.m.js';
-import 'chrome://resources/cr_elements/cr_splitter/cr_splitter.m.js';
+import 'chrome://resources/cr_elements/cr_splitter/cr_splitter.js';
import './folder_node.js';
import './list.js';
import './router.js';
@@ -64,7 +64,7 @@ Polymer({
dndManager_: null,
/** @override */
- created: function() {
+ created() {
// Regular expression that captures the leading slash, the content and the
// trailing slash in three different groups.
const CANONICAL_PATH_REGEX = /(^\/)([\/-\w]+)(\/$)/;
@@ -75,7 +75,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
document.documentElement.classList.remove('loading');
this.watch('searchTerm_', function(state) {
@@ -117,7 +117,7 @@ Polymer({
this.dndManager_.init();
},
- detached: function() {
+ detached() {
window.removeEventListener('resize', this.boundUpdateSidebarWidth_);
this.dndManager_.destroy();
destroyApiListener();
@@ -127,7 +127,7 @@ Polymer({
* Set up the splitter and set the initial width from localStorage.
* @private
*/
- initializeSplitter_: function() {
+ initializeSplitter_() {
const splitter = this.$.splitter;
const splitterTarget = this.$.sidebar;
@@ -150,14 +150,14 @@ Polymer({
},
/** @private */
- updateSidebarWidth_: function() {
+ updateSidebarWidth_() {
this.sidebarWidth_ =
/** @type {string} */ (getComputedStyle(this.$.sidebar).width);
},
/** @private */
- searchTermChanged_: function(newValue, oldValue) {
- if (oldValue != undefined && !newValue) {
+ searchTermChanged_(newValue, oldValue) {
+ if (oldValue !== undefined && !newValue) {
this.fire(
'iron-announce', {text: loadTimeData.getString('searchCleared')});
}
@@ -180,13 +180,13 @@ Polymer({
},
/** @private */
- folderOpenStateChanged_: function() {
+ folderOpenStateChanged_() {
window.localStorage[LOCAL_STORAGE_FOLDER_STATE_KEY] =
JSON.stringify(Array.from(this.folderOpenState_));
},
// Override FindShortcutBehavior methods.
- handleFindShortcut: function(modalContextOpen) {
+ handleFindShortcut(modalContextOpen) {
if (modalContextOpen) {
return false;
}
@@ -195,12 +195,12 @@ Polymer({
},
// Override FindShortcutBehavior methods.
- searchInputHasFocus: function() {
+ searchInputHasFocus() {
return this.$$('bookmarks-toolbar').searchField.isSearchFocused();
},
/** @private */
- onUndoClick_: function() {
+ onUndoClick_() {
this.fire('command-undo');
},
});
diff --git a/chromium/chrome/browser/resources/bookmarks/command_manager.js b/chromium/chrome/browser/resources/bookmarks/command_manager.js
index 6539f75e8e0..0326cdaa772 100644
--- a/chromium/chrome/browser/resources/bookmarks/command_manager.js
+++ b/chromium/chrome/browser/resources/bookmarks/command_manager.js
@@ -79,8 +79,8 @@ export const CommandManager = Polymer({
/** @private {?Function} */
confirmOpenCallback_: null,
- attached: function() {
- assert(CommandManager.instance_ == null);
+ attached() {
+ assert(CommandManager.instance_ === null);
CommandManager.instance_ = this;
/** @private {!BrowserProxy} */
@@ -126,7 +126,7 @@ export const CommandManager = Polymer({
const addDocumentListenerForCommand = (eventName, command) => {
addDocumentListener(eventName, (e) => {
- if (e.path[0].tagName == 'INPUT') {
+ if (e.path[0].tagName === 'INPUT') {
return;
}
@@ -146,7 +146,7 @@ export const CommandManager = Polymer({
});
},
- detached: function() {
+ detached() {
CommandManager.instance_ = null;
this.boundListeners_.forEach(
(handler, eventName) =>
@@ -162,7 +162,7 @@ export const CommandManager = Polymer({
* @param {MenuSource} source
* @param {Set<string>=} items
*/
- openCommandMenuAtPosition: function(x, y, source, items) {
+ openCommandMenuAtPosition(x, y, source, items) {
this.menuSource_ = source;
this.menuIds_ = items || this.getState().selection.items;
@@ -182,7 +182,7 @@ export const CommandManager = Polymer({
* @param {!Element} target
* @param {MenuSource} source
*/
- openCommandMenuAtElement: function(target, source) {
+ openCommandMenuAtElement(target, source) {
this.menuSource_ = source;
this.menuIds_ = this.getState().selection.items;
@@ -196,7 +196,7 @@ export const CommandManager = Polymer({
});
},
- closeCommandMenu: function() {
+ closeCommandMenu() {
this.menuIds_ = new Set();
this.menuSource_ = MenuSource.NONE;
/** @type {!CrActionMenuElement} */ (this.$.dropdown.get()).close();
@@ -213,7 +213,7 @@ export const CommandManager = Polymer({
* @param {!Set<string>} itemIds
* @return {boolean}
*/
- canExecute: function(command, itemIds) {
+ canExecute(command, itemIds) {
const state = this.getState();
switch (command) {
case Command.OPEN:
@@ -232,7 +232,7 @@ export const CommandManager = Polymer({
return !canEditNode(state, node.id);
});
case Command.PASTE:
- return state.search.term == '' &&
+ return state.search.term === '' &&
canReorderChildren(state, state.selectedFolder);
default:
return this.isCommandVisible_(command, itemIds) &&
@@ -246,10 +246,10 @@ export const CommandManager = Polymer({
* @return {boolean} True if the command should be visible in the context
* menu.
*/
- isCommandVisible_: function(command, itemIds) {
+ isCommandVisible_(command, itemIds) {
switch (command) {
case Command.EDIT:
- return itemIds.size == 1 && this.globalCanEdit_;
+ return itemIds.size === 1 && this.globalCanEdit_;
case Command.PASTE:
return this.globalCanEdit_;
case Command.CUT:
@@ -260,10 +260,10 @@ export const CommandManager = Polymer({
case Command.DELETE:
return itemIds.size > 0 && this.globalCanEdit_;
case Command.SHOW_IN_FOLDER:
- return this.menuSource_ == MenuSource.ITEM && itemIds.size == 1 &&
- this.getState().search.term != '' &&
+ return this.menuSource_ === MenuSource.ITEM && itemIds.size === 1 &&
+ this.getState().search.term !== '' &&
!this.containsMatchingNode_(itemIds, function(node) {
- return !node.parentId || node.parentId == ROOT_NODE_ID;
+ return !node.parentId || node.parentId === ROOT_NODE_ID;
});
case Command.OPEN_NEW_TAB:
case Command.OPEN_NEW_WINDOW:
@@ -286,7 +286,7 @@ export const CommandManager = Polymer({
* @return {boolean} True if the command should be clickable in the context
* menu.
*/
- isCommandEnabled_: function(command, itemIds) {
+ isCommandEnabled_(command, itemIds) {
const state = this.getState();
switch (command) {
case Command.EDIT:
@@ -299,7 +299,8 @@ export const CommandManager = Polymer({
return this.expandUrls_(itemIds).length > 0;
case Command.OPEN_INCOGNITO:
return this.expandUrls_(itemIds).length > 0 &&
- state.prefs.incognitoAvailability != IncognitoAvailability.DISABLED;
+ state.prefs.incognitoAvailability !==
+ IncognitoAvailability.DISABLED;
case Command.SORT:
return this.canChangeList_() &&
state.nodes[state.selectedFolder].children.length > 1;
@@ -320,9 +321,9 @@ export const CommandManager = Polymer({
* @private
* @return {boolean}
*/
- canChangeList_: function() {
+ canChangeList_() {
const state = this.getState();
- return state.search.term == '' &&
+ return state.search.term === '' &&
canReorderChildren(state, state.selectedFolder);
},
@@ -330,7 +331,7 @@ export const CommandManager = Polymer({
* @param {Command} command
* @param {!Set<string>} itemIds
*/
- handle: function(command, itemIds) {
+ handle(command, itemIds) {
const state = this.getState();
switch (command) {
case Command.EDIT: {
@@ -344,10 +345,10 @@ export const CommandManager = Polymer({
const idList = Array.from(itemIds);
chrome.bookmarkManagerPrivate.copy(idList, () => {
let labelPromise;
- if (command == Command.COPY_URL) {
+ if (command === Command.COPY_URL) {
labelPromise =
Promise.resolve(loadTimeData.getString('toastUrlCopied'));
- } else if (idList.length == 1) {
+ } else if (idList.length === 1) {
labelPromise =
Promise.resolve(loadTimeData.getString('toastItemCopied'));
} else {
@@ -373,7 +374,7 @@ export const CommandManager = Polymer({
const title = state.nodes[idList[0]].title;
let labelPromise;
- if (idList.length == 1) {
+ if (idList.length === 1) {
labelPromise =
Promise.resolve(loadTimeData.getString('toastItemDeleted'));
} else {
@@ -462,7 +463,7 @@ export const CommandManager = Polymer({
* @return {boolean} True if the event was handled, triggering a keyboard
* shortcut.
*/
- handleKeyEvent: function(e, itemIds) {
+ handleKeyEvent(e, itemIds) {
for (const commandTuple of this.shortcuts_) {
const command = /** @type {Command} */ (commandTuple[0]);
const shortcut =
@@ -492,7 +493,7 @@ export const CommandManager = Polymer({
* @param {string=} macShortcut If set, enables a replacement shortcut for
* Mac.
*/
- addShortcut_: function(command, shortcut, macShortcut) {
+ addShortcut_(command, shortcut, macShortcut) {
shortcut = (isMac && macShortcut) ? macShortcut : shortcut;
this.shortcuts_.set(command, new KeyboardShortcutList(shortcut));
},
@@ -506,12 +507,12 @@ export const CommandManager = Polymer({
* @param {!Set<string>} itemIds
* @return {!Set<string>}
*/
- minimizeDeletionSet_: function(itemIds) {
+ minimizeDeletionSet_(itemIds) {
const minimizedSet = new Set();
const nodes = this.getState().nodes;
itemIds.forEach(function(itemId) {
let currentId = itemId;
- while (currentId != ROOT_NODE_ID) {
+ while (currentId !== ROOT_NODE_ID) {
currentId = assert(nodes[currentId].parentId);
if (itemIds.has(currentId)) {
return;
@@ -529,22 +530,22 @@ export const CommandManager = Polymer({
* @param {Command} command
* @private
*/
- openUrls_: function(urls, command) {
+ openUrls_(urls, command) {
assert(
- command == Command.OPEN || command == Command.OPEN_NEW_TAB ||
- command == Command.OPEN_NEW_WINDOW ||
- command == Command.OPEN_INCOGNITO);
+ command === Command.OPEN || command === Command.OPEN_NEW_TAB ||
+ command === Command.OPEN_NEW_WINDOW ||
+ command === Command.OPEN_INCOGNITO);
- if (urls.length == 0) {
+ if (urls.length === 0) {
return;
}
const openUrlsCallback = function() {
- const incognito = command == Command.OPEN_INCOGNITO;
- if (command == Command.OPEN_NEW_WINDOW || incognito) {
+ const incognito = command === Command.OPEN_INCOGNITO;
+ if (command === Command.OPEN_NEW_WINDOW || incognito) {
chrome.windows.create({url: urls, incognito: incognito});
} else {
- if (command == Command.OPEN) {
+ if (command === Command.OPEN) {
chrome.tabs.create({url: urls.shift(), active: true});
}
urls.forEach(function(url) {
@@ -575,7 +576,7 @@ export const CommandManager = Polymer({
* @return {!Array<string>}
* @private
*/
- expandUrls_: function(itemIds) {
+ expandUrls_(itemIds) {
const urls = [];
const nodes = this.getState().nodes;
@@ -602,7 +603,7 @@ export const CommandManager = Polymer({
* @return {boolean} True if any node in |itemIds| returns true for
* |predicate|.
*/
- containsMatchingNode_: function(itemIds, predicate) {
+ containsMatchingNode_(itemIds, predicate) {
const nodes = this.getState().nodes;
return Array.from(itemIds).some(function(id) {
@@ -616,8 +617,8 @@ export const CommandManager = Polymer({
* node.
* @private
*/
- isSingleBookmark_: function(itemIds) {
- return itemIds.size == 1 &&
+ isSingleBookmark_(itemIds) {
+ return itemIds.size === 1 &&
this.containsMatchingNode_(itemIds, function(node) {
return !!node.url;
});
@@ -628,8 +629,8 @@ export const CommandManager = Polymer({
* @return {boolean}
* @private
*/
- isFolder_: function(itemIds) {
- return itemIds.size == 1 &&
+ isFolder_(itemIds) {
+ return itemIds.size === 1 &&
this.containsMatchingNode_(itemIds, node => !node.url);
},
@@ -638,7 +639,7 @@ export const CommandManager = Polymer({
* @return {string}
* @private
*/
- getCommandLabel_: function(command) {
+ getCommandLabel_(command) {
const multipleNodes = this.menuIds_.size > 1 ||
this.containsMatchingNode_(this.menuIds_, function(node) {
return !node.url;
@@ -646,7 +647,7 @@ export const CommandManager = Polymer({
let label;
switch (command) {
case Command.EDIT:
- if (this.menuIds_.size != 1) {
+ if (this.menuIds_.size !== 1) {
return '';
}
@@ -710,7 +711,7 @@ export const CommandManager = Polymer({
* @return {string}
* @private
*/
- getCommandSublabel_: function(command) {
+ getCommandSublabel_(command) {
const multipleNodes = this.menuIds_.size > 1 ||
this.containsMatchingNode_(this.menuIds_, function(node) {
return !node.url;
@@ -725,7 +726,7 @@ export const CommandManager = Polymer({
},
/** @private */
- computeMenuCommands_: function() {
+ computeMenuCommands_() {
switch (this.menuSource_) {
case MenuSource.ITEM:
case MenuSource.TREE:
@@ -770,13 +771,13 @@ export const CommandManager = Polymer({
* @return {boolean}
* @private
*/
- computeHasAnySublabel_: function() {
- if (this.menuIds_ == undefined || this.menuCommands_ == undefined) {
+ computeHasAnySublabel_() {
+ if (this.menuIds_ === undefined || this.menuCommands_ === undefined) {
return false;
}
return this.menuCommands_.some(
- (command) => this.getCommandSublabel_(command) != '');
+ (command) => this.getCommandSublabel_(command) !== '');
},
/**
@@ -785,12 +786,12 @@ export const CommandManager = Polymer({
* @return {boolean}
* @private
*/
- showDividerAfter_: function(command, itemIds) {
+ showDividerAfter_(command, itemIds) {
switch (command) {
case Command.SORT:
case Command.ADD_FOLDER:
case Command.EXPORT:
- return this.menuSource_ == MenuSource.TOOLBAR;
+ return this.menuSource_ === MenuSource.TOOLBAR;
case Command.DELETE:
return this.globalCanEdit_;
case Command.PASTE:
@@ -805,8 +806,8 @@ export const CommandManager = Polymer({
* @param {number} command
* @private
*/
- recordCommandHistogram_: function(itemIds, histogram, command) {
- if (command == Command.OPEN) {
+ recordCommandHistogram_(itemIds, histogram, command) {
+ if (command === Command.OPEN) {
command =
this.isFolder_(itemIds) ? Command.OPEN_FOLDER : Command.OPEN_BOOKMARK;
}
@@ -844,7 +845,7 @@ export const CommandManager = Polymer({
* @param {number} targetId
* @private
*/
- updateCanPaste_: function(targetId) {
+ updateCanPaste_(targetId) {
return new Promise(resolve => {
chrome.bookmarkManagerPrivate.canPaste(`${targetId}`, result => {
this.canPaste_ = result;
@@ -876,7 +877,7 @@ export const CommandManager = Polymer({
* @param {Event} e
* @private
*/
- onCommandClick_: function(e) {
+ onCommandClick_(e) {
this.handle(
/** @type {Command} */ (
Number(e.currentTarget.getAttribute('command'))),
@@ -888,13 +889,13 @@ export const CommandManager = Polymer({
* @param {!Event} e
* @private
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
const path = e.composedPath();
- if (path[0].tagName == 'INPUT') {
+ if (path[0].tagName === 'INPUT') {
return;
}
- if ((e.target == document.body ||
- path.some(el => el.tagName == 'BOOKMARKS-TOOLBAR')) &&
+ if ((e.target === document.body ||
+ path.some(el => el.tagName === 'BOOKMARKS-TOOLBAR')) &&
!DialogFocusManager.getInstance().hasOpenDialog()) {
this.handleKeyEvent(e, this.getState().selection.items);
}
@@ -907,8 +908,8 @@ export const CommandManager = Polymer({
* @param {Event} e
* @private
*/
- onMenuMousedown_: function(e) {
- if (e.path[0].tagName != 'DIALOG') {
+ onMenuMousedown_(e) {
+ if (e.path[0].tagName !== 'DIALOG') {
return;
}
@@ -916,12 +917,12 @@ export const CommandManager = Polymer({
},
/** @private */
- onOpenCancelTap_: function() {
+ onOpenCancelTap_() {
this.$.openDialog.get().cancel();
},
/** @private */
- onOpenConfirmTap_: function() {
+ onOpenConfirmTap_() {
this.confirmOpenCallback_();
this.$.openDialog.get().close();
},
diff --git a/chromium/chrome/browser/resources/bookmarks/dialog_focus_manager.js b/chromium/chrome/browser/resources/bookmarks/dialog_focus_manager.js
index 7caf84b3049..e099f933316 100644
--- a/chromium/chrome/browser/resources/bookmarks/dialog_focus_manager.js
+++ b/chromium/chrome/browser/resources/bookmarks/dialog_focus_manager.js
@@ -33,7 +33,7 @@ export class DialogFocusManager {
// Update the focus if there are no open dialogs or if this is the only
// dialog and it's getting reshown.
if (!this.dialogs_.size ||
- (this.dialogs_.has(dialog) && this.dialogs_.size == 1)) {
+ (this.dialogs_.has(dialog) && this.dialogs_.size === 1)) {
this.updatePreviousFocus_();
}
diff --git a/chromium/chrome/browser/resources/bookmarks/dnd_manager.js b/chromium/chrome/browser/resources/bookmarks/dnd_manager.js
index da49cf9207e..30fbdbbae33 100644
--- a/chromium/chrome/browser/resources/bookmarks/dnd_manager.js
+++ b/chromium/chrome/browser/resources/bookmarks/dnd_manager.js
@@ -24,7 +24,7 @@ const DRAG_THRESHOLD = 15;
* @return {boolean}
*/
function isBookmarkItem(element) {
- return element.tagName == 'BOOKMARKS-ITEM';
+ return element.tagName === 'BOOKMARKS-ITEM';
}
/**
@@ -32,7 +32,7 @@ function isBookmarkItem(element) {
* @return {boolean}
*/
function isBookmarkFolderNode(element) {
- return element.tagName == 'BOOKMARKS-FOLDER-NODE';
+ return element.tagName === 'BOOKMARKS-FOLDER-NODE';
}
/**
@@ -40,7 +40,7 @@ function isBookmarkFolderNode(element) {
* @return {boolean}
*/
function isBookmarkList(element) {
- return element.tagName == 'BOOKMARKS-LIST';
+ return element.tagName === 'BOOKMARKS-LIST';
}
/**
@@ -103,7 +103,7 @@ function getBookmarkElement(path) {
function getDragElement(path) {
const dragElement = getBookmarkElement(path);
for (let i = 0; i < path.length; i++) {
- if (path[i].tagName == 'BUTTON') {
+ if (path[i].tagName === 'BUTTON') {
return null;
}
}
@@ -162,7 +162,7 @@ export class DragInfo {
isDraggingBookmark(bookmarkId) {
return !!this.dragData && this.isSameProfile() &&
this.dragData.elements.some(function(node) {
- return node.id == bookmarkId;
+ return node.id === bookmarkId;
});
}
@@ -170,7 +170,7 @@ export class DragInfo {
isDraggingChildBookmark(folderId) {
return !!this.dragData && this.isSameProfile() &&
this.dragData.elements.some(function(node) {
- return node.parentId == folderId;
+ return node.parentId === folderId;
});
}
@@ -222,7 +222,7 @@ class AutoExpander {
// If dragging over a new closed folder node with children reset the
// expander. Falls through to reset the expander delay.
- if (overElement && overElement != this.lastElement_ &&
+ if (overElement && overElement !== this.lastElement_ &&
isClosedBookmarkFolderNode(overElement) &&
hasChildFolders(/** @type {string} */ (itemId), store.data.nodes)) {
this.reset();
@@ -230,7 +230,7 @@ class AutoExpander {
}
// If dragging over the same node, reset the expander delay.
- if (overElement && overElement == this.lastElement_) {
+ if (overElement && overElement === this.lastElement_) {
this.debouncer_.restartTimeout(this.EXPAND_FOLDER_DELAY);
return;
}
@@ -283,9 +283,9 @@ class DropIndicator {
* @param {DropPosition} position
*/
addDropIndicatorStyle(indicatorElement, position) {
- const indicatorStyleName = position == DropPosition.ABOVE ?
+ const indicatorStyleName = position === DropPosition.ABOVE ?
'drag-above' :
- position == DropPosition.BELOW ? 'drag-below' : 'drag-on';
+ position === DropPosition.BELOW ? 'drag-below' : 'drag-on';
this.lastIndicatorElement_ =
/** @type {BookmarkElement} */ (indicatorElement);
@@ -431,7 +431,7 @@ export class DNDManager {
// delay on large amount of bookmark dragging.
for (const itemId of displayingItems) {
for (const element of dragData.elements) {
- if (element.id == itemId) {
+ if (element.id === itemId) {
draggedNodes.push(element.id);
break;
}
@@ -441,10 +441,10 @@ export class DNDManager {
draggedNodes = dragData.elements.map((item) => item.id);
}
- assert(draggedNodes.length == dragData.elements.length);
+ assert(draggedNodes.length === dragData.elements.length);
const dragNodeIndex = draggedNodes.indexOf(dragElement.itemId);
- assert(dragNodeIndex != -1);
+ assert(dragNodeIndex !== -1);
chrome.bookmarkManagerPrivate.startDrag(
draggedNodes, dragNodeIndex, this.lastPointerWasTouch_, e.clientX,
@@ -470,7 +470,7 @@ export class DNDManager {
if (this.dropDestination_) {
const dropInfo = this.calculateDropInfo_(this.dropDestination_);
- const index = dropInfo.index != -1 ? dropInfo.index : undefined;
+ const index = dropInfo.index !== -1 ? dropInfo.index : undefined;
const shouldHighlight = this.shouldHighlight_(this.dropDestination_);
if (shouldHighlight) {
@@ -586,7 +586,7 @@ export class DNDManager {
let index = -1;
let parentId = node.id;
- if (position != DropPosition.ON) {
+ if (position !== DropPosition.ON) {
const state = Store.getInstance().data;
// Drops between items in the normal list and the sidebar use the drop
@@ -594,7 +594,7 @@ export class DNDManager {
parentId = assert(node.parentId);
index = state.nodes[parentId].children.indexOf(node.id);
- if (position == DropPosition.BELOW) {
+ if (position === DropPosition.BELOW) {
index++;
}
}
@@ -622,7 +622,7 @@ export class DNDManager {
// Change selection to the dragged node if the node is not part of the
// existing selection.
if (isBookmarkFolderNode(dragElement) ||
- draggedNodes.indexOf(dragId) == -1) {
+ draggedNodes.indexOf(dragId) === -1) {
store.dispatch(deselectItems());
if (!isBookmarkFolderNode(dragElement)) {
store.dispatch(selectItem(dragId, state, {
@@ -660,7 +660,7 @@ export class DNDManager {
*/
calculateDropDestination_(elementClientY, overElement) {
const validDropPositions = this.calculateValidDropPositions_(overElement);
- if (validDropPositions == DropPosition.NONE) {
+ if (validDropPositions === DropPosition.NONE) {
return null;
}
@@ -740,7 +740,7 @@ export class DNDManager {
}
// We cannot drop between Bookmarks bar and Other bookmarks.
- if (getBookmarkNode(overElement).parentId == ROOT_NODE_ID) {
+ if (getBookmarkNode(overElement).parentId === ROOT_NODE_ID) {
return DropPosition.NONE;
}
@@ -788,7 +788,7 @@ export class DNDManager {
if (isBookmarkList(overElement)) {
const state = Store.getInstance().data;
return !!state.selectedFolder &&
- state.nodes[state.selectedFolder].children.length == 0;
+ state.nodes[state.selectedFolder].children.length === 0;
}
// We can only drop on a folder.
diff --git a/chromium/chrome/browser/resources/bookmarks/edit_dialog.js b/chromium/chrome/browser/resources/bookmarks/edit_dialog.js
index eb3003523f2..28ba59bc16a 100644
--- a/chromium/chrome/browser/resources/bookmarks/edit_dialog.js
+++ b/chromium/chrome/browser/resources/bookmarks/edit_dialog.js
@@ -53,7 +53,7 @@ Polymer({
* @param {boolean} isFolder
* @param {string} parentId
*/
- showAddDialog: function(isFolder, parentId) {
+ showAddDialog(isFolder, parentId) {
this.reset_();
this.isEdit_ = false;
this.isFolder_ = isFolder;
@@ -66,7 +66,7 @@ Polymer({
* Show the edit dialog for |editItem|.
* @param {BookmarkNode} editItem
*/
- showEditDialog: function(editItem) {
+ showEditDialog(editItem) {
this.reset_();
this.isEdit_ = true;
this.isFolder_ = !editItem.url;
@@ -84,7 +84,7 @@ Polymer({
* Clear out existing values from the dialog, allowing it to be reused.
* @private
*/
- reset_: function() {
+ reset_() {
this.editItem_ = null;
this.parentId_ = null;
this.$.url.invalid = false;
@@ -98,7 +98,7 @@ Polymer({
* @return {string}
* @private
*/
- getDialogTitle_: function(isFolder, isEdit) {
+ getDialogTitle_(isFolder, isEdit) {
let title;
if (isEdit) {
title = isFolder ? 'renameFolderTitle' : 'editBookmarkTitle';
@@ -115,7 +115,7 @@ Polymer({
* @return {boolean}
* @private
*/
- validateUrl_: function() {
+ validateUrl_() {
const urlInput = /** @type {CrInputElement} */ (this.$.url);
const originalValue = this.urlValue_;
@@ -134,7 +134,7 @@ Polymer({
},
/** @private */
- onSaveButtonTap_: function() {
+ onSaveButtonTap_() {
const edit = {'title': this.titleValue_};
if (!this.isFolder_) {
if (!this.validateUrl_()) {
@@ -155,7 +155,7 @@ Polymer({
},
/** @private */
- onCancelButtonTap_: function() {
+ onCancelButtonTap_() {
this.$.dialog.cancel();
},
});
diff --git a/chromium/chrome/browser/resources/bookmarks/folder_node.html b/chromium/chrome/browser/resources/bookmarks/folder_node.html
index 93881544176..3feb68702b3 100644
--- a/chromium/chrome/browser/resources/bookmarks/folder_node.html
+++ b/chromium/chrome/browser/resources/bookmarks/folder_node.html
@@ -9,7 +9,7 @@
display: grid;
grid-template-areas: 'arrow folder label';
grid-template-columns: 24px 24px auto;
- height: 40px;
+ min-height: 40px;
min-width: fit-content;
overflow: hidden;
padding-inline-start: calc(var(--node-depth, 0) * 15px);
diff --git a/chromium/chrome/browser/resources/bookmarks/folder_node.js b/chromium/chrome/browser/resources/bookmarks/folder_node.js
index 4c7de78508d..dea9ed75a29 100644
--- a/chromium/chrome/browser/resources/bookmarks/folder_node.js
+++ b/chromium/chrome/browser/resources/bookmarks/folder_node.js
@@ -79,7 +79,7 @@ Polymer({
],
/** @override */
- attached: function() {
+ attached() {
this.watch('item_', state => {
return /** @type {!BookmarksPageState} */ (state).nodes[this.itemId];
});
@@ -100,12 +100,12 @@ Polymer({
},
/** @return {!HTMLElement} */
- getFocusTarget: function() {
+ getFocusTarget() {
return /** @type {!HTMLDivElement} */ (this.$.container);
},
/** @return {HTMLElement} */
- getDropTarget: function() {
+ getDropTarget() {
return /** @type {!HTMLDivElement} */ (this.$.container);
},
@@ -113,25 +113,25 @@ Polymer({
* @private
* @param {!Event} e
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
let yDirection = 0;
let xDirection = 0;
let handled = true;
- if (e.key == 'ArrowUp') {
+ if (e.key === 'ArrowUp') {
yDirection = -1;
- } else if (e.key == 'ArrowDown') {
+ } else if (e.key === 'ArrowDown') {
yDirection = 1;
- } else if (e.key == 'ArrowLeft') {
+ } else if (e.key === 'ArrowLeft') {
xDirection = -1;
- } else if (e.key == 'ArrowRight') {
+ } else if (e.key === 'ArrowRight') {
xDirection = 1;
- } else if (e.key == ' ') {
+ } else if (e.key === ' ') {
this.selectFolder_();
} else {
handled = false;
}
- if (this.getComputedStyleValue('direction') == 'rtl') {
+ if (this.getComputedStyleValue('direction') === 'rtl') {
xDirection *= -1;
}
@@ -157,12 +157,12 @@ Polymer({
* @param {number} yDirection
* @param {!HTMLElement} currentFocus
*/
- changeKeyboardSelection_: function(xDirection, yDirection, currentFocus) {
+ changeKeyboardSelection_(xDirection, yDirection, currentFocus) {
let newFocusFolderNode = null;
const isChildFolderNodeFocused =
- currentFocus && currentFocus.tagName == 'BOOKMARKS-FOLDER-NODE';
+ currentFocus && currentFocus.tagName === 'BOOKMARKS-FOLDER-NODE';
- if (xDirection == 1) {
+ if (xDirection === 1) {
// The right arrow opens a folder if closed and goes to the first child
// otherwise.
if (this.hasChildFolder_) {
@@ -172,14 +172,14 @@ Polymer({
yDirection = 1;
}
}
- } else if (xDirection == -1) {
+ } else if (xDirection === -1) {
// The left arrow closes a folder if open and goes to the parent
// otherwise.
if (this.hasChildFolder_ && this.isOpen) {
this.dispatch(changeFolderOpen(this.item_.id, false));
} else {
const parentFolderNode = this.getParentFolderNode_();
- if (parentFolderNode.itemId != ROOT_NODE_ID) {
+ if (parentFolderNode.itemId !== ROOT_NODE_ID) {
parentFolderNode.getFocusTarget().focus();
}
}
@@ -190,7 +190,7 @@ Polymer({
}
// The current node's successor is its first child when open.
- if (!isChildFolderNodeFocused && yDirection == 1 && this.isOpen) {
+ if (!isChildFolderNodeFocused && yDirection === 1 && this.isOpen) {
const children = this.getChildFolderNodes_();
if (children.length) {
newFocusFolderNode = children[0];
@@ -201,19 +201,19 @@ Polymer({
// Get the next child folder node if a child is focused.
if (!newFocusFolderNode) {
newFocusFolderNode = this.getNextChild_(
- yDirection == -1,
+ yDirection === -1,
/** @type {!BookmarksFolderNodeElement} */ (currentFocus));
}
// The first child's predecessor is this node.
- if (!newFocusFolderNode && yDirection == -1) {
+ if (!newFocusFolderNode && yDirection === -1) {
newFocusFolderNode = this;
}
}
// If there is no newly focused node, allow the parent to handle the change.
if (!newFocusFolderNode) {
- if (this.itemId != ROOT_NODE_ID) {
+ if (this.itemId !== ROOT_NODE_ID) {
this.getParentFolderNode_().changeKeyboardSelection_(
0, yDirection, this);
}
@@ -222,7 +222,7 @@ Polymer({
}
// The root node is not navigable.
- if (newFocusFolderNode.itemId != ROOT_NODE_ID) {
+ if (newFocusFolderNode.itemId !== ROOT_NODE_ID) {
newFocusFolderNode.getFocusTarget().focus();
}
},
@@ -235,17 +235,17 @@ Polymer({
* @return {BookmarksFolderNodeElement|null} Returns null if there is no child
* before/after |child|.
*/
- getNextChild_: function(reverse, child) {
+ getNextChild_(reverse, child) {
let newFocus = null;
const children = this.getChildFolderNodes_();
const index = children.indexOf(child);
- assert(index != -1);
+ assert(index !== -1);
if (reverse) {
// A child node's predecessor is either the previous child's last visible
// descendant, or this node, which is its immediate parent.
newFocus =
- index == 0 ? null : children[index - 1].getLastVisibleDescendant_();
+ index === 0 ? null : children[index - 1].getLastVisibleDescendant_();
} else if (index < children.length - 1) {
// A successor to a child is the next child.
newFocus = children[index + 1];
@@ -259,10 +259,10 @@ Polymer({
* @private
* @return {BookmarksFolderNodeElement|null}
*/
- getParentFolderNode_: function() {
+ getParentFolderNode_() {
let parentFolderNode = this.parentNode;
while (parentFolderNode &&
- parentFolderNode.tagName != 'BOOKMARKS-FOLDER-NODE') {
+ parentFolderNode.tagName !== 'BOOKMARKS-FOLDER-NODE') {
parentFolderNode = parentFolderNode.parentNode || parentFolderNode.host;
}
return parentFolderNode || null;
@@ -272,9 +272,9 @@ Polymer({
* @private
* @return {BookmarksFolderNodeElement}
*/
- getLastVisibleDescendant_: function() {
+ getLastVisibleDescendant_() {
const children = this.getChildFolderNodes_();
- if (!this.isOpen || children.length == 0) {
+ if (!this.isOpen || children.length === 0) {
return this;
}
@@ -282,7 +282,7 @@ Polymer({
},
/** @private */
- selectFolder_: function() {
+ selectFolder_() {
if (!this.isSelectedFolder_) {
this.dispatch(selectFolder(this.itemId, this.getState().nodes));
}
@@ -292,7 +292,7 @@ Polymer({
* @param {!Event} e
* @private
*/
- onContextMenu_: function(e) {
+ onContextMenu_(e) {
e.preventDefault();
this.selectFolder_();
CommandManager.getInstance().openCommandMenuAtPosition(
@@ -303,7 +303,7 @@ Polymer({
* @private
* @return {!Array<!BookmarksFolderNodeElement>}
*/
- getChildFolderNodes_: function() {
+ getChildFolderNodes_() {
return Array.from(this.root.querySelectorAll('bookmarks-folder-node'));
},
@@ -312,7 +312,7 @@ Polymer({
* @private
* @param {!Event} e
*/
- toggleFolder_: function(e) {
+ toggleFolder_(e) {
this.dispatch(changeFolderOpen(this.itemId, !this.isOpen));
e.stopPropagation();
},
@@ -321,7 +321,7 @@ Polymer({
* @private
* @param {!Event} e
*/
- preventDefault_: function(e) {
+ preventDefault_(e) {
e.preventDefault();
},
@@ -331,22 +331,22 @@ Polymer({
* @param {string} selectedFolder
* @return {boolean}
*/
- computeIsSelected_: function(itemId, selectedFolder, searchActive) {
- return itemId == selectedFolder && !searchActive;
+ computeIsSelected_(itemId, selectedFolder, searchActive) {
+ return itemId === selectedFolder && !searchActive;
},
/**
* @private
* @return {boolean}
*/
- computeHasChildFolder_: function() {
+ computeHasChildFolder_() {
return hasChildFolders(this.itemId, this.getState().nodes);
},
/** @private */
- depthChanged_: function() {
+ depthChanged_() {
this.style.setProperty('--node-depth', String(this.depth));
- if (this.depth == -1) {
+ if (this.depth === -1) {
this.$.descendants.removeAttribute('role');
}
},
@@ -355,7 +355,7 @@ Polymer({
* @private
* @return {number}
*/
- getChildDepth_: function() {
+ getChildDepth_() {
return this.depth + 1;
},
@@ -364,7 +364,7 @@ Polymer({
* @private
* @return {boolean}
*/
- isFolder_: function(itemId) {
+ isFolder_(itemId) {
return !this.getState().nodes[itemId].url;
},
@@ -372,19 +372,19 @@ Polymer({
* @private
* @return {boolean}
*/
- isRootFolder_: function() {
- return this.itemId == ROOT_NODE_ID;
+ isRootFolder_() {
+ return this.itemId === ROOT_NODE_ID;
},
/**
* @private
* @return {string}
*/
- getTabIndex_: function() {
+ getTabIndex_() {
// This returns a tab index of 0 for the cached selected folder when the
// search is active, even though this node is not technically selected. This
// allows the sidebar to be focusable during a search.
- return this.selectedFolder_ == this.itemId ? '0' : '-1';
+ return this.selectedFolder_ === this.itemId ? '0' : '-1';
},
/**
@@ -394,7 +394,7 @@ Polymer({
* @param {boolean} isOpen
* @private
*/
- updateAriaExpanded_: function(hasChildFolder, isOpen) {
+ updateAriaExpanded_(hasChildFolder, isOpen) {
if (hasChildFolder) {
this.getFocusTarget().setAttribute('aria-expanded', String(isOpen));
} else {
@@ -406,7 +406,7 @@ Polymer({
* Scrolls the folder node into view when the folder is selected.
* @private
*/
- scrollIntoViewIfNeeded_: function() {
+ scrollIntoViewIfNeeded_() {
if (!this.isSelectedFolder_) {
return;
}
@@ -419,7 +419,7 @@ Polymer({
* @param {number} depth
* @return {boolean}
*/
- computeIsOpen_: function(openState, depth) {
+ computeIsOpen_(openState, depth) {
return openState != null ? openState :
depth <= FOLDER_OPEN_BY_DEFAULT_DEPTH;
},
diff --git a/chromium/chrome/browser/resources/bookmarks/item.js b/chromium/chrome/browser/resources/bookmarks/item.js
index 744a5d002df..ff508f77c90 100644
--- a/chromium/chrome/browser/resources/bookmarks/item.js
+++ b/chromium/chrome/browser/resources/bookmarks/item.js
@@ -76,7 +76,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
this.watch('item_', store => store.nodes[this.itemId]);
this.watch(
'isSelectedItem_', store => store.selection.items.has(this.itemId));
@@ -85,12 +85,12 @@ Polymer({
this.updateFromStore();
},
- focusMenuButton: function() {
+ focusMenuButton() {
focusWithoutInk(this.$.menuButton);
},
/** @return {BookmarksItemElement} */
- getDropTarget: function() {
+ getDropTarget() {
return this;
},
@@ -98,7 +98,7 @@ Polymer({
* @param {Event} e
* @private
*/
- onContextMenu_: function(e) {
+ onContextMenu_(e) {
e.preventDefault();
e.stopPropagation();
@@ -125,7 +125,7 @@ Polymer({
* @param {Event} e
* @private
*/
- onMenuButtonClick_: function(e) {
+ onMenuButtonClick_(e) {
e.stopPropagation();
e.preventDefault();
@@ -141,7 +141,7 @@ Polymer({
},
/** @private */
- selectThisItem_: function() {
+ selectThisItem_() {
this.dispatch(selectItem(this.itemId, this.getState(), {
clear: true,
range: false,
@@ -150,7 +150,7 @@ Polymer({
},
/** @private */
- onItemIdChanged_: function() {
+ onItemIdChanged_() {
// TODO(tsergeant): Add a histogram to measure whether this assertion fails
// for real users.
assert(this.getState().nodes[this.itemId]);
@@ -158,7 +158,7 @@ Polymer({
},
/** @private */
- onItemChanged_: function() {
+ onItemChanged_() {
this.isFolder_ = !this.item_.url;
this.setAttribute(
'aria-label',
@@ -170,10 +170,10 @@ Polymer({
* @param {MouseEvent} e
* @private
*/
- onClick_: function(e) {
+ onClick_(e) {
// Ignore double clicks so that Ctrl double-clicking an item won't deselect
// the item before opening.
- if (e.detail != 2) {
+ if (e.detail !== 2) {
const addKey = isMac ? e.metaKey : e.ctrlKey;
this.dispatch(selectItem(this.itemId, this.getState(), {
clear: !addKey,
@@ -189,10 +189,10 @@ Polymer({
* @private
* @param {KeyboardEvent} e
*/
- onKeydown_: function(e) {
- if (e.key == 'ArrowLeft') {
+ onKeydown_(e) {
+ if (e.key === 'ArrowLeft') {
this.focus();
- } else if (e.key == 'ArrowRight') {
+ } else if (e.key === 'ArrowRight') {
this.$.menuButton.focus();
}
},
@@ -201,7 +201,7 @@ Polymer({
* @param {MouseEvent} e
* @private
*/
- onDblClick_: function(e) {
+ onDblClick_(e) {
if (!this.isSelectedItem_) {
this.selectThisItem_();
}
@@ -217,8 +217,8 @@ Polymer({
* @param {MouseEvent} e
* @private
*/
- onMiddleClick_: function(e) {
- if (e.button != 1) {
+ onMiddleClick_(e) {
+ if (e.button !== 1) {
return;
}
@@ -239,7 +239,7 @@ Polymer({
* @param {TouchEvent} e
* @private
*/
- onTouchStart_: function(e) {
+ onTouchStart_(e) {
this.lastTouchPoints_ = e.touches.length;
},
@@ -249,8 +249,8 @@ Polymer({
* @param {MouseEvent} e
* @private
*/
- cancelMiddleMouseBehavior_: function(e) {
- if (e.button == 1) {
+ cancelMiddleMouseBehavior_(e) {
+ if (e.button === 1) {
e.preventDefault();
}
},
@@ -259,7 +259,7 @@ Polymer({
* @param {string} url
* @private
*/
- updateFavicon_: function(url) {
+ updateFavicon_(url) {
this.$.icon.className = url ? 'website-icon' : 'folder-icon';
this.$.icon.style.backgroundImage =
url ? getFaviconForPageURL(url, false) : '';
@@ -269,7 +269,7 @@ Polymer({
* @return {string}
* @private
*/
- getButtonAriaLabel_: function() {
+ getButtonAriaLabel_() {
if (!this.item_) {
return ''; // Item hasn't loaded, skip for now.
}
@@ -287,7 +287,7 @@ Polymer({
* @return {boolean}
* @private
*/
- isMultiSelectMenu_: function() {
+ isMultiSelectMenu_() {
return this.isSelectedItem_ && this.isMultiSelect_;
},
});
diff --git a/chromium/chrome/browser/resources/bookmarks/list.html b/chromium/chrome/browser/resources/bookmarks/list.html
index a03d4f3400c..37642ab8420 100644
--- a/chromium/chrome/browser/resources/bookmarks/list.html
+++ b/chromium/chrome/browser/resources/bookmarks/list.html
@@ -11,9 +11,9 @@
}
#list {
- @apply --cr-card-elevation;
background-color: var(--cr-card-background-color);
border-radius: var(--cr-card-border-radius);
+ box-shadow: var(--cr-card-shadow);
margin: 0 auto;
max-width: var(--card-max-width);
padding: 8px 0;
@@ -31,6 +31,10 @@
user-select: none;
white-space: nowrap;
}
+
+ [role='row']:focus-within {
+ z-index: 1;
+ }
</style>
<iron-list id="list"
items="[[displayedList_]]"
diff --git a/chromium/chrome/browser/resources/bookmarks/list.js b/chromium/chrome/browser/resources/bookmarks/list.js
index 009e98fef93..27fc650d9ae 100644
--- a/chromium/chrome/browser/resources/bookmarks/list.js
+++ b/chromium/chrome/browser/resources/bookmarks/list.js
@@ -43,7 +43,7 @@ Polymer({
*/
displayedList_: {
type: Array,
- value: function() {
+ value() {
// Use an empty list during initialization so that the databinding to
// hide #list takes effect.
return [];
@@ -78,7 +78,7 @@ Polymer({
'open-command-menu': 'onOpenCommandMenu_',
},
- attached: function() {
+ attached() {
const list = /** @type {IronListElement} */ (this.$.list);
list.scrollTarget = this;
@@ -106,13 +106,13 @@ Polymer({
});
},
- detached: function() {
+ detached() {
document.removeEventListener(
'highlight-items', this.boundOnHighlightItems_);
},
/** @return {HTMLElement} */
- getDropTarget: function() {
+ getDropTarget() {
return /** @type {!HTMLDivElement} */ (this.$.message);
},
@@ -130,10 +130,11 @@ Polymer({
if (this.matches(':focus-within')) {
if (this.selectedItems_.size > 0) {
const selectedId = Array.from(this.selectedItems_)[0];
- skipFocus = newValue.some(id => id == selectedId);
- selectIndex = this.displayedList_.findIndex(({id}) => selectedId == id);
+ skipFocus = newValue.some(id => id === selectedId);
+ selectIndex =
+ this.displayedList_.findIndex(({id}) => selectedId === id);
}
- if (selectIndex == -1 && updatedList.length > 0) {
+ if (selectIndex === -1 && updatedList.length > 0) {
selectIndex = 0;
} else {
selectIndex = Math.min(selectIndex, updatedList.length - 1);
@@ -160,7 +161,7 @@ Polymer({
},
/** @private */
- onDisplayedListSourceChange_: function() {
+ onDisplayedListSourceChange_() {
this.scrollTop = 0;
},
@@ -169,7 +170,7 @@ Polymer({
* @param {string} itemId
* @private
*/
- scrollToId_: function(itemId) {
+ scrollToId_(itemId) {
const index = this.displayedIds_.indexOf(itemId);
const list = this.$.list;
if (index >= 0 && index < list.firstVisibleIndex ||
@@ -179,7 +180,7 @@ Polymer({
},
/** @private */
- emptyListMessage_: function() {
+ emptyListMessage_() {
let emptyListMessage = 'noSearchResults';
if (!this.searchTerm_) {
emptyListMessage =
@@ -191,12 +192,12 @@ Polymer({
},
/** @private */
- isEmptyList_: function() {
- return this.displayedList_.length == 0;
+ isEmptyList_() {
+ return this.displayedList_.length === 0;
},
/** @private */
- deselectItems_: function() {
+ deselectItems_() {
this.dispatch(deselectItems());
},
@@ -204,17 +205,17 @@ Polymer({
* @param{HTMLElement} el
* @private
*/
- getIndexForItemElement_: function(el) {
+ getIndexForItemElement_(el) {
return this.$.list.modelForElement(el).index;
},
/**
- * @param {Event} e
+ * @param {!CustomEvent<{source: !MenuSource}>} e
* @private
*/
- onOpenCommandMenu_: function(e) {
+ onOpenCommandMenu_(e) {
// If the item is not visible, scroll to it before rendering the menu.
- if (e.source == MenuSource.ITEM) {
+ if (e.detail.source === MenuSource.ITEM) {
this.scrollToId_(
/** @type {BookmarksItemElement} */ (e.composedPath()[0]).itemId);
}
@@ -226,12 +227,12 @@ Polymer({
* @param {Event} e
* @private
*/
- onHighlightItems_: function(e) {
+ onHighlightItems_(e) {
// Ensure that we only select items which are actually being displayed.
// This should only matter if an unrelated update to the bookmark model
// happens with the perfect timing to end up in a tracked batch update.
const toHighlight = /** @type {!Array<string>} */
- (e.detail.filter((item) => this.displayedIds_.indexOf(item) != -1));
+ (e.detail.filter((item) => this.displayedIds_.indexOf(item) !== -1));
if (toHighlight.length <= 0) {
return;
@@ -244,7 +245,7 @@ Polymer({
this.async(function() {
this.scrollToId_(leadId);
const leadIndex = this.displayedIds_.indexOf(leadId);
- assert(leadIndex != -1);
+ assert(leadIndex !== -1);
this.$.list.focusItem(leadIndex);
});
},
@@ -253,7 +254,7 @@ Polymer({
* @param {Event} e
* @private
*/
- onItemKeydown_: function(e) {
+ onItemKeydown_(e) {
let handled = true;
const list = this.$.list;
let focusMoved = false;
@@ -261,20 +262,20 @@ Polymer({
this.getIndexForItemElement_(/** @type {HTMLElement} */ (e.target));
const oldFocusedIndex = focusedIndex;
const cursorModifier = isMac ? e.metaKey : e.ctrlKey;
- if (e.key == 'ArrowUp') {
+ if (e.key === 'ArrowUp') {
focusedIndex--;
focusMoved = true;
- } else if (e.key == 'ArrowDown') {
+ } else if (e.key === 'ArrowDown') {
focusedIndex++;
focusMoved = true;
e.preventDefault();
- } else if (e.key == 'Home') {
+ } else if (e.key === 'Home') {
focusedIndex = 0;
focusMoved = true;
- } else if (e.key == 'End') {
+ } else if (e.key === 'End') {
focusedIndex = list.items.length - 1;
focusMoved = true;
- } else if (e.key == ' ' && cursorModifier) {
+ } else if (e.key === ' ' && cursorModifier) {
this.dispatch(
selectItem(this.displayedIds_[focusedIndex], this.getState(), {
clear: false,
@@ -293,7 +294,7 @@ Polymer({
this.dispatch(updateAnchor(this.displayedIds_[focusedIndex]));
} else {
// If shift-selecting with no anchor, use the old focus index.
- if (e.shiftKey && this.getState().selection.anchor == null) {
+ if (e.shiftKey && this.getState().selection.anchor === null) {
this.dispatch(updateAnchor(this.displayedIds_[oldFocusedIndex]));
}
@@ -311,8 +312,8 @@ Polymer({
}
// Prevent the iron-list from changing focus on enter.
- if (e.key == 'Enter') {
- if (e.composedPath()[0].tagName == 'CR-ICON-BUTTON') {
+ if (e.key === 'Enter') {
+ if (e.composedPath()[0].tagName === 'CR-ICON-BUTTON') {
return;
}
if (e.composedPath()[0] instanceof HTMLButtonElement) {
@@ -334,7 +335,7 @@ Polymer({
* @param {Event} e
* @private
*/
- onContextMenu_: function(e) {
+ onContextMenu_(e) {
e.preventDefault();
this.deselectItems_();
@@ -351,7 +352,7 @@ Polymer({
* @return {number}
* @private
*/
- getAriaRowindex_: function(index) {
+ getAriaRowindex_(index) {
return index + 1;
},
});
diff --git a/chromium/chrome/browser/resources/bookmarks/mouse_focus_behavior.js b/chromium/chrome/browser/resources/bookmarks/mouse_focus_behavior.js
index 22ef6349dfe..67409966b2f 100644
--- a/chromium/chrome/browser/resources/bookmarks/mouse_focus_behavior.js
+++ b/chromium/chrome/browser/resources/bookmarks/mouse_focus_behavior.js
@@ -12,7 +12,7 @@ export const HIDE_FOCUS_RING_ATTRIBUTE = 'hide-focus-ring';
* @polymerBehavior
*/
export const MouseFocusBehavior = {
- attached: function() {
+ attached() {
this.boundOnMousedown_ = this.onMousedown_.bind(this);
this.boundOnKeydown = this.onKeydown_.bind(this);
@@ -24,13 +24,13 @@ export const MouseFocusBehavior = {
document.addEventListener('keydown', this.boundOnKeydown, true);
},
- detached: function() {
+ detached() {
document.removeEventListener('mousedown', this.boundOnMousedown_, true);
document.removeEventListener('keydown', this.boundOnKeydown, true);
},
/** @private */
- onMousedown_: function() {
+ onMousedown_() {
this.setAttribute(HIDE_FOCUS_RING_ATTRIBUTE, '');
},
@@ -38,7 +38,7 @@ export const MouseFocusBehavior = {
* @param {KeyboardEvent} e
* @private
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
if (!['Shift', 'Alt', 'Control', 'Meta'].includes(e.key)) {
this.removeAttribute(HIDE_FOCUS_RING_ATTRIBUTE);
}
diff --git a/chromium/chrome/browser/resources/bookmarks/reducers.js b/chromium/chrome/browser/resources/bookmarks/reducers.js
index 287b94e6aad..ea2453167ee 100644
--- a/chromium/chrome/browser/resources/bookmarks/reducers.js
+++ b/chromium/chrome/browser/resources/bookmarks/reducers.js
@@ -101,7 +101,7 @@ export function updateSelection(selection, action) {
// Deselect items when they are moved to another folder, since they will
// no longer be visible on screen (for simplicity, ignores items visible
// in search results).
- if (action.parentId != action.oldParentId &&
+ if (action.parentId !== action.oldParentId &&
selection.items.has(action.id)) {
return deselectItems(selection, new Set([action.id]));
}
@@ -259,7 +259,7 @@ function moveBookmark(nodes, action) {
// Add to new parent.
const parentId = action.parentId;
- const parentChildren = oldParentId == parentId ?
+ const parentChildren = oldParentId === parentId ?
oldParentChildren :
nodes[parentId].children.slice();
parentChildren.splice(action.index, 0, action.id);
@@ -332,7 +332,7 @@ function isAncestorOf(nodes, ancestorId, childId) {
let currentId = childId;
// Work upwards through the tree from child.
while (currentId) {
- if (currentId == ancestorId) {
+ if (currentId === ancestorId) {
return true;
}
currentId = nodes[currentId].parentId;
diff --git a/chromium/chrome/browser/resources/bookmarks/router.js b/chromium/chrome/browser/resources/bookmarks/router.js
index 4a0aaaac41d..08f44cb649f 100644
--- a/chromium/chrome/browser/resources/bookmarks/router.js
+++ b/chromium/chrome/browser/resources/bookmarks/router.js
@@ -60,7 +60,7 @@ Polymer({
'onStateChanged_(searchTerm_, selectedId_)',
],
- attached: function() {
+ attached() {
this.watch('selectedId_', function(state) {
return state.selectedFolder;
});
@@ -71,19 +71,19 @@ Polymer({
},
/** @private */
- onQueryParamsChanged_: function() {
+ onQueryParamsChanged_() {
const searchTerm = this.queryParams_.q || '';
let selectedId = this.queryParams_.id;
if (!selectedId && !searchTerm) {
selectedId = BOOKMARKS_BAR_ID;
}
- if (searchTerm != this.searchTerm_) {
+ if (searchTerm !== this.searchTerm_) {
this.searchTerm_ = searchTerm;
this.dispatch(setSearchTerm(searchTerm));
}
- if (selectedId && selectedId != this.selectedId_) {
+ if (selectedId && selectedId !== this.selectedId_) {
this.selectedId_ = selectedId;
// Need to dispatch a deferred action so that during page load
// `this.getState()` will only evaluate after the Store is initialized.
@@ -98,27 +98,27 @@ Polymer({
* @param {?string} previous Previous value of the query.
* @private
*/
- onQueryChanged_: function(current, previous) {
+ onQueryChanged_(current, previous) {
if (previous !== undefined) {
this.urlQuery_ = this.query_;
}
},
/** @private */
- onUrlQueryChanged_: function() {
+ onUrlQueryChanged_() {
this.query_ = this.urlQuery_;
},
/** @private */
- onStateChanged_: function() {
+ onStateChanged_() {
this.debounce('updateQueryParams', this.updateQueryParams_.bind(this));
},
/** @private */
- updateQueryParams_: function() {
+ updateQueryParams_() {
if (this.searchTerm_) {
this.queryParams_ = {q: this.searchTerm_};
- } else if (this.selectedId_ != BOOKMARKS_BAR_ID) {
+ } else if (this.selectedId_ !== BOOKMARKS_BAR_ID) {
this.queryParams_ = {id: this.selectedId_};
} else {
this.queryParams_ = {};
diff --git a/chromium/chrome/browser/resources/bookmarks/store_client.js b/chromium/chrome/browser/resources/bookmarks/store_client.js
index 60025943ddb..a53697ca5c7 100644
--- a/chromium/chrome/browser/resources/bookmarks/store_client.js
+++ b/chromium/chrome/browser/resources/bookmarks/store_client.js
@@ -21,21 +21,21 @@ const BookmarksStoreClientImpl = {
* @param {string} localProperty
* @param {function(Object)} valueGetter
*/
- watch: function(localProperty, valueGetter) {
+ watch(localProperty, valueGetter) {
this.watch_(localProperty, valueGetter);
},
/**
* @return {BookmarksPageState}
*/
- getState: function() {
+ getState() {
return this.getStore().data;
},
/**
* @return {Store}
*/
- getStore: function() {
+ getStore() {
return Store.getInstance();
},
};
diff --git a/chromium/chrome/browser/resources/bookmarks/toolbar.js b/chromium/chrome/browser/resources/bookmarks/toolbar.js
index 4a2457293c6..94ecd659a88 100644
--- a/chromium/chrome/browser/resources/bookmarks/toolbar.js
+++ b/chromium/chrome/browser/resources/bookmarks/toolbar.js
@@ -59,7 +59,7 @@ Polymer({
globalCanEdit_: Boolean,
},
- attached: function() {
+ attached() {
this.watch('searchTerm_', function(state) {
return state.search.term;
});
@@ -82,7 +82,7 @@ Polymer({
* @param {Event} e
* @private
*/
- onMenuButtonOpenTap_: function(e) {
+ onMenuButtonOpenTap_(e) {
this.fire('open-command-menu', {
targetElement: e.target,
source: MenuSource.TOOLBAR,
@@ -90,7 +90,7 @@ Polymer({
},
/** @private */
- onDeleteSelectionTap_: function() {
+ onDeleteSelectionTap_() {
const selection = this.selectedItems_;
const commandManager = CommandManager.getInstance();
assert(commandManager.canExecute(Command.DELETE, selection));
@@ -98,7 +98,7 @@ Polymer({
},
/** @private */
- onClearSelectionTap_: function() {
+ onClearSelectionTap_() {
this.dispatch(deselectItems());
},
@@ -106,19 +106,19 @@ Polymer({
* @param {!CustomEvent<string>} e
* @private
*/
- onSearchChanged_: function(e) {
- if (e.detail != this.searchTerm_) {
+ onSearchChanged_(e) {
+ if (e.detail !== this.searchTerm_) {
this.dispatch(setSearchTerm(e.detail));
}
},
/** @private */
- onSidebarWidthChanged_: function() {
+ onSidebarWidthChanged_() {
this.style.setProperty('--sidebar-width', this.sidebarWidth);
},
/** @private */
- onSearchTermChanged_: function() {
+ onSearchTermChanged_() {
this.searchField.setValue(this.searchTerm_ || '');
},
@@ -126,7 +126,7 @@ Polymer({
* @return {boolean}
* @private
*/
- shouldShowSelectionOverlay_: function() {
+ shouldShowSelectionOverlay_() {
return this.selectedItems_.size > 1 && this.globalCanEdit_;
},
@@ -134,7 +134,7 @@ Polymer({
* @return {boolean}
* @private
*/
- canDeleteSelection_: function() {
+ canDeleteSelection_() {
return this.showSelectionOverlay &&
CommandManager.getInstance().canExecute(
Command.DELETE, this.selectedItems_);
@@ -144,7 +144,7 @@ Polymer({
* @return {string}
* @private
*/
- getItemsSelectedString_: function() {
+ getItemsSelectedString_() {
return loadTimeData.getStringF('itemsSelected', this.selectedItems_.size);
},
});
diff --git a/chromium/chrome/browser/resources/bookmarks/util.js b/chromium/chrome/browser/resources/bookmarks/util.js
index 8053b7f2154..cbe9aa0c072 100644
--- a/chromium/chrome/browser/resources/bookmarks/util.js
+++ b/chromium/chrome/browser/resources/bookmarks/util.js
@@ -110,8 +110,8 @@ export function isShowingSearch(state) {
* @return {boolean}
*/
export function canEditNode(state, itemId) {
- return itemId != ROOT_NODE_ID &&
- state.nodes[itemId].parentId != ROOT_NODE_ID &&
+ return itemId !== ROOT_NODE_ID &&
+ state.nodes[itemId].parentId !== ROOT_NODE_ID &&
!state.nodes[itemId].unmodifiable && state.prefs.canEdit;
}
@@ -123,7 +123,7 @@ export function canEditNode(state, itemId) {
* @return {boolean}
*/
export function canReorderChildren(state, itemId) {
- return itemId != ROOT_NODE_ID && !state.nodes[itemId].unmodifiable &&
+ return itemId !== ROOT_NODE_ID && !state.nodes[itemId].unmodifiable &&
state.prefs.canEdit;
}
diff --git a/chromium/chrome/browser/resources/browser_switch/BUILD.gn b/chromium/chrome/browser/resources/browser_switch/BUILD.gn
index 7b25cc542d0..6e61ba0d07a 100644
--- a/chromium/chrome/browser/resources/browser_switch/BUILD.gn
+++ b/chromium/chrome/browser/resources/browser_switch/BUILD.gn
@@ -23,9 +23,7 @@ js_library("app") {
}
js_library("browser_switch_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
}
polymer_modulizer("app") {
diff --git a/chromium/chrome/browser/resources/browser_switch/app.html b/chromium/chrome/browser/resources/browser_switch/app.html
index 69890063617..c79562c0827 100644
--- a/chromium/chrome/browser/resources/browser_switch/app.html
+++ b/chromium/chrome/browser/resources/browser_switch/app.html
@@ -1,8 +1,9 @@
<style>
:host {
- @apply --cr-card-elevation;
background-color: var(--cr-card-background-color);
border-radius: var(--cr-card-border-radius);
+ box-shadow: var(--cr-card-shadow);
+ color: var(--cr-primary-text-color);
display: block;
margin: 16px;
max-width: 640px;
@@ -11,7 +12,6 @@
}
h1 {
- color: var(--cr-primary-text-color);
font-size: 1rem;
font-weight: 500;
margin: 0;
@@ -19,13 +19,22 @@
}
p {
- color: var(--cr-primary-text-color);
/* Should be 13px when html font-size is 16px */
font-size: 0.8125rem;
margin: 0;
max-width: 450px;
}
+
+ iron-icon {
+ height: 24px;
+ margin-inline-end: 0.5rem;
+ margin-top: -0.4rem;
+ width: 24px;
+ }
</style>
-<h1>[[computeTitle_(error_, secondCounter_)]]</h1>
+<h1>
+ <iron-icon icon="cr:domain"></iron-icon>
+ [[computeTitle_(error_, secondCounter_)]]
+</h1>
<p inner-h-t-m-l="[[computeDescription_(url_, error_)]]"></p>
diff --git a/chromium/chrome/browser/resources/browser_switch/app.js b/chromium/chrome/browser/resources/browser_switch/app.js
index 6e4522ed222..32578aa083b 100644
--- a/chromium/chrome/browser/resources/browser_switch/app.js
+++ b/chromium/chrome/browser/resources/browser_switch/app.js
@@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'chrome://resources/cr_elements/icons.m.js';
import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
import './strings.m.js';
import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
@@ -34,7 +36,7 @@ Polymer({
*/
url_: {
type: String,
- value: function() {
+ value() {
return (new URLSearchParams(window.location.search)).get('url') || '';
},
},
@@ -60,7 +62,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
// If '?done=...' is specified in the URL, this tab was-reopened, or the
// entire browser was closed by LBS and re-opened. In that case, go to NTP
// instead.
@@ -84,7 +86,7 @@ Polymer({
},
/** @private */
- launchAndCloseTab_: function() {
+ launchAndCloseTab_() {
// Mark this page with '?done=...' so that restoring the tab doesn't
// immediately re-trigger LBS.
history.pushState({}, '', '/?done=true');
@@ -98,7 +100,7 @@ Polymer({
* @param {number} seconds
* @private
*/
- startCountdown_: function(seconds) {
+ startCountdown_(seconds) {
this.secondCounter_ = seconds;
const intervalId = setInterval(() => {
this.secondCounter_--;
@@ -112,7 +114,7 @@ Polymer({
* @return {string}
* @private
*/
- computeTitle_: function() {
+ computeTitle_() {
if (this.error_) {
return this.i18n('errorTitle', getBrowserName());
}
@@ -126,7 +128,7 @@ Polymer({
* @return {string}
* @private
*/
- computeDescription_: function() {
+ computeDescription_() {
if (this.error_) {
return this.i18n(
this.error_, getUrlHostname(this.url_), getBrowserName());
diff --git a/chromium/chrome/browser/resources/browser_switch/internals/BUILD.gn b/chromium/chrome/browser/resources/browser_switch/internals/BUILD.gn
index a5bdb4911b9..570cc867b5e 100644
--- a/chromium/chrome/browser/resources/browser_switch/internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/browser_switch/internals/BUILD.gn
@@ -5,14 +5,13 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":browser_switch_internals",
- ]
+ uses_js_modules = true
+ deps = [ ":browser_switch_internals" ]
}
js_library("browser_switch_internals") {
deps = [
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:util",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:util.m",
]
}
diff --git a/chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.html b/chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.html
index 05f5edf80ad..14fbf5fb85c 100644
--- a/chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.html
+++ b/chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.html
@@ -4,10 +4,6 @@
<meta charset="utf-8">
<title>Legacy Browser Support Internals</title>
- <script src="chrome://resources/js/promise_resolver.js"></script>
- <script src="chrome://resources/js/cr.js"></script>
- <script src="chrome://resources/js/util.js"></script>
-
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
<style>
@@ -129,6 +125,6 @@
</tr>
</template>
- <script src="/internals/browser_switch_internals.js"></script>
+ <script type="module" src="/internals/browser_switch_internals.js"></script>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.js b/chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.js
index 2b57bf2a681..b79d221a88d 100644
--- a/chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.js
+++ b/chromium/chrome/browser/resources/browser_switch/internals/browser_switch_internals.js
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-'use strict';
+import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
/**
* @typedef {{
@@ -121,7 +122,7 @@ function checkUrl() {
$('output').innerText = '';
return;
}
- cr.sendWithPromise('getDecision', url)
+ sendWithPromise('getDecision', url)
.then(decision => {
// URL is valid.
$('output').innerText = JSON.stringify(decision, null, 2);
@@ -208,9 +209,9 @@ function updateXmlTable({browser_switcher: sources}) {
* Called by C++ when we need to update everything on the page.
*/
function updateEverything() {
- cr.sendWithPromise('getAllRulesets').then(updateTables);
- cr.sendWithPromise('getTimestamps').then(updateTimestamps);
- cr.sendWithPromise('getRulesetSources').then(updateXmlTable);
+ sendWithPromise('getAllRulesets').then(updateTables);
+ sendWithPromise('getTimestamps').then(updateTimestamps);
+ sendWithPromise('getRulesetSources').then(updateXmlTable);
checkUrl();
}
diff --git a/chromium/chrome/browser/resources/chrome_urls_disabled_page/app.html b/chromium/chrome/browser/resources/chrome_urls_disabled_page/app.html
new file mode 100644
index 00000000000..df789944c83
--- /dev/null
+++ b/chromium/chrome/browser/resources/chrome_urls_disabled_page/app.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
+<meta charset="utf-8">
+<meta name="viewport"
+ content="initial-scale=1, minimum-scale=1,width=device-width">
+<title>$i18n{disabledPageTitle}</title>
+<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+</head>
+<body id="chrome-urls-disabled-block">
+ <div class ="frame-disabled">
+ <div id="information-container">
+ <div id="main-message">
+ <h1 id="disabled-page-header">$i18n{disabledPageHeader}</h1>
+ <p id="disabled-message"> $i18n{disabledPageMessage}</p>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/chromium/chrome/browser/resources/chromeos/BUILD.gn b/chromium/chrome/browser/resources/chromeos/BUILD.gn
index 95900fbae81..d4f57c718a8 100644
--- a/chromium/chrome/browser/resources/chromeos/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/BUILD.gn
@@ -47,12 +47,10 @@ grit("camera_resources") {
output_dir = "$root_gen_dir/chrome"
deps = [
+ "//components/arc/mojom:camera_intent_js",
"//media/capture/video/chromeos/mojom:cros_camera_js",
]
- # The .grd contains references to generated files.
- source_is_generated = true
-
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
@@ -68,10 +66,12 @@ group("closure_compile") {
"bluetooth_pairing_dialog:closure_compile",
"camera/src/js:closure_compile",
"crostini_installer:closure_compile",
+ "edu_login:closure_compile",
"emulator:closure_compile",
"internet_config_dialog:closure_compile",
"internet_detail_dialog:closure_compile",
"login:closure_compile",
+ "login/components:closure_compile",
"machine_learning:closure_compile",
"multidevice_setup:closure_compile",
"network_ui:closure_compile",
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/BUILD.gn
new file mode 100644
index 00000000000..0f4967d66af
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/BUILD.gn
@@ -0,0 +1,115 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+import("//chrome/common/features.gni")
+import("//chromecast/chromecast.gni")
+import("strings/accessibility_strings.gni")
+
+assert(is_chromeos || is_chromecast)
+
+accessibility_out_dir = "$root_out_dir/resources/chromeos/accessibility/"
+
+group("build") {
+ deps = [
+ ":accessibility_strings",
+ ":chromevox_guest_manifest",
+ ":chromevox_manifest",
+ "chromevox:build",
+ "common:build",
+ ]
+ if (is_chromeos) {
+ deps += [
+ ":select_to_speak_guest_manifest",
+ ":select_to_speak_manifest",
+ ":switch_access_guest_manifest",
+ ":switch_access_manifest",
+ "autoclick:build",
+ "select_to_speak:build",
+ "switch_access:build",
+ ]
+ }
+}
+
+template("manifest") {
+ version_file = "//chrome/VERSION"
+ version_script = "//build/util/version.py"
+ template_file = invoker.input_file
+ output_file = invoker.output_file
+ key = invoker.key
+ action(target_name) {
+ script = "//chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_manifest.py"
+ inputs = [
+ version_file,
+ version_script,
+ ]
+ sources = [ template_file ]
+ outputs = [ output_file ]
+ args = [
+ "--key=$key",
+ "--version_file=" + rebase_path(version_file, root_build_dir),
+ "--output_manifest=" + rebase_path(output_file, root_build_dir),
+ ]
+ if (defined(invoker.is_guest_manifest) && invoker.is_guest_manifest) {
+ args += [ "--is_guest_manifest=1" ]
+ }
+ args += rebase_path(sources, root_build_dir)
+ }
+}
+
+manifest("chromevox_manifest") {
+ input_file = "chromevox_manifest.json.jinja2"
+ output_file = "$accessibility_out_dir/chromevox_manifest.json"
+ key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDltVl1k15pjRzuZfMc3B69inxwm2bZeZ2O8/zFO+NluHnBm3GJ3fzdOoFGJd+M16I8p7zxxQyHeDMfWYASyCeB8XnUEDKjqNLQfCnncsANzHsYoEbYj2nEUML2P13b9q+AAvpCBpAJ4cZp81e9n1y/vbSXHE4385cgkKueItzikQIDAQAB"
+}
+
+manifest("chromevox_guest_manifest") {
+ input_file = "chromevox_manifest.json.jinja2"
+ output_file = "$accessibility_out_dir/chromevox_manifest_guest.json"
+ key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDltVl1k15pjRzuZfMc3B69inxwm2bZeZ2O8/zFO+NluHnBm3GJ3fzdOoFGJd+M16I8p7zxxQyHeDMfWYASyCeB8XnUEDKjqNLQfCnncsANzHsYoEbYj2nEUML2P13b9q+AAvpCBpAJ4cZp81e9n1y/vbSXHE4385cgkKueItzikQIDAQAB"
+ is_guest_manifest = true
+}
+
+manifest("select_to_speak_manifest") {
+ input_file = "select_to_speak_manifest.json.jinja2"
+ output_file = "$accessibility_out_dir/select_to_speak_manifest.json"
+ key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAukZ6JJWr0jHmFTkn0pcigpjI+cP0FqTo8FRIcCwy2fPeM+Ymf+7C9MK642i+Nhdr2qSsRF26AMIKbBdSDUnh04bfg5J/rKa/VO88LvXENYQMGhTo1y9mVg2OsbQJtEL9aTLU2G0SoKcr3g/+lggBKR5ydW1Qa0WGGAM9XrLm8iu/wn2uF4mfcMii6KfyEsAwWalpr/Td5WbtIoNNDpNeKO4ZSZJis1n9PZXqaOKpW7PqFDpEHw2PnPATxkcqj/wIx+Shgada0fhrzMlhXLhhj7ThSSWbuTz5n5NebuQ49/Z2ATgpBCSzYBVXEXMDe6LBBtGiZ/QR9UkA8Lz8bP6xIQIDAQAB"
+}
+
+manifest("select_to_speak_guest_manifest") {
+ input_file = "select_to_speak_manifest.json.jinja2"
+ output_file = "$accessibility_out_dir/select_to_speak_manifest_guest.json"
+ key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAukZ6JJWr0jHmFTkn0pcigpjI+cP0FqTo8FRIcCwy2fPeM+Ymf+7C9MK642i+Nhdr2qSsRF26AMIKbBdSDUnh04bfg5J/rKa/VO88LvXENYQMGhTo1y9mVg2OsbQJtEL9aTLU2G0SoKcr3g/+lggBKR5ydW1Qa0WGGAM9XrLm8iu/wn2uF4mfcMii6KfyEsAwWalpr/Td5WbtIoNNDpNeKO4ZSZJis1n9PZXqaOKpW7PqFDpEHw2PnPATxkcqj/wIx+Shgada0fhrzMlhXLhhj7ThSSWbuTz5n5NebuQ49/Z2ATgpBCSzYBVXEXMDe6LBBtGiZ/QR9UkA8Lz8bP6xIQIDAQAB"
+ is_guest_manifest = true
+}
+
+manifest("switch_access_manifest") {
+ input_file = "switch_access_manifest.json.jinja2"
+ output_file = "$accessibility_out_dir/switch_access_manifest.json"
+ key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVWTYdXNGhIG6FJKIhaohRRrYYGwg9cR2jea2NRBSEg+T7E3EvUyFy0ouez0N0omeSAL/xlvQtCjZJ72eCqDBgON/49SRtUdLS5TQ2U9cHYcIwI86llKMqqws6uMSwlWXldyNwKx5LVT1nR0+x3J744E2mymCSip2Y+NrGEA2yCUFL8D+O/uS+d5pVFb3NNjPTVbNOlhIs5ZUVX3FBij86ILivoSfRZMIZqK7MU8XDT1zolpFPiSYvDh1Qivwqar0pVYmNbCSjEgbGIuQh7zMaMdHC1HtvjbI20XFzWHyP/cW2YKszlfqawH+kdHSp4ANIjc7GCAjGJNxm33iMNwcFAgMBAAECggEAL47YakkzjZheKp3U6mAGDSAXHV6BQrkBY1yPXGstq7B/DZzy4RrF3QOkDf2jys8dCUXTg7YjrhqVqXuNdmmphvmGq8dxnFDeDxb6wZWE3GdlUzfYK77rdGp2cVuYtMhI05LwOmPSN/bDXk9eK4bDhTTy+lgomOH/aYcntXkEpIfVQ1kVs7RLvBs3tF3QfsL7t+aqphUlbyVRxCzogK3EDnLD0NODrydx5xB2UMKcxrQD8mVl8IhyBUeluWmcqVkIv7z9C9Y6s9HgcQdxsxhClymAsXtjkZVyP/xst9iwIxOyTijffcqbQOPtB9w1d7GWUrdpwCys0TveJslU7zo6jQKBgQD3VOJSiJuENck71q2Sg4yP0ytBNWVO7xLeTDc6OPEuhqtennWYFeprdplL8aejHqPFiNi7L2QVguP1JDLWPPu+RHHsZDtvG+stssE9Z+oVzBowDJZO1EvBH7nvqgxFz4utoDIrQmkbCcsBqOqwv1i7UdJ0DPIofZE/u0G8wONriwKBgQDc02xS5HZ8ysxEdhL9dC8FSvd12lHocEuBML5ufCkK4SUo8EFeg8k+2UVwd0xXwFNv3nKRPfr/yOQ0CRlKTo3IXXj4Uie+ww3j1jWIMPzC5Oo7IUHRd69KfLvG5N9byGv4wdsPKsXsGrUlvP4meD1U9fujxJdE9RC9evZss33prwKBgAQE7BydPbG7UgbX6UAtRRZ9PwGzRW8v8WWNZYRbsoeoBpbmClErYgDXD4ytY6UB9XVbUPJRxdWXp+6u5OiYWxrvb86AnnqiwIKgmgVOb/5kr7RCMBsd1hFQW6wqXkKwKbvrk4UiciTPVu4y+YVfxqhcnwflwfWofLjFaT8Q/2EbAoGANkdtr+5iRYhfr1BKmKwvRqDHtNtGGNlJZecCWAwC1p7C0I5FsyK3m9AyJlPcmxE2MSA/jv3qLWdG2JeH9ODcLuzy6C7hgB1X07H6lJBeANXd0Uz6ba96kdeZHGlzkY7xI0MbQl4kKkXiUvVijzgs8y5HfVi8SgHm7HxGCDASehcCgYEAnw1yu4eaWqsq7ECyjEBM7sQcMVGypiG3VupzLKA75iPkg/E+peUZyDRg7LPCiX/UcW22bliUw1ASRzY+thuVlGWC2CPah95Z4m+H4cJVSEEqKUbYRGfsDlDIJNxPihGvhoTniKZwvpUacbAhop7rbiAVGx+RJ+tFG8P56AbvBVE="
+}
+
+manifest("switch_access_guest_manifest") {
+ input_file = "switch_access_manifest.json.jinja2"
+ output_file = "$accessibility_out_dir/switch_access_manifest_guest.json"
+ key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVWTYdXNGhIG6FJKIhaohRRrYYGwg9cR2jea2NRBSEg+T7E3EvUyFy0ouez0N0omeSAL/xlvQtCjZJ72eCqDBgON/49SRtUdLS5TQ2U9cHYcIwI86llKMqqws6uMSwlWXldyNwKx5LVT1nR0+x3J744E2mymCSip2Y+NrGEA2yCUFL8D+O/uS+d5pVFb3NNjPTVbNOlhIs5ZUVX3FBij86ILivoSfRZMIZqK7MU8XDT1zolpFPiSYvDh1Qivwqar0pVYmNbCSjEgbGIuQh7zMaMdHC1HtvjbI20XFzWHyP/cW2YKszlfqawH+kdHSp4ANIjc7GCAjGJNxm33iMNwcFAgMBAAECggEAL47YakkzjZheKp3U6mAGDSAXHV6BQrkBY1yPXGstq7B/DZzy4RrF3QOkDf2jys8dCUXTg7YjrhqVqXuNdmmphvmGq8dxnFDeDxb6wZWE3GdlUzfYK77rdGp2cVuYtMhI05LwOmPSN/bDXk9eK4bDhTTy+lgomOH/aYcntXkEpIfVQ1kVs7RLvBs3tF3QfsL7t+aqphUlbyVRxCzogK3EDnLD0NODrydx5xB2UMKcxrQD8mVl8IhyBUeluWmcqVkIv7z9C9Y6s9HgcQdxsxhClymAsXtjkZVyP/xst9iwIxOyTijffcqbQOPtB9w1d7GWUrdpwCys0TveJslU7zo6jQKBgQD3VOJSiJuENck71q2Sg4yP0ytBNWVO7xLeTDc6OPEuhqtennWYFeprdplL8aejHqPFiNi7L2QVguP1JDLWPPu+RHHsZDtvG+stssE9Z+oVzBowDJZO1EvBH7nvqgxFz4utoDIrQmkbCcsBqOqwv1i7UdJ0DPIofZE/u0G8wONriwKBgQDc02xS5HZ8ysxEdhL9dC8FSvd12lHocEuBML5ufCkK4SUo8EFeg8k+2UVwd0xXwFNv3nKRPfr/yOQ0CRlKTo3IXXj4Uie+ww3j1jWIMPzC5Oo7IUHRd69KfLvG5N9byGv4wdsPKsXsGrUlvP4meD1U9fujxJdE9RC9evZss33prwKBgAQE7BydPbG7UgbX6UAtRRZ9PwGzRW8v8WWNZYRbsoeoBpbmClErYgDXD4ytY6UB9XVbUPJRxdWXp+6u5OiYWxrvb86AnnqiwIKgmgVOb/5kr7RCMBsd1hFQW6wqXkKwKbvrk4UiciTPVu4y+YVfxqhcnwflwfWofLjFaT8Q/2EbAoGANkdtr+5iRYhfr1BKmKwvRqDHtNtGGNlJZecCWAwC1p7C0I5FsyK3m9AyJlPcmxE2MSA/jv3qLWdG2JeH9ODcLuzy6C7hgB1X07H6lJBeANXd0Uz6ba96kdeZHGlzkY7xI0MbQl4kKkXiUvVijzgs8y5HfVi8SgHm7HxGCDASehcCgYEAnw1yu4eaWqsq7ECyjEBM7sQcMVGypiG3VupzLKA75iPkg/E+peUZyDRg7LPCiX/UcW22bliUw1ASRzY+thuVlGWC2CPah95Z4m+H4cJVSEEqKUbYRGfsDlDIJNxPihGvhoTniKZwvpUacbAhop7rbiAVGx+RJ+tFG8P56AbvBVE="
+ is_guest_manifest = true
+}
+
+accessibility_strings("accessibility_strings") {
+ out_dir = accessibility_out_dir
+}
+
+group("browser_tests") {
+ testonly = true
+ if (is_chromeos) {
+ deps = [
+ "autoclick:browser_tests",
+ "chromevox:browser_tests",
+ "common:browser_tests",
+ "select_to_speak:browser_tests",
+ "switch_access:browser_tests",
+ ]
+ }
+}
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/autoclick/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/autoclick/BUILD.gn
index fe42432c110..f4cc2e8b078 100644
--- a/chromium/chrome/browser/resources/chromeos/accessibility/autoclick/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/autoclick/BUILD.gn
@@ -25,9 +25,7 @@ group("build") {
run_jsbundler("autoclick_copied_files") {
mode = "copy"
dest_dir = autoclick_dir
- sources = [
- "autoclick.js",
- ]
+ sources = [ "autoclick.js" ]
rewrite_rules = [
rebase_path(".", root_build_dir) + ":",
rebase_path(closure_library_dir, root_build_dir) + ":closure",
@@ -48,12 +46,8 @@ template("manifest") {
version_file,
version_script,
]
- sources = [
- template_file,
- ]
- outputs = [
- output_file,
- ]
+ sources = [ template_file ]
+ outputs = [ output_file ]
args = [
"--key=$key",
"--version_file=" + rebase_path(version_file, root_build_dir),
@@ -79,9 +73,7 @@ source_set("browser_tests") {
testonly = true
assert(enable_extensions)
- deps = [
- ":autoclick_extjs_tests",
- ]
+ deps = [ ":autoclick_extjs_tests" ]
data = [
"$root_out_dir/chrome_100_percent.pak",
@@ -101,9 +93,7 @@ source_set("browser_tests") {
js2gtest("autoclick_extjs_tests") {
test_type = "extension"
- sources = [
- "autoclick_test.extjs",
- ]
+ sources = [ "autoclick_test.js" ]
gen_include_files = [
"../chromevox/testing/callback_helper.js",
"mock_accessibility_private.js",
@@ -121,9 +111,7 @@ js2gtest("autoclick_extjs_tests") {
}
js_type_check("closure_compile") {
- deps = [
- ":autoclick",
- ]
+ deps = [ ":autoclick" ]
}
js_library("autoclick") {
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn
index 7e818527c8c..87c9f49a092 100644
--- a/chromium/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/braille_ime/BUILD.gn
@@ -8,9 +8,7 @@ import("//third_party/closure_compiler/compile_js.gni")
assert(is_chromeos || is_chromecast)
copy("braille_ime_manifest") {
- sources = [
- "manifest.json",
- ]
+ sources = [ "manifest.json" ]
outputs = [
"$root_out_dir/resources/chromeos/accessibility/braille_ime/manifest.json",
]
@@ -31,7 +29,5 @@ js_library("braille_ime") {
}
js_library("main") {
- deps = [
- ":braille_ime",
- ]
+ deps = [ ":braille_ime" ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
index 42866852f93..72c226e7b04 100644
--- a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -5,13 +5,9 @@
import("//build/config/features.gni")
import("//chrome/common/features.gni")
import("//chrome/test/base/js2gtest.gni")
-import("//chromecast/chromecast.gni")
import("//testing/test.gni")
import("//third_party/closure_compiler/compile_js.gni")
import("run_jsbundler.gni")
-import("strings/chromevox_strings.gni")
-
-assert(is_chromeos || is_chromecast)
declare_args() {
# Whether to compress the main Chromevox javascript files or load the
@@ -25,52 +21,22 @@ closure_library_dir =
# List of all modules that are included in one or more of the production
# chromevox scripts.
chromevox_modules = [
- "braille/braille_display_manager.js",
- "braille/braille_input_handler.js",
- "braille/braille_key_event_rewriter.js",
- "braille/braille_key_types.js",
- "braille/braille_table.js",
- "braille/braille_translator_manager.js",
- "braille/bluetooth_braille_display_manager.js",
- "braille/bluetooth_braille_display_ui.js",
- "braille/expanding_braille_translator.js",
- "braille/liblouis.js",
- "braille/nav_braille.js",
- "braille/pan_strategy.js",
- "braille/spans.js",
- "background/background.js",
- "background/classic_background.js",
- "background/braille_captions_background.js",
- "background/injected_script_loader.js",
- "background/learn_mode/kbexplorer.js",
- "background/keymaps/key_map.js",
- "background/options/options.js",
- "background/prefs.js",
- "background/tabs_api_handler.js",
- "injected/api_implementation.js",
- "injected/script_installer.js",
- "common/chromevox.js",
- "common/command_store.js",
- "common/composite_tts.js",
- "common/editable_text_base.js",
- "common/key_sequence.js",
- "common/key_util.js",
- "common/keyboard_handler.js",
- "common/msgs.js",
- "common/nav_description.js",
- "common/spannable.js",
- "common/string_util.js",
+ "background/annotation/node_identifier.js",
+ "background/annotation/user_annotation_handler.js",
"background/automation_object_constructor_installer.js",
- "background/automation_predicate.js",
- "background/automation_util.js",
+ "../common/automation_predicate.js",
+ "../common/automation_util.js",
+ "background/background.js",
"background/base_automation_handler.js",
+ "background/braille_background.js",
+ "background/braille_captions_background.js",
"background/braille_command_data.js",
"background/braille_command_handler.js",
- "background/color.js",
"background/chromevox_state.js",
+ "background/classic_background.js",
+ "background/color.js",
"background/command_handler.js",
- "common/console_tts.js",
- "background/constants.js",
+ "../common/constants.js",
"background/cursors.js",
"background/custom_automation_event.js",
"background/desktop_automation_handler.js",
@@ -78,44 +44,77 @@ chromevox_modules = [
"background/earcon_engine.js",
"background/editing.js",
"background/event_source.js",
- "background/logging/event_stream_logger.js",
"background/find_handler.js",
+ "background/focus_automation_handler.js",
"background/gesture_command_data.js",
"background/gesture_command_handler.js",
- "background/panel/i_search.js",
- "background/language_switching.js",
+ "background/injected_script_loader.js",
"background/keyboard_handler.js",
+ "background/keymaps/key_map.js",
+ "background/locale_output_helper.js",
+ "learn_mode/kbexplorer.js",
"background/live_regions.js",
+ "background/logging/event_stream_logger.js",
"background/logging/log.js",
"background/logging/log_store.js",
"background/logging/log_types.js",
+ "background/logging/output_logger.js",
+ "background/logging/tree_dumper.js",
"background/math_handler.js",
"background/media_automation_handler.js",
"background/mouse_handler.js",
"background/next_earcons.js",
"background/notifications.js",
"background/output.js",
- "background/logging/output_logger.js",
- "background/panel/panel.js",
- "background/panel/panel_command.js",
- "background/panel/panel_menu.js",
- "background/panel/panel_menu_item.js",
+ "background/panel_command.js",
"background/phonetic_data.js",
- "background/focus_automation_handler.js",
+ "background/prefs.js",
"background/range_automation_handler.js",
"background/recovery_strategy.js",
- "background/logging/tree_dumper.js",
- "background/tree_walker.js",
- "background/panel/tutorial.js",
- "injected/loader.js",
- "background/braille_background.js",
- "common/extension_bridge.js",
- "common/tts_background.js",
- "common/tts_base.js",
+ "background/tabs_api_handler.js",
+ "../common/tree_walker.js",
+ "braille/bluetooth_braille_display_manager.js",
+ "braille/bluetooth_braille_display_ui.js",
+ "braille/braille_display_manager.js",
+ "braille/braille_input_handler.js",
+ "braille/braille_key_event_rewriter.js",
+ "braille/braille_key_types.js",
+ "braille/braille_table.js",
+ "braille/braille_translator_manager.js",
+ "braille/expanding_braille_translator.js",
+ "braille/liblouis.js",
+ "braille/nav_braille.js",
+ "braille/pan_strategy.js",
+ "braille/spans.js",
"common/abstract_earcons.js",
"common/abstract_tts.js",
"common/braille_interface.js",
+ "common/chromevox.js",
+ "common/command_store.js",
+ "common/composite_tts.js",
+ "common/console_tts.js",
+ "common/editable_text_base.js",
+ "common/extension_bridge.js",
+ "common/key_sequence.js",
+ "common/key_util.js",
+ "common/keyboard_handler.js",
+ "common/msgs.js",
+ "common/nav_description.js",
+ "common/spannable.js",
+ "common/string_util.js",
+ "common/tts_background.js",
+ "common/tts_base.js",
"common/tts_interface.js",
+ "injected/api_implementation.js",
+ "injected/loader.js",
+ "injected/script_installer.js",
+ "options/options.js",
+ "panel/annotations_ui.js",
+ "panel/i_search.js",
+ "panel/panel.js",
+ "panel/panel_menu.js",
+ "panel/panel_menu_item.js",
+ "panel/tutorial.js",
"third_party/tamachiyomi/ja_phonetic_data.js",
]
@@ -137,12 +136,9 @@ closure_library_modules =
chromevox_out_dir = "$root_out_dir/resources/chromeos/accessibility/chromevox"
-group("chromevox") {
+group("build") {
deps = [
":chromevox_copied_files",
- ":chromevox_guest_manifest",
- ":chromevox_manifest",
- ":chromevox_strings",
"//chrome/browser/resources/chromeos/accessibility/braille_ime:braille_ime_manifest",
"//third_party/chromevox:chromevox_third_party_resources",
"//third_party/liblouis",
@@ -162,11 +158,11 @@ group("chromevox") {
}
chromevox_background_script_loader_file = "background/loader.js"
-chromevox_learn_mode_loader_file = "background/learn_mode/kbexplorer_loader.js"
+chromevox_learn_mode_loader_file = "learn_mode/kbexplorer_loader.js"
chromevox_log_loader_file = "background/logging/log_loader.js"
chromevox_min_content_script_loader_file = "injected/loader.js"
-chromevox_options_script_loader_file = "background/options/options_loader.js"
-chromevox_panel_script_loader_file = "background/panel/panel_loader.js"
+chromevox_options_script_loader_file = "options/options_loader.js"
+chromevox_panel_script_loader_file = "panel/panel_loader.js"
# Instead of setting up one copy target for each subdirectory, use a script
# to copy all files.
@@ -181,16 +177,9 @@ run_jsbundler("chromevox_copied_files") {
"background/earcons/skim.wav",
"background/earcons/small_room_2.wav",
"background/earcons/static.wav",
- "background/keymaps/next_keymap.json",
- "background/learn_mode/kbexplorer.html",
+ "background/keymaps/default_keymap.json",
"background/logging/log.css",
"background/logging/log.html",
- "background/options/checked.png",
- "background/options/options.css",
- "background/options/options.html",
- "background/options/unchecked.png",
- "background/panel/panel.css",
- "background/panel/panel.html",
"images/chromevox-128.png",
"images/chromevox-16.png",
"images/chromevox-19.png",
@@ -202,6 +191,13 @@ run_jsbundler("chromevox_copied_files") {
"images/options-hover-19.png",
"images/triangle-6.png",
"injected/api.js",
+ "learn_mode/kbexplorer.html",
+ "options/checked.png",
+ "options/options.css",
+ "options/options.html",
+ "options/unchecked.png",
+ "panel/panel.css",
+ "panel/panel.html",
]
if (!chromevox_compress_js) {
sources += chromevox_modules
@@ -224,54 +220,6 @@ run_jsbundler("chromevox_copied_files") {
]
}
-# TODO(crbug/978200): refactor this into another file like generate_manifest.gni
-# to share with other extensions.
-template("manifest") {
- version_file = "//chrome/VERSION"
- version_script = "//build/util/version.py"
- template_file = "manifest.json.jinja2"
- output_file = invoker.output_file
- key = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDltVl1k15pjRzuZfMc3B69inxwm2bZeZ2O8/zFO+NluHnBm3GJ3fzdOoFGJd+M16I8p7zxxQyHeDMfWYASyCeB8XnUEDKjqNLQfCnncsANzHsYoEbYj2nEUML2P13b9q+AAvpCBpAJ4cZp81e9n1y/vbSXHE4385cgkKueItzikQIDAQAB"
- action(target_name) {
- script = "tools/generate_manifest.py"
- inputs = [
- version_file,
- version_script,
- ]
- sources = [
- template_file,
- ]
- outputs = [
- output_file,
- ]
- args = [
- "--key=$key",
- "--version_file=" + rebase_path(version_file, root_build_dir),
- "--output_manifest=" + rebase_path(output_file, root_build_dir),
- ]
- if (defined(invoker.is_guest_manifest) && invoker.is_guest_manifest) {
- args += [ "--is_guest_manifest=1" ]
- }
- if (!chromevox_compress_js) {
- args += [ "--is_js_compressed=0" ]
- }
- args += rebase_path(sources, root_build_dir)
- }
-}
-
-manifest("chromevox_manifest") {
- output_file = "$chromevox_out_dir/manifest.json"
-}
-
-manifest("chromevox_guest_manifest") {
- output_file = "$chromevox_out_dir/manifest_guest.json"
- is_guest_manifest = true
-}
-
-chromevox_strings("chromevox_strings") {
- out_dir = chromevox_out_dir
-}
-
template("generate_deps_js") {
if (defined(invoker.rewrite_rules)) {
rewrite_rules = invoker.rewrite_rules
@@ -285,9 +233,7 @@ template("generate_deps_js") {
script = "tools/generate_deps.py"
inputs = jsbundler_modules
sources = invoker.sources
- outputs = [
- invoker.output_file,
- ]
+ outputs = [ invoker.output_file ]
args = [
"-o",
rebase_path(invoker.output_file, root_build_dir),
@@ -317,44 +263,32 @@ if (chromevox_compress_js) {
}
compress_js("chromevox_learn_mode_script") {
- sources = [
- chromevox_learn_mode_loader_file,
- ]
+ sources = [ chromevox_learn_mode_loader_file ]
output_file = "$chromevox_out_dir/chromeVoxKbExplorerScript.js"
}
compress_js("chromevox_log_script") {
- sources = [
- chromevox_log_loader_file,
- ]
+ sources = [ chromevox_log_loader_file ]
output_file = "$chromevox_out_dir/chromeVoxLogScript.js"
}
compress_js("chromevox_options_script") {
- sources = [
- chromevox_options_script_loader_file,
- ]
+ sources = [ chromevox_options_script_loader_file ]
output_file = "$chromevox_out_dir/chromeVoxChromeOptionsScript.js"
}
compress_js("chromevox_background_script") {
- sources = [
- chromevox_background_script_loader_file,
- ]
+ sources = [ chromevox_background_script_loader_file ]
output_file = "$chromevox_out_dir/chromeVoxChromeBackgroundScript.js"
}
compress_js("chromevox_min_content_script") {
- sources = [
- chromevox_min_content_script_loader_file,
- ]
+ sources = [ chromevox_min_content_script_loader_file ]
output_file = "$chromevox_out_dir/chromeVoxChromePageScript.js"
}
compress_js("chromevox_panel_script") {
- sources = [
- chromevox_panel_script_loader_file,
- ]
+ sources = [ chromevox_panel_script_loader_file ]
output_file = "$chromevox_out_dir/chromeVoxPanelScript.js"
}
} else {
@@ -388,80 +322,71 @@ if (is_chromeos) {
"$root_out_dir/resources/chromeos/accessibility/chromevox/",
"$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/chromevox/",
- # Surprisingly, the test uses data from the original location, not the
- # copied one.
+ "//chrome/browser/resources/chromeos/accessibility/common",
"//chrome/browser/resources/chromeos/accessibility/chromevox/",
"//third_party/chromevox/",
]
data += js2gtest_js_libraries
}
-}
-action("chromevox_test_messages_js") {
- script = "tools/generate_test_messages.py"
- sources = [
- "$chromevox_out_dir/_locales/en/messages.json",
- ]
- output_file = "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/chromevox/host/testing/test_messages.js"
- outputs = [
- output_file,
- ]
- deps = [
- ":chromevox_strings",
- ]
- args = [
- "-o",
- rebase_path(output_file, root_build_dir),
- ] + rebase_path(sources, root_build_dir)
-}
+ action("chromevox_test_messages_js") {
+ script = "tools/generate_test_messages.py"
+ sources = [ "$root_out_dir/resources/chromeos/accessibility/_locales/en/messages.json.gz" ]
+ output_file = "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/chromevox/host/testing/test_messages.js"
+ outputs = [ output_file ]
+ deps = [
+ "//chrome/browser/resources/chromeos/accessibility:accessibility_strings",
+ ]
+ args = [
+ "-o",
+ rebase_path(output_file, root_build_dir),
+ ] + rebase_path(sources, root_build_dir)
+ }
-chromevox_test_modules = [ "testing/test_msgs.js" ] +
- get_target_outputs(":chromevox_test_messages_js")
+ chromevox_test_modules = [ "testing/test_msgs.js" ] +
+ get_target_outputs(":chromevox_test_messages_js")
-generate_deps_js("chromevox_test_deps_js") {
- sources = closure_library_modules + chromevox_modules + chromevox_test_modules
- output_file = "$target_gen_dir/test_deps.js"
- rewrite_rules = [
- rebase_path("//", root_build_dir) + ":",
- rebase_path("$root_out_dir/test_data", root_build_dir) + ":",
- ]
- deps = [
- ":chromevox_test_messages_js",
- ]
-}
+ generate_deps_js("chromevox_test_deps_js") {
+ sources =
+ closure_library_modules + chromevox_modules + chromevox_test_modules
+ output_file = "$target_gen_dir/test_deps.js"
+ rewrite_rules = [
+ rebase_path("//", root_build_dir) + ":",
+ rebase_path("$root_out_dir/test_data", root_build_dir) + ":",
+ ]
+ deps = [ ":chromevox_test_messages_js" ]
+ }
-js2gtest("chromevox_unitjs_tests") {
- test_type = "webui"
- sources = [
- "braille/bluetooth_braille_display_manager_test.js",
- "braille/bluetooth_braille_display_ui_test.js",
- "braille/braille_display_manager_test.js",
- "braille/braille_input_handler_test.js",
- "braille/expanding_braille_translator_test.js",
- "braille/pan_strategy_test.js",
- "common/key_sequence_test.js",
- "common/spannable_test.js",
- "testing/mock_feedback_test.js",
- ]
- gen_include_files = [
- "testing/assert_additions.js",
- "testing/callback_helper.js",
- "testing/chromevox_unittest_base.js",
- "testing/mock_feedback.js",
- ]
- test_deps_js_outputs = get_target_outputs(":chromevox_test_deps_js")
- deps_js = test_deps_js_outputs[0]
- deps = [
- ":chromevox_test_deps_js",
- ]
- defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
-}
+ js2gtest("chromevox_unitjs_tests") {
+ test_type = "webui"
+ sources = [
+ "braille/bluetooth_braille_display_manager_test.js",
+ "braille/bluetooth_braille_display_ui_test.js",
+ "braille/braille_display_manager_test.js",
+ "braille/braille_input_handler_test.js",
+ "braille/expanding_braille_translator_test.js",
+ "braille/pan_strategy_test.js",
+ "common/key_sequence_test.js",
+ "common/spannable_test.js",
+ "testing/mock_feedback_test.js",
+ ]
+ gen_include_files = [
+ "testing/assert_additions.js",
+ "testing/callback_helper.js",
+ "testing/chromevox_unittest_base.js",
+ "testing/mock_feedback.js",
+ ]
+ test_deps_js_outputs = get_target_outputs(":chromevox_test_deps_js")
+ deps_js = test_deps_js_outputs[0]
+ deps = [ ":chromevox_test_deps_js" ]
+ defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
+ }
-if (is_chromeos) {
js2gtest("chromevox_extjs_tests") {
test_type = "extension"
sources = [
- "background/automation_util_test.js",
+ "background/annotation/node_identifier_test.js",
+ "background/annotation/user_annotation_handler_test.js",
"background/background_test.js",
"background/braille_command_data_test.js",
"background/color_test.js",
@@ -469,18 +394,18 @@ if (is_chromeos) {
"background/download_handler_test.js",
"background/editing_test.js",
"background/keyboard_handler_test.js",
- "background/language_switching_test.js",
"background/live_regions_test.js",
+ "background/locale_output_helper_test.js",
"background/logging/log_store_test.js",
"background/output_test.js",
- "background/panel/i_search_test.js",
- "background/panel/panel_test.js",
"background/recovery_strategy_test.js",
- "background/tree_walker_test.js",
"braille/braille_table_test.js",
"braille/braille_translator_manager_test.js",
"braille/liblouis_test.js",
"common/tts_background_test.js",
+ "options/options_test.js",
+ "panel/i_search_test.js",
+ "panel/panel_test.js",
]
gen_include_files = [
"testing/assert_additions.js",
@@ -500,36 +425,3 @@ if (is_chromeos) {
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
}
}
-
-js_library("tree_walker") {
- sources = [
- "background/tree_walker.js",
- ]
- deps = [
- ":automation_predicate",
- ":constants",
- ]
- externs_list = [
- "$externs_path/automation.js",
- "$externs_path/chrome_extensions.js",
- ]
-}
-
-js_library("automation_predicate") {
- sources = [
- "background/automation_predicate.js",
- ]
- deps = [
- ":constants",
- ]
- externs_list = [
- "$externs_path/automation.js",
- "$externs_path/chrome_extensions.js",
- ]
-}
-
-js_library("constants") {
- sources = [
- "background/constants.js",
- ]
-}
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/common/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/common/BUILD.gn
index bff72b83e22..5ec8a3441e8 100644
--- a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/common/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/common/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":chrome_extension_externs",
- ]
+ deps = [ ":chrome_extension_externs" ]
}
js_library("chrome_extension_externs") {
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni
index aef350a32a3..c68bb6df6fa 100644
--- a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni
@@ -37,15 +37,11 @@ template("run_jsbundler") {
depfile = "$target_out_dir/" +
get_path_info(invoker.output_file, "name") + ".d"
}
- outputs = [
- invoker.output_file,
- ]
+ outputs = [ invoker.output_file ]
} else {
assert(!defined(invoker.modules))
stampfile = "$target_out_dir/${target_name}_copy.stamp"
- outputs = [
- stampfile,
- ]
+ outputs = [ stampfile ]
}
args = [
"-m",
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.gni b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.gni
deleted file mode 100644
index ef565efd9af..00000000000
--- a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.gni
+++ /dev/null
@@ -1,73 +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.
-
-import("//chrome/common/features.gni")
-import("//tools/grit/grit_rule.gni")
-
-template("chromevox_strings") {
- grit(target_name) {
- source = "//chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd"
- defines = chrome_grit_defines
- outputs = [
- "_locales/am/messages.json",
- "_locales/ar/messages.json",
- "_locales/bg/messages.json",
- "_locales/bn/messages.json",
- "_locales/ca/messages.json",
- "_locales/cs/messages.json",
- "_locales/da/messages.json",
- "_locales/de/messages.json",
- "_locales/el/messages.json",
- "_locales/en_GB/messages.json",
- "_locales/en/messages.json",
- "_locales/es/messages.json",
- "_locales/es_419/messages.json",
- "_locales/et/messages.json",
- "_locales/fa/messages.json",
- "_locales/fi/messages.json",
- "_locales/fil/messages.json",
- "_locales/fr/messages.json",
- "_locales/gu/messages.json",
- "_locales/he/messages.json",
- "_locales/hi/messages.json",
- "_locales/hr/messages.json",
- "_locales/hu/messages.json",
- "_locales/id/messages.json",
- "_locales/it/messages.json",
- "_locales/ja/messages.json",
- "_locales/kn/messages.json",
- "_locales/ko/messages.json",
- "_locales/lt/messages.json",
- "_locales/lv/messages.json",
- "_locales/ml/messages.json",
- "_locales/mr/messages.json",
- "_locales/ms/messages.json",
- "_locales/nl/messages.json",
- "_locales/nb/messages.json",
- "_locales/pl/messages.json",
- "_locales/pt_BR/messages.json",
- "_locales/pt_PT/messages.json",
- "_locales/ro/messages.json",
- "_locales/ru/messages.json",
- "_locales/sk/messages.json",
- "_locales/sl/messages.json",
- "_locales/sr/messages.json",
- "_locales/sv/messages.json",
- "_locales/sw/messages.json",
- "_locales/ta/messages.json",
- "_locales/te/messages.json",
- "_locales/th/messages.json",
- "_locales/tr/messages.json",
- "_locales/uk/messages.json",
- "_locales/vi/messages.json",
- "_locales/zh_CN/messages.json",
- "_locales/zh_TW/messages.json",
- ]
- output_dir = invoker.out_dir
-
- # Don't polute the extension directory with stamp and .d files.
- depfile_dir = target_out_dir
- resource_ids = ""
- }
-}
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd b/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd
deleted file mode 100644
index 78c326dc581..00000000000
--- a/chromium/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd
+++ /dev/null
@@ -1,3813 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<grit base_dir="." current_release="1" latest_public_release="0"
- output_all_resource_defines="false" enc_check="möl" source_lang_id="en">
- <outputs>
- <output filename="_locales/am/messages.json" type="chrome_messages_json" lang="am"/>
- <output filename="_locales/ar/messages.json" type="chrome_messages_json" lang="ar"/>
- <output filename="_locales/bg/messages.json" type="chrome_messages_json" lang="bg"/>
- <output filename="_locales/bn/messages.json" type="chrome_messages_json" lang="bn"/>
- <output filename="_locales/ca/messages.json" type="chrome_messages_json" lang="ca"/>
- <output filename="_locales/cs/messages.json" type="chrome_messages_json" lang="cs"/>
- <output filename="_locales/da/messages.json" type="chrome_messages_json" lang="da"/>
- <output filename="_locales/de/messages.json" type="chrome_messages_json" lang="de"/>
- <output filename="_locales/el/messages.json" type="chrome_messages_json" lang="el"/>
- <output filename="_locales/en_GB/messages.json" type="chrome_messages_json" lang="en-GB"/>
- <output filename="_locales/en/messages.json" type="chrome_messages_json" lang="en"/>
- <output filename="_locales/es/messages.json" type="chrome_messages_json" lang="es"/>
- <output filename="_locales/es_419/messages.json" type="chrome_messages_json" lang="es-419"/>
- <output filename="_locales/et/messages.json" type="chrome_messages_json" lang="et"/>
- <output filename="_locales/fa/messages.json" type="chrome_messages_json" lang="fa"/>
- <output filename="_locales/fi/messages.json" type="chrome_messages_json" lang="fi"/>
- <output filename="_locales/fil/messages.json" type="chrome_messages_json" lang="fil"/>
- <output filename="_locales/fr/messages.json" type="chrome_messages_json" lang="fr"/>
- <output filename="_locales/gu/messages.json" type="chrome_messages_json" lang="gu"/>
- <output filename="_locales/he/messages.json" type="chrome_messages_json" lang="he"/>
- <output filename="_locales/hi/messages.json" type="chrome_messages_json" lang="hi"/>
- <output filename="_locales/hr/messages.json" type="chrome_messages_json" lang="hr"/>
- <output filename="_locales/hu/messages.json" type="chrome_messages_json" lang="hu"/>
- <output filename="_locales/id/messages.json" type="chrome_messages_json" lang="id"/>
- <output filename="_locales/it/messages.json" type="chrome_messages_json" lang="it"/>
- <output filename="_locales/ja/messages.json" type="chrome_messages_json" lang="ja"/>
- <output filename="_locales/kn/messages.json" type="chrome_messages_json" lang="kn"/>
- <output filename="_locales/ko/messages.json" type="chrome_messages_json" lang="ko"/>
- <output filename="_locales/lt/messages.json" type="chrome_messages_json" lang="lt"/>
- <output filename="_locales/lv/messages.json" type="chrome_messages_json" lang="lv"/>
- <output filename="_locales/ml/messages.json" type="chrome_messages_json" lang="ml"/>
- <output filename="_locales/mr/messages.json" type="chrome_messages_json" lang="mr"/>
- <output filename="_locales/ms/messages.json" type="chrome_messages_json" lang="ms"/>
- <output filename="_locales/nl/messages.json" type="chrome_messages_json" lang="nl"/>
- <output filename="_locales/nb/messages.json" type="chrome_messages_json" lang="no"/>
- <output filename="_locales/pl/messages.json" type="chrome_messages_json" lang="pl"/>
- <output filename="_locales/pt_BR/messages.json" type="chrome_messages_json" lang="pt-BR"/>
- <output filename="_locales/pt_PT/messages.json" type="chrome_messages_json" lang="pt-PT"/>
- <output filename="_locales/ro/messages.json" type="chrome_messages_json" lang="ro"/>
- <output filename="_locales/ru/messages.json" type="chrome_messages_json" lang="ru"/>
- <output filename="_locales/sk/messages.json" type="chrome_messages_json" lang="sk"/>
- <output filename="_locales/sl/messages.json" type="chrome_messages_json" lang="sl"/>
- <output filename="_locales/sr/messages.json" type="chrome_messages_json" lang="sr"/>
- <output filename="_locales/sv/messages.json" type="chrome_messages_json" lang="sv"/>
- <output filename="_locales/sw/messages.json" type="chrome_messages_json" lang="sw"/>
- <output filename="_locales/ta/messages.json" type="chrome_messages_json" lang="ta"/>
- <output filename="_locales/te/messages.json" type="chrome_messages_json" lang="te"/>
- <output filename="_locales/th/messages.json" type="chrome_messages_json" lang="th"/>
- <output filename="_locales/tr/messages.json" type="chrome_messages_json" lang="tr"/>
- <output filename="_locales/uk/messages.json" type="chrome_messages_json" lang="uk"/>
- <output filename="_locales/vi/messages.json" type="chrome_messages_json" lang="vi"/>
- <output filename="_locales/zh_CN/messages.json" type="chrome_messages_json" lang="zh-CN"/>
- <output filename="_locales/zh_TW/messages.json" type="chrome_messages_json" lang="zh-TW"/>
- </outputs>
- <translations>
- <file path="chromevox_strings_af.xtb" lang="af" />
- <file path="chromevox_strings_am.xtb" lang="am" />
- <file path="chromevox_strings_ar.xtb" lang="ar" />
- <file path="chromevox_strings_as.xtb" lang="as" />
- <file path="chromevox_strings_az.xtb" lang="az" />
- <file path="chromevox_strings_be.xtb" lang="be" />
- <file path="chromevox_strings_bg.xtb" lang="bg" />
- <file path="chromevox_strings_bn.xtb" lang="bn" />
- <file path="chromevox_strings_bs.xtb" lang="bs" />
- <file path="chromevox_strings_ca.xtb" lang="ca" />
- <file path="chromevox_strings_cs.xtb" lang="cs" />
- <file path="chromevox_strings_da.xtb" lang="da" />
- <file path="chromevox_strings_de.xtb" lang="de" />
- <file path="chromevox_strings_el.xtb" lang="el" />
- <file path="chromevox_strings_en-GB.xtb" lang="en-GB" />
- <file path="chromevox_strings_es.xtb" lang="es" />
- <file path="chromevox_strings_es-419.xtb" lang="es-419" />
- <file path="chromevox_strings_et.xtb" lang="et" />
- <file path="chromevox_strings_eu.xtb" lang="eu" />
- <file path="chromevox_strings_fa.xtb" lang="fa" />
- <file path="chromevox_strings_fi.xtb" lang="fi" />
- <file path="chromevox_strings_fil.xtb" lang="fil" />
- <file path="chromevox_strings_fr.xtb" lang="fr" />
- <file path="chromevox_strings_fr-CA.xtb" lang="fr-CA" />
- <file path="chromevox_strings_gl.xtb" lang="gl" />
- <file path="chromevox_strings_gu.xtb" lang="gu" />
- <file path="chromevox_strings_hi.xtb" lang="hi" />
- <file path="chromevox_strings_hr.xtb" lang="hr" />
- <file path="chromevox_strings_hu.xtb" lang="hu" />
- <file path="chromevox_strings_hy.xtb" lang="hy" />
- <file path="chromevox_strings_id.xtb" lang="id" />
- <file path="chromevox_strings_is.xtb" lang="is" />
- <file path="chromevox_strings_it.xtb" lang="it" />
- <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
- <file path="chromevox_strings_iw.xtb" lang="he" />
- <file path="chromevox_strings_ja.xtb" lang="ja" />
- <file path="chromevox_strings_ka.xtb" lang="ka" />
- <file path="chromevox_strings_kk.xtb" lang="kk" />
- <file path="chromevox_strings_km.xtb" lang="km" />
- <file path="chromevox_strings_kn.xtb" lang="kn" />
- <file path="chromevox_strings_ko.xtb" lang="ko" />
- <file path="chromevox_strings_ky.xtb" lang="ky" />
- <file path="chromevox_strings_lo.xtb" lang="lo" />
- <file path="chromevox_strings_lt.xtb" lang="lt" />
- <file path="chromevox_strings_lv.xtb" lang="lv" />
- <file path="chromevox_strings_mk.xtb" lang="mk" />
- <file path="chromevox_strings_ml.xtb" lang="ml" />
- <file path="chromevox_strings_mn.xtb" lang="mn" />
- <file path="chromevox_strings_mr.xtb" lang="mr" />
- <file path="chromevox_strings_ms.xtb" lang="ms" />
- <file path="chromevox_strings_my.xtb" lang="my" />
- <file path="chromevox_strings_ne.xtb" lang="ne" />
- <file path="chromevox_strings_nl.xtb" lang="nl" />
- <file path="chromevox_strings_no.xtb" lang="no" />
- <file path="chromevox_strings_or.xtb" lang="or" />
- <file path="chromevox_strings_pa.xtb" lang="pa" />
- <file path="chromevox_strings_pl.xtb" lang="pl" />
- <file path="chromevox_strings_pt-BR.xtb" lang="pt-BR" />
- <file path="chromevox_strings_pt-PT.xtb" lang="pt-PT" />
- <file path="chromevox_strings_ro.xtb" lang="ro" />
- <file path="chromevox_strings_ru.xtb" lang="ru" />
- <file path="chromevox_strings_si.xtb" lang="si" />
- <file path="chromevox_strings_sk.xtb" lang="sk" />
- <file path="chromevox_strings_sl.xtb" lang="sl" />
- <file path="chromevox_strings_sq.xtb" lang="sq" />
- <file path="chromevox_strings_sr.xtb" lang="sr" />
- <file path="chromevox_strings_sv.xtb" lang="sv" />
- <file path="chromevox_strings_sw.xtb" lang="sw" />
- <file path="chromevox_strings_ta.xtb" lang="ta" />
- <file path="chromevox_strings_te.xtb" lang="te" />
- <file path="chromevox_strings_th.xtb" lang="th" />
- <file path="chromevox_strings_tr.xtb" lang="tr" />
- <file path="chromevox_strings_uk.xtb" lang="uk" />
- <file path="chromevox_strings_ur.xtb" lang="ur" />
- <file path="chromevox_strings_uz.xtb" lang="uz" />
- <file path="chromevox_strings_vi.xtb" lang="vi" />
- <file path="chromevox_strings_zh-CN.xtb" lang="zh-CN" />
- <file path="chromevox_strings_zh-HK.xtb" lang="zh-HK" />
- <file path="chromevox_strings_zh-TW.xtb" lang="zh-TW" />
- <file path="chromevox_strings_zu.xtb" lang="zu" />
- </translations>
- <release allow_pseudo="false" seq="1">
- <messages fallback_to_english="true">
- <message desc="The locale you're translating into. For use in URL to localized pages. e.g. http://www.google.com/?hl=en." name="IDS_LOCALE">
- en
- </message>
- <message desc="The product name for ChromeVox." name="IDS_CHROMEVOX_NAME">
- ChromeVox
- </message>
- <message desc="The product description, displayed in the Chrome Extensions page." name="IDS_CHROMEVOX_DESCRIPTION">
- ChromeVox - Giving Voice to Chrome
- </message>
- <message desc="The description of the stopSpeech key. Displayed in the Options page." name="IDS_CHROMEVOX_STOP_SPEECH_KEY">
- Stop speech
- </message>
- <message desc="The description of the toggleStickyMode key. Displayed in the Options page." name="IDS_CHROMEVOX_TOGGLE_STICKY_MODE">
- Enable/Disable sticky mode
- </message>
- <message desc="The description of the prefix key. Displayed in the Options page." name="IDS_CHROMEVOX_PREFIX_KEY">
- Prefix key
- </message>
- <message desc="The description of the handleTab key. Displayed in the Options page." name="IDS_CHROMEVOX_HANDLE_TAB_NEXT">
- Jump to next focusable item
- </message>
- <message desc="The description of the handleTab key. Displayed in the Options page." name="IDS_CHROMEVOX_HANDLE_TAB_PREV">
- Jump to previous focusable item
- </message>
- <message desc="The description of the backward key. Displayed in the Options page." name="IDS_CHROMEVOX_BACKWARD">
- Navigate backward
- </message>
- <message desc="The description of the forward key. Displayed in the Options page." name="IDS_CHROMEVOX_FORWARD">
- Navigate forward
- </message>
- <message desc="The description of the left key. Displayed in the Options page." name="IDS_CHROMEVOX_LEFT">
- Move left
- </message>
- <message desc="The description of the right key. Displayed in the Options page." name="IDS_CHROMEVOX_RIGHT">
- Move right
- </message>
- <message desc="The description of the skip backward key that functions only during continuous reading (when ChromeVox is speaking the entire page without pausing). The skip backward key allows the user to skip backward without pausing the continuous reading. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_BACKWARD">
- Skip backward during continuous reading
- </message>
- <message desc="The description of the skip forward key that functions only during continuous reading (when ChromeVox is speaking the entire page without pausing). The skip forward key allows the user to skip forward without pausing the continuous reading. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_FORWARD">
- Skip forward during continuous reading
- </message>
- <message desc="The description of the previousGranularity key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_GRANULARITY">
- Decrease navigation granularity
- </message>
- <message desc='The description of the nextGranularity key. Navigation granularity can be e.g. "sentence level", "word level". Granularity is also referred as "level of detail". c.f. http://chromevox.com/tutorial/text_navigation.html Displayed in the Options page.' name="IDS_CHROMEVOX_NEXT_GRANULARITY">
- Increase navigation granularity
- </message>
- <message desc="The description of the previousAtGranularity gesture. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_AT_GRANULARITY">
- Move to previous at granularity
- </message>
- <message desc='The description of the nextGranularity gesture. Navigation granularity can be e.g. "word level". Granularity is also referred as "level of detail". c.f. http://chromevox.com/tutorial/text_navigation.html Displayed in the Options page.' name="IDS_CHROMEVOX_NEXT_AT_GRANULARITY">
- Move to next at granularity
- </message>
- <message desc="The description of the actOnCurrentItem key. The current item is the HTML element which has focus. Taking action is similar to using the mouse to click on the element. Displayed in the Options page." name="IDS_CHROMEVOX_ACT_ON_CURRENT_ITEM">
- Take action on current item
- </message>
- <message desc="The description of the forceClickOnCurrentItem key. Displayed in the Options page." name="IDS_CHROMEVOX_FORCE_CLICK_ON_CURRENT_ITEM">
- Click on current item
- </message>
- <message desc="The description of the readLinkURL key. Displayed in the Options page." name="IDS_CHROMEVOX_READ_LINK_URL">
- Announce the URL behind a link
- </message>
- <message desc="The description of the readCurrentTitle key. Displayed in the Options page." name="IDS_CHROMEVOX_READ_CURRENT_TITLE">
- Announce the title of the current page
- </message>
- <message desc="The description of the readCurrentURL key. Displayed in the Options page." name="IDS_CHROMEVOX_READ_CURRENT_URL">
- Announce the URL of the current page
- </message>
- <message desc="The description of the readFromHere key. Displayed in the Options page." name="IDS_CHROMEVOX_READ_FROM_HERE">
- Start reading from current location
- </message>
- <message desc="The description of the command to show the ChromeVox menu. This menu is the application menu for ChromeVox and contains commands, as well as other useful menu items such as help." name="IDS_CHROMEVOX_SHOW_PANEL_MENU">
- Open ChromeVox menus
- </message>
- <message desc="The description of the hidePowerKey key. Displayed in the Options page." name="IDS_CHROMEVOX_HIDE_POWER_KEY">
- Hide ChromeVox help
- </message>
- <message desc="Spoken instruction on navigating power key." name="IDS_CHROMEVOX_POWER_KEY_HELP">
- Press up or down to review commands, press enter to activate
- </message>
- <message desc="The description of the help key. Displayed in the Options page." name="IDS_CHROMEVOX_HELP">
- Open ChromeVox tutorial
- </message>
- <message desc="The description of the toggleSearchWidget key. Displayed in the Options page." name="IDS_CHROMEVOX_TOGGLE_SEARCH_WIDGET">
- ChromeVox find in page
- </message>
- <message desc="The description of the showOptionsPage key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_OPTIONS_PAGE">
- Open options page
- </message>
- <message desc="The description of the showLogPage key. Displayed in the ChromeVox panel." name="IDS_CHROMEVOX_SHOW_LOG_PAGE">
- Open developer log page
- </message>
- <message desc="The description of the showKbExplorerPage key; this allows users to learn about their keyboard. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_KB_EXPLORER_PAGE">
- Open learn mode
- </message>
- <message desc="The description of the decreaseTtsRate key. Displayed in the Options page." name="IDS_CHROMEVOX_DECREASE_TTS_RATE">
- Decrease rate of speech
- </message>
- <message desc="The description of the increaseTtsRate key. Displayed in the Options page." name="IDS_CHROMEVOX_INCREASE_TTS_RATE">
- Increase rate of speech
- </message>
- <message desc="The description of the decreaseTtsPitch key. This key's action is passed to the text-to-speech voice engine and controls the voice's pitch. c.f. http://en.wikipedia.org/wiki/Pitch_(music) Displayed in the Options page." name="IDS_CHROMEVOX_DECREASE_TTS_PITCH">
- Decrease pitch
- </message>
- <message desc="The description of the increaseTtsPitch key. Displayed in the Options page." name="IDS_CHROMEVOX_INCREASE_TTS_PITCH">
- Increase pitch
- </message>
- <message desc="The description of the decreaseTtsVolume key. Displayed in the Options page." name="IDS_CHROMEVOX_DECREASE_TTS_VOLUME">
- Decrease speech volume
- </message>
- <message desc="The description of the increaseTtsVolume key. Displayed in the Options page." name="IDS_CHROMEVOX_INCREASE_TTS_VOLUME">
- Increase speech volume
- </message>
- <message desc="The description of the showFormsList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_FORMS_LIST">
- Show forms list
- </message>
- <message desc="The description of the showHeadingsList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_HEADINGS_LIST">
- Show headings list
- </message>
- <message desc="The description of the showLinksList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_LINKS_LIST">
- Show links list
- </message>
- <message desc="The description of the showTablesList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_TABLES_LIST">
- Show tables list
- </message>
- <message desc="The description of the showLandmarksList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_LANDMARKS_LIST">
- Show landmarks list
- </message>
- <message desc="The description of the previousRow key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_ROW">
- Previous table row
- </message>
- <message desc="The description of the nextRow key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_ROW">
- Next table row
- </message>
- <message desc="The description of the previousCol key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_COL">
- Previous table column
- </message>
- <message desc="The description of the nextCol key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_COL">
- Next table column
- </message>
- <message desc="The description of the announceHeaders key. Displayed in the Options page." name="IDS_CHROMEVOX_ANNOUNCE_HEADERS">
- Announce the headers of the current cell
- </message>
- <message desc="The description of the speakTableLocation key. This key's action will describe where in the table the focus currently is. Displayed in the Options page." name="IDS_CHROMEVOX_SPEAK_TABLE_LOCATION">
- Announce current cell coordinates
- </message>
- <message desc="The description of the guessRowHeader key. In a table, attempt to determine the header for the row containing the current cell, even if uncertain. Displayed in the Options page." name="IDS_CHROMEVOX_GUESS_ROW_HEADER">
- Make a guess at the row header of the current cell
- </message>
- <message desc="The description of the guessColHeader key. Displayed in the Options page." name="IDS_CHROMEVOX_GUESS_COL_HEADER">
- Make a guess at the column header of the current cell
- </message>
- <message desc="The description of the skipToBeginning key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_BEGINNING">
- Go to beginning of table
- </message>
- <message desc="The description of the skipToEnd key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_END">
- Go to end of table
- </message>
- <message desc="The description of the skipToRowBeginning key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_ROW_BEGINNING">
- Go to beginning of the current row
- </message>
- <message desc="The description of the skipToRowEnd key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_ROW_END">
- Go to end of the current row
- </message>
- <message desc="The description of the skipToColBeginning key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_COL_BEGINNING">
- Go to beginning of the current column
- </message>
- <message desc="The description of the skipToColEnd key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_COL_END">
- Go to end of the current column
- </message>
- <message desc="Describes the command to move to the previous row. Displayed in a help menu." name="IDS_CHROMEVOX_SKIP_TO_PREV_ROW">
- Go to the previous row
- </message>
- <message desc="Describes the command to move to the next row. Displayed in a help menu." name="IDS_CHROMEVOX_SKIP_TO_NEXT_ROW">
- Go to the next row
- </message>
- <message desc="Describes the command to move to the previous column. Displayed in a help menu." name="IDS_CHROMEVOX_SKIP_TO_PREV_COL">
- Go to the previous column
- </message>
- <message desc="Describes the command to move to the next column. Displayed in a help menu." name="IDS_CHROMEVOX_SKIP_TO_NEXT_COL">
- Go to the next column
- </message>
- <message desc='The description of the nextHeading1 key. In most cases, "level 1 heading" is a H1 HTML tag. ChromeVox will search, from the current focus, for the next heading on the page. If a heading is found, ChromeVox will focus on the heading. Displayed in the Options page.' name="IDS_CHROMEVOX_NEXT_HEADING1">
- Next level 1 heading
- </message>
- <message desc="The description of the previousHeading1 key. Behaves like nextHeading1, but this key's action will search backwards (up the page). Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING1">
- Previous level 1 heading
- </message>
- <message desc="The description of the nextHeading2 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING2">
- Next level 2 heading
- </message>
- <message desc="The description of the previousHeading2 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING2">
- Previous level 2 heading
- </message>
- <message desc="The description of the nextHeading3 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING3">
- Next level 3 heading
- </message>
- <message desc="The description of the previousHeading3 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING3">
- Previous level 3 heading
- </message>
- <message desc="The description of the nextHeading4 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING4">
- Next level 4 heading
- </message>
- <message desc="The description of the previousHeading4 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING4">
- Previous level 4 heading
- </message>
- <message desc="The description of the nextHeading5 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING5">
- Next level 5 heading
- </message>
- <message desc="The description of the previousHeading5 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING5">
- Previous level 5 heading
- </message>
- <message desc="The description of the nextHeading6 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING6">
- Next level 6 heading
- </message>
- <message desc="The description of the previousHeading6 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING6">
- Previous level 6 heading
- </message>
- <message desc="The description of the nextComboBox key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_COMBO_BOX">
- Next combo box
- </message>
- <message desc="The description of the previousComboBox key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_COMBO_BOX">
- Previous combo box
- </message>
- <message desc="The description of the nextEditText key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_EDIT_TEXT">
- Next editable text area
- </message>
- <message desc="The description of the previousEditText key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_EDIT_TEXT">
- Previous editable text area
- </message>
- <message desc="The description of the nextFormField key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_FORM_FIELD">
- Next form field
- </message>
- <message desc="The description of the previousFormField key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_FORM_FIELD">
- Previous form field
- </message>
- <message desc="The description of the nextGraphic key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_GRAPHIC">
- Next graphic
- </message>
- <message desc="The description of the previousGraphic key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_GRAPHIC">
- Previous graphic
- </message>
- <message desc="The description of the nextHeading key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING">
- Next heading
- </message>
- <message desc="The description of the previousHeading key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING">
- Previous heading
- </message>
- <message desc="The description of the nextListItem key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LIST_ITEM">
- Next list item
- </message>
- <message desc="The description of the previousListItem key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LIST_ITEM">
- Previous list item
- </message>
- <message desc="The description of the nextJump key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_JUMP">
- Next jump
- </message>
- <message desc="The description of the previousJump key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_JUMP">
- Previous jump
- </message>
- <message desc="The description of the nextLink key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LINK">
- Next link
- </message>
- <message desc="The description of the previousLink key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LINK">
- Previous link
- </message>
- <message desc="The description of the nextList key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LIST">
- Next list
- </message>
- <message desc="The description of the previousList key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LIST">
- Previous list
- </message>
- <message desc="The description of the nextMath key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_MATH">
- Next math
- </message>
- <message desc="The description of the previousMath key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_MATH">
- Previous math
- </message>
- <message desc="The description of the nextMedia key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_MEDIA">
- Next media
- </message>
- <message desc="The description of the previousMedia key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_MEDIA">
- Previous media
- </message>
- <message desc="The description of the nextBlockquote key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_BLOCKQUOTE">
- Next block quote
- </message>
- <message desc="The description of the previousBlockquote key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_BLOCKQUOTE">
- Previous block quote
- </message>
- <message desc="The description of the nextRadio key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_RADIO">
- Next radio button
- </message>
- <message desc="The description of the previousRadio key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_RADIO">
- Previous radio button
- </message>
- <message desc="The description of the nextSlider key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_SLIDER">
- Next slider
- </message>
- <message desc="The description of the previousSlider key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_SLIDER">
- Previous slider
- </message>
- <message desc="The description of the nextTable key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_TABLE">
- Next table
- </message>
- <message desc="The description of the nextVisitedLink key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_VISITED_LINK">
- Next visited link
- </message>
- <message desc="The description of the previousTable key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_TABLE">
- Previous table
- </message>
- <message desc="The description of the previousVisitedLink key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_VISITED_LINK">
- Previous visited link
- </message>
- <message desc="The description of the nextButton key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_BUTTON">
- Next button
- </message>
- <message desc="The description of the previousButton key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_BUTTON">
- Previous button
- </message>
- <message desc="The description of the nextCheckbox key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_CHECKBOX">
- Next checkbox
- </message>
- <message desc="The description of the previousCheckbox key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_CHECKBOX">
- Previous checkbox
- </message>
- <message desc="The description of the nextLandmark key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LANDMARK">
- Next landmark
- </message>
- <message desc="The description of the previousLandmark key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LANDMARK">
- Previous landmark
- </message>
- <message desc="The description of the benchmark key. Launches a benchmark tool useful for debugging. Displayed in the Options page." name="IDS_CHROMEVOX_BENCHMARK">
- Debug benchmark
- </message>
- <message desc="The description of the announcePosition key. Displayed in the Options page." name="IDS_CHROMEVOX_ANNOUNCE_POSITION">
- Announces a brief description of the current position
- </message>
- <message desc="The description of the fullyDescribe key. Displayed in the Options page." name="IDS_CHROMEVOX_FULLY_DESCRIBE">
- Announces a complete description of the current position
- </message>
- <message desc="The title of the extension's options page." name="IDS_CHROMEVOX_OPTIONS_PAGE_TITLE">
- ChromeVox Options
- </message>
- <message desc="An options page section header for options about the ChromeVox virtual display. This section lets users change the rows, columns, and display style of the virtual braille display." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY">
- Virtual Braille Display
- </message>
- <message desc="An explanatory paragraph as part of the ChromeVox options page. Explains that the section on virtual braille display allows the user to control a simulation of a refreshable braille display (a physical hardware device) in the panel at the top of the screen." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_DETAILS">
- Simulates the output of a refreshable braille display
- in the ChromeVox panel at the top of the screen.
- </message>
- <message desc="The label for a numberic input field where the user can choose the number of lines of text in a grid." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_ROWS">
- Lines:
- </message>
- <message desc="The label for a numberic input field where the user can choose the number of cells in each line of a grid." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_COLUMNS">
- Cells in each line:
- </message>
- <message desc="A description that tells the user that the current display style of the virtual display interleaves braille and regular text, one on top of the other." name="IDS_CHROMEVOX_OPTIONS_CURRENT_DISPLAY_STYLE_INTERLEAVE">
- Current display style is interleave.
- </message>
- <message desc="A description that tells the user that the current display style of the virtual display is side by side, where regular text is on the left and braille is on the right." name="IDS_CHROMEVOX_OPTIONS_CURRENT_DISPLAY_STYLE_SIDE_BY_SIDE">
- Current display style is side by side.
- </message>
- <message desc="Labels the change display style button when the display style is side by side. Pressing the button would make the text interleave with the braille cells, one on top of the other." name="IDS_CHROMEVOX_OPTIONS_CHANGE_CURRENT_DISPLAY_STYLE_INTERLEAVE">
- Change display style to interleave.
- </message>
- <message desc="Labels the change display style button when the display style is interleave. Pressing the button would put all the text on the left side and all the braille cells on the right." name="IDS_CHROMEVOX_OPTIONS_CHANGE_CURRENT_DISPLAY_STYLE_SIDE_BY_SIDE">
- Change display style to side by side.
- </message>
- <message desc="The summary of the extension's options. Shown at the top of the options page." name="IDS_CHROMEVOX_OPTIONS_PAGE_SUMMARY">
- Use the options below to customize ChromeVox. Changes take effect immediately.
- </message>
- <message desc="An option to enable the page focus following the mouse. Focus represents the current HTML element or group of elements that are being spoken and can be acted upon. There is also a visual UI which highlights the focused elements. * This key's action allows the user to change focus with the mouse. Focus can also be changed using the ChromeVox navigation keys and an API." name="IDS_CHROMEVOX_OPTIONS_MOUSE_FOCUS_FOLLOWS">
- Use the mouse to change focus.
- </message>
- <message desc="An option to have an item's context placed at the beginning of its description. For example, reload button, toolbar would become, toolbar, reload button" name="IDS_CHROMEVOX_OPTIONS_OUTPUT_CONTEXT_FIRST">
- Display an item's context before other information (such as its name).
- </message>
- <message desc="An option to enhance the experience of specific sites such as Google Search." name="IDS_CHROMEVOX_OPTIONS_SITE_SPECIFIC_ENHANCEMENTS">
- Enhance specific sites (like Google Search).
- </message>
- <message desc="An option to use more verbose feedback for the user." name="IDS_CHROMEVOX_OPTIONS_VERBOSITY_VERBOSE">
- Enable verbose descriptions.
- </message>
- <message desc="An option to automatically read the page after it loads." name="IDS_CHROMEVOX_OPTIONS_AUTO_READ">
- Automatically read page after it finishes loading.
- </message>
- <message desc="Describes the multi select option for how to play audio when ChromeVox speaks using text to speech." name="IDS_CHROMEVOX_OPTIONS_AUDIO_DESCRIPTION">
- When playing audio...
- </message>
- <message desc="Sets audio playback to be at normal volume." name="IDS_CHROMEVOX_OPTIONS_AUDIO_NORMAL">
- Play at normal volume even if ChromeVox is speaking
- </message>
- <message desc="An option to use audio ducking." name="IDS_CHROMEVOX_OPTIONS_AUDIO_duck">
- Play at lower volume when ChromeVox is speaking
- </message>
- <message desc="An option to use audio suspension while text to speech is speaking." name="IDS_CHROMEVOX_OPTIONS_AUDIO_suspend">
- Pause playback when ChromeVox is speaking
- </message>
- <message desc="An option to show the cursor between characters." name="IDS_CHROMEVOX_OPTIONS_CURSOR_BETWEEN_CHARACTERS">
- Place cursor between characters when editing text (like Mac OS X).
- </message>
- <message desc="An option to speak text under the mouse." name="IDS_CHROMEVOX_OPTIONS_SPEAK_MOUSE">
- Speak text under the mouse.
- </message>
- <message desc="An options page section header for options about the ChromeVox voice. This section lets users change the voice by selecting a different voice from a listbox." name="IDS_CHROMEVOX_OPTIONS_VOICES">
- Voices
- </message>
- <message desc="Labels the voice selection list box." name="IDS_CHROMEVOX_OPTIONS_VOICES_DESCRIPTION">
- Select current voice:
- </message>
- <message desc="An options page section header for options about the ChromeVox braille support. This section allows the user to customize varous aspects of the braille output and input support." name="IDS_CHROMEVOX_OPTIONS_BRAILLE">
- Braille
- </message>
- <message desc="Labels the braille table type button when the current table is an 6 dot table. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_TABLE_TYPE_6">
- Switch to 8 dot braille
- </message>
- <message desc="Labels the braille table type button when the current table is an 8 dot table. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_TABLE_TYPE_8">
- Switch to 6 dot braille
- </message>
- <message desc="Labels the braille table selection list box. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_DESCRIPTION_6">
- Select a 6-dot braille table:
- </message>
- <message desc="How to present the name of a braille table to the user. For example, a locale could be 'English (United States)' and a grade could be '2'. Together they would be 'English (UnitedStates), Grade 2'. A braille table describes how text gets converted from Unicode text into a pattern of braille dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_BRAILLE_TABLE_NAME_WITH_GRADE">
- <ph name="locale">$1</ph>, Grade <ph name="grade">$2</ph>
- </message>
- <message desc="How to present the name of a braille table to the user. For example, a locale could be 'English' and a variant could be 'UEB' (for 'Unified English Braille'). Together they would be 'English (UEB)'. A braille table describes how text gets converted from Unicode text into a pattern of braille dots. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_BRAILLE_TABLE_NAME_WITH_VARIANT">
- <ph name="locale">$1</ph> (<ph name="variant">$2</ph>)
- </message>
- <message desc="How to present the name of a braille table to the user. For example, a locale could be 'English', variant could be 'UEB' (for 'Unified English Braille') and a grade could be '2'. Together they would be 'English (UEB), Grade 2'. A braille table describes how text gets converted from Unicode text into a pattern of braille dots. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_BRAILLE_TABLE_NAME_WITH_VARIANT_AND_GRADE">
- <ph name="locale">$1</ph> (<ph name="variant">$2</ph>), Grade <ph name="grade">$3</ph>
- </message>
- <message desc="Labels the braille table selection list box. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_DESCRIPTION_8">
- Select an 8-dot braille table:
- </message>
- <message desc="Labels the checkbox that enables wrapping of words if a whole line doesn't fit on a braille display. When this option is enabled, an effort is made to keep the characters of words together on the display. Otherwise, as many characters as possible are put on each braille display line, possible splitting words between lines." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_WORD_WRAP">
- Enable word wrap
- </message>
- <message desc="An options page section header for options about key shortcuts. This section lets users change the key bindings for ChromeVox actions. The section has a list of actions and a text field to change the binding (e.g. Ctrl-B) for each action." name="IDS_CHROMEVOX_OPTIONS_KEYBOARD_SHORTCUTS">
- Keyboard shortcuts
- </message>
- <message desc="Labels the key map selection combo box. Key maps describe a pairing of keys users use to invoke a command." name="IDS_CHROMEVOX_OPTIONS_KEYMAP_DESCRIPTION">
- Change the current keymap by selecting an option from the list below.
- </message>
- <message desc="A button to reset the key assignments in the options page." name="IDS_CHROMEVOX_OPTIONS_SELECT_KEYS">
- Reset current keymap
- </message>
- <message desc="Labels the keyboard shortcut section." name="IDS_CHROMEVOX_OPTIONS_SHORTCUTS_DESCRIPTION">
- Customize keyboard shortcuts for frequently used commands by typing them into the corresponding fields below.
- </message>
- <message desc="An options page section header for the modifier key section." name="IDS_CHROMEVOX_OPTIONS_MODIFIER_KEYS">
- Modifier keys
- </message>
- <message desc="An option for setting the key combination that will be used as the ChromeVox modifier key (aka, the 'Cvox' key)." name="IDS_CHROMEVOX_OPTIONS_CVOX_MODIFIER_KEY">
- ChromeVox modifier key
- </message>
- <message desc="Labels the checkbox that enables developer options for ChromeVox." name="IDS_CHROMEVOX_OPTIONS_DEVELOPER_OPTIONS">
- Enable Developer Options
- </message>
- <message desc="Enable chromevox earcon logging." name="IDS_CHROMEVOX_OPTIONS_DEVELOPER_EARCON_LOGGING">
- Enable earcon logging
- </message>
- <message desc="Enable chromevox speech logging." name="IDS_CHROMEVOX_OPTIONS_DEVELOPER_SPEECH_LOGGING">
- Enable speech logging
- </message>
- <message desc="Enable event stream logging in chromevox for developer options." name="IDS_CHROMEVOX_OPTIONS_EVENT_STREAM_LOGGING">
- Enable event stream logging
- </message>
- <message desc="Show ChromeVox Event Log." name="IDS_CHROMEVOX_OPTIONS_SHOW_LOG">
- Show Log
- </message>
- <message desc="Keyboard shortcut to show the ChromeVox log." name="IDS_CHROMEVOX_OPTIONS_SHOW_LOG_KEY">
- Search + O + W
- </message>
- <message desc="Show event stream filters options for event stream logging." name="IDS_CHROMEVOX_OPTIONS_SHOW_EVENT_STREAM_FILTERS">
- Show event stream filters
- </message>
- <message desc="Hide event stream filters options for event stream logging." name="IDS_CHROMEVOX_OPTIONS_HIDE_EVENT_STREAM_FILTERS">
- Hide event stream filters
- </message>
- <message desc="Set all event stream logging filters to on." name="IDS_CHROMEVOX_OPTIONS_ENABLE_ALL_EVENT_STREAM_FILTERS">
- Enable all event filters
- </message>
- <message desc="Set all event stream logging filters to off." name="IDS_CHROMEVOX_OPTIONS_DISABLE_ALL_EVENT_STREAM_FILTERS">
- Disable all event filters
- </message>
- <message desc="Enable chromevox braille logging." name="IDS_CHROMEVOX_OPTIONS_DEVELOPER_BRAILLE_LOGGING">
- Enable braille logging
- </message>
- <message desc="The title of ChromeVox Learn Mode page. The keyboard explorer voices the name of each key when the user presses it." name="IDS_CHROMEVOX_KBEXPLORER_TITLE">
- ChromeVox Learn Mode
- </message>
- <message desc="The title of ChromeVox Log page." name="IDS_CHROMEVOX_LOG_TITLE">
- ChromeVox Log
- </message>
- <message desc="The instructions for ChromeVox Learn Mode. The keyboard explorer voices the name of each key when the user presses it. * These instructions describe how to use the keyboard explorer." name="IDS_CHROMEVOX_KBEXPLORER_INSTRUCTIONS">
- Press any key to learn its name. Ctrl+W will close learn mode.
- </message>
- <message desc="Spoken when a new Chrome tab named 'title' is opened." name="IDS_CHROMEVOX_CHROME_TAB_CREATED">
- tab created
- </message>
- <message desc="Spoken when the user changes to different tab showing the 'title' page." name="IDS_CHROMEVOX_CHROME_TAB_SELECTED">
- <ph name="title">$1</ph>, tab
- </message>
- <message desc="Spoken when the user changes to a different normal window showing the 'title' page." name="IDS_CHROMEVOX_CHROME_NORMAL_WINDOW_SELECTED">
- window <ph name="title">$1</ph> tab
- </message>
- <message desc="Spoken when the user changes to a different incognito window showing the 'title' page in the current (displayed) tab." name="IDS_CHROMEVOX_CHROME_INCOGNITO_WINDOW_SELECTED">
- incognito window <ph name="title">$1</ph> tab
- </message>
- <message desc="Spoken when the user opens a Chrome menu named 'title'." name="IDS_CHROMEVOX_CHROME_MENU_OPENED">
- <ph name="title">$1</ph> menu opened
- </message>
- <message desc="Spoken when the user closes any Chrome menu." name="IDS_CHROMEVOX_CHROME_MENU_CLOSED">
- menu closed
- </message>
- <message desc="Describes a HTML checkbox named 'name' in the checked state." name="IDS_CHROMEVOX_DESCRIBE_CHECKBOX_CHECKED">
- <ph name="name">$1</ph> checkbox checked
- </message>
- <message desc="The checked state for a checkbox." name="IDS_CHROMEVOX_CHECKBOX_CHECKED_STATE">
- checked
- </message>
- <message desc="Describes a HTML checkbox named 'name' in the unchecked state." name="IDS_CHROMEVOX_DESCRIBE_CHECKBOX_UNCHECKED">
- <ph name="name">$1</ph>, checkbox not checked
- </message>
- <message desc="The unchecked state for a checkbox." name="IDS_CHROMEVOX_CHECKBOX_UNCHECKED_STATE">
- not checked
- </message>
- <message desc="Describes a switch named 'name' in the on/checked state." name="IDS_CHROMEVOX_DESCRIBE_SWITCH_ON">
- <ph name="name">$1</ph>, switch on
- </message>
- <message desc="Describes a switch named 'name' in the off/unchecked state." name="IDS_CHROMEVOX_DESCRIBE_SWITCH_OFF">
- <ph name="name">$1</ph>, switch off
- </message>
- <message desc="Describes a HTML radio button named 'name' in the selected state." name="IDS_CHROMEVOX_DESCRIBE_RADIO_SELECTED">
- <ph name="name">$1</ph>, radio button selected
- </message>
- <message desc="The selected state for a radio button." name="IDS_CHROMEVOX_RADIO_SELECTED_STATE">
- selected
- </message>
- <message desc="Describes a HTML radio button named 'name' in the unselected state." name="IDS_CHROMEVOX_DESCRIBE_RADIO_UNSELECTED">
- <ph name="name">$1</ph>, radio button unselected
- </message>
- <message desc="The unselected state for a radio button." name="IDS_CHROMEVOX_RADIO_UNSELECTED_STATE">
- unselected
- </message>
- <message desc="Describes a menu named 'name'." name="IDS_CHROMEVOX_DESCRIBE_MENU">
- <ph name="name">$1</ph>, menu
- </message>
- <message desc="Describes a menu item named 'name'." name="IDS_CHROMEVOX_DESCRIBE_MENU_ITEM">
- <ph name="name">$1</ph>, menu item
- </message>
- <message desc="Describes a menu item named 'name' with a submenu." name="IDS_CHROMEVOX_DESCRIBE_MENU_ITEM_WITH_SUBMENU">
- <ph name="name">$1</ph>, menu item, with submenu
- </message>
- <message desc="Describes a window named 'name'." name="IDS_CHROMEVOX_DESCRIBE_WINDOW">
- <ph name="name">$1</ph>, window
- </message>
- <message desc="Describes a HTML textbox named 'name' with value 'value'." name="IDS_CHROMEVOX_DESCRIBE_TEXTBOX">
- <ph name="value">$1</ph>, <ph name="name">$2</ph>, text box
- </message>
- <message desc="Describes an unnamed HTML textbox with value 'value'." name="IDS_CHROMEVOX_DESCRIBE_UNNAMED_TEXTBOX">
- <ph name="value">$1</ph>, text box
- </message>
- <message desc="Describes a HTML password textbox named 'name' with value 'value'." name="IDS_CHROMEVOX_DESCRIBE_PASSWORD">
- <ph name="value">$1</ph>, <ph name="name">$2</ph>, password text box
- </message>
- <message desc="Describes an unnamed HTML password textbox with value 'value'." name="IDS_CHROMEVOX_DESCRIBE_UNNAMED_PASSWORD">
- <ph name="value">$1</ph>, password text box
- </message>
- <message desc="Describes a HTML button named 'name'." name="IDS_CHROMEVOX_DESCRIBE_BUTTON">
- <ph name="name">$1</ph>, button
- </message>
- <message desc="Describes a HTML combo box named 'name'." name="IDS_CHROMEVOX_DESCRIBE_COMBOBOX">
- <ph name="value">$1</ph>, <ph name="name">$2</ph>, combo box
- </message>
- <message desc="Describes an unnamed HTML combo box." name="IDS_CHROMEVOX_DESCRIBE_UNNAMED_COMBOBOX">
- <ph name="value">$1</ph>, combo box
- </message>
- <message desc="Describes a HTML listbox named 'name'." name="IDS_CHROMEVOX_DESCRIBE_LISTBOX">
- <ph name="value">$1</ph>, <ph name="name">$2</ph>, list box
- </message>
- <message desc="Describes an unnamed HTML list box." name="IDS_CHROMEVOX_DESCRIBE_UNNAMED_LISTBOX">
- <ph name="value">$1</ph>, list box
- </message>
- <message desc="Describes a HTML link named 'name'." name="IDS_CHROMEVOX_DESCRIBE_LINK">
- <ph name="name">$1</ph>, link
- </message>
- <message desc="Describes a Chrome tab named 'name'." name="IDS_CHROMEVOX_DESCRIBE_TAB">
- <ph name="name">$1</ph>, tab
- </message>
- <message desc="Describes a slider with name 'name' and value 'value'." name="IDS_CHROMEVOX_DESCRIBE_SLIDER">
- <ph name="value">$1</ph> <ph name="name">$2</ph> slider
- </message>
- <message desc="Spoken through the a11y api after describing an element if it is selected." name="IDS_CHROMEVOX_DESCRIBE_SELECTED">
- , selected
- </message>
- <message desc="Spoken through the a11y api after describing an element if it is unselected." name="IDS_CHROMEVOX_DESCRIBE_UNSELECTED">
- , unselected
- </message>
- <message desc="Spoken through the a11y api after describing an element if it is part of a group." name="IDS_CHROMEVOX_DESCRIBE_INDEX">
- ''' <ph name="index">$1</ph> of <ph name="total">$2</ph> '''
- </message>
- <message desc="Braille for describing an index of an element in a group." name="IDS_CHROMEVOX_DESCRIBE_INDEX_BRL">
- <ph name="index">$1</ph>/<ph name="total">$2</ph>
- </message>
- <message desc="Spoken through the a11y api when moving between treeitems of differing depth." name="IDS_CHROMEVOX_DESCRIBE_DEPTH">
- ''' level <ph name="depth">$1</ph> '''
- </message>
- <message desc="Describes the rate of synthesized speech as a percentage of the normal speaking rate, like 50% for slow speech or 200% for fast speech." name="IDS_CHROMEVOX_ANNOUNCE_RATE">
- Rate <ph name="percent">$1</ph> percent
- </message>
- <message desc="Describes the pitch of synthesized speech as a percentage of the normal pitch, like 50% for low pitch or 150% for high pitch." name="IDS_CHROMEVOX_ANNOUNCE_PITCH">
- Pitch <ph name="percent">$1</ph> percent
- </message>
- <message desc="Describes the volume of synthesized speech as a percentage where 100% is full volume." name="IDS_CHROMEVOX_ANNOUNCE_VOLUME">
- Volume <ph name="percent">$1</ph> percent
- </message>
- <message desc="Spoken when the user exits a dialog. For example an alert dialog." name="IDS_CHROMEVOX_EXITING_DIALOG">
- Exited dialog.
- </message>
- <message desc="Spoken when the user exits a container." name="IDS_CHROMEVOX_EXITED_CONTAINER">
- Exited <ph name="type">$1</ph>.
- </message>
- <message desc="Spoken when the user enters a dialog with the text 'text'." name="IDS_CHROMEVOX_ENTERING_DIALOG">
- Entered dialog
- </message>
- <message desc="Spoken before the list of elements when a live region of a page is removed." name="IDS_CHROMEVOX_LIVE_REGIONS_REMOVED">
- removed:
- </message>
- <message desc="Tells the user that sticky mode is enabled. Sticky mode allows the user to navigate without pressing the modifier keys." name="IDS_CHROMEVOX_STICKY_MODE_ENABLED">
- Sticky mode enabled
- </message>
- <message desc="Tells the user that sticky mode is disabled. Sticky mode allows the user to navigate without pressing the modifier keys." name="IDS_CHROMEVOX_STICKY_MODE_DISABLED">
- Sticky mode disabled
- </message>
- <message desc="Prompt spoken when the user first opens the Keyboard Help Widget." name="IDS_CHROMEVOX_KEYBOARD_HELP_INTRO">
- Keyboard Help
- </message>
- <message desc="Prompt spoken when user opens the Context Menu Widget." name="IDS_CHROMEVOX_CONTEXT_MENU_INTRO">
- Context Menu
- </message>
- <message desc="Prompt spoken as a generic name for any choice widget of some type." name="IDS_CHROMEVOX_CHOICE_WIDGET_NAME">
- <ph name="type">$1</ph> list.
- </message>
- <message desc="Prompt spoken as a help message when any choice widget is opened." name="IDS_CHROMEVOX_CHOICE_WIDGET_HELP">
- Use up and down arrow keys to browse, or type to search.
- </message>
- <message desc="Prompt spoken when any ChoiceWidget exits." name="IDS_CHROMEVOX_CHOICE_WIDGET_EXITED">
- Exited
- </message>
- <message desc="Spoken when table mode reachs the end of a cell." name="IDS_CHROMEVOX_END_OF_CELL">
- End of cell.
- </message>
- <message desc="Spoken when the user reads a link without a URL." name="IDS_CHROMEVOX_NO_URL_FOUND">
- No URL found
- </message>
- <message desc="Spoken, in table mode, when the user leaves an HTML table." name="IDS_CHROMEVOX_LEAVING_TABLE">
- Leaving table.
- </message>
- <message desc="Spoken, in table mode, when the user leaves a grid." name="IDS_CHROMEVOX_LEAVING_GRID">
- Leaving grid.
- </message>
- <message desc="Spoken, in table mode, when the user is inside an HTML table." name="IDS_CHROMEVOX_INSIDE_TABLE">
- Inside table
- </message>
- <message desc="Spoken when the user attempts to enter table mode, but there is no HTML tables." name="IDS_CHROMEVOX_NO_TABLES">
- No table found.
- </message>
- <message desc="Spoken when the user attempts a table mode command, but is not in a table." name="IDS_CHROMEVOX_NOT_INSIDE_TABLE">
- Not inside table.
- </message>
- <message desc="Spoken when the user attempts to use a table command inside a table, but without using table mode." name="IDS_CHROMEVOX_NOT_IN_TABLE_MODE">
- Not in table mode.
- </message>
- <message desc="Spoken, in table mode, when the user attempts to navigate to a non-existant next row." name="IDS_CHROMEVOX_NO_CELL_BELOW">
- No cell below.
- </message>
- <message desc="Spoken, in table mode, when the user attempts to navigate to a non-existant previous row." name="IDS_CHROMEVOX_NO_CELL_ABOVE">
- No cell above.
- </message>
- <message desc="Spoken, in table mode, when the user attempts to navigate to a non-existant row to the right." name="IDS_CHROMEVOX_NO_CELL_RIGHT">
- No cell right.
- </message>
- <message desc="Spoken, in table mode, when the user attempts to navigate to a non-existant row to the left." name="IDS_CHROMEVOX_NO_CELL_LEFT">
- No cell left.
- </message>
- <message desc="Spoken, in table mode, when the user moves to an empty cell." name="IDS_CHROMEVOX_EMPTY_CELL">
- Empty cell.
- </message>
- <message desc="Spoken, in table mode, when the user moves to a cell that has rowspan or colspan &gt; 1." name="IDS_CHROMEVOX_SPANNED">
- Spanned.
- </message>
- <message desc="Describes a row header in an HTML table." name="IDS_CHROMEVOX_ROW_HEADER">
- Row header:
- </message>
- <message desc="Describes an empty row header in an HTML table." name="IDS_CHROMEVOX_EMPTY_ROW_HEADER">
- Empty row header
- </message>
- <message desc="Describes a column header in an HTML table." name="IDS_CHROMEVOX_COLUMN_HEADER">
- Column header:
- </message>
- <message desc="Describes an empty column header in an HTML table." name="IDS_CHROMEVOX_EMPTY_COLUMN_HEADER">
- Empty column header
- </message>
- <message desc="Describes the headers on a table with no headers." name="IDS_CHROMEVOX_NO_HEADERS">
- No headers
- </message>
- <message desc="Describes the headers on a table with empty headers." name="IDS_CHROMEVOX_EMPTY_HEADERS">
- Empty headers
- </message>
- <message desc="Descibes the user's location within a table." name="IDS_CHROMEVOX_TABLE_LOCATION">
- Row <ph name="rowIndex">$1</ph> of <ph name="rowTotal">$2</ph>, Column <ph name="colIndex">$3</ph> of <ph name="colTotal">$4</ph>
- </message>
- <message desc="summarizes a table." name="IDS_CHROMEVOX_TABLE_SUMMARY">
- Table <ph name="tableName">$1</ph>, <ph name="tableRows">$2</ph> by <ph name="tableCols">$3</ph>
- </message>
- <message desc="summarizes a html data table for braille. If the description for the table (and not the substitutions after the initial description) is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TABLE_SUMMARY_BRL">
- tbl <ph name="tableName">$1</ph> <ph name="tableRows">$2</ph>x<ph name="tableCols">$3</ph>
- </message>
- <message desc="summarizes a table cell." name="IDS_CHROMEVOX_CELL_SUMMARY">
- row <ph name="tableCellRowIndex">$1</ph> column <ph name="tableCellColumnIndex">$2</ph>
- </message>
- <message desc="summarizes a table cell for braille; for example, r1c2 means row 1, column 2. Try to localize the 'r' and 'c' to the first letter of something that would be recognizable." name="IDS_CHROMEVOX_CELL_SUMMARY_BRL">
- r<ph name="tableCellRowIndex">$1</ph>c<ph name="tableCellColumnIndex">$2</ph>
- </message>
- <message desc="Spoken if the user attempts to jump to the next checkbox when none exists." name="IDS_CHROMEVOX_NO_NEXT_CHECKBOX">
- No next checkbox.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous checkbox when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_CHECKBOX">
- No previous checkbox.
- </message>
- <message desc="Spoken if the user attempts to jump to the next editable text field when none exists." name="IDS_CHROMEVOX_NO_NEXT_EDIT_TEXT">
- No next editable text field.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous editable text field when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_EDIT_TEXT">
- No previous editable text field.
- </message>
- <message desc="Spoken if the user attempts to jump to the next heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING">
- No next heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING">
- No previous heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the next level 1 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_1">
- No next level 1 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous level 1 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_1">
- No previous level 1 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the next level 2 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_2">
- No next level 2 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous level 2 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_2">
- No previous level 2 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the next level 3 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_3">
- No next level 3 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous level 3 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_3">
- No previous level 3 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the next level 4 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_4">
- No next level 4 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous level 4 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_4">
- No previous level 4 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the next level 5 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_5">
- No next level 5 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous level 5 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_5">
- No previous level 5 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the next level 6 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_6">
- No next level 6 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous level 6 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_6">
- No previous level 6 heading.
- </message>
- <message desc="Spoken if the user attempts to jump to the next item that isn\'t a link when none exists." name="IDS_CHROMEVOX_NO_NEXT_NOT_LINK">
- No next item that isn't a link.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous item that isn\'t a link when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_NOT_LINK">
- No previous item that isn't a link.
- </message>
- <message desc="Spoken if the user attempts to jump to the next anchor when none exists." name="IDS_CHROMEVOX_NO_NEXT_ANCHOR">
- No next anchor.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous anchor when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_ANCHOR">
- No previous anchor.
- </message>
- <message desc="Spoken if the user attempts to jump to the next link when none exists." name="IDS_CHROMEVOX_NO_NEXT_LINK">
- No next link.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous link when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_LINK">
- No previous link.
- </message>
- <message desc="Spoken if the user attempts to jump to the next table when none exists." name="IDS_CHROMEVOX_NO_NEXT_TABLE">
- No next table.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous table when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_TABLE">
- No previous table.
- </message>
- <message desc="Spoken if the user attempts to jump to the next visited link when none exists." name="IDS_CHROMEVOX_NO_NEXT_VISITED_LINK">
- No next visited link.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous visited link when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_VISITED_LINK">
- No previous visited link.
- </message>
- <message desc="Spoken if the user attempts to jump to the next math expression when none exists." name="IDS_CHROMEVOX_NO_NEXT_MATH">
- No next math expression.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous math expression when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_MATH">
- No previous math expression.
- </message>
- <message desc="Spoken if the user attempts to jump to the next media widget (audio/video) when none exists." name="IDS_CHROMEVOX_NO_NEXT_MEDIA_WIDGET">
- No next media widget.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous media widget (audio/video) when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_MEDIA_WIDGET">
- No previous media widget.
- </message>
- <message desc="Spoken if the user attempts to jump to the next list when none exists." name="IDS_CHROMEVOX_NO_NEXT_LIST">
- No next list.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous list when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_LIST">
- No previous list.
- </message>
- <message desc="Spoken if the user attempts to jump to the next list item when none exists." name="IDS_CHROMEVOX_NO_NEXT_LIST_ITEM">
- No next list item.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous list item when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_LIST_ITEM">
- No previous list item.
- </message>
- <message desc="Spoken if the user attempts to jump to the next blockquote when none exists." name="IDS_CHROMEVOX_NO_NEXT_BLOCKQUOTE">
- No next blockquote.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous blockquote when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_BLOCKQUOTE">
- No previous blockquote.
- </message>
- <message desc="Spoken if the user attempts to jump to the next form field when none exists." name="IDS_CHROMEVOX_NO_NEXT_FORM_FIELD">
- No next form field.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous form field when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_FORM_FIELD">
- No previous form field.
- </message>
- <message desc="Spoken if the user attempts to jump to the next jump point when none exists." name="IDS_CHROMEVOX_NO_NEXT_JUMP">
- No next jump point.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous jump point when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_JUMP">
- No previous jump point.
- </message>
- <message desc="Spoken if the user attempts to jump to the next ARIA landmark when none exists." name="IDS_CHROMEVOX_NO_NEXT_LANDMARK">
- No next ARIA landmark.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous ARIA landmark when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_LANDMARK">
- No previous ARIA landmark.
- </message>
- <message desc="Spoken if the user attempts to jump to the next combo box when none exists." name="IDS_CHROMEVOX_NO_NEXT_COMBO_BOX">
- No next combo box.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous combo box when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_COMBO_BOX">
- No previous combo box.
- </message>
- <message desc="Spoken if the user attempts to jump to the next button when none exists." name="IDS_CHROMEVOX_NO_NEXT_BUTTON">
- No next button.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous button when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_BUTTON">
- No previous button.
- </message>
- <message desc="Spoken if the user attempts to jump to the next graphic when none exists." name="IDS_CHROMEVOX_NO_NEXT_GRAPHIC">
- No next graphic.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous graphic when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_GRAPHIC">
- No previous graphic.
- </message>
- <message desc="Spoken if the user attempts to jump to the next slider when none exists." name="IDS_CHROMEVOX_NO_NEXT_SLIDER">
- No next slider.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous slider when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_SLIDER">
- No previous slider.
- </message>
- <message desc="Spoken if the user attempts to jump to the next radio button when none exists." name="IDS_CHROMEVOX_NO_NEXT_RADIO_BUTTON">
- No next radio button.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous radio button when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_RADIO_BUTTON">
- No previous radio button.
- </message>
- <message desc="Spoken if the user attempts to jump to the next section when none exists." name="IDS_CHROMEVOX_NO_NEXT_SECTION">
- No next section.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous section when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_SECTION">
- No previous section.
- </message>
- <message desc="Spoken if the user attempts to jump to the next control when none exists." name="IDS_CHROMEVOX_NO_NEXT_CONTROL">
- No next control.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous control when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_CONTROL">
- No previous control.
- </message>
- <message desc="Spoken when the current HTML element is clicked." name="IDS_CHROMEVOX_ELEMENT_CLICKED">
- Clicked
- </message>
- <message desc="Spoken when the current HTML element is double clicked." name="IDS_CHROMEVOX_ELEMENT_DOUBLE_CLICKED">
- double clicked
- </message>
- <message desc="Spoken in PowerKey if there are no headings to display." name="IDS_CHROMEVOX_POWERKEY_NO_HEADINGS">
- No headings.
- </message>
- <message desc="Spoken in PowerKey if there are no links to display." name="IDS_CHROMEVOX_POWERKEY_NO_LINKS">
- No links.
- </message>
- <message desc="Spoken in PowerKey if there are no forms to display." name="IDS_CHROMEVOX_POWERKEY_NO_FORMS">
- No forms.
- </message>
- <message desc="Spoken in PowerKey if there are no tables to display." name="IDS_CHROMEVOX_POWERKEY_NO_TABLES">
- No tables.
- </message>
- <message desc="Spoken in PowerKey if there are no ARIA landmarks to display." name="IDS_CHROMEVOX_POWERKEY_NO_LANDMARKS">
- No ARIA landmarks.
- </message>
- <message desc="Spoken in PowerKey if there are no jumps to display." name="IDS_CHROMEVOX_POWERKEY_NO_JUMPS">
- No jumps.
- </message>
- <message desc="Describes the list position of a list item in spoken feedback." name="IDS_CHROMEVOX_LIST_POSITION">
- <ph name="index">$1</ph> of <ph name="total">$2</ph>
- </message>
- <message desc="Describes the list position of a list item in braille." name="IDS_CHROMEVOX_LIST_POSITION_BRL">
- <ph name="index">$1</ph>/<ph name="total">$2</ph>
- </message>
- <message desc='Spoken after a menu is spoken if the menu has a submenu. For example "Menu Options has submenu"' name="IDS_CHROMEVOX_ARIA_HAS_SUBMENU">
- has submenu
- </message>
- <message desc='Spoken after an element is spoken if the element has a pop up. For example "Button Add friends has pop up"' name="IDS_CHROMEVOX_ARIA_HAS_POPUP">
- has pop up
- </message>
- <message desc="This is a suffix shown on a braille display for a widget (such as a button) that opens some kind of popup. When translating, keep the plus sign and append the translated word for 'popup'. If it is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_HAS_POPUP_BRL">
- +popup
- </message>
- <message desc='Spoken when describing an ARIA value minimun. For example "Distance, in meters textbox 6, min 2, max 10"' name="IDS_CHROMEVOX_ARIA_VALUE_MIN">
- Min <ph name="x">$1</ph>
- </message>
- <message desc='Brailled when describing an ARIA value minimum. For example "Distance, in meters: 6 min:6 max:10"' name="IDS_CHROMEVOX_ARIA_VALUE_MIN_BRL">
- min:<ph name="x">$1</ph>
- </message>
- <message desc='Spoken when describing an ARIA value maximum. For example "Distance, in meters textbox 6, min 2, max 10"' name="IDS_CHROMEVOX_ARIA_VALUE_MAX">
- Max <ph name="x">$1</ph>
- </message>
- <message desc='Brailled when describing an ARIA value maximum. For example "Distance, in meters: 6 min:2 max:10".' name="IDS_CHROMEVOX_ARIA_VALUE_MAX_BRL">
- max:<ph name="x">$1</ph>
- </message>
- <message desc="Describes an element with the ARIA role alert." name="IDS_CHROMEVOX_ROLE_ALERT">
- Alert
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translated word 'alert' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_ALERT_BRL">
- alrt
- </message>
- <message desc="Describes an element with the ARIA role alertdialog." name="IDS_CHROMEVOX_ROLE_ALERTDIALOG">
- Alert dialog
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'alert dialog' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_ALERTDIALOG_BRL">
- alrt dlg
- </message>
- <message desc="Describes an element with the ARIA role button." name="IDS_CHROMEVOX_ROLE_BUTTON">
- Button
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translated word for 'button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_BUTTON_BRL">
- btn
- </message>
- <message desc="Describes an element with the ARIA role checkbox." name="IDS_CHROMEVOX_ROLE_CHECKBOX">
- Check box
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'check box' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_CHECKBOX_BRL">
- chk
- </message>
- <message desc="Describes an element with the ARIA role combobox." name="IDS_CHROMEVOX_ROLE_COMBOBOX">
- Combo box
- </message>
- <message desc="Accessibility role description for a single comment" name="IDS_CHROMEVOX_ROLE_COMMENT">
- Comment
- </message>
- <message desc="Accessibility role description for a comment section" name="IDS_CHROMEVOX_ROLE_COMMENT_SECTION">
- Comment section
- </message>
- <message desc="Accessibility role description for content deletion, meaning content that is has been or is suggested to be removed from a document, such as in a revision review" name="IDS_CHROMEVOX_ROLE_CONTENT_DELETION">
- Deletion
- </message>
- <message desc="Accessibility role description for content insertion, meaning content that is has been or is suggested to be inserted into a document, such as in a revision review" name="IDS_CHROMEVOX_ROLE_CONTENT_INSERTION">
- Insertion
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'combo box' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_COMBOBOX_BRL">
- cbo
- </message>
- <message desc="Describes an element with the ARIA role dialog." name="IDS_CHROMEVOX_ROLE_DIALOG">
- Dialog
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'dialog' (as in dialog box on a computer screen) according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DIALOG_BRL">
- dlg
- </message>
- <message desc="Accessibility role description for abstract" name="IDS_CHROMEVOX_ROLE_DOC_ABSTRACT">
- Abstract
- </message>
- <message desc="Accessibility role description for acknowledgments" name="IDS_CHROMEVOX_ROLE_DOC_ACKNOWLEDGMENTS">
- Acknowledgments
- </message>
- <message desc="Accessibility role description for afterword" name="IDS_CHROMEVOX_ROLE_DOC_AFTERWORD">
- Afterword
- </message>
- <message desc="Accessibility role description for appendix" name="IDS_CHROMEVOX_ROLE_DOC_APPENDIX">
- Appendix
- </message>
- <message desc="Accessibility role description for back link" name="IDS_CHROMEVOX_ROLE_DOC_BACK_LINK">
- Back link
- </message>
- <message desc="Accessibility role description for bibliography entry" name="IDS_CHROMEVOX_ROLE_DOC_BIBLIO_ENTRY">
- Bibliography entry
- </message>
- <message desc="Accessibility role description for bibliography" name="IDS_CHROMEVOX_ROLE_DOC_BIBLIOGRAPHY">
- Bibliography
- </message>
- <message desc="Accessibility role description for bibliography reference" name="IDS_CHROMEVOX_ROLE_DOC_BIBLIO_REF">
- Bibliography reference
- </message>
- <message desc="Accessibility role description for chapter" name="IDS_CHROMEVOX_ROLE_DOC_CHAPTER">
- Chapter
- </message>
- <message desc="Accessibility role description for colophon" name="IDS_CHROMEVOX_ROLE_DOC_COLOPHON">
- Colophon
- </message>
- <message desc="Accessibility role description for conclusion" name="IDS_CHROMEVOX_ROLE_DOC_CONCLUSION">
- Conclusion
- </message>
- <message desc="Accessibility role description for cover" name="IDS_CHROMEVOX_ROLE_DOC_COVER">
- Cover
- </message>
- <message desc="Accessibility role description for credit" name="IDS_CHROMEVOX_ROLE_DOC_CREDIT">
- Credit
- </message>
- <message desc="Accessibility role description for credits" name="IDS_CHROMEVOX_ROLE_DOC_CREDITS">
- Credits
- </message>
- <message desc="Accessibility role description for dedication" name="IDS_CHROMEVOX_ROLE_DOC_DEDICATION">
- Dedication
- </message>
- <message desc="Accessibility role description for endnote" name="IDS_CHROMEVOX_ROLE_DOC_ENDNOTE">
- Endnote
- </message>
- <message desc="Accessibility role description for endnotes" name="IDS_CHROMEVOX_ROLE_DOC_ENDNOTES">
- Endnotes
- </message>
- <message desc="Accessibility role description for epigraph" name="IDS_CHROMEVOX_ROLE_DOC_EPIGRAPH">
- Epigraph
- </message>
- <message desc="Accessibility role description for epilogue" name="IDS_CHROMEVOX_ROLE_DOC_EPILOGUE">
- Epilogue
- </message>
- <message desc="Accessibility role description for errata" name="IDS_CHROMEVOX_ROLE_DOC_ERRATA">
- Errata
- </message>
- <message desc="Accessibility role description for example" name="IDS_CHROMEVOX_ROLE_DOC_EXAMPLE">
- Example
- </message>
- <message desc="Accessibility role description for footnote" name="IDS_CHROMEVOX_ROLE_DOC_FOOTNOTE">
- Footnote
- </message>
- <message desc="Accessibility role description for foreword" name="IDS_CHROMEVOX_ROLE_DOC_FOREWORD">
- Foreword
- </message>
- <message desc="Accessibility role description for glossary" name="IDS_CHROMEVOX_ROLE_DOC_GLOSSARY">
- Glossary
- </message>
- <message desc="Accessibility role description for glossary reference" name="IDS_CHROMEVOX_ROLE_DOC_GLOSS_REF">
- Glossary reference
- </message>
- <message desc="Accessibility role description for index" name="IDS_CHROMEVOX_ROLE_DOC_INDEX">
- Index
- </message>
- <message desc="Accessibility role description for introduction" name="IDS_CHROMEVOX_ROLE_DOC_INTRODUCTION">
- Introduction
- </message>
- <message desc="Accessibility role description for note reference" name="IDS_CHROMEVOX_ROLE_DOC_NOTE_REF">
- Note reference
- </message>
- <message desc="Accessibility role description for notice" name="IDS_CHROMEVOX_ROLE_DOC_NOTICE">
- Notice
- </message>
- <message desc="Accessibility role description for page break" name="IDS_CHROMEVOX_ROLE_DOC_PAGE_BREAK">
- Page break
- </message>
- <message desc="Accessibility role description for page list" name="IDS_CHROMEVOX_ROLE_DOC_PAGE_LIST">
- Page list
- </message>
- <message desc="Accessibility role description for part" name="IDS_CHROMEVOX_ROLE_DOC_PART">
- Part
- </message>
- <message desc="Accessibility role description for preface" name="IDS_CHROMEVOX_ROLE_DOC_PREFACE">
- Preface
- </message>
- <message desc="Accessibility role description for prologue" name="IDS_CHROMEVOX_ROLE_DOC_PROLOGUE">
- Prologue
- </message>
- <message desc="Accessibility role description for pullquote" name="IDS_CHROMEVOX_ROLE_DOC_PULLQUOTE">
- Pullquote
- </message>
- <message desc="Accessibility role description for Q+A (questions and answers)" name="IDS_CHROMEVOX_ROLE_DOC_QNA">
- Q&amp;A
- </message>
- <message desc="Accessibility role description for subtitle" name="IDS_CHROMEVOX_ROLE_DOC_SUBTITLE">
- Subtitle
- </message>
- <message desc="Accessibility role description for tip" name="IDS_CHROMEVOX_ROLE_DOC_TIP">
- Tip
- </message>
- <message desc="Accessibility role description for table of contents" name="IDS_CHROMEVOX_ROLE_DOC_TOC">
- Table of contents
- </message>
- <message desc="Accessibility role description for graphics document" name="IDS_CHROMEVOX_ROLE_GRAPHICS_DOCUMENT">
- Graphics document
- </message>
- <message desc="Accessibility role description for graphics object" name="IDS_CHROMEVOX_ROLE_GRAPHICS_OBJECT">
- Graphics object
- </message>
- <message desc="Accessibility role description for graphics symbol" name="IDS_CHROMEVOX_ROLE_GRAPHICS_SYMBOL">
- Graphics symbol
- </message>
- <message desc="Describes an element with the ARIA role grid." name="IDS_CHROMEVOX_ROLE_GRID">
- Grid
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'grid' (a kind of tabular layout) according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_GRID_BRL">
- grd
- </message>
- <message desc="Describes an element with the ARIA role gridcell." name="IDS_CHROMEVOX_ROLE_GRIDCELL">
- Cell
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'cell' (as a part of a grid or tabular layout) according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_GRIDCELL_BRL">
- cll
- </message>
- <message desc="Describes the position of an element with the ARIA role gridcell." name="IDS_CHROMEVOX_ROLE_GRIDCELL_POS">
- row <ph name="row">$1</ph> column <ph name="col">$2</ph>
- </message>
- <message desc="Spoken to describe a link in a document." name="IDS_CHROMEVOX_ROLE_LINK">
- Link
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'link' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LINK_BRL">
- lnk
- </message>
- <message desc="Describes an element with the ARIA role listbox." name="IDS_CHROMEVOX_ROLE_LISTBOX">
- List box
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'list box' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LISTBOX_BRL">
- lstbx
- </message>
- <message desc="Describes an element with the ARIA role log." name="IDS_CHROMEVOX_ROLE_LOG">
- Log
- </message>
- <message desc="This is an ARIA widget role name shown on a braille display. If the translation is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LOG_BRL">
- log
- </message>
- <message desc="Describes an element with the ARIA role marquee." name="IDS_CHROMEVOX_ROLE_MARQUEE">
- Marquee
- </message>
- <message desc="This is an ARIA widget role name shown on a braille display. When translating, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MARQUEE_BRL">
- marquee
- </message>
- <message desc="Describes an element with the ARIA role menu." name="IDS_CHROMEVOX_ROLE_MENU">
- Menu
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENU_BRL">
- mnu
- </message>
- <message desc="Describes an element with the ARIA role menubar." name="IDS_CHROMEVOX_ROLE_MENUBAR">
- Menu bar
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu bar' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENUBAR_BRL">
- mnubr
- </message>
- <message desc="Describes an element with the ARIA role menuitem." name="IDS_CHROMEVOX_ROLE_MENUITEM">
- Menu item
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu item' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENUITEM_BRL">
- mnuitm
- </message>
- <message desc="Describes an element with the ARIA role menuitemcheckbox." name="IDS_CHROMEVOX_ROLE_MENUITEMCHECKBOX">
- Menu item check box
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu item with checkbox' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENUITEMCHECKBOX_BRL">
- chkmnuitm
- </message>
- <message desc="Describes an element with the ARIA role menuitemradio." name="IDS_CHROMEVOX_ROLE_MENUITEMRADIO">
- Menu item radio button
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu item with radio button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENUITEMRADIO_BRL">
- rdmnuitm
- </message>
- <message desc="Describes an element with the ARIA role button, with a pop-up." name="IDS_CHROMEVOX_ROLE_POPUP_BUTTON">
- Pop-up button
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'pop up button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_POPUP_BUTTON_BRL">
- popbtn
- </message>
- <message desc="Describes an element with the ARIA role progressbar." name="IDS_CHROMEVOX_ROLE_PROGRESSBAR">
- Progress bar
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'progress bar' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_PROGRESSBAR_BRL">
- pgbar
- </message>
- <message desc="Describes a progress indicator widget." name="IDS_CHROMEVOX_ROLE_PROGRESS_INDICATOR">
- Progress indicator
- </message>
- <message desc="This is an abbreviated widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'progress indicator' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_PROGRESS_INDICATOR_BRL">
- pgbar
- </message>
- <message desc="Describes an element with the ARIA role radio." name="IDS_CHROMEVOX_ROLE_RADIO">
- Radio button
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'radio button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_RADIO_BRL">
- rbtn
- </message>
- <message desc="Describes an element with the ARIA role radiogroup." name="IDS_CHROMEVOX_ROLE_RADIOGROUP">
- Radio button group
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'radio button group' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_RADIOGROUP_BRL">
- rdgrp
- </message>
- <message desc="Accessibility role description for revision, meaning historical change info tied to this content" name="IDS_CHROMEVOX_ROLE_REVISION">
- Revision
- </message>
- <message desc="Describes an element with the ARIA role scrollbar." name="IDS_CHROMEVOX_ROLE_SCROLLBAR">
- Scroll bar
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'scroll bar' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_SCROLLBAR_BRL">
- scbr
- </message>
- <message desc="Describes an element with the ARIA role slider." name="IDS_CHROMEVOX_ROLE_SLIDER">
- Slider
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'slider' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_SLIDER_BRL">
- sldr
- </message>
- <message desc="Describes an element with the ARIA role spinbutton." name="IDS_CHROMEVOX_ROLE_SPINBUTTON">
- Spin button
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'spin button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_SPINBUTTON_BRL">
- spnbtn
- </message>
- <message desc="Describes an element with the ARIA role status." name="IDS_CHROMEVOX_ROLE_STATUS">
- Status
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'status' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_STATUS_BRL">
- sts
- </message>
- <message desc="Accessibility role description for suggestion, meaning a suggested change to some content" name="IDS_CHROMEVOX_ROLE_SUGGESTION" >
- Suggestion
- </message>
- <message desc="Describes an element with the ARIA role tab." name="IDS_CHROMEVOX_ROLE_TAB" meaning="UI element">
- Tab
- </message>
- <message desc="This is an ARIA widget role name shown on a braille display. If the translation is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TAB_BRL">
- tab
- </message>
- <message desc="Describes an element with the ARIA role table." name="IDS_CHROMEVOX_ROLE_TABLE">
- Table
- </message>
- <message desc="This is an ARIA widget role name shown on a braille display. If the translation is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TABLE_BRL">
- table
- </message>
- <message desc="Describes an element with the ARIA role tablist." name="IDS_CHROMEVOX_ROLE_TABLIST">
- Tab list
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tab list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TABLIST_BRL">
- tablst
- </message>
- <message desc="Describes an element with the ARIA role tabpanel." name="IDS_CHROMEVOX_ROLE_TABPANEL">
- Tab panel
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tab panel' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TABPANEL_BRL">
- tabpnl
- </message>
- <message desc="Describes an element with the ARIA role textbox." name="IDS_CHROMEVOX_ROLE_TEXTBOX">
- Text box
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'editable' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TEXTBOX_BRL">
- ed
- </message>
- <message desc="Describes an element with the ARIA role timer." name="IDS_CHROMEVOX_ROLE_TIMER">
- Timer
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'timer' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TIMER_BRL">
- tmr
- </message>
- <message desc="Describes an element with the ARIA role toolbar." name="IDS_CHROMEVOX_ROLE_TOOLBAR">
- Tool bar
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tool bar' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TOOLBAR_BRL">
- tlbar
- </message>
- <message desc="Describes an element with the ARIA role tooltip." name="IDS_CHROMEVOX_ROLE_TOOLTIP">
- Tool tip
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tool tip' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TOOLTIP_BRL">
- tltip
- </message>
- <message desc="Describes an element with the ARIA role tree. Note that the word tree is used metaphorically and refers to a user interface widget." name="IDS_CHROMEVOX_ROLE_TREE">
- Tree
- </message>
- <message desc="This is an ARIA widget role name shown on a braille display. If the translation is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible. Note that the word tree is used metaphorically and refers to a user interface widget." name="IDS_CHROMEVOX_ROLE_TREE_BRL">
- tree
- </message>
- <message desc="Describes an element with the ARIA role treeitem." name="IDS_CHROMEVOX_ROLE_TREEITEM">
- Tree item
- </message>
- <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tree item' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TREEITEM_BRL">
- tritm
- </message>
- <message desc="Describes an element with the ARIA role article." name="IDS_CHROMEVOX_ROLE_ARTICLE">
- Article
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_ARTICLE_BRL">
- article
- </message>
- <message desc="Describes an element with the ARIA role application." name="IDS_CHROMEVOX_ROLE_APPLICATION">
- Application
- </message>
- <message desc="This is an ARIA navigational landmark role name shown on a braille display. When translating, try to find a contracted form of the translation for 'application' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_APPLICATION_BRL">
- app
- </message>
- <message desc="Describes an element with the ARIA role banner." name="IDS_CHROMEVOX_ROLE_BANNER">
- Banner
- </message>
- <message desc="This is an ARIA navigational landmark role name shown on a braille display. When translating, try to find a contracted form of the translation for 'banner' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_BANNER_BRL">
- bnr
- </message>
- <message desc="Describes an element with the ARIA role columnheader." name="IDS_CHROMEVOX_ROLE_COLUMNHEADER">
- Column header
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'column header' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_COLUMNHEADER_BRL">
- colhdr
- </message>
- <message desc="Describes an element with the ARIA role complementary." name="IDS_CHROMEVOX_ROLE_COMPLEMENTARY">
- Complementary
- </message>
- <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_COMPLEMENTARY_BRL">
- complementary
- </message>
- <message desc="Describes an element with the ARIA role contentinfo." name="IDS_CHROMEVOX_ROLE_CONTENTINFO">
- Content info
- </message>
- <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, try to find a contracted form of the translation for 'content info' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_CONTENTINFO_BRL">
- cntntinfo
- </message>
- <message desc="Describes an element with the ARIA role definition." name="IDS_CHROMEVOX_ROLE_DEFINITION">
- Definition
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'definition' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DEFINITION_BRL">
- def
- </message>
- <message desc="Describes an element with the ARIA role directory." name="IDS_CHROMEVOX_ROLE_DIRECTORY">
- Directory
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'directory' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DIRECTORY_BRL">
- dir
- </message>
- <message desc="Describes an element with the ARIA role document." name="IDS_CHROMEVOX_ROLE_DOCUMENT">
- Document
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'document' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DOCUMENT_BRL">
- doc
- </message>
- <message desc="Describes an element with the ARIA role form." name="IDS_CHROMEVOX_ROLE_FORM">
- Form
- </message>
- <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_FORM_BRL">
- form
- </message>
- <message desc="Describes an element with the ARIA role group." name="IDS_CHROMEVOX_ROLE_GROUP">
- Group
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'group' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_GROUP_BRL">
- grp
- </message>
- <message desc="Describes an element with the ARIA role heading." name="IDS_CHROMEVOX_ROLE_HEADING">
- Heading
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'heading' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_HEADING_BRL">
- hdng
- </message>
- <message desc="Describes an element with the ARIA role img." name="IDS_CHROMEVOX_ROLE_IMG">
- Image
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'image' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_IMG_BRL">
- img
- </message>
- <message desc="Describes an element with the ARIA role list." name="IDS_CHROMEVOX_ROLE_LIST">
- List
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LIST_BRL">
- lst
- </message>
- <message desc="Describes an element with the internal role of listGrid. This is similar to an ARIA grid." name="IDS_CHROMEVOX_ROLE_LIST_GRID">
- List grid
- </message>
- <message desc="This is the name of an internal role shown on a braille display. When translating, try to find a contracted form of the translation for 'list grid' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LIST_GRID_BRL">
- lstgrd
- </message>
- <message desc="Describes an element with the ARIA role listitem." name="IDS_CHROMEVOX_ROLE_LISTITEM">
- List item
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'list item' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LISTITEM_BRL">
- lstitm
- </message>
- <message desc="Describes an element with the ARIA role main." name="IDS_CHROMEVOX_ROLE_MAIN">
- Main
- </message>
- <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_MAIN_BRL">
- main
- </message>
- <message desc="Describes an element with the ARIA role math." name="IDS_CHROMEVOX_ROLE_MATH">
- Math
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_MATH_BRL">
- math
- </message>
- <message desc="Describes an element with the ARIA role navigation." name="IDS_CHROMEVOX_ROLE_NAVIGATION">
- Navigation
- </message>
- <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, try to find a contracted form of the translation for 'navigation' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_NAVIGATION_BRL">
- nav
- </message>
- <message desc="Describes an element with the ARIA role note." name="IDS_CHROMEVOX_ROLE_NOTE">
- Note
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_NOTE_BRL">
- note
- </message>
- <message desc="Describes an element with the ARIA role region." name="IDS_CHROMEVOX_ROLE_REGION">
- Region
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'region' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_REGION_BRL">
- rgn
- </message>
- <message desc="Describes an element with the ARIA role rowheader." name="IDS_CHROMEVOX_ROLE_ROWHEADER">
- Row header
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'row header' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_ROWHEADER_BRL">
- rwhdr
- </message>
- <message desc="Describes an element with the ARIA role search." name="IDS_CHROMEVOX_ROLE_SEARCH">
- Search
- </message>
- <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_SEARCH_BRL">
- search
- </message>
- <message desc="Describes an element with the ARIA role separator." name="IDS_CHROMEVOX_ROLE_SEPARATOR">
- Separator
- </message>
- <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'separator' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_SEPARATOR_BRL">
- seprtr
- </message>
- <message desc="Describes an element with the ARIA role meter." name="IDS_CHROMEVOX_ROLE_METER">
- Meter
- </message>
- <message desc="This is the name of an ARIA meter role shown on a braille display. When translating, try to find a contracted form of the translation for meter according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_METER_BRL">
- meter
- </message>
- <message desc="Describes an element with the ARIA attribute aria-autocomplete=inline." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_INLINE">
- Autocompletion inline
- </message>
- <message desc="Shown on a braille display as a suffix to text fields and combo boxes when suggestions on how to complete the field are shown as text after the caret. When translating, try to find a contracted form of the translation for 'autocomplete inline' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_INLINE_BRL">
- autoinl
- </message>
- <message desc="Describes an element with the ARIA attribute aria-autocomplete=list." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_LIST">
- Autocompletion list
- </message>
- <message desc="Shown on a braille display as a suffix to text fields and combo boxes when suggestions on how to complete the field are shown in a list. When translating, try to find a contracted form of the translation for 'autocomplete list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_LIST_BRL">
- autolst
- </message>
- <message desc="Describes an element with the ARIA attribute aria-autocomplete=both." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_BOTH">
- Autocompletion inline and list
- </message>
- <message desc="Shown on a braille display as a suffix to text fields and combo boxes when suggestions on how to complete the field are shown in a list and the currently selected value is shown as text after the caret in the input field. When translating, try to find a contracted form of the translation for 'autocomplete inline and list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_BOTH_BRL">
- autoinl+lst
- </message>
- <message desc="Describes an element that is checked." name="IDS_CHROMEVOX_CHECKED_TRUE">
- Checked
- </message>
- <message desc="Describes an element that is unchecked." name="IDS_CHROMEVOX_CHECKED_FALSE">
- Not checked
- </message>
- <message desc="Describes an element where the checked state is mixed or indeterminate." name="IDS_CHROMEVOX_CHECKED_MIXED">
- Partially checked
- </message>
- <message desc="Describes an element with the ARIA attribute aria-disabled=true." name="IDS_CHROMEVOX_ARIA_DISABLED_TRUE">
- Disabled
- </message>
- <message desc="Describes an element with the ARIA attribute aria-expanded=true." name="IDS_CHROMEVOX_ARIA_EXPANDED_TRUE">
- Expanded
- </message>
- <message desc="Describes an element with the ARIA attribute aria-expanded=false." name="IDS_CHROMEVOX_ARIA_EXPANDED_FALSE">
- Collapsed
- </message>
- <message desc="Describes an element with the ARIA attribute aria-invalid=true." name="IDS_CHROMEVOX_ARIA_INVALID_TRUE">
- Invalid input
- </message>
- <message desc="Describes an element with the ARIA attribute aria-invalid=grammar." name="IDS_CHROMEVOX_ARIA_INVALID_GRAMMAR">
- Grammatical mistake detected
- </message>
- <message desc="Shown on a braille display as a suffix to text fields that are marked as containing a grammatical mistake. When translating, stick to lowercase." name="IDS_CHROMEVOX_ARIA_INVALID_GRAMMAR_BRL">
- grammatical mistake
- </message>
- <message desc="Describes an element with the ARIA attribute aria-invalid=spelling." name="IDS_CHROMEVOX_ARIA_INVALID_SPELLING">
- Spelling mistake detected
- </message>
- <message desc="Shown on a braille display as a suffix to text fields that are marked as containing a misspelling. When translating, stick to lowercase." name="IDS_CHROMEVOX_ARIA_INVALID_SPELLING_BRL">
- misspelled
- </message>
- <message desc="Describes an element with the ARIA attribute aria-multiline=true." name="IDS_CHROMEVOX_ARIA_MULTILINE_TRUE">
- Multi line
- </message>
- <message desc="Shown on a braille display as a suffix to text fields that accept multiline input. When translating, try to find a contracted form of the translation for 'multiple lines' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_MULTILINE_TRUE_BRL">
- multln
- </message>
- <message desc="Describes an element with the ARIA attribute aria-multiselectable=true." name="IDS_CHROMEVOX_ARIA_MULTISELECTABLE_TRUE">
- Multi select
- </message>
- <message desc="Shown on a braille display for list boxes that allow more than one selected list item. When translating, try to find a contracted form of the translation for 'multiple selections' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_MULTISELECTABLE_TRUE_BRL">
- multsel
- </message>
- <message desc="Describes an element with the ARIA attribute aria-pressed=true." name="IDS_CHROMEVOX_ARIA_PRESSED_TRUE">
- Pressed
- </message>
- <message desc="Describes an element with the ARIA attribute aria-pressed=false." name="IDS_CHROMEVOX_ARIA_PRESSED_FALSE">
- Not pressed
- </message>
- <message desc="Describes an element with the ARIA attribute aria-pressed=mixed." name="IDS_CHROMEVOX_ARIA_PRESSED_MIXED">
- Partially pressed
- </message>
- <message desc="Describes an element with the ARIA attribute aria-readonly=true." name="IDS_CHROMEVOX_ARIA_READONLY_TRUE">
- Read only
- </message>
- <message desc="Shown on a braille display for read-only controls. When translating, try to find a contracted form of the translation for 'read only' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_READONLY_TRUE_BRL">
- rdonly
- </message>
- <message desc="Describes an element with the ARIA attribute aria-required=true." name="IDS_CHROMEVOX_ARIA_REQUIRED_TRUE">
- Required
- </message>
- <message desc="Shown on a braille display for required fields. When translating, try to find a contracted form of the translation for 'required' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_REQUIRED_TRUE_BRL">
- rq
- </message>
- <message desc="Describes an element with the ARIA attribute aria-selected=true." name="IDS_CHROMEVOX_ARIA_SELECTED_TRUE">
- Selected
- </message>
- <message desc="Describes an element with the ARIA attribute aria-selected=false." name="IDS_CHROMEVOX_ARIA_SELECTED_FALSE">
- Not selected
- </message>
- <message desc="Spoken to describe a visited link." name="IDS_CHROMEVOX_VISITED_LINK">
- Visited link
- </message>
- <message desc="Shown on a braille display as a suffix to visited links in a document. When translating, try to find a contracted form of the translation for 'visited link' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_VISITED_LINK_BRL">
- vlnk
- </message>
- <message desc="Spoken to describe the visited state (e.g. for links)." name="IDS_CHROMEVOX_VISITED_STATE">
- Visited
- </message>
- <message desc="Shown on a braille display for widget in the visited state (e.g. for links). When translating, try to find a contracted form of the translation for 'visited' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_VISITED_STATE_BRL">
- vtd
- </message>
- <message desc="Spoken to describe a &lt;h1&gt; tag." name="IDS_CHROMEVOX_TAG_H1">
- Heading 1
- </message>
- <message desc="Shown on a braille display to describe a heading on level 1 in a document. When translating, try to find a contracted form of the translation for 'heading 1' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H1_BRL">
- h1
- </message>
- <message desc="Spoken to describe a &lt;h2&gt; tag." name="IDS_CHROMEVOX_TAG_H2">
- Heading 2
- </message>
- <message desc="Shown on a braille display to describe a heading on level 2 in a document. When translating, try to find a contracted form of the translation for 'heading 2' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H2_BRL">
- h2
- </message>
- <message desc="Spoken to describe a &lt;h3&gt; tag." name="IDS_CHROMEVOX_TAG_H3">
- Heading 3
- </message>
- <message desc="Shown on a braille display to describe a heading on level 3 in a document. When translating, try to find a contracted form of the translation for 'heading 3' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H3_BRL">
- h3
- </message>
- <message desc="Spoken to describe a &lt;h4&gt; tag." name="IDS_CHROMEVOX_TAG_H4">
- Heading 4
- </message>
- <message desc="Shown on a braille display to describe a heading on level 4 in a document. When translating, try to find a contracted form of the translation for 'heading 4' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H4_BRL">
- h4
- </message>
- <message desc="Spoken to describe a &lt;h5&gt; tag." name="IDS_CHROMEVOX_TAG_H5">
- Heading 5
- </message>
- <message desc="Shown on a braille display to describe a heading on level 5 in a document. When translating, try to find a contracted form of the translation for 'heading 5' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H5_BRL">
- h5
- </message>
- <message desc="Spoken to describe a &lt;h6&gt; tag." name="IDS_CHROMEVOX_TAG_H6">
- Heading 6
- </message>
- <message desc="Shown on a braille display to describe a heading on level 6 in a document. When translating, try to find a contracted form of the translation for 'heading 6' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H6_BRL">
- h6
- </message>
- <message desc="Spoken to describe a &lt;li&gt; tag." name="IDS_CHROMEVOX_TAG_LI">
- List item
- </message>
- <message desc="Brailled to describe a &lt;li&gt; tag." name="IDS_CHROMEVOX_TAG_LI_BRL">
- lstitm
- </message>
- <message desc="Spoken to describe a &lt;ol&gt; tag." name="IDS_CHROMEVOX_TAG_OL">
- Ordered List
- </message>
- <message desc="Brailled to describe a &lt;ol&gt; tag." name="IDS_CHROMEVOX_TAG_OL_BRL">
- lst
- </message>
- <message desc="Spoken to describe a &lt;select&gt; tag." name="IDS_CHROMEVOX_TAG_SELECT">
- Combo box
- </message>
- <message desc="Brailled to describe a &lt;select&gt; tag." name="IDS_CHROMEVOX_TAG_SELECT_BRL">
- cbo
- </message>
- <message desc="Spoken to describe a &lt;textarea&gt; tag." name="IDS_CHROMEVOX_TAG_TEXTAREA">
- Text area
- </message>
- <message desc="Brailled to describe a &lt;textarea&gt; tag." name="IDS_CHROMEVOX_TAG_TEXTAREA_BRL">
- mled
- </message>
- <message desc="Spoken to describe a &lt;table&gt; tag." name="IDS_CHROMEVOX_TAG_TABLE">
- table
- </message>
- <message desc="Brailled to describe a &lt;table&gt; tag." name="IDS_CHROMEVOX_TAG_TABLE_BRL">
- tbl
- </message>
- <message desc="Spoken to describe a &lt;ul&gt; tag." name="IDS_CHROMEVOX_TAG_UL">
- List
- </message>
- <message desc="Brailled to describe a &lt;ul&gt; tag." name="IDS_CHROMEVOX_TAG_UL_BRL">
- lst
- </message>
- <message desc="Spoken to describe a &lt;section&gt; tag." name="IDS_CHROMEVOX_TAG_SECTION">
- Section
- </message>
- <message desc="Brailled to describe a &lt;section&gt; tag." name="IDS_CHROMEVOX_TAG_SECTION_BRL">
- sctn
- </message>
- <message desc="Spoken to describe a &lt;nav&gt; tag." name="IDS_CHROMEVOX_TAG_NAV">
- Navigation
- </message>
- <message desc="Brailled to describe a &lt;nav&gt; tag." name="IDS_CHROMEVOX_TAG_NAV_BRL">
- nav
- </message>
- <message desc="Spoken to describe a &lt;article&gt; tag." name="IDS_CHROMEVOX_TAG_ARTICLE">
- Article
- </message>
- <message desc="Brailled to describe a &lt;article&gt; tag." name="IDS_CHROMEVOX_TAG_ARTICLE_BRL">
- article
- </message>
- <message desc="Spoken to describe a &lt;aside&gt; tag." name="IDS_CHROMEVOX_TAG_ASIDE">
- Aside
- </message>
- <message desc="Brailled to describe a &lt;aside&gt; tag." name="IDS_CHROMEVOX_TAG_ASIDE_BRL">
- aside
- </message>
- <message desc="Spoken to describe a &lt;hgroup&gt; tag." name="IDS_CHROMEVOX_TAG_HGROUP">
- Heading group
- </message>
- <message desc="Brailled to describe a &lt;hgroup&gt; tag." name="IDS_CHROMEVOX_TAG_HGROUP_BRL">
- hdnggrp
- </message>
- <message desc="Spoken to describe a &lt;header&gt; tag." name="IDS_CHROMEVOX_TAG_HEADER">
- Header
- </message>
- <message desc="Brailled to describe a &lt;header&gt; tag." name="IDS_CHROMEVOX_TAG_HEADER_BRL">
- hdr
- </message>
- <message desc="Spoken to describe a &lt;footer&gt; tag." name="IDS_CHROMEVOX_TAG_FOOTER">
- Footer
- </message>
- <message desc="Brailled to describe a &lt;footer&gt; tag." name="IDS_CHROMEVOX_TAG_FOOTER_BRL">
- ftr
- </message>
- <message desc="Spoken to describe a &lt;time&gt; tag." name="IDS_CHROMEVOX_TAG_TIME">
- Time
- </message>
- <message desc="Spoken to describe a &lt;mark&gt; tag." name="IDS_CHROMEVOX_TAG_MARK">
- Mark
- </message>
- <message desc="Brailled to describe a &lt;mark&gt; tag." name="IDS_CHROMEVOX_TAG_MARK_BRL">
- mark
- </message>
- <message desc="Spoken to describe a &lt;video&gt; tag." name="IDS_CHROMEVOX_TAG_VIDEO">
- Video
- </message>
- <message desc="Brailled to describe a &lt;video&gt; tag." name="IDS_CHROMEVOX_TAG_VIDEO_BRL">
- video
- </message>
- <message desc="Spoken to describe a &lt;audio&gt; tag." name="IDS_CHROMEVOX_TAG_AUDIO">
- Audio
- </message>
- <message desc="Brailled to describe a &lt;audio&gt; tag." name="IDS_CHROMEVOX_TAG_AUDIO_BRL">
- audio
- </message>
- <message desc="Describes an &lt;input&gt; element with type=color." name="IDS_CHROMEVOX_INPUT_TYPE_COLOR">
- Color picker
- </message>
- <message desc="Brailles an &lt;input&gt; element with type=color." name="IDS_CHROMEVOX_INPUT_TYPE_COLOR_BRL">
- color picker
- </message>
- <message desc="Describes an &lt;input&gt; element with type=datetime." name="IDS_CHROMEVOX_INPUT_TYPE_DATETIME">
- Date time control
- </message>
- <message desc="Brailles an &lt;input&gt; element with type=datetime." name="IDS_CHROMEVOX_INPUT_TYPE_DATETIME_BRL">
- date time
- </message>
- <message desc="Describes an &lt;input&gt; element with type=time." name="IDS_CHROMEVOX_INPUT_TYPE_TIME">
- Time control
- </message>
- <message desc="Brailles an &lt;input&gt; element with type=datetime." name="IDS_CHROMEVOX_INPUT_TYPE_TIME_BRL">
- time
- </message>
- <message desc="Describes an &lt;input&gt; element with type=datetime-local." name="IDS_CHROMEVOX_INPUT_TYPE_DATETIME_LOCAL">
- Date time control
- </message>
- <message desc="Brailles an &lt;input&gt; element with type=datetime-local." name="IDS_CHROMEVOX_INPUT_TYPE_DATETIME_LOCAL_BRL">
- date time
- </message>
- <message desc="Describes an &lt;input&gt; element with type=date." name="IDS_CHROMEVOX_INPUT_TYPE_DATE">
- Date control
- </message>
- <message desc="Brailles an &lt;input&gt; element with type=date." name="IDS_CHROMEVOX_INPUT_TYPE_DATE_BRL">
- date
- </message>
- <message desc="Describes an &lt;input&gt; element with type=email." name="IDS_CHROMEVOX_INPUT_TYPE_EMAIL">
- Edit text, email entry
- </message>
- <message desc="Shown on a braille display for a text field that accept an email address as input. When translating, keep the @ sign and try to find an abbreviation for 'edit field 8 dot' according to local conventions; 8 dot refers to the braille table chosen by the user that includes 8 dots in a braille cell appropriate for writing computer symbols. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_EMAIL_BRL">
- @ed 8dot
- </message>
- <message desc="Describes an &lt;input&gt; element with type=file." name="IDS_CHROMEVOX_INPUT_TYPE_FILE">
- File selection
- </message>
- <message desc="Brailles an &lt;input&gt; element with type=file." name="IDS_CHROMEVOX_INPUT_TYPE_FILE_BRL">
- file
- </message>
- <message desc="Describes an &lt;input&gt; element with type=month." name="IDS_CHROMEVOX_INPUT_TYPE_MONTH">
- Month control
- </message>
- <message desc="Shown on a braille display for a control allowing the user to input a month value. When translating, stick to lowercase." name="IDS_CHROMEVOX_INPUT_TYPE_MONTH_BRL">
- month
- </message>
- <message desc="Describes an &lt;input&gt; element with type=number." name="IDS_CHROMEVOX_INPUT_TYPE_NUMBER">
- Edit text numeric only
- </message>
- <message desc="Shown on a braille display for a text field that accept numeric input only. When translating, keep the # sign, if it can be used to represent numbers in the target language and try to find an abbreviation for 'edit field'. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_NUMBER_BRL">
- #ed
- </message>
- <message desc="Describes an &lt;input&gt; element with type=password." name="IDS_CHROMEVOX_INPUT_TYPE_PASSWORD">
- Password edit text
- </message>
- <message desc="Shown on a braille display for a password text field. When translating, try to find a contracted form of the translation of 'password edit' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_PASSWORD_BRL">
- pwded
- </message>
- <message desc="Describes an &lt;input&gt; element with type=reset." name="IDS_CHROMEVOX_INPUT_TYPE_RESET">
- Reset
- </message>
- <message desc="Shown on a braille display for a reset button. When translating, stick to lowercase." name="IDS_CHROMEVOX_INPUT_TYPE_RESET_BRL">
- reset
- </message>
- <message desc="Describes an &lt;input&gt; element with type=search." name="IDS_CHROMEVOX_INPUT_TYPE_SEARCH">
- Edit text, search entry
- </message>
- <message desc="Shown on a braille display for an input field of type search. When translating, try to find a contracted form of the translation for 'search edit field' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_SEARCH_BRL">
- srched
- </message>
- <message desc="Describes an &lt;input&gt; element with type=text." name="IDS_CHROMEVOX_INPUT_TYPE_TEXT">
- Edit text
- </message>
- <message desc="Shown on a braille display to describe a text field. When translating, try to find a contracted form of the translation for 'edit field' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_TEXT_BRL">
- ed
- </message>
- <message desc="Describes an &lt;input&gt; element with type=url." name="IDS_CHROMEVOX_INPUT_TYPE_URL">
- Edit text, URL entry
- </message>
- <message desc="Shown on a braille display to describe a text field for entering a URL. When translating, try to find a contracted form of the translation for 'url edit field 8 dot' according to local conventions; 8 dot refers to the braille table chosen by the user that includes 8 dots in a braille cell appropriate for writing computer symbols. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_URL_BRL">
- urled 8dot
- </message>
- <message desc="Describes an &lt;input&gt; element with type=week." name="IDS_CHROMEVOX_INPUT_TYPE_WEEK">
- Week of the year control
- </message>
- <message desc="Shown on a braille display to describe a widget for entering a week number. When translating, stick to lowercase." name="IDS_CHROMEVOX_INPUT_TYPE_WEEK_BRL">
- week
- </message>
- <message desc="Spoken to describe a &lt;a&gt; tag with a link to an internal anchor." name="IDS_CHROMEVOX_INTERNAL_LINK">
- Internal link
- </message>
- <message desc="Shown on a braille display to describe a link to a different part of the same web page. When translating, try to find a contracted form of the translation for 'internal link' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INTERNAL_LINK_BRL">
- intlnk
- </message>
- <message desc="In an editable text box, describes a blank line." name="IDS_CHROMEVOX_TEXT_BOX_BLANK">
- Blank
- </message>
- <message desc="In an editable text box, describes a line with only whitespace." name="IDS_CHROMEVOX_TEXT_BOX_WHITESPACE" meaning="UI element">
- Space
- </message>
- <!-- TODO(crbug.com/999781): The following 3 messages are combined with other message fragments. -->
- <!-- Combining message fragments is a I18N code-smell. Combine fragments into a single message. -->
- <message desc="Further describes a list-like element with a number of items. e.g. This will be combined with other messages to produce: List with 3 items." name="IDS_CHROMEVOX_LIST_WITH_ITEMS_NOT_PLURALIZED">
- with <ph name="num">$1</ph> items
- </message>
- <message desc="Further describes a list-like element with a number of items for braille. e.g. This will be combined with other messages to produce: lst +3." name="IDS_CHROMEVOX_LIST_WITH_ITEMS_NOT_PLURALIZED_BRL">
- +<ph name="num">$1</ph>
- </message>
- <message desc="Further describes a list-like element with a number of items. e.g. This will be combined with other messages to produce: List with 3 items." name="IDS_CHROMEVOX_LIST_WITH_ITEMS">
- {COUNT, plural, =1{with # item} other{with # items}}
- </message>
- <!-- TODO(crbug.com/999781): This should not need ICU msg format. Fix where the message is used. -->
- <message desc="Further describes a list-like element with a number of items in braille." name="IDS_CHROMEVOX_LIST_WITH_ITEMS_BRL">
- {COUNT, plural, =1{+#} other{+#}}
- </message>
- <message desc="Describes the state of a progress bar, in percent." name="IDS_CHROMEVOX_STATE_PERCENT">
- <ph name="num">$1</ph>%
- </message>
- <message desc="Brailles the state of a progress bar, in percent." name="IDS_CHROMEVOX_STATE_PERCENT_BRL">
- <ph name="num">$1</ph>%
- </message>
- <message desc="Phrase indicating a menu item has a submenu." name="IDS_CHROMEVOX_HAS_SUBMENU">
- with submenu
- </message>
- <message desc="Phrase indicating a control has a pop-up component to it." name="IDS_CHROMEVOX_HAS_POPUP">
- has popup
- </message>
- <message desc="Brailled phrase indicating a control has a pop-up component to it." name="IDS_CHROMEVOX_HAS_POPUP_BRL">
- has popup
- </message>
- <message desc="Describes a collection of tags. e.g. A 'link collection'." name="IDS_CHROMEVOX_COLLECTION">
- <ph name="tag">$1</ph> collection with <ph name="num">$2</ph> items
- </message>
- <message desc='The "Enter" key on the keyboard.' name="IDS_CHROMEVOX_ENTER_KEY">
- Enter
- </message>
- <message desc='The "Space" key on the keyboard.' name="IDS_CHROMEVOX_SPACE_KEY">
- Space
- </message>
- <message desc='The "Backspace" key on the keyboard.' name="IDS_CHROMEVOX_BACKSPACE_KEY">
- Backspace
- </message>
- <message desc='The "Tab" key on the keyboard.' name="IDS_CHROMEVOX_TAB_KEY">
- Tab
- </message>
- <message desc='The "Left" key on the keyboard.' name="IDS_CHROMEVOX_LEFT_KEY">
- Left
- </message>
- <message desc='The "Up" key on the keyboard.' name="IDS_CHROMEVOX_UP_KEY">
- Up
- </message>
- <message desc='The "Right" key on the keyboard.' name="IDS_CHROMEVOX_RIGHT_KEY">
- Right
- </message>
- <message desc='The "Down" key on the keyboard.' name="IDS_CHROMEVOX_DOWN_KEY">
- Down
- </message>
- <message desc="Describes an element with a link that has no known URL." name="IDS_CHROMEVOX_UNKNOWN_LINK">
- Unknown link
- </message>
- <message desc="The spoken feedback for the command to toggle ChromeVox between active and inactive states." name="IDS_CHROMEVOX_TOGGLE_CHROMEVOX_ACTIVE">
- Toggle ChromeVox active or inactive.
- </message>
- <message desc="The spoken feedback when ChromeVox becomes inactive." name="IDS_CHROMEVOX_CHROMEVOX_INACTIVE">
- ChromeVox is now inactive.
- </message>
- <message desc="The description of the command to toggle ChromeVox classic." name="IDS_CHROMEVOX_TOGGLE_CHROMEVOX">
- Toggle ChromeVox classic.
- </message>
- <message desc="The indicator of a pause to tts." name="IDS_CHROMEVOX_PAUSE">
- , '''
- </message>
- <message desc="Description of the previous different element command displayed in the options page." name="IDS_CHROMEVOX_PREVIOUS_DIFFERENT_ELEMENT">
- Previous different element.
- </message>
- <message desc="Description of the next different element command displayed in the options page." name="IDS_CHROMEVOX_NEXT_DIFFERENT_ELEMENT">
- Next different element.
- </message>
- <message desc="Description of the previous similar element command displayed in the options page." name="IDS_CHROMEVOX_PREVIOUS_SIMILAR_ELEMENT">
- Previous similar element.
- </message>
- <message desc="Description of the next similar element command." name="IDS_CHROMEVOX_NEXT_SIMILAR_ELEMENT">
- Next similar element.
- </message>
- <message desc="Verbal indication of no more similar elements." name="IDS_CHROMEVOX_NO_MORE_SIMILAR_ELEMENTS">
- No more similar elements.
- </message>
- <message desc="Verbal indication of no more different elements." name="IDS_CHROMEVOX_NO_MORE_DIFFERENT_ELEMENTS">
- No more different elements.
- </message>
- <message desc="Description of the enter group exploration user command. Displayed in the Options page." name="IDS_CHROMEVOX_ENTER_CSS_SPACE">
- Enter group exploration
- </message>
- <message desc="Spoken when entering group exploration." name="IDS_CHROMEVOX_ENTER_GROUP_EXPLORATION">
- Exploring groups
- </message>
- <message desc="A message spoken when the user switches to the object granularity, which allows users to navigate the page by objects." name="IDS_CHROMEVOX_OBJECT_STRATEGY">
- Object
- </message>
- <message desc="A message spoken when the user switches to the group granularity, which allows users to navigate the page by groups." name="IDS_CHROMEVOX_GROUP_STRATEGY">
- Group
- </message>
- <message desc="A message spoken when the user switches to the table granularity, which allows users to navigate within a group." name="IDS_CHROMEVOX_TABLE_STRATEGY">
- Table
- </message>
- <message desc="A message spoken when the user switches to the row granularity, which allows users to navigate within a table." name="IDS_CHROMEVOX_ROW_GRANULARITY">
- Row
- </message>
- <message desc="A message spoken when the user switches to the column granularity, which allows users to navigate within a column." name="IDS_CHROMEVOX_COLUMN_GRANULARITY">
- Column
- </message>
- <message desc="Describes rows within tables on the web." name="IDS_CHROMEVOX_ROLE_ROW">
- Row
- </message>
- <message desc="Describes row groups within tables on the web." name="IDS_CHROMEVOX_ROLE_ROW_GROUP">
- Row group
- </message>
- <message desc="Describes columns within tables on the web." name="IDS_CHROMEVOX_ROLE_COLUMN">
- Column
- </message>
- <message desc="Describes rows within tables on the web." name="IDS_CHROMEVOX_ROLE_ROW_BRL">
- row
- </message>
- <message desc="Describes columns within tables on the web." name="IDS_CHROMEVOX_ROLE_COLUMN_BRL">
- col
- </message>
- <message desc="A message spoken when the user switches to the MathMl tree granularity, which allows users to navigate within a math expression." name="IDS_CHROMEVOX_MATHML_TREE_GRANULARITY">
- Math ML Tree
- </message>
- <message desc="A message spoken when the user switches to the MathMl layout granularity, which allows users to navigate within a math expression." name="IDS_CHROMEVOX_MATHML_LAYOUT_GRANULARITY">
- Math ML Layout
- </message>
- <message desc="A message spoken when the user switches to the MathMl token granularity, which allows users to navigate within a math expression." name="IDS_CHROMEVOX_MATHML_TOKEN_GRANULARITY">
- Math ML Token
- </message>
- <message desc="A message spoken when the user switches to the MathMl leaf granularity, which allows users to navigate within a math expression." name="IDS_CHROMEVOX_MATHML_LEAF_GRANULARITY">
- Math ML Leaf
- </message>
- <message desc="A message spoken when the user switches to the visual granularity, which allows users to navigate the page by visual regions." name="IDS_CHROMEVOX_VISUAL_STRATEGY">
- Visual
- </message>
- <message desc="A message spoken when the user switches to a custom granularity, which allows users to navigate in a yet-to-be-defined manner." name="IDS_CHROMEVOX_CUSTOM_STRATEGY">
- Custom
- </message>
- <message desc="A message spoken when the user switches to the line granularity, which allows users to navigate the page one line at a time." name="IDS_CHROMEVOX_LINE_GRANULARITY">
- Line
- </message>
- <message desc="A message spoken when the user switches to the sentence granularity, which allows users to navigate the page one sentence at a time." name="IDS_CHROMEVOX_SENTENCE_GRANULARITY">
- Sentence
- </message>
- <message desc="A message spoken when the user switches to the word granularity, which allows users to navigate the page one word at a time." name="IDS_CHROMEVOX_WORD_GRANULARITY">
- Word
- </message>
- <message desc="A message spoken when the user switches to the character granularity, which allows users to navigate the page one character at a time." name="IDS_CHROMEVOX_CHARACTER_GRANULARITY">
- Character
- </message>
- <message desc="Spoken when the search widget first shows." name="IDS_CHROMEVOX_SEARCH_WIDGET_INTRO">
- Find in page.
- </message>
- <message desc="Spoken help message when the search widget shows." name="IDS_CHROMEVOX_SEARCH_WIDGET_INTRO_HELP">
- Enter a search query.
- </message>
- <message desc="Spoken message when the search widget hides." name="IDS_CHROMEVOX_SEARCH_WIDGET_OUTRO">
- Exited find in page.
- </message>
- <message desc="Spoken message when the search widget has no more search results." name="IDS_CHROMEVOX_SEARCH_WIDGET_NO_RESULTS">
- No more results.
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_MODIFIER_KEYS">
- Modifier Keys
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_NAVIGATION">
- ChromeVox Navigation
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_INFORMATION">
- Information
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_HELP_COMMANDS">
- Help Commands
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_CONTROLLING_SPEECH">
- Controlling Speech
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_OVERVIEW">
- Overview
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_TABLES">
- Tables
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_JUMP_COMMANDS">
- Jump Commands
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_BRAILLE">
- Braille
- </message>
- <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_DEVELOPER">
- Developer
- </message>
- <message desc="Name of the classic key map." name="IDS_CHROMEVOX_KEYMAP_CLASSIC">
- Classic keymap
- </message>
- <message desc="Name of the key map for release of ChromeVox named Next." name="IDS_CHROMEVOX_KEYMAP_NEXT">
- Next keymap
- </message>
- <message desc="Name of the flat key map." name="IDS_CHROMEVOX_KEYMAP_FLAT">
- Flat keymap
- </message>
- <message desc="Name of the experimental key map." name="IDS_CHROMEVOX_KEYMAP_EXPERIMENTAL">
- Experimental keymap
- </message>
- <message desc="Description of the TTS console logging command. Displayed in the options page." name="IDS_CHROMEVOX_ENABLE_TTS_LOG">
- Enable TTS logging
- </message>
- <message desc="Spoken when a user begins a selection on a webpage." name="IDS_CHROMEVOX_BEGIN_SELECTION">
- Start selection
- </message>
- <message desc="Spoken when a user ends a selection on a webpage." name="IDS_CHROMEVOX_END_SELECTION">
- End selection
- </message>
- <message desc="Spoken to describe the current selection." name="IDS_CHROMEVOX_SELECTION_IS">
- Selection is '''
- </message>
- <message desc="Describes the toggle selection command. Displayed in the options page." name="IDS_CHROMEVOX_TOGGLE_SELECTION">
- Start or end selection.
- </message>
- <message desc="Spoken when the browser's copy command is invoked." name="IDS_CHROMEVOX_COPY">
- copy <ph name="TEXT">$1</ph>.
- </message>
- <message desc="Spoken when the browser's cut command is invoked." name="IDS_CHROMEVOX_CUT">
- cut <ph name="TEXT">$1</ph>.
- </message>
- <message desc="Spoken when the browser's paste command is invoked." name="IDS_CHROMEVOX_PASTE">
- paste <ph name="TEXT">$1</ph>.
- </message>
- <message desc="Spoken when additional characters are selected in editable text." name="IDS_CHROMEVOX_SELECTED">
- selected
- </message>
- <message desc="Spoken in editable text when text is unselected." name="IDS_CHROMEVOX_UNSELECTED">
- unselected
- </message>
- <message desc="Spoken when more than one character gets added to selection in editable text." name="IDS_CHROMEVOX_ADDED_TO_SELECTION">
- added to selection
- </message>
- <message desc="Spoken when more than one character gets removed from selection in editable text." name="IDS_CHROMEVOX_REMOVED_FROM_SELECTION">
- removed from selection
- </message>
- <message desc="Spoken as the conjunction between hotkey combinations like ctrl then alt followed by a." name="IDS_CHROMEVOX_THEN">
- then
- </message>
- <message desc="Spoken as the conjunction between hotkey combinations like ctrl then alt followed by a." name="IDS_CHROMEVOX_FOLLOWED_BY">
- followed by
- </message>
- <message desc="Spoken to describe the ChromeVox modifier keys when describing a key combination." name="IDS_CHROMEVOX_MODIFIER_KEY">
- ChromeVox modifier
- </message>
- <message desc="Spoken when a key conflict occurs in the options page." name="IDS_CHROMEVOX_KEY_CONFLICT">
- <ph name="key">$1</ph> is already assigned to a command.
- </message>
- <message desc="Spoken to describe the current selection is a Math object." name="IDS_CHROMEVOX_MATH_EXPR">
- Math
- </message>
- <message desc="Brailled phrase indicating the current selection is a Math object. When translating, stick to lowercase." name="IDS_CHROMEVOX_MATH_EXPR_BRL">
- math
- </message>
- <message desc="Describes an element with the ARIA role math." name="IDS_CHROMEVOX_NOT_INSIDE_MATH">
- Not inside math
- </message>
- <message desc="Time widget. Indicates the user is on the AM/PM field." name="IDS_CHROMEVOX_TIMEWIDGET_AMPM">
- AM PM
- </message>
- <message desc="Time widget. Indicates the user is on the hours field." name="IDS_CHROMEVOX_TIMEWIDGET_HOURS">
- hours
- </message>
- <message desc="Time widget. Indicates the user is on the minutes field." name="IDS_CHROMEVOX_TIMEWIDGET_MINUTES">
- minutes
- </message>
- <message desc="Time widget. Indicates the user is on the seconds field." name="IDS_CHROMEVOX_TIMEWIDGET_SECONDS">
- seconds
- </message>
- <message desc="Time widget. Indicates the user is on the milliseconds field." name="IDS_CHROMEVOX_TIMEWIDGET_MILLISECONDS">
- milliseconds
- </message>
- <message desc="Time widget. Indicates the AM/PM is set to AM." name="IDS_CHROMEVOX_TIMEWIDGET_AM">
- AM
- </message>
- <message desc="Time widget. Indicates the AM/PM is set to PM." name="IDS_CHROMEVOX_TIMEWIDGET_PM">
- PM
- </message>
- <message desc="Date widget. Indicates the user is on the week field." name="IDS_CHROMEVOX_DATEWIDGET_WEEK">
- week
- </message>
- <message desc="Date widget. Indicates that the month is January." name="IDS_CHROMEVOX_DATEWIDGET_JANUARY">
- January
- </message>
- <message desc="Date widget. Indicates that the month is February." name="IDS_CHROMEVOX_DATEWIDGET_FEBRUARY">
- February
- </message>
- <message desc="Date widget. Indicates that the month is March." name="IDS_CHROMEVOX_DATEWIDGET_MARCH">
- March
- </message>
- <message desc="Date widget. Indicates that the month is April." name="IDS_CHROMEVOX_DATEWIDGET_APRIL">
- April
- </message>
- <message desc="Date widget. Indicates that the month is May." name="IDS_CHROMEVOX_DATEWIDGET_MAY">
- May
- </message>
- <message desc="Date widget. Indicates that the month is June." name="IDS_CHROMEVOX_DATEWIDGET_JUNE">
- June
- </message>
- <message desc="Date widget. Indicates that the month is July." name="IDS_CHROMEVOX_DATEWIDGET_JULY">
- July
- </message>
- <message desc="Date widget. Indicates that the month is August." name="IDS_CHROMEVOX_DATEWIDGET_AUGUST">
- August
- </message>
- <message desc="Date widget. Indicates that the month is September." name="IDS_CHROMEVOX_DATEWIDGET_SEPTEMBER">
- September
- </message>
- <message desc="Date widget. Indicates that the month is October." name="IDS_CHROMEVOX_DATEWIDGET_OCTOBER">
- October
- </message>
- <message desc="Date widget. Indicates that the month is November." name="IDS_CHROMEVOX_DATEWIDGET_NOVEMBER">
- November
- </message>
- <message desc="Date widget. Indicates that the month is December." name="IDS_CHROMEVOX_DATEWIDGET_DECEMBER">
- December
- </message>
- <message desc="Spoken when a user switches to a mode announcing no punctuation." name="IDS_CHROMEVOX_NO_PUNCTUATION">
- No punctuation
- </message>
- <message desc="Spoken when a user switches to a mode announcing some punctuation." name="IDS_CHROMEVOX_SOME_PUNCTUATION">
- Some punctuation
- </message>
- <message desc="Spoken when a user switches to a mode announcing all punctuation." name="IDS_CHROMEVOX_ALL_PUNCTUATION">
- All punctuation
- </message>
- <message desc="Spoken as help after every search result in search widget." name="IDS_CHROMEVOX_SEARCH_HELP_ITEM">
- Press enter to accept or escape to cancel, down for next and up for previous.
- </message>
- <message desc="Spoken to describe a clickable element." name="IDS_CHROMEVOX_CLICKABLE">
- clickable
- </message>
- <message desc="Brailled to describe a clickable element." name="IDS_CHROMEVOX_CLICKABLE_BRL">
- clk
- </message>
- <message desc="The description of the previous character command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_CHARACTER">
- Previous Character
- </message>
- <message desc="The description of the next character command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_CHARACTER">
- Next Character
- </message>
- <message desc="The description of the previous word command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_WORD">
- Previous Word
- </message>
- <message desc="The description of the next word command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_WORD">
- Next Word
- </message>
- <message desc="The description of the previous sentence command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_SENTENCE">
- Previous Sentence
- </message>
- <message desc="The description of the next sentence command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_SENTENCE">
- Next Sentence
- </message>
- <message desc="The description of the previous line command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LINE">
- Previous Line
- </message>
- <message desc="The description of the next line command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LINE">
- Next Line
- </message>
- <message desc="The description of the previous object command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_OBJECT">
- Previous Object
- </message>
- <message desc="The description of the next object command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_OBJECT">
- Next Object
- </message>
- <message desc="The description of the previous group command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_GROUP">
- Previous Group
- </message>
- <message desc="The description of the next group command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_GROUP">
- Next Group
- </message>
- <message desc="The description of the previous similar command." name="IDS_CHROMEVOX_PREVIOUS_SIMILAR_ITEM">
- Previous similar item
- </message>
- <message desc="The description of the next similar item command." name="IDS_CHROMEVOX_NEXT_SIMILAR_ITEM">
- Next similar item
- </message>
- <message desc="Describes nodes or anything describing them as a landmark." name="IDS_CHROMEVOX_ROLE_LANDMARK">
- Landmark
- </message>
- <message desc="Describes a button that can be pressed/toggled." name="IDS_CHROMEVOX_ROLE_TOGGLE_BUTTON">
- Toggle Button
- </message>
- <message desc="Brailles a button that can be pressed/toggled." name="IDS_CHROMEVOX_ROLE_TOGGLE_BUTTON_BRL">
- tgl btn
- </message>
- <message desc="Spoken when user types invalid keys into the modifier selection field." name="IDS_CHROMEVOX_MODIFIER_ENTRY_ERROR">
- No modifier pressed; please press and hold one or more modifiers; lift your fingers once done and you will hear the keys set. Tab to exit.
- </message>
- <message desc="Spoken when a modifier key becomes successfully set." name="IDS_CHROMEVOX_MODIFIER_ENTRY_SET">
- <ph name="key">$1</ph> is now the new ChromeVox modifier.
- </message>
- <message desc="Spoken when resetting the current keymap to defaults." name="IDS_CHROMEVOX_KEYMAP_RESET">
- <ph name="key">$1</ph> has been reset.
- </message>
- <message desc="Spoken when switched to a keymap different from the current one." name="IDS_CHROMEVOX_KEYMAP_SWITCH">
- Switched to <ph name="key">$1</ph>.
- </message>
- <message desc="The description of the key to move to the beginning of the page. Displayed in the Options page." name="IDS_CHROMEVOX_JUMP_TO_TOP">
- Jump to the top of the page
- </message>
- <message desc="The description of the key to move to the end of the page. Displayed in the Options page." name="IDS_CHROMEVOX_JUMP_TO_BOTTOM">
- Jump to the bottom of the page
- </message>
- <message desc="Message telling the user that they will wrap to the top of the page." name="IDS_CHROMEVOX_WRAPPED_TO_TOP">
- Wrapped to top
- </message>
- <message desc="Message telling the user that they will wrap to the bottom of the page." name="IDS_CHROMEVOX_WRAPPED_TO_BOTTOM">
- Wrapped to bottom
- </message>
- <message desc="Description of the cycle punctuation echo key. Shown in options page." name="IDS_CHROMEVOX_CYCLE_PUNCTUATION_ECHO">
- Cycle punctuation echo
- </message>
- <message desc="Description of the cycle typing echo key. Shown in options page." name="IDS_CHROMEVOX_CYCLE_TYPING_ECHO">
- Cycle typing echo
- </message>
- <message desc="The description of the pauseAllMedia key. Shown in options page." name="IDS_CHROMEVOX_PAUSE_ALL_MEDIA">
- Pauses all currently playing media widgets
- </message>
- <message desc="The description of the openLongDesc key. Shown in options page." name="IDS_CHROMEVOX_OPEN_LONG_DESC">
- Open long description in a new tab
- </message>
- <message desc="Message telling the user that there is no long description if they try to open the long description for an element which does not have one." name="IDS_CHROMEVOX_NO_LONG_DESC">
- No long description
- </message>
- <message desc="Message telling the user that the current image has a long description." name="IDS_CHROMEVOX_IMAGE_WITH_LONG_DESC">
- Image with long description
- </message>
- <message desc="Describes the value of a selection of items within a listbox. For example, 'Mercury to Jupiter, selected 5 items'." name="IDS_CHROMEVOX_SELECTED_OPTIONS_VALUE">
- <ph name="v1">$1</ph> to <ph name="v2">$2</ph>
- </message>
- <message desc="Brailles the value of a selection of items within a listbox. For example, 'Mercury-Jupiter, sld 5'." name="IDS_CHROMEVOX_SELECTED_OPTIONS_VALUE_BRL">
- <ph name="v1">$1</ph>-<ph name="v2">$2</ph>
- </message>
- <message desc="Describes the count of a selection of items within a listbox. For example, 'Mercury to Jupiter, selected 5 items'." name="IDS_CHROMEVOX_SELECTED_OPTIONS_STATE">
- selected <ph name="count">$1</ph> items
- </message>
- <message desc="Brailles the count of a selection of items within a listbox. For example, 'Mercury-Jupiter, sld 5'." name="IDS_CHROMEVOX_SELECTED_OPTIONS_STATE_BRL">
- sld <ph name="count">$1</ph>
- </message>
- <message desc="Spoken when a selection on a page is cleared." name="IDS_CHROMEVOX_CLEAR_PAGE_SELECTION">
- cleared selection
- </message>
- <message desc="Spoken to describe character echo (a setting to speak characters while typing into editable text fields)." name="IDS_CHROMEVOX_CHARACTER_ECHO">
- character echo
- </message>
- <message desc="Spoken to describe word echo (a setting to speak words while typing into editable text fields)." name="IDS_CHROMEVOX_WORD_ECHO">
- word echo
- </message>
- <message desc="Spoken to describe character and word echo (a setting to speak characters and words while typing into editable text fields)." name="IDS_CHROMEVOX_CHARACTER_AND_WORD_ECHO">
- character and word echo
- </message>
- <message desc="Spoken to describe no echo (a setting to not speak characters or words while typing into editable text fields)." name="IDS_CHROMEVOX_NONE_ECHO">
- no typing echo
- </message>
- <message desc="Describes the enter content command in the options page. Content refers to any special structure on the page such as tables or math." name="IDS_CHROMEVOX_ENTER_CONTENT">
- enter structured content, such as tables
- </message>
- <message desc="Describes the exit content command in the options page. Content refers to any special structure on the page such as tables or math." name="IDS_CHROMEVOX_EXIT_CONTENT">
- exit structured content, such as tables
- </message>
- <message desc="Announced when user enters special content such as tables." name="IDS_CHROMEVOX_ENTER_CONTENT_SAY">
- entered <ph name="type">$1</ph>
- </message>
- <message desc="Spoken to describe structural lines." name="IDS_CHROMEVOX_STRUCTURAL_LINE">
- structural line
- </message>
- <message desc="Spoken to describe layout lines." name="IDS_CHROMEVOX_LAYOUT_LINE">
- line
- </message>
- <message desc="Displayed to describe the toggle line type (structural or layout). Shown in the options page." name="IDS_CHROMEVOX_TOGGLE_LINE_TYPE">
- Toggle line type between structural or layout
- </message>
- <message desc="Describes the collection of navigation strategies for a table." name="IDS_CHROMEVOX_TABLE_SHIFTER">
- table
- </message>
- <message desc="Describes the defaultset of navigation strategies." name="IDS_CHROMEVOX_NAVIGATION_SHIFTER">
- default navigation
- </message>
- <message desc="Describes the collection of navigation strategies for math." name="IDS_CHROMEVOX_MATH_SHIFTER">
- math
- </message>
- <message desc="Displayed to describes the key that toggles semantic interpretation of mathematical formulas." name="IDS_CHROMEVOX_TOGGLE_SEMANTICS">
- Toggle interpretation of math expressions between structural and semantic
- </message>
- <message desc="Spoken when semantics interpretation is switched on." name="IDS_CHROMEVOX_SEMANTICS_ON">
- Semantics on
- </message>
- <message desc="Spoken when semantics interpretation is switched off." name="IDS_CHROMEVOX_SEMANTICS_OFF">
- Semantics off
- </message>
- <message desc='Used as a phonetic word hint for a particular letter. The word is used to clarify similarly sounding letters like m and n. This mapping is taken directly from the NATO phonetic standard: https://en.wikipedia.org/wiki/NATO_phonetic_alphabet Please retain the structure of this string. The structure is of the form {"letter": "phonetic word equivalent", ..., "letter": "phonetic word equivalent"}. The first part of the mapping (letter) should be all letters of the localization in lower case. The second part (phonetic word equivalent) should be the word that describes the letter.' name="IDS_CHROMEVOX_PHONETIC_MAP">
- {"a": "alpha", "b": "bravo", "c": "charlie", "d": "delta", "e": "echo", "f": "foxtrot", "g": "golf", "h": "hotel", "i": "india", "j": "juliet","k": "kilo", "l": "lima", "m": "mike", "n": "november", "o": "oscar","p": "papa", "q": "quebec", "r": "romeo", "s": "sierra", "t": "tango", "u": "uniform", "v": "victor", "w": "whiskey","x": "xray", "y": "yankee", "z": "zulu"}
- </message>
- <message desc="Describes a key sequence that will let the user review (examine and make a decision on) all of the alerts on the page." name="IDS_CHROMEVOX_REVIEW_ALERTS">
- Press Alt+Shift+A to review alerts
- </message>
- <message desc="Spoken if the user attempts to jump to the next article when none exists." name="IDS_CHROMEVOX_NO_NEXT_ARTICLE">
- No next article.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous article when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_ARTICLE">
- No previous article.
- </message>
- <message desc="Spoken when the browser first starts and ChromeVox is active." name="IDS_CHROMEVOX_CHROMEVOX_INTRO">
- ChromeVox spoken feedback is ready
- </message>
- <message desc="Brailled when ChromeVox is connected to a braille display." name="IDS_CHROMEVOX_INTRO_BRL">
- ChromeVox ready
- </message>
- <message desc="Spoken when earcons are on." name="IDS_CHROMEVOX_EARCONS_ON">
- Earcons on
- </message>
- <message desc="Spoken when earcons are off." name="IDS_CHROMEVOX_EARCONS_OFF">
- Earcons off
- </message>
- <message desc="Description of the toggle earcons key. Shown in options page." name="IDS_CHROMEVOX_TOGGLE_EARCONS">
- Turn sound feedback (earcons) on or off.
- </message>
- <message desc="Description of the speak time and date key. Shown in options page." name="IDS_CHROMEVOX_SPEAK_TIME_AND_DATE">
- Speak the current time and date.
- </message>
- <message desc="Abbreviation indicating following text is an incremental search result. For example, in English, the abbreviation might be 'S:' for 'Search'." name="IDS_CHROMEVOX_MARK_AS_SEARCH_RESULT_BRL">
- S:<ph name="result">$1</ph>
- </message>
- <message desc="Announced when text within an editable text field gets deleted." name="IDS_CHROMEVOX_TEXT_DELETED">
- Deleted
- </message>
- <message desc="Describes the perform default action command. This is usually triggered by hitting the enter key over a control. Shown in options page." name="IDS_CHROMEVOX_PERFORM_DEFAULT_ACTION">
- Perform default action
- </message>
- <message desc="Exclamation (!) character description." name="IDS_CHROMEVOX_EXCLAMATION">
- {COUNT, plural, =1 {exclamation}other {# exclamations}}
- </message>
- <message desc="Space ( ) character description." name="IDS_CHROMEVOX_SPACE">
- {COUNT, plural, =1 {space}other {# spaces}}
- </message>
- <message desc="Backtcik (`) character description." name="IDS_CHROMEVOX_BACKTICK">
- {COUNT, plural, =1 {backtick}other {# backticks}}
- </message>
- <message desc="Tilde (~) character description." name="IDS_CHROMEVOX_TILDE">
- {COUNT, plural, =1 {TILDE}other {# tildes}}
- </message>
- <message desc="At (@) character description." name="IDS_CHROMEVOX_AT">
- {COUNT, plural, =1 {at}other {# at signs}}
- </message>
- <message desc="Pound (#) character description." name="IDS_CHROMEVOX_POUND">
- {COUNT, plural, =1 {pound}other {# pound signs}}
- </message>
- <message desc="Dollar ($) character description." name="IDS_CHROMEVOX_DOLLAR">
- {COUNT, plural, =1 {dollar}other {# dollar signs}}
- </message>
- <message desc="Percent (%) character description." name="IDS_CHROMEVOX_PERCENT">
- {COUNT, plural, =1 {percent}other {# percent signs}}
- </message>
- <message desc="Caret (^) character description." name="IDS_CHROMEVOX_CARET">
- {COUNT, plural, =1 {caret}other {# carets}}
- </message>
- <message desc="Ampersand (&amp;) character description." name="IDS_CHROMEVOX_AMPERSAND">
- {COUNT, plural, =1 {ampersand}other {# ampersands}}
- </message>
- <message desc="Asterisk (*) character description." name="IDS_CHROMEVOX_ASTERISK">
- {COUNT, plural, =1 {asterisk}other {# asterisks}}
- </message>
- <message desc="Left parenthesis (() character description." name="IDS_CHROMEVOX_OPEN_PAREN">
- {COUNT, plural, =1 {open paren}other {# open parens}}
- </message>
- <message desc="Right parenthesis ()) character description." name="IDS_CHROMEVOX_CLOSE_PAREN">
- {COUNT, plural, =1 {close paren}other {# close parens}}
- </message>
- <message desc="Dash (-) character description." name="IDS_CHROMEVOX_DASH">
- {COUNT, plural, =1 {dash}other {# dashes}}
- </message>
- <message desc="Underscore (_) character description." name="IDS_CHROMEVOX_UNDERSCORE">
- {COUNT, plural, =1 {underscore}other {# underscores}}
- </message>
- <message desc="Equals (=) character description." name="IDS_CHROMEVOX_EQUALS">
- {COUNT, plural, =1 {equal}other {# equal signs}}
- </message>
- <message desc="Plus (+) character description." name="IDS_CHROMEVOX_PLUS">
- {COUNT, plural, =1 {plus}other {# plus signs}}
- </message>
- <message desc="Left bracket ([) character description." name="IDS_CHROMEVOX_LEFT_BRACKET">
- {COUNT, plural, =1 {left bracket}other {# left brackets}}
- </message>
- <message desc="Right bracket (]) character description." name="IDS_CHROMEVOX_RIGHT_BRACKET">
- {COUNT, plural, =1 {right bracket}other {# right brackets}}
- </message>
- <message desc="Left brace ({) character description." name="IDS_CHROMEVOX_LEFT_BRACE">
- {COUNT, plural, =1 {left brace}other {# left braces}}
- </message>
- <message desc="Right brace (}) character description." name="IDS_CHROMEVOX_RIGHT_BRACE">
- {COUNT, plural, =1 {right brace}other {# right braces}}
- </message>
- <message desc="Pipe (|) character description." name="IDS_CHROMEVOX_PIPE">
- {COUNT, plural, =1 {pipe}other {# vertical pipes}}
- </message>
- <message desc="Semicolon (;) character description." name="IDS_CHROMEVOX_SEMICOLON">
- {COUNT, plural, =1 {semicolon}other {# semicolons}}
- </message>
- <message desc="Colon (:) character description." name="IDS_CHROMEVOX_COLON">
- {COUNT, plural, =1 {colon}other {# colons}}
- </message>
- <message desc="Comma (,) character description." name="IDS_CHROMEVOX_COMMA">
- {COUNT, plural, =1 {comma}other {# commas}}
- </message>
- <message desc="Dot (.) character description." name="IDS_CHROMEVOX_DOT">
- {COUNT, plural, =1 {dot}=3 {ellipsis}other {# dots}}
- </message>
- <message desc="Less than (&lt;) character description." name="IDS_CHROMEVOX_LESS_THAN">
- {COUNT, plural, =1 {less than}other {# less than signs}}
- </message>
- <message desc="Greater than (&gt;) character description." name="IDS_CHROMEVOX_GREATER_THAN">
- {COUNT, plural, =1 {greater than}other {# greater than signs}}
- </message>
- <message desc="Slash (/) character description." name="IDS_CHROMEVOX_SLASH">
- {COUNT, plural, =1 {slash}other {# slashes}}
- </message>
- <message desc="Question mark (?) character description." name="IDS_CHROMEVOX_QUESTION_MARK">
- {COUNT, plural, =1 {question mark}other {# question marks}}
- </message>
- <message desc='Quote (") character description.' name="IDS_CHROMEVOX_QUOTE">
- {COUNT, plural, =1 {quote}other {# quotes}}
- </message>
- <message desc="Apostrophe (') character description." name="IDS_CHROMEVOX_APOSTROPHE">
- {COUNT, plural, =1 {apostrophe}other {# apostrophes}}
- </message>
- <message desc="Tab (\t) character description." name="IDS_CHROMEVOX_TAB">
- {COUNT, plural, =1 {tab}other {# tabs}}
- </message>
- <message desc="Backslash (\) character description." name="IDS_CHROMEVOX_BACKSLASH">
- {COUNT, plural, =1 {backslash}other {# backslashes}}
- </message>
- <message desc="BULLET (•) character description." name="IDS_CHROMEVOX_BULLET">
- {COUNT, plural, =1 {bullet}other {# bullets}}
- </message>
- <message desc="Describes the braille click command. Displayed in the options page." name="IDS_CHROMEVOX_BRAILLE_ROUTING">
- Click the item under routing key <ph name="ROUTING_KEY_NUMBER">$1</ph>
- </message>
- <message desc="Describes the braille pan backward command. Displayed in the options page." name="IDS_CHROMEVOX_BRAILLE_PAN_LEFT">
- Pan backward
- </message>
- <message desc="Describes the braille pan forward command. Displayed in the options page." name="IDS_CHROMEVOX_BRAILLE_PAN_RIGHT">
- Pan forward
- </message>
- <message desc="The description of the braille previous line command. Displayed in the Options page." name="IDS_CHROMEVOX_BRAILLE_LINE_UP">
- Braille previous Line
- </message>
- <message desc="The description of the braille next line command. Displayed in the Options page." name="IDS_CHROMEVOX_BRAILLE_LINE_DOWN">
- Braille next Line
- </message>
- <message desc="The description of the braille top command. Displayed in the Options page." name="IDS_CHROMEVOX_BRAILLE_TOP">
- Move braille display to top of page
- </message>
- <message desc="The description of the braille bottom command. Displayed in the Options page." name="IDS_CHROMEVOX_BRAILLE_BOTTOM">
- Move braille display to bottom of page
- </message>
- <message desc="Describes a single physical braille dot on a refreshable braille display. Will usually be followed with numbers to describe the layout of a braille cell. For example, dot 8" name="IDS_CHROMEVOX_BRAILLE_DOT">
- dot <ph name="dot">$1</ph>
- </message>
- <message desc="Describes multiple physical braille dots on a refreshable braille display. Will usually be followed with numbers to describe the layout of a braille cell. For example, dots 1 2 3 4 8" name="IDS_CHROMEVOX_BRAILLE_DOTS">
- dots <ph name="dot">$1</ph>
- </message>
- <message desc="Describes dots on a refreshable braille display pressed with the space key. For example, dots 1 2 3 4 8 chord" name="IDS_CHROMEVOX_BRAILLE_CHORD">
- <ph name="dot">$1</ph> chord
- </message>
- <message desc="The description of the command that allows the user to view a graphic as a dot pattern on a refreshable braille display." name="IDS_CHROMEVOX_VIEW_GRAPHIC_AS_BRAILLE">
- View Graphic As Braille
- </message>
- <message desc="Spoken to describe an access key. An access key consists of a single letter. When pressed along with a modifier (usually alt, but depends on platform), a targetted node will be activated." name="IDS_CHROMEVOX_ACCESS_KEY">
- has access key, <ph name="key">$1</ph>
- </message>
- <message desc="Brailled to describe an access key. An access key consists of a single letter. When pressed along with a modifier (usually alt, but depends on platform), a targetted node will be activated. When translating, stick to lower case." name="IDS_CHROMEVOX_ACCESS_KEY_BRL">
- access key:<ph name="key">$1</ph>
- </message>
- <message desc="A dictionary mapping locale identifiers to their corresponding language names. The format is the following: { ..., 'en_US': 'English (United States)', ...}. Translation only needed for the language and country names (e.g. English (United States)). All other strings must be kept as is." name="IDS_CHROMEVOX_LOCALE_DICT">
- {"ar": "Arabic",
- "as": "Assamese",
- "aw": "Awadhi",
- "be": "Bengali",
- "bg": "Bulgarian",
- "bh": "Bihari",
- "bo": "Tibetan",
- "br": "Braj",
- "ca": "Catalan",
- "ckb": "Sorani",
- "cs": "Czech",
- "cy": "Welsh",
- "da": "Danish",
- "de": "German",
- "de_CH": "German (Switzerland)",
- "de_DE": "German (Germany)",
- "dra": "Dravidian",
- "el": "Greek",
- "en": "English",
- "en_CA": "English (Canada)",
- "en_GB": "English (United Kingdom)",
- "en_US": "English (United States)",
- "eo": "Esperanto",
- "es": "Spanish",
- "et": "Estonian",
- "fa": "Persian",
- "fr": "French",
- "fr_CA": "French (Canada)",
- "fr_FR": "French (France)",
- "fi": "Finnish",
- "ga": "Irish",
- "gd": "Gaelic",
- "gon": "Gondi",
- "gu": "Gujarati",
- "he": "Hebrew",
- "hi": "Hindi",
- "hr": "Croatian",
- "hu": "Hungarian",
- "hy": "Armenian",
- "is": "Icelandic",
- "it": "Italian",
- "iu": "Inuktitut",
- "ka": "Kannada",
- "kh": "Khasi",
- "ko": "Korean",
- "kok": "Konkani",
- "kru": "Kurukh",
- "ks": "Kashmiri",
- "lt": "Lithuanian",
- "lv": "Latvian",
- "mao": "Maori",
- "ml": "Malayalam",
- "mt": "Maltese",
- "mwr": "Marwari",
- "mn": "Mongolian",
- "mun": "Munda",
- "nb": "Norwegian Bokmål",
- "ne": "Nepali",
- "nl": "Dutch",
- "no": "Norwegian",
- "or": "Oriya",
- "pi": "Pali",
- "pl": "Polish",
- "pt": "Portuguese",
- "pu": "Punjabi",
- "ro": "Romanian",
- "ru": "Russian",
- "sa": "Sanskrit",
- "si": "Sindhi",
- "sin": "Sinhala",
- "sk": "Slovak",
- "sl": "Slovenian",
- "sr": "Serbian",
- "sv": "Swedish",
- "ta": "Tamil",
- "te": "Telugu",
- "tr": "Turkish",
- "tsn": "Afrikaans",
- "uk": "Ukrainian",
- "ur": "Urdu",
- "vi": "Vietnamese",
- "zh": "Chinese",
- "zh_TW": "Chinese (Traditional Han)"}
- </message>
- <message desc="The text to speak when the user moves their cursor to the end of a block of editable text, in verbose mode." name="IDS_CHROMEVOX_END_OF_TEXT_VERBOSE">
- End of text
- </message>
- <message desc="The text to speak when the user moves their cursor to the end of a block of editable text, in brief mode." name="IDS_CHROMEVOX_END_OF_TEXT_BRIEF">
- End
- </message>
- <message desc="Spoken to describe a new line ('\n')." name="IDS_CHROMEVOX_NEW_LINE">
- new line
- </message>
- <message desc="Spoken to describe a carriage return ('\r')." name="IDS_CHROMEVOX_RETURN">
- return
- </message>
- <message desc="Spoken after pressing the pass through key command." name="IDS_CHROMEVOX_PASS_THROUGH_KEY">
- Ignoring next key press
- </message>
- <message desc="Describes the pass through key command. Shown in options page." name="IDS_CHROMEVOX_PASS_THROUGH_KEY_DESCRIPTION">
- Pass through key
- </message>
- <message desc="Describes the show context menu command. Shown in options page." name="IDS_CHROMEVOX_SHOW_CONTEXT_MENU">
- Show context menu
- </message>
- <message desc="Describes the braille caption feature. Braille captioning provides an overlay showing both text and braille of what ChromeVox would show on a refreshable braille display. Shown in the options page as a label." name="IDS_CHROMEVOX_BRAILLE_CAPTIONS">
- Toggle braille captions
- </message>
- <message desc="Spoken and brailled when the braille captions feature is enabled. This feature shows the braille output in a small overlay on the screen for development and demonstration purposes." name="IDS_CHROMEVOX_BRAILLE_CAPTIONS_ENABLED">
- Braille captions enabled.
- </message>
- <message desc="Spoken and brailled when the braille captions feature is disabled. This feature shows the braille output in a small overlay on the screen for development and demonstration purposes." name="IDS_CHROMEVOX_BRAILLE_CAPTIONS_DISABLED">
- Braille captions disabled.
- </message>
- <message desc="Message spoken to user when switching to a mode where searching is not case-sensitive." name="IDS_CHROMEVOX_IGNORING_CASE">
- Ignoring case.
- </message>
- <message desc="Message spoken to user when switching to a mode where searching is case-sensitive." name="IDS_CHROMEVOX_CASE_SENSITIVE">
- Case sensitive.
- </message>
-
- <!-- Keyboard Explorer -->
- <message desc="Describes the back key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_BACK_KEY">
- back
- </message>
- <message desc="Describes the forward key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_FORWARD_KEY">
- forward
- </message>
- <message desc="Describes the refresh key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_REFRESH_KEY">
- refresh
- </message>
- <message desc="Describes the key to toggle full screen in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_TOGGLE_FULL_SCREEN_KEY">
- toggle full screen
- </message>
- <message desc="Describes the key to toggle window overview in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_WINDOW_OVERVIEW_KEY">
- window overview
- </message>
- <message desc="Describes the brightness down key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_BRIGHTNESS_DOWN_KEY">
- Brightness down
- </message>
- <message desc="Describes the brightness up key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_BRIGHTNESS_UP_KEY">
- Brightness up
- </message>
- <message desc="Describes the volume mute key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_MUTE_KEY">
- volume mute
- </message>
- <message desc="Describes the volume down key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_DOWN_KEY">
- volume down
- </message>
- <message desc="Describes the volume up key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_UP_KEY">
- volume up
- </message>
- <message desc="Describes the Assistant key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_ASSISTANT_KEY">
- Google Assistant
- </message>
-
- <!-- Panel -->
- <message desc="Title of the ChromeVox panel, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_TITLE">
- ChromeVox Panel
- </message>
- <message desc="Title of the ChromeVox panel when menus are open, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_MENUS_TITLE">
- ChromeVox Menus
- </message>
- <message desc="Title of the ChromeVox panel when the tutorial is open, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_TUTORIAL_TITLE">
- ChromeVox Tutorial
- </message>
- <message desc="Title of the button that opens up the ChromeVox menus." name="IDS_CHROMEVOX_MENUS_TITLE">
- ChromeVox Menus
- </message>
- <message desc="Title of the button that opens up ChromeVox options." name="IDS_CHROMEVOX_OPTIONS">
- ChromeVox Options
- </message>
- <message desc="Title of the button that disables ChromeVox." name="IDS_CHROMEVOX_DISABLE_CHROMEVOX">
- Disable ChromeVox
- </message>
- <message desc="Text in parentheses to be appended next to a tab that's currently active." name="IDS_CHROMEVOX_ACTIVE_TAB">
- (active)
- </message>
- <message desc="Title displayed in the panel for the jump menu." name="IDS_CHROMEVOX_PANEL_MENU_JUMP">
- Jump
- </message>
- <message desc="Title displayed in the panel for the speech menu." name="IDS_CHROMEVOX_PANEL_MENU_SPEECH">
- Speech
- </message>
- <message desc="Title displayed in the panel for the tabs menu." name="IDS_CHROMEVOX_PANEL_MENU_TABS">
- Tabs
- </message>
- <message desc="Title displayed in the panel for the ChromeVox menu." name="IDS_CHROMEVOX_PANEL_MENU_CHROMEVOX">
- ChromeVox
- </message>
- <message desc="Title displayed in the panel for the actions menu." name="IDS_CHROMEVOX_PANEL_MENU_ACTIONS">
- Actions
- </message>
- <message desc="Title displayed in the panel when there are no menu items." name="IDS_CHROMEVOX_PANEL_MENU_ITEM_NONE">
- No items.
- </message>
- <message desc="Title displayed in the panel for the menuitem to report an issue." name="IDS_CHROMEVOX_PANEL_MENU_ITEM_REPORT_ISSUE">
- Report an issue
- </message>
- <message desc="Title of a notification that ChromeVox has been updated." name="IDS_CHROMEVOX_UPDATE_TITLE">
- ChromeVox Updated
- </message>
- <message desc="Message text for a notification that ChromeVox has been updated for a new release." name="IDS_CHROMEVOX_UPDATE_MESSAGE_NEW">
- Press ChromeVox o, n to find out what's new
- </message>
- <message desc="Options page description for the command to show ChromeVox's update page." name="IDS_CHROMEVOX_SHOW_NEXT_UPDATE_DESCRIPTION">
- Show update notes
- </message>
- <message desc="Description of button that closes the ChromeVox Tutorial" name="IDS_CHROMEVOX_CLOSE_TUTORIAL">
- Close ChromeVox Tutorial
- </message>
- <message desc="Button that goes to the previous page in the ChromeVox Tutorial" name="IDS_CHROMEVOX_TUTORIAL_PREVIOUS">
- Previous
- </message>
- <message desc="Button that goes to the next page in the ChromeVox Tutorial" name="IDS_CHROMEVOX_TUTORIAL_NEXT">
- Next
- </message>
- <message desc="Heading that welcomes users to the ChromeVox tutorial" name="IDS_CHROMEVOX_TUTORIAL_WELCOME_HEADING">
- Welcome to ChromeVox!
- </message>
- <message desc="Introductory text for the 'ChromeVox' tutorial" name="IDS_CHROMEVOX_TUTORIAL_WELCOME_TEXT">
- Are you using ChromeVox spoken feedback for the first time? This quick tutorial explains the essentials for getting started with ChromeVox.
- </message>
- <message desc="Text that tells users to press the enter key to move to the next page or backspace to move to the previous page in the tutorial" name="IDS_CHROMEVOX_TUTORIAL_ENTER_TO_ADVANCE">
- To advance, press enter; to go back, press backspace.
- </message>
- <message desc="Heading that talks about turning ChromeVox on, off, and stopping it from speaking" name="IDS_CHROMEVOX_TUTORIAL_ON_OFF_HEADING">
- On, Off, and Stop
- </message>
- <message desc="Part of ChromeVox tutorial, explains that pressing Control on the keyboard stops it from speaking" name="IDS_CHROMEVOX_TUTORIAL_CONTROL">
- To temporarily stop ChromeVox from speaking, press the Control key.
- </message>
- <message desc="Part of ChromeVox tutorial, explains that you can turn ChromeVox on or turn it off, by pressing Control+Alt+Z on the keyboard" name="IDS_CHROMEVOX_TUTORIAL_ON_OFF">
- To turn ChromeVox on or off, use Control+Alt+Z.
- </message>
- <message desc="Heading for a section of the ChromeVox tutorial talking about the ChromeVox modifier key" name="IDS_CHROMEVOX_TUTORIAL_MODIFIER_HEADING">
- The ChromeVox modifier key
- </message>
- <message desc="Text explaining that the Search key on the keyboard will be held down for most ChromeVox shortcuts" name="IDS_CHROMEVOX_TUTORIAL_MODIFIER">
- In ChromeVox, the Search key is the modifier key. Most ChromeVox shortcuts start with the Search key. You’ll also use the arrow keys for navigation.
- </message>
- <message desc="Text explaining where to find the Search key on a Chromebook keyboard" name="IDS_CHROMEVOX_TUTORIAL_CHROMEBOOK_SEARCH">
- On the Chromebook, the Search key is immediately above the left Shift key.
- </message>
- <message desc="Text explaining that while the ChromeVox tutorial is open, users can press any key to hear the key's name" name="IDS_CHROMEVOX_TUTORIAL_ANY_KEY">
- During this tutorial, press any key to hear its name.
- </message>
- <message desc="Heading as part of the ChromeVox tutorial for a section on how to navigate within a webpage" name="IDS_CHROMEVOX_TUTORIAL_BASIC_NAVIGATION_HEADING">
- Basic Navigation
- </message>
- <message desc="Part of the ChromeVox tutorial, explanation of keystrokes to navigate a webpage." name="IDS_CHROMEVOX_TUTORIAL_BASIC_NAVIGATION">
- To move forward between items on a page, press Search + Right Arrow, or Search + Left Arrow to jump back. To go to the next line, press Search + Down Arrow. To get to the previous line, use Search + Up Arrow. If you reach an item you want to click, press Search + Space.
- </message>
- <message desc="Part of the ChromeVox tutorial, instructs the user to use key combinations to find and click a button titled 'Next' on the page and click it." name="IDS_CHROMEVOX_TUTORIAL_CLICK_NEXT">
- Try using Search + Right Arrow now to find the Next button, then press Search + Space to click it.
- </message>
- <message desc="Heading for a section of the ChromeVox tutorial on commands to jump" name="IDS_CHROMEVOX_TUTORIAL_JUMP_HEADING">
- Jump Commands
- </message>
- <message desc="Part of the ChromeVox tutorial, explains two keystrokes to jump to the next or previous heading." name="IDS_CHROMEVOX_TUTORIAL_JUMP">
- Use jump commands to skip to specific types of elements. To jump forward between headings, press Search + H, or to jump backward, press Search + Shift + H.
- </message>
- <message desc="Part of the ChromeVox tutorial, heading used to illustrate jumping." name="IDS_CHROMEVOX_TUTORIAL_JUMP_SECOND_HEADING">
- This is the second heading. Keep going; either press Search+H or Search+Shift+H
- </message>
- <message desc="Part of the ChromeVox tutorial, heading used to illustrate jumping from last heading." name="IDS_CHROMEVOX_TUTORIAL_JUMP_WRAP_HEADING">
- This is the last heading. Press Search+H to wrap to the first heading, or Search+Shift+H to go to the second heading on this page.
- </message>
- <message desc="Heading for a section of the ChromeVox tutorial on menus of ChromeVox commands to press" name="IDS_CHROMEVOX_TUTORIAL_MENUS_HEADING">
- Command Menus
- </message>
- <message desc="Part of the ChromeVox tutorial, explains the keystrokes to press to open and use a menu of commands." name="IDS_CHROMEVOX_TUTORIAL_MENUS">
- To explore all ChromeVox commands and shortcuts, press Search + Period, then use the Arrow keys to navigate the menus, and Enter to activate a command. Return here by pressing Search+o then t.
- </message>
- <message desc="Heading for a section of the ChromeVox tutorial on Chrome shortcuts" name="IDS_CHROMEVOX_TUTORIAL_CHROME_SHORTCUTS_HEADING">
- Helpful Chrome Shortcuts
- </message>
- <message desc="Part of the ChromeVox tutorial, explains some common Chrome keyboard shortcuts" name="IDS_CHROMEVOX_TUTORIAL_CHROME_SHORTCUTS">
- The next few shortcuts aren’t ChromeVox commands, but they’re still very useful for getting the most out of Chrome.
-To navigate forward through actionable items like buttons and links, press the Tab key. To navigate backwards, press Shift+Tab.
-To enter the Chrome browser address box, also called the omnibox, press Control + L.
-To open and go to a new tab automatically, press Control+T. Your cursor will be in the omnibox.
-To close a tab, press Control+W.
-To move forward between open tabs, use Control+Tab.
-To open the Chrome browser menu, press Alt+F.
- </message>
- <message desc="Part of the ChromeVox tutorial, explains a keyboard shortcut to press on Chromebook keyboards" name="IDS_CHROMEVOX_TUTORIAL_CHROMEBOOK_CTRL_FORWARD">
- To jump to other parts of the screen, like toolbars or the system tray, press Control+Forward. On a Chromebook, the Forward key is immediately above the number 2 key.
- </message>
- <message desc="Heading for a section of the ChromeVox tutorial where the user can learn more" name="IDS_CHROMEVOX_TUTORIAL_LEARN_MORE_HEADING">
- Learn More
- </message>
- <message desc="Part of the ChromeVox tutorial, explaining that this is the end of the tutorial and that there are links to more information." name="IDS_CHROMEVOX_TUTORIAL_LEARN_MORE">
- Congratulations! You’ve learned the essentials to use ChromeVox successfully. Remember that you can open the ChromeVox command menu at any time by pressing Search+Period. To learn even more about ChromeVox and Chrome OS, visit the following articles.
-If you're done with the tutorial, use ChromeVox to navigate to the Close button and click it.
- </message>
- <message desc="Part of the ChromeVox update notes for m63, title." name="IDS_CHROMEVOX_UPDATE_63_TITLE">
- You've been updated to ChromeVox 63!
- </message>
- <message desc="Part of the ChromeVox update notes for m63, introductory text." name="IDS_CHROMEVOX_UPDATE_63_INTRO">
- We have some exciting changes in this new release; here's what's new:
- </message>
- <message desc="Part of the ChromeVox update notes for 63, new items 1." name="IDS_CHROMEVOX_UPDATE_63_ITEM_1">
- Classic removed. The keyboard toggle to switch back into ChromeVox Classic has been removed.
- </message>
- <message desc="Part of the ChromeVox update notes for m63, new items 2." name="IDS_CHROMEVOX_UPDATE_63_ITEM_2">
- Rich text support. ChromeVox now supports rich text fields including jump commands, braille cursor routing, selection, and more.
- </message>
- <message desc="Part of the ChromeVox update notes for m63, new items 3." name="IDS_CHROMEVOX_UPDATE_63_ITEM_3">
- Android apps for Chrome. If you have Play Store on your device, get a sneak peek at ChromeVox with Android apps. Try the experimental support by downloading Google Chrome Canary from the Play Store.
- </message>
- <message desc="Part of the ChromeVox update notes for m63, closing paragraph." name="IDS_CHROMEVOX_UPDATE_63_OUTTRO">
- As always, you can send us feedback directly by pressing Search+a then i. We're eager to hear from you.
- </message>
- <message desc="Title of an article on the command reference for 'ChromeVox'" name="IDS_CHROMEVOX_NEXT_COMMAND_REFERENCE">
- ChromeVox Command Reference
- </message>
- <message desc="Title of an article on keyboard shortcuts for Chromebooks" name="IDS_CHROMEVOX_CHROME_KEYBOARD_SHORTCUTS">
- Chromebook keyboard shortcuts
- </message>
- <message desc="Title of an article on how to use accessibility features of the Chromebook touch screen" name="IDS_CHROMEVOX_TOUCHSCREEN_ACCESSIBILITY">
- Use Chromebook touch screen accessibility features
- </message>
- <message desc="Describes a UI element that is busy" name="IDS_CHROMEVOX_BUSY_STATE">
- busy
- </message>
- <message desc="Brailled for a UI element that is busy" name="IDS_CHROMEVOX_BUSY_STATE_BRL">
- busy
- </message>
- <message desc="Describes a UI element invoked after pressing enter such as an ok button in a dialog" name="IDS_CHROMEVOX_DEFAULT_STATE">
- default
- </message>
- <message desc="Brailles for a UI element invoked after pressing enter such as an ok button in a dialog" name="IDS_CHROMEVOX_DEFAULT_STATE_BRL">
- default
- </message>
- <message desc="Title of the earcon page in the ChromeVox tutorial" name="IDS_CHROMEVOX_TUTORIAL_EARCON_PAGE_TITLE">
- Sounds
- </message>
- <message desc="Body text of the earcon page in the ChromeVox tutorial" name="IDS_CHROMEVOX_TUTORIAL_EARCON_PAGE_BODY">
- ChromeVox uses sounds to give you essential and additional information. You can use these sounds to navigate more quickly by learning what each sound means. Once you get more comfortable, you can turn off verbose descriptions in speech and rely on them for essential information about the page. Here's a complete list of sounds and what they mean.
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_ALERT_MODAL_EARCON_DESCRIPTION">
- A modal alert
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_ALERT_NONMODAL_EARCON_DESCRIPTION">
- A non modal alert
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_BUTTON_EARCON_DESCRIPTION">
- A button
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_CHECK_OFF_EARCON_DESCRIPTION">
- An unchecked checkbox
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_CHECK_ON_EARCON_DESCRIPTION">
- A checked checkbox
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_EDITABLE_TEXT_EARCON_DESCRIPTION">
- An editable text field
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_INVALID_KEYPRESS_EARCON_DESCRIPTION">
- An invalid key press
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_LINK_EARCON_DESCRIPTION">
- A link
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_LISTBOX_EARCON_DESCRIPTION">
- A listbox or combo box
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_PAGE_START_LOADING_EARCON_DESCRIPTION">
- A page load in progress
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_POP_UP_BUTTON_EARCON_DESCRIPTION">
- A pop up button
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_SLIDER_EARCON_DESCRIPTION">
- A slider
- </message>
- <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_WRAP_EARCON_DESCRIPTION">
- Wrap from beginning to end or end to beginning inside of a page, dialog, or other container
- </message>
- <message desc="Describes a command to turn off the visual display for accessibility without impacting usage of the machine." name="IDS_CHROMEVOX_DARKEN_SCREEN">
- Darken screen
- </message>
- <message desc="Describes a command to turn the visual display on for accessibility undoing any previous request to turn off the visual display." name="IDS_CHROMEVOX_UNDARKEN_SCREEN">
- Undarken screen
- </message>
- <message desc="Describes a command that turns text to speech feedback off." name="IDS_CHROMEVOX_SPEECH_OFF">
- Speech off
- </message>
- <message desc="Describes a command that turns text to speech feedback on." name="IDS_CHROMEVOX_SPEECH_ON">
- Speech on
- </message>
- <message desc="Description of a command that toggles text to speech feedback on or off." name="IDS_CHROMEVOX_SPEECH_ON_OFF_DESCRIPTION">
- Toggle speech on or off
- </message>
- <message desc="Description of a command that toggles between 6 and 8 dot braille." name="IDS_CHROMEVOX_TOGGLE_BRAILLE_TABLE">
- Toggle between 6 and 8 dot braille
- </message>
- <message desc="Spoken when a user navigates into a misspelled word." name="IDS_CHROMEVOX_MISSPELLING_START">
- Misspelled
- </message>
- <message desc="Spoken when a user navigates out of a misspelled word." name="IDS_CHROMEVOX_MISSPELLING_END">
- Leaving misspelled
- </message>
- <message desc="Spoken when a user navigates into a grammar error." name="IDS_CHROMEVOX_GRAMMAR_START">
- Grammar error
- </message>
- <message desc="Spoken when a user navigates out of a grammar error." name="IDS_CHROMEVOX_GRAMMAR_END">
- Leaving grammar error
- </message>
- <message desc="Spoken to describe text that is superscript." name="IDS_CHROMEVOX_SUPERSCRIPT">
- Superscript
- </message>
- <message desc="Spoken to describe text that is not superscript." name="IDS_CHROMEVOX_NOT_SUPERSCRIPT">
- Not superscript
- </message>
- <message desc="Spoken to describe text that is subscript." name="IDS_CHROMEVOX_SUBSCRIPT">
- Subscript
- </message>
- <message desc="Spoken to describe text that is not subscript." name="IDS_CHROMEVOX_NOT_SUBSCRIPT">
- Not subscript
- </message>
- <message desc="Spoken to describe bolded text." name="IDS_CHROMEVOX_BOLD">
- Bold
- </message>
- <message desc="Spoken to describe non bolded text." name="IDS_CHROMEVOX_NOT_BOLD">
- Not bold
- </message>
- <message desc="Spoken to describe italicized text." name="IDS_CHROMEVOX_ITALIC">
- Italic
- </message>
- <message desc="Spoken to describe non italicized text." name="IDS_CHROMEVOX_NOT_ITALIC">
- Not italic
- </message>
- <message desc="Spoken to describe underlined text." name="IDS_CHROMEVOX_UNDERLINE">
- Underline
- </message>
- <message desc="Spoken to describe non underlined text." name="IDS_CHROMEVOX_NOT_UNDERLINE">
- Not underline
- </message>
- <message desc="Spoken to describe line-through text." name="IDS_CHROMEVOX_LINETHROUGH">
- Line through
- </message>
- <message desc="Spoken to describe non line-through text." name="IDS_CHROMEVOX_NOT_LINETHROUGH">
- Not line through
- </message>
- <message desc="Spoken when a user navigates to text and the link state changes" name="IDS_CHROMEVOX_LINK">
- Link
- </message>
- <message desc="Spoken to describe non-linked text." name="IDS_CHROMEVOX_NOT_LINK">
- Not link
- </message>
- <message desc="Spoken when a user navigates to text and the font family changes, e.g. 'Font Arial'" name="IDS_CHROMEVOX_FONT_FAMILY">
- Font <ph name="font_family">$1<ex>Arial</ex></ph>
- </message>
- <message desc="Spoken when a user navigates to text and the font size changes, e.g. 'Size 12'" name="IDS_CHROMEVOX_FONT_SIZE">
- Size <ph name="font_size">$1<ex>12</ex></ph>
- </message>
- <message desc="Spoken when a user navigates to text and the font color changes, e.g. 'Red, 100% opacity'" name="IDS_CHROMEVOX_FONT_COLOR">
- <ph name="font_color">$1<ex>Red, 100% opacity</ex></ph>
- </message>
- <message desc="Shown to a user when they press a braille keyboard command that requires on screen keyboard to be enabled." name="IDS_CHROMEVOX_ENABLE_VIRTUAL_KEYBOARD">
- Please enable the on screen keyboard under status tray, accessibility to use extended braille commands.
- </message>
- <message desc="Shown to a user when they invoke the read current title command in a context without a title." name="IDS_CHROMEVOX_NO_TITLE">
- No title
- </message>
- <message desc="Spoken when a user issues a command when nothing is focused." name="IDS_CHROMEVOX_WARNING_NO_CURRENT_RANGE">
- No focus. Press Ctrl+T to open a new tab.
- </message>
- <message desc="A hint to the user that the current control is checkable." name="IDS_CHROMEVOX_HINT_CHECKABLE">
- Press Search+Space to toggle.
- </message>
- <message desc="A hint to the user that the current control is clickable." name="IDS_CHROMEVOX_HINT_CLICKABLE">
- Press Search+Space to activate.
- </message>
- <message desc="A hint to the user that the current control has a list of auto completions." name="IDS_CHROMEVOX_HINT_AUTOCOMPLETE_LIST">
- Press up or down arrow for auto completions.
- </message>
- <message desc="A hint to the user that the current control has inline auto completions." name="IDS_CHROMEVOX_HINT_AUTOCOMPLETE_INLINE">
- Type to auto complete.
- </message>
- <message desc="A hint to the user for interacting with the table control." name="IDS_CHROMEVOX_HINT_TABLE">
- Press Search+Ctrl+Alt with arrows to navigate by cell.
- </message>
- <message desc="A hint to the user for interacting with the menu control." name="IDS_CHROMEVOX_HINT_MENU">
- Press up or down arrow to navigate; enter to activate.
- </message>
- <message desc="A hint to the user that there are details associated with this element." name="IDS_CHROMEVOX_HINT_DETAILS">
- Press Search+A, J to jump to details.
- </message>
- <message desc="The display name of the command that will jump to more details about an item." name="IDS_CHROMEVOX_JUMP_TO_DETAILS">
- Jump to Details
- </message>
- <message desc="Describes the action of decrementing a control." name="IDS_CHROMEVOX_ACTION_DECREMENT_DESCRIPTION">
- Decrease value
- </message>
- <message desc="Describes the action of incrementing a control." name="IDS_CHROMEVOX_ACTION_INCREMENT_DESCRIPTION">
- Increase value
- </message>
- <message desc="Describes the action of scrolling backward." name="IDS_CHROMEVOX_ACTION_SCROLL_BACKWARD_DESCRIPTION">
- Scroll back
- </message>
- <message desc="Describes the action of scrolling forward." name="IDS_CHROMEVOX_ACTION_SCROLL_FORWARD_DESCRIPTION">
- Scroll forward
- </message>
- <message desc="A hint to the user that they are editing text within a text field. This text will be spoken using text to speech along with a description of the text field's name and value" name="IDS_CHROMEVOX_HINT_IS_EDITING">
- is editing
- </message>
- <message desc="A hint to the user about the special behavior of the Search key with arrows within a text field. This text will be spoken using text to speech along with a description of the text field's name and value. The text is intentionally in fragments to reduce the time needed to convey this information via text to speech. Keys are capitalized and do not contain plus separators because it adds to the spoken announcement's duration. As a general guide, try to read the string aloud." name="IDS_CHROMEVOX_HINT_SEARCH_WITHIN_TEXT_FIELD">
- Use Search Left or Right for Home or End, Search Control Left or Right for Control Home or End, Search Up or Down for Page Up or Down.
- </message>
- <message desc="A hint to the user controls that can be double tapped." name="IDS_CHROMEVOX_HINT_DOUBLE_TAP">
- Double tap to activate
- </message>
- <message desc="Shown to the user in braille and speech when the device goes into landscape orientation." name="IDS_CHROMEVOX_DEVICE_LANDSCAPE">
- landscape
- </message>
- <message desc="Shown to the user in braille and speech when the device goes into portrait orientation." name="IDS_CHROMEVOX_DEVICE_PORTRAIT">
- portrait
- </message>
- <message desc="A hint to the user for how to interact with math content using the keyboard." name="IDS_CHROMEVOX_HINT_MATH_KEYBOARD">
- Press up, down, left, or right to explore math.
- </message>
- <message desc="Voice name for the system default Text-to-Speech voice" name="IDS_CHROMEVOX_SYSTEM_VOICE">
- System Text-to-Speech voice
- </message>
- <message desc="Menu item text for a command to open the text to speech settings page" name="IDS_CHROMEVOX_SHOW_TTS_SETTINGS">
- Open text-to-speech settings
- </message>
- <message desc="A hint to the user on how to interact with the virtual on screen keyboard." name="IDS_CHROMEVOX_HINT_TOUCH_TYPE">
- Find a key, then lift to type
- </message>
- <message desc="Hint for how to start editing a text field while exploring the screen using touch exploration." name="IDS_CHROMEVOX_HINT_DOUBLE_TAP_TO_EDIT">
- Double tap to start editing
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPEUP1_GESTURE">
- Swipe one finger up
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPEDOWN1_GESTURE">
- Swipe one finger down
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPELEFT1_GESTURE">
- Swipe one finger left
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPERIGHT1_GESTURE">
- Swipe one finger right
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPEUP2_GESTURE">
- Swipe two fingers up
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPEDOWN2_GESTURE">
- Swipe two fingers down
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPELEFT2_GESTURE">
- Swipe two fingers left
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPERIGHT2_GESTURE">
- Swipe two fingers right
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPEUP3_GESTURE">
- Swipe three fingers up
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPEDOWN3_GESTURE">
- Swipe three fingers down
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPELEFT3_GESTURE">
- Swipe three fingers left
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_SWIPERIGHT3_GESTURE">
- Swipe three fingers right
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_TAP2_GESTURE">
- Tap with two fingers
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_TAP4_GESTURE">
- Tap with four fingers
- </message>
- <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_CLICK_GESTURE">
- Double tap with one finger
- </message>
- <message desc="Describes Learn Mode when the mode is initially entered." name="IDS_CHROMEVOX_LEARN_MODE_INTRO">
- Starting Learn Mode. Press a qwerty key, refreshable braille key, or touch gesture to learn its function. Press control with w or escape to exit.
- </message>
- <message desc="Output when leaving Learn Mode." name="IDS_CHROMEVOX_LEARN_MODE_OUTTRO">
- Stopping Learn Mode.
- </message>
- <message desc="Part of the ChromeVox touch tutorial page. Title of the tutorial page for touch support." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_HEADING">
- Touch
- </message>
- <message desc="Part of the ChromeVox touch tutorial page. Introduces this page." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_INTRO">
- You can use ChromeVox with the touchscreen.
- </message>
- <message desc="Part of the ChromeVox touch tutorial page. Describes dragging a finger on the touch screen to get spoken feedback." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_DRAG_ONE_FINGER">
- Drag one finger to hear what you touch
- </message>
- <message desc="Part of the ChromeVox touch tutorial page. Describes swiping left or right with one finger to move item by item." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_SWIPE_LEFT_RIGHT">
- Swipe left or right to move by item
- </message>
-
- <message desc="Part of the ChromeVox touch tutorial page. Describes swiping up or down with one finger to move line by line." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_SWIPE_UP_DOWN">
- Swipe up or down to move by line
- </message>
- <message desc="Part of the ChromeVox touch tutorial page. Describes double tapping with one finger to activate an item." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_DOUBLE_TAP">
- Double-tap to activate what is focused
- </message>
- <message desc="Part of the ChromeVox touch tutorial page. Describes a single tap of four fingers to enter the ChromeVox menus." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_FOUR_FINGER_TAP">
- Tap with 4 fingers to enter the ChromeVox menus
- </message>
- <message desc="Part of the ChromeVox touch tutorial page. Describes a two finger tap to stop speech." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_TWO_FINGER_TAP">
- Tap with 2 fingers to temporarily stop speech
- </message>
- <message desc="Part of the ChromeVox touch tutorial page. Concludes this page." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_LEARN_MORE">
- Explore more gestures in Learn Mode and the Chromebook Help Center
- </message>
- <message desc="Title of the bluetooth braille display section in ChromeVox options." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_TITLE">
- Bluetooth Braille Display
- </message>
- <message desc="Labels a button which when pressed, connects to a selected braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_CONNECT">
- Connect
- </message>
- <message desc="Labels a button which when pressed, disconnects from a selected braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_DISCONNECT">
- Disconnect
- </message>
- <message desc="Labels a button which is disabled and indicates the system is connecting to a braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_CONNECTING">
- Connecting
- </message>
- <message desc="Labels a button which when pressed, forgets the selected braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_FORGET">
- Forget
- </message>
- <message desc="Labels a text field which prompts the user for a pincode when pairing a braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_PINCODE_LABEL">
- Please enter a pin
- </message>
- <message desc="Labels a select control which lists all bluetooth braille displays." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_SELECT_LABEL">
- Select a bluetooth braille display
- </message>
- <message desc="Describes web content that has no title." name="IDS_CHROMEVOX_WEB_CONTENT">
- Web Content
- </message>
- <message desc="The text label for ChromeVox language switching checkbox."
- name="IDS_CHROMEVOX_OPTIONS_LANG_SWITCHING_CHECKBOX_LABEL">
- Automatically switch ChromeVox voice based on language
- </message>
- <message desc="Spoken to describe all rich text attributes of a node." name="IDS_CHROMEVOX_RICH_TEXT_ATTRIBUTES">
- Text formatting.
- <ph name="font_size_string">$1<ex>Size 12</ex></ph>
- <ph name="color_string">$2<ex>Red, 100% opacity.</ex></ph>
- <ph name="bold_string">$3<ex>Bold</ex></ph>
- <ph name="italic_string">$4<ex>Italic</ex></ph>
- <ph name="underline_string">$5<ex>Unerline</ex></ph>
- <ph name="line_through_string">$6<ex>Line through</ex></ph>
- <ph name="font_family_string">$7<ex>Arial</ex></ph>
- </message>
-
- <!-- Colors -->
- <message desc="Spoken to describe color and opacity of text" name="IDS_CHROMEVOX_COLOR_DESCRIPTION">
- <ph name="color">$1<ex>Red</ex></ph>, <ph name="opacity_percentage">$2<ex>50</ex></ph>% opacity.
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLACK">
- Black
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_GREEN">
- Dark Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GREEN">
- Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PURPLE">
- Purple
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_GOLDEN_ROD">
- Dark Golden Rod
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LEMON_CHIFFON">
- Lemon Chiffon
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SIENNA">
- Sienna
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ORANGE">
- Orange
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SADDLE_BROWN">
- Saddle Brown
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CYAN">
- Cyan
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GREEN_YELLOW">
- Green Yellow
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CHOCOLATE">
- Chocolate
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MAROON">
- Maroon
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GOLDEN_ROD">
- Golden Rod
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_FOREST_GREEN">
- Forest Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_OLIVE_DRAB">
- Olive Drab
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_IVORY">
- Ivory
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BEIGE">
- Beige
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BROWN">
- Brown
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_YELLOW_GREEN">
- Yellow Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ORANGE_RED">
- Orange Red
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_OLIVE_GREEN">
- Dark Olive Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIME_GREEN">
- Lime Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIME">
- Lime
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_GOLDEN_ROD">
- Pale Golden Rod
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_HOT_PINK">
- Hot Pink
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CRIMSON">
- Crimson
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_POWDER_BLUE">
- Powder Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_OLIVE">
- Olive
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_YELLOW">
- Light Yellow
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LINEN">
- Linen
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_BLUE">
- Dark Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GHOST_WHITE">
- Ghost White
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TOMATO">
- Tomato
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_KHAKI">
- Khaki
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SLATE_GREY">
- Dark Slate Grey
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CORAL">
- Coral
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MINT_CREAM">
- Mint Cream
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TEAL">
- Teal
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_MAGENTA">
- Dark Magenta
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SALMON">
- Light Salmon
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SEA_GREEN">
- Sea Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_RED">
- Red
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ROSY_BROWN">
- Rosy Brown
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_INDIAN_RED">
- Indian Red
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_GREY">
- Light Grey
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SANDY_BROWN">
- Sandy Brown
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_GREEN">
- Light Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_BLUE">
- Light Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_ORANGE">
- Dark Orange
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DIM_GREY">
- Dim Grey
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLANCHED_ALMOND">
- Blanched Almond
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_KHAKI">
- Dark Khaki
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MAGENTA">
- Magenta
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MIDNIGHT_BLUE">
- Midnight Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_SEA_GREEN">
- Medium Sea Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SALMON">
- Salmon
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DEEP_PINK">
- Deep Pink
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SALMON">
- Dark Salmon
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PERU">
- Peru
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SPRING_GREEN">
- Spring Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_NAVY">
- Navy
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_CORAL">
- Light Coral
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_INDIGO">
- Indigo
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_WHITE">
- White
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_VIOLET_RED">
- Medium Violet Red
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BURLY_WOOD">
- Burly Wood
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LAVENDER">
- Lavender
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SLATE_BLUE">
- Dark Slate Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TAN">
- Tan
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SEA_GREEN">
- Dark Sea Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SLATE_GREY">
- Slate Grey
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_VIOLET_RED">
- Pale Violet Red
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CORNSILK">
- Cornsilk
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_TURQUOISE">
- Pale Turquoise
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SLATE_GREY">
- Light Slate Grey
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_GREEN">
- Pale Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_REBECCA_PURPLE">
- Rebecca Purple
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_SPRING_GREEN">
- Medium Spring Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PINK">
- Pink
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CADET_BLUE">
- Cadet Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GREY">
- Grey
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_VIOLET">
- Violet
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_GREY">
- Dark Grey
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SEA_GREEN">
- Light Sea Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_CYAN">
- Dark Cyan
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_NAVAJO_WHITE">
- Navajo White
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ALICE_BLUE">
- Alice Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_FLORAL_WHITE">
- Floral White
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MISTY_ROSE">
- Misty Rose
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_WHEAT">
- Wheat
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_STEEL_BLUE">
- Steel Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MOCCASIN">
- Moccasin
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PEACH_PUFF">
- Peach Puff
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GOLD">
- Gold
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LAVENDER_BLUSH">
- Lavender Blush
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SILVER">
- Silver
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_PINK">
- Light Pink
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_AZURE">
- Azure
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BISQUE">
- Bisque
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_ORCHID">
- Dark Orchid
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_OLD_LACE">
- Old Lace
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_TURQUOISE">
- Medium Turquoise
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SLATE_BLUE">
- Slate Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_BLUE">
- Medium Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TURQUOISE">
- Turquoise
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_TURQUOISE">
- Dark Turquoise
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_GOLDEN_ROD_YELLOW">
- Light Golden Rod Yellow
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_VIOLET">
- Dark Violet
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_AQUAMARINE">
- Aquamarine
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PAPAYA_WHIP">
- Papaya Whip
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ORCHID">
- Orchid
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ANTIQUE_WHITE">
- Antique White
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_THISTLE">
- Thistle
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_PURPLE">
- Medium Purple
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GAINSBORO">
- Gainsboro
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PLUM">
- Plum
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_STEEL_BLUE">
- Light Steel Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_RED">
- Dark Red
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SEA_SHELL">
- Sea Shell
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ROYAL_BLUE">
- Royal Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLUE_VIOLET">
- Blue Violet
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LAWN_GREEN">
- Lawn Green
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_CYAN">
- Light Cyan
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_FIRE_BRICK">
- Fire Brick
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SKY_BLUE">
- Sky Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CORNFLOWER_BLUE">
- Cornflower Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_SLATE_BLUE">
- Medium Slate Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLUE">
- Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_HONEYDEW">
- HoneyDew
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_ORCHID">
- Medium Orchid
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_WHITE_SMOKE">
- White Smoke
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_YELLOW">
- Yellow
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SKY_BLUE">
- Light Sky Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DEEP_SKY_BLUE">
- Deep Sky Blue
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SNOW">
- Snow
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_AQUA_MARINE">
- Medium Aqua Marine
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CHARTREUSE">
- Chartreuse
- </message>
- <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DODGER_BLUE">
- Dodger Blue
- </message>
- <message desc="An options page section header for options about ChromeVox rich text behavior. This section lets users set preferences on how rich text attributes should be indicated." name="IDS_CHROMEVOX_OPTIONS_RICH_TEXT_HEADER">
- Formatting
- </message>
- <message desc="The text label for ChromeVox automatic rich text indication checkbox." name="IDS_CHROMEVOX_OPTIONS_RICH_TEXT_CHECKBOX_LABEL">
- Announce text styling
- </message>
- <message desc="Labels the misspell list box." name="IDS_CHROMEVOX_OPTIONS_MISSPELL_DESCRIPTION">
- Indicate misspell:
- </message>
- <message desc="Labels the bold list box." name="IDS_CHROMEVOX_OPTIONS_BOLD_DESCRIPTION">
- Indicate bold:
- </message>
- <message desc="Labels the italic list box." name="IDS_CHROMEVOX_OPTIONS_ITALIC_DESCRIPTION">
- Indicate italic:
- </message>
- <message desc="Labels the underline list box." name="IDS_CHROMEVOX_OPTIONS_UNDERLINE_DESCRIPTION">
- Indicate underline:
- </message>
- <message desc="A menulist option in ChromeVox rich text settings to do nothing to indicate rich text" name="IDS_CHROMEVOX_RICH_TEXT_DO_NOTHING">
- Do nothing
- </message>
- <message desc="A menulist option in ChromeVox rich text settings to announce rich text" name="IDS_CHROMEVOX_RICH_TEXT_ANNOUNCE">
- Announce
- </message>
-
- <message desc="An option to announce download notifications." name="IDS_CHROMEVOX_OPTIONS_ANNOUNCE_DOWNLOAD">
- Announce download notifications
- </message>
- <message desc="Spoken when a download is started" name="IDS_CHROMEVOX_DOWNLOAD_STARTED">
- Download started <ph name="file_name">$1<ex>test.pdf</ex></ph>
- </message>
- <message desc="Spoken when a download is completed" name="IDS_CHROMEVOX_DOWNLOAD_COMPLETED">
- Download completed <ph name="file_name">$1<ex>test.pdf</ex></ph>
- </message>
- <message desc="Spoken when a download is stopped" name="IDS_CHROMEVOX_DOWNLOAD_STOPPED">
- Download stopped <ph name="file_name">$1<ex>test.pdf</ex></ph>
- </message>
- <message desc="Spoken when a download is paused" name="IDS_CHROMEVOX_DOWNLOAD_PAUSED">
- Download paused <ph name="file_name">$1<ex>test.pdf</ex></ph>
- </message>
- <message desc="Spoken when a download is resumed" name="IDS_CHROMEVOX_DOWNLOAD_RESUMED">
- Download resumed <ph name="file_name">$1<ex>test.pdf</ex></ph>
- </message>
- <message desc="Spoken to give progress on a current download, specifying percent complete and time remaining." name="IDS_CHROMEVOX_DOWNLOAD_PROGRESS">
- Download <ph name="progress">$1<ex>50</ex></ph>% complete <ph name="file_name">$2<ex>test.pdf</ex></ph>. About <ph name="time">$3<ex>30</ex></ph> <ph name="units">$4<ex>minutes</ex></ph> remaining.
- </message>
- <message desc="A string to specify time units in seconds." name="IDS_CHROMEVOX_SECONDS">
- {COUNT, plural, =1 {second}other {seconds}}
- </message>
- <message desc="A string to specify time units in minutes." name="IDS_CHROMEVOX_MINUTES">
- {COUNT, plural, =1 {minute}other {minutes}}
- </message>
- <message desc="A string to specify time units in hours." name="IDS_CHROMEVOX_HOURS">
- {COUNT, plural, =1 {hour}other {hours}}
- </message>
- <message desc="Appends language in front of content." name="IDS_CHROMEVOX_LANGUAGE_SWITCH">
- <ph name="language">$1<ex>English</ex></ph>: <ph name="content">$2<ex>This is example content</ex></ph>
- </message>
- <message desc="The description of the readPhoneticPronunciation key. Displayed in the ChromeVox menu." name="IDS_CHROMEVOX_READ_PHONETIC_PRONUNCIATION">
- Announce phonetic pronunciation for word
- </message>
- <message desc="Spoken to inform the user that the node's name is empty" name="IDS_CHROMEVOX_EMPTY_NAME">
- No available text for this item
- </message>
- <message desc="The description of the announceBatteryDescription key. Displayed in the ChromeVox menu." name="IDS_CHROMEVOX_ANNOUNCE_BATTERY_DESCRIPTION">
- Announce current battery status
- </message>
- <message desc="The description of the announceRichTextDescription key. Displayed in the ChromeVox menu." name="IDS_CHROMEVOX_ANNOUNCE_RICH_TEXT_DESCRIPTION">
- Announce formatting for current item
- </message>
- <message desc="Announced when there is no available voice for a language." name="IDS_CHROMEVOX_VOICE_UNAVAILABLE_FOR_LANGUAGE">
- No voice available for language: <ph name="language">$1<ex>English</ex></ph>
- </message>
- <message desc="Used to describe the link behind a url." name="IDS_CHROMEVOX_URL_BEHIND_LINK">
- Link URL: <ph name="link_url">$1</ph>
- </message>
- <message desc="Describes an HTML description list element." name="IDS_CHROMEVOX_ROLE_DESCRIPTION_LIST">
- Description list
- </message>
- <message desc="Describes an HTML description list detail element." name="IDS_CHROMEVOX_ROLE_DESCRIPTION_LIST_DETAIL">
- Description list detail
- </message>
- <message desc="This is an abbreviated HTML description list element shown on a braille display. When translating, try to find a contracted form of the translation for 'description list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DESCRIPTION_LIST_BRL">
- dscrplst
- </message>
- <message desc="This is an abbreviated HTML description list detail element shown on a braille display. When translating, try to find a contracted form of the translation for 'description list detail' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DESCRIPTION_LIST_DETAIL_BRL">
- dscrplst dtl
- </message>
- <message desc="Spoken if the user attempts to jump to the next paragraph when none exists." name="IDS_CHROMEVOX_NO_NEXT_PARAGRAPH">
- No next paragraph.
- </message>
- <message desc="Spoken if the user attempts to jump to the previous paragraph when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_PARAGRAPH">
- No previous paragraph.
- </message>
- <message desc="Spoken when the user resets text to speech settings back to their default values" name="IDS_CHROMEVOX_ANNOUNCE_TTS_DEFAULT_SETTINGS">
- Reset text to speech settings to default values.
- </message>
- <message desc="The description of the resetTextToSpeechSettings key. Displayed in the Options page." name="IDS_CHROMEVOX_RESET_TTS_SETTINGS">
- Reset text to speech settings
- </message>
- <message desc="The description of the openKeyboardShortcutsMenu key. Displayed in the ChromeVox menu" name="IDS_CHROMEVOX_OPEN_KEYBOARD_SHORTCUTS_MENU">
- Open keyboard shortcuts menu
- </message>
- </messages>
- </release>
-</grit>
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
new file mode 100644
index 00000000000..bfdf5800371
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/common/BUILD.gn
@@ -0,0 +1,124 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/features.gni")
+import(
+ "//chrome/browser/resources/chromeos/accessibility/chromevox/run_jsbundler.gni")
+import("//chrome/common/features.gni")
+import("//chrome/test/base/js2gtest.gni")
+import("//testing/test.gni")
+import("//third_party/closure_compiler/compile_js.gni")
+
+assert(is_chromeos || is_chromecast)
+
+accessibility_common_out_dir =
+ "$root_out_dir/resources/chromeos/accessibility/common"
+
+group("build") {
+ deps = [ ":accessibility_common_copied_files" ]
+}
+
+run_jsbundler("accessibility_common_copied_files") {
+ mode = "copy"
+ dest_dir = accessibility_common_out_dir
+ sources = [
+ "automation_predicate.js",
+ "automation_util.js",
+ "closure_shim.js",
+ "constants.js",
+ "tree_walker.js",
+ ]
+ rewrite_rules = [ rebase_path(".", root_build_dir) + ":" ]
+}
+
+js_library("tree_walker") {
+ sources = [ "tree_walker.js" ]
+ deps = [
+ ":automation_predicate",
+ ":constants",
+ ]
+ externs_list = [
+ "$externs_path/automation.js",
+ "$externs_path/chrome_extensions.js",
+ ]
+}
+
+js_library("automation_predicate") {
+ sources = [ "automation_predicate.js" ]
+ deps = [ ":constants" ]
+ externs_list = [
+ "$externs_path/automation.js",
+ "$externs_path/chrome_extensions.js",
+ ]
+}
+
+js_library("constants") {
+ sources = [ "constants.js" ]
+}
+
+js_library("closure_shim") {
+}
+
+js_library("automation_util") {
+ deps = [
+ ":automation_predicate",
+ ":constants",
+ ":tree_walker",
+ ]
+ externs_list = [
+ "$externs_path/automation.js",
+ "$externs_path/chrome_extensions.js",
+ ]
+}
+
+source_set("browser_tests") {
+ testonly = true
+ assert(enable_extensions)
+
+ deps = [ ":accessibility_tests" ]
+
+ # TODO(jamescook): Figure out which of these are really necessary.
+ data = [
+ "$root_out_dir/chrome_100_percent.pak",
+ "$root_out_dir/chrome_200_percent.pak",
+ "$root_out_dir/locales/en-US.pak",
+ "$root_out_dir/locales/fr.pak",
+ "$root_out_dir/resources.pak",
+ "$root_out_dir/resources/chromeos/accessibility/chromevox/",
+ "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/chromevox/",
+
+ # The test uses data from the original location.
+ "//chrome/browser/resources/chromeos/accessibility/chromevox/",
+ "//chrome/browser/resources/chromeos/accessibility/common/",
+ "//third_party/chromevox/",
+ ]
+ data += js2gtest_js_libraries
+}
+
+# Note that this suite of tests still uses ChromeVox's background page as a runtime environment. There should not be anything specific to ChromeVox within the tests themselves though.
+js2gtest("accessibility_tests") {
+ test_type = "extension"
+ sources = [
+ "automation_util_test.js",
+ "tree_walker_test.js",
+ ]
+ gen_include_files = [
+ "../chromevox/testing/assert_additions.js",
+ "../chromevox/testing/callback_helper.js",
+ "../chromevox/testing/chromevox_e2e_test_base.js",
+ "../chromevox/testing/chromevox_next_e2e_test_base.js",
+ "../chromevox/testing/mock_feedback.js",
+ ]
+
+ if (is_chromeos) {
+ # The test base classes generate C++ code with these deps.
+ deps = [
+ "//ash",
+ "//base",
+ "//chrome/browser/chromeos",
+ "//chrome/common",
+ ]
+ }
+ defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
+}
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
index a83339ad89b..e2cf38296ad 100644
--- a/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/BUILD.gn
@@ -16,12 +16,7 @@ select_to_speak_out_dir =
"$root_out_dir/resources/chromeos/accessibility/select_to_speak"
group("build") {
- deps = [
- ":select_to_speak_copied_files",
- ":select_to_speak_guest_manifest",
- ":select_to_speak_manifest",
- "//chrome/browser/resources/chromeos/accessibility/select_to_speak/strings:select_to_speak_strings",
- ]
+ deps = [ ":select_to_speak_copied_files" ]
}
# Instead of setting up one copy target for each subdirectory, use a script
@@ -30,12 +25,7 @@ run_jsbundler("select_to_speak_copied_files") {
mode = "copy"
dest_dir = select_to_speak_out_dir
sources = [
- "../chromevox/background/automation_predicate.js",
- "../chromevox/background/automation_util.js",
- "../chromevox/background/constants.js",
- "../chromevox/background/tree_walker.js",
"checked.png",
- "closure_shim.js",
"earcons/null_selection.ogg",
"input_handler.js",
"metrics_utils.js",
@@ -56,58 +46,14 @@ run_jsbundler("select_to_speak_copied_files") {
rewrite_rules = [
rebase_path(".", root_build_dir) + ":",
rebase_path(closure_library_dir, root_build_dir) + ":closure",
- rebase_path("../chromevox/background", root_build_dir) + ":",
]
}
-# TODO(crbug/978200): refactor this into another file like generate_manifest.gni
-# to share with other extensions.
-template("manifest") {
- version_file = "//chrome/VERSION"
- version_script = "//build/util/version.py"
- template_file = "manifest.json.jinja2"
- output_file = invoker.output_file
- key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAukZ6JJWr0jHmFTkn0pcigpjI+cP0FqTo8FRIcCwy2fPeM+Ymf+7C9MK642i+Nhdr2qSsRF26AMIKbBdSDUnh04bfg5J/rKa/VO88LvXENYQMGhTo1y9mVg2OsbQJtEL9aTLU2G0SoKcr3g/+lggBKR5ydW1Qa0WGGAM9XrLm8iu/wn2uF4mfcMii6KfyEsAwWalpr/Td5WbtIoNNDpNeKO4ZSZJis1n9PZXqaOKpW7PqFDpEHw2PnPATxkcqj/wIx+Shgada0fhrzMlhXLhhj7ThSSWbuTz5n5NebuQ49/Z2ATgpBCSzYBVXEXMDe6LBBtGiZ/QR9UkA8Lz8bP6xIQIDAQAB"
- action(target_name) {
- script = "//chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_manifest.py"
- inputs = [
- version_file,
- version_script,
- ]
- sources = [
- template_file,
- ]
- outputs = [
- output_file,
- ]
- args = [
- "--key=$key",
- "--version_file=" + rebase_path(version_file, root_build_dir),
- "--output_manifest=" + rebase_path(output_file, root_build_dir),
- ]
- if (defined(invoker.is_guest_manifest) && invoker.is_guest_manifest) {
- args += [ "--is_guest_manifest=1" ]
- }
- args += rebase_path(sources, root_build_dir)
- }
-}
-
-manifest("select_to_speak_manifest") {
- output_file = "$select_to_speak_out_dir/manifest.json"
-}
-
-manifest("select_to_speak_guest_manifest") {
- output_file = "$select_to_speak_out_dir/manifest_guest.json"
- is_guest_manifest = true
-}
-
source_set("browser_tests") {
testonly = true
assert(enable_extensions)
- deps = [
- ":select_to_speak_extjs_tests",
- ]
+ deps = [ ":select_to_speak_extjs_tests" ]
# TODO(jamescook): Figure out which of these are really necessary.
data = [
@@ -129,9 +75,9 @@ source_set("browser_tests") {
js2gtest("select_to_speak_extjs_tests") {
test_type = "extension"
sources = [
- "select_to_speak_keystroke_selection_test.extjs",
- "select_to_speak_mouse_selection_test.extjs",
- "select_to_speak_prefs_test.extjs",
+ "select_to_speak_keystroke_selection_test.js",
+ "select_to_speak_mouse_selection_test.js",
+ "select_to_speak_prefs_test.js",
]
gen_include_files = [
"../chromevox/testing/callback_helper.js",
@@ -158,11 +104,6 @@ js2gtest("select_to_speak_extjs_tests") {
js_type_check("closure_compile") {
deps = [
- ":../chromevox/background/automation_predicate",
- ":../chromevox/background/automation_util",
- ":../chromevox/background/constants",
- ":../chromevox/background/tree_walker",
- ":closure_shim",
":input_handler",
":metrics_utils",
":node_utils",
@@ -172,13 +113,16 @@ js_type_check("closure_compile") {
":select_to_speak",
":select_to_speak_options",
":word_utils",
+ "../common:automation_predicate",
+ "../common:automation_util",
+ "../common:closure_shim",
+ "../common:constants",
+ "../common:tree_walker",
]
}
js_library("select_to_speak") {
deps = [
- ":../chromevox/background/automation_util",
- ":../chromevox/background/constants",
":input_handler",
":metrics_utils",
":node_utils",
@@ -186,6 +130,8 @@ js_library("select_to_speak") {
":prefs_manager",
":rect_utils",
":word_utils",
+ "../common:automation_util",
+ "../common:constants",
]
externs_list = [
"$externs_path/accessibility_private.js",
@@ -198,9 +144,7 @@ js_library("select_to_speak") {
}
js_library("select_to_speak_options") {
- deps = [
- ":prefs_manager",
- ]
+ deps = [ ":prefs_manager" ]
externs_list = [
"$externs_path/accessibility_private.js",
"$externs_path/automation.js",
@@ -218,9 +162,7 @@ js_library("node_utils") {
}
js_library("word_utils") {
- deps = [
- ":paragraph_utils",
- ]
+ deps = [ ":paragraph_utils" ]
externs_list = [ "$externs_path/automation.js" ]
}
@@ -233,9 +175,7 @@ js_library("paragraph_utils") {
}
js_library("input_handler") {
- deps = [
- ":rect_utils",
- ]
+ deps = [ ":rect_utils" ]
}
js_library("rect_utils") {
@@ -246,47 +186,6 @@ js_library("prefs_manager") {
}
js_library("metrics_utils") {
- deps = [
- ":prefs_manager",
- ]
+ deps = [ ":prefs_manager" ]
externs_list = [ "$externs_path/metrics_private.js" ]
}
-
-js_library("../chromevox/background/automation_util") {
- deps = [
- ":../chromevox/background/automation_predicate",
- ":../chromevox/background/constants",
- ":../chromevox/background/tree_walker",
- ]
- externs_list = [
- "$externs_path/automation.js",
- "$externs_path/chrome_extensions.js",
- ]
-}
-
-js_library("../chromevox/background/tree_walker") {
- deps = [
- ":../chromevox/background/automation_predicate",
- ":../chromevox/background/constants",
- ]
- externs_list = [
- "$externs_path/automation.js",
- "$externs_path/chrome_extensions.js",
- ]
-}
-
-js_library("../chromevox/background/automation_predicate") {
- deps = [
- ":../chromevox/background/constants",
- ]
- externs_list = [
- "$externs_path/automation.js",
- "$externs_path/chrome_extensions.js",
- ]
-}
-
-js_library("../chromevox/background/constants") {
-}
-
-js_library("closure_shim") {
-}
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/strings/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/strings/BUILD.gn
deleted file mode 100644
index ed0489e4422..00000000000
--- a/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/strings/BUILD.gn
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//chrome/common/features.gni")
-import("//tools/grit/grit_rule.gni")
-
-select_to_speak_out_dir =
- "$root_out_dir/resources/chromeos/accessibility/select_to_speak"
-
-grit("select_to_speak_strings") {
- source = "select_to_speak_strings.grd"
- defines = chrome_grit_defines
- outputs = [
- "_locales/am/messages.json",
- "_locales/ar/messages.json",
- "_locales/bg/messages.json",
- "_locales/bn/messages.json",
- "_locales/ca/messages.json",
- "_locales/cs/messages.json",
- "_locales/da/messages.json",
- "_locales/de/messages.json",
- "_locales/el/messages.json",
- "_locales/en_GB/messages.json",
- "_locales/en/messages.json",
- "_locales/es/messages.json",
- "_locales/es_419/messages.json",
- "_locales/et/messages.json",
- "_locales/fa/messages.json",
- "_locales/fi/messages.json",
- "_locales/fil/messages.json",
- "_locales/fr/messages.json",
- "_locales/gu/messages.json",
- "_locales/he/messages.json",
- "_locales/hi/messages.json",
- "_locales/hr/messages.json",
- "_locales/hu/messages.json",
- "_locales/id/messages.json",
- "_locales/it/messages.json",
- "_locales/ja/messages.json",
- "_locales/kn/messages.json",
- "_locales/ko/messages.json",
- "_locales/lt/messages.json",
- "_locales/lv/messages.json",
- "_locales/ml/messages.json",
- "_locales/mr/messages.json",
- "_locales/ms/messages.json",
- "_locales/nl/messages.json",
- "_locales/nb/messages.json",
- "_locales/pl/messages.json",
- "_locales/pt_BR/messages.json",
- "_locales/pt_PT/messages.json",
- "_locales/ro/messages.json",
- "_locales/ru/messages.json",
- "_locales/sk/messages.json",
- "_locales/sl/messages.json",
- "_locales/sr/messages.json",
- "_locales/sv/messages.json",
- "_locales/sw/messages.json",
- "_locales/ta/messages.json",
- "_locales/te/messages.json",
- "_locales/th/messages.json",
- "_locales/tr/messages.json",
- "_locales/uk/messages.json",
- "_locales/vi/messages.json",
- "_locales/zh_CN/messages.json",
- "_locales/zh_TW/messages.json",
- ]
- output_dir = select_to_speak_out_dir
-
- # Don't polute the extension directory with stamp and .d files.
- depfile_dir = target_out_dir
- resource_ids = ""
-}
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/strings/select_to_speak_strings.grd b/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/strings/select_to_speak_strings.grd
deleted file mode 100644
index febff4ec63d..00000000000
--- a/chromium/chrome/browser/resources/chromeos/accessibility/select_to_speak/strings/select_to_speak_strings.grd
+++ /dev/null
@@ -1,221 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<grit base_dir="." current_release="1" latest_public_release="0"
- output_all_resource_defines="false" enc_check="möl" source_lang_id="en">
- <outputs>
- <output filename="_locales/am/messages.json" type="chrome_messages_json" lang="am"/>
- <output filename="_locales/ar/messages.json" type="chrome_messages_json" lang="ar"/>
- <output filename="_locales/bg/messages.json" type="chrome_messages_json" lang="bg"/>
- <output filename="_locales/bn/messages.json" type="chrome_messages_json" lang="bn"/>
- <output filename="_locales/ca/messages.json" type="chrome_messages_json" lang="ca"/>
- <output filename="_locales/cs/messages.json" type="chrome_messages_json" lang="cs"/>
- <output filename="_locales/da/messages.json" type="chrome_messages_json" lang="da"/>
- <output filename="_locales/de/messages.json" type="chrome_messages_json" lang="de"/>
- <output filename="_locales/el/messages.json" type="chrome_messages_json" lang="el"/>
- <output filename="_locales/en_GB/messages.json" type="chrome_messages_json" lang="en-GB"/>
- <output filename="_locales/en/messages.json" type="chrome_messages_json" lang="en"/>
- <output filename="_locales/es/messages.json" type="chrome_messages_json" lang="es"/>
- <output filename="_locales/es_419/messages.json" type="chrome_messages_json" lang="es-419"/>
- <output filename="_locales/et/messages.json" type="chrome_messages_json" lang="et"/>
- <output filename="_locales/fa/messages.json" type="chrome_messages_json" lang="fa"/>
- <output filename="_locales/fi/messages.json" type="chrome_messages_json" lang="fi"/>
- <output filename="_locales/fil/messages.json" type="chrome_messages_json" lang="fil"/>
- <output filename="_locales/fr/messages.json" type="chrome_messages_json" lang="fr"/>
- <output filename="_locales/gu/messages.json" type="chrome_messages_json" lang="gu"/>
- <output filename="_locales/he/messages.json" type="chrome_messages_json" lang="he"/>
- <output filename="_locales/hi/messages.json" type="chrome_messages_json" lang="hi"/>
- <output filename="_locales/hr/messages.json" type="chrome_messages_json" lang="hr"/>
- <output filename="_locales/hu/messages.json" type="chrome_messages_json" lang="hu"/>
- <output filename="_locales/id/messages.json" type="chrome_messages_json" lang="id"/>
- <output filename="_locales/it/messages.json" type="chrome_messages_json" lang="it"/>
- <output filename="_locales/ja/messages.json" type="chrome_messages_json" lang="ja"/>
- <output filename="_locales/kn/messages.json" type="chrome_messages_json" lang="kn"/>
- <output filename="_locales/ko/messages.json" type="chrome_messages_json" lang="ko"/>
- <output filename="_locales/lt/messages.json" type="chrome_messages_json" lang="lt"/>
- <output filename="_locales/lv/messages.json" type="chrome_messages_json" lang="lv"/>
- <output filename="_locales/ml/messages.json" type="chrome_messages_json" lang="ml"/>
- <output filename="_locales/mr/messages.json" type="chrome_messages_json" lang="mr"/>
- <output filename="_locales/ms/messages.json" type="chrome_messages_json" lang="ms"/>
- <output filename="_locales/nl/messages.json" type="chrome_messages_json" lang="nl"/>
- <output filename="_locales/nb/messages.json" type="chrome_messages_json" lang="no"/>
- <output filename="_locales/pl/messages.json" type="chrome_messages_json" lang="pl"/>
- <output filename="_locales/pt_BR/messages.json" type="chrome_messages_json" lang="pt-BR"/>
- <output filename="_locales/pt_PT/messages.json" type="chrome_messages_json" lang="pt-PT"/>
- <output filename="_locales/ro/messages.json" type="chrome_messages_json" lang="ro"/>
- <output filename="_locales/ru/messages.json" type="chrome_messages_json" lang="ru"/>
- <output filename="_locales/sk/messages.json" type="chrome_messages_json" lang="sk"/>
- <output filename="_locales/sl/messages.json" type="chrome_messages_json" lang="sl"/>
- <output filename="_locales/sr/messages.json" type="chrome_messages_json" lang="sr"/>
- <output filename="_locales/sv/messages.json" type="chrome_messages_json" lang="sv"/>
- <output filename="_locales/sw/messages.json" type="chrome_messages_json" lang="sw"/>
- <output filename="_locales/ta/messages.json" type="chrome_messages_json" lang="ta"/>
- <output filename="_locales/te/messages.json" type="chrome_messages_json" lang="te"/>
- <output filename="_locales/th/messages.json" type="chrome_messages_json" lang="th"/>
- <output filename="_locales/tr/messages.json" type="chrome_messages_json" lang="tr"/>
- <output filename="_locales/uk/messages.json" type="chrome_messages_json" lang="uk"/>
- <output filename="_locales/vi/messages.json" type="chrome_messages_json" lang="vi"/>
- <output filename="_locales/zh_CN/messages.json" type="chrome_messages_json" lang="zh-CN"/>
- <output filename="_locales/zh_TW/messages.json" type="chrome_messages_json" lang="zh-TW"/>
- </outputs>
- <translations>
- <file path="select_to_speak_strings_af.xtb" lang="af" />
- <file path="select_to_speak_strings_am.xtb" lang="am" />
- <file path="select_to_speak_strings_ar.xtb" lang="ar" />
- <file path="select_to_speak_strings_as.xtb" lang="as" />
- <file path="select_to_speak_strings_az.xtb" lang="az" />
- <file path="select_to_speak_strings_be.xtb" lang="be" />
- <file path="select_to_speak_strings_bg.xtb" lang="bg" />
- <file path="select_to_speak_strings_bn.xtb" lang="bn" />
- <file path="select_to_speak_strings_bs.xtb" lang="bs" />
- <file path="select_to_speak_strings_ca.xtb" lang="ca" />
- <file path="select_to_speak_strings_cs.xtb" lang="cs" />
- <file path="select_to_speak_strings_da.xtb" lang="da" />
- <file path="select_to_speak_strings_de.xtb" lang="de" />
- <file path="select_to_speak_strings_el.xtb" lang="el" />
- <file path="select_to_speak_strings_en-GB.xtb" lang="en-GB" />
- <file path="select_to_speak_strings_es.xtb" lang="es" />
- <file path="select_to_speak_strings_es-419.xtb" lang="es-419" />
- <file path="select_to_speak_strings_et.xtb" lang="et" />
- <file path="select_to_speak_strings_eu.xtb" lang="eu" />
- <file path="select_to_speak_strings_fa.xtb" lang="fa" />
- <file path="select_to_speak_strings_fi.xtb" lang="fi" />
- <file path="select_to_speak_strings_fil.xtb" lang="fil" />
- <file path="select_to_speak_strings_fr.xtb" lang="fr" />
- <file path="select_to_speak_strings_fr-CA.xtb" lang="fr-CA" />
- <file path="select_to_speak_strings_gl.xtb" lang="gl" />
- <file path="select_to_speak_strings_gu.xtb" lang="gu" />
- <file path="select_to_speak_strings_hi.xtb" lang="hi" />
- <file path="select_to_speak_strings_hr.xtb" lang="hr" />
- <file path="select_to_speak_strings_hu.xtb" lang="hu" />
- <file path="select_to_speak_strings_hy.xtb" lang="hy" />
- <file path="select_to_speak_strings_id.xtb" lang="id" />
- <file path="select_to_speak_strings_is.xtb" lang="is" />
- <file path="select_to_speak_strings_it.xtb" lang="it" />
- <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
- <file path="select_to_speak_strings_iw.xtb" lang="he" />
- <file path="select_to_speak_strings_ja.xtb" lang="ja" />
- <file path="select_to_speak_strings_ka.xtb" lang="ka" />
- <file path="select_to_speak_strings_kk.xtb" lang="kk" />
- <file path="select_to_speak_strings_km.xtb" lang="km" />
- <file path="select_to_speak_strings_kn.xtb" lang="kn" />
- <file path="select_to_speak_strings_ko.xtb" lang="ko" />
- <file path="select_to_speak_strings_ky.xtb" lang="ky" />
- <file path="select_to_speak_strings_lo.xtb" lang="lo" />
- <file path="select_to_speak_strings_lt.xtb" lang="lt" />
- <file path="select_to_speak_strings_lv.xtb" lang="lv" />
- <file path="select_to_speak_strings_mk.xtb" lang="mk" />
- <file path="select_to_speak_strings_ml.xtb" lang="ml" />
- <file path="select_to_speak_strings_mn.xtb" lang="mn" />
- <file path="select_to_speak_strings_mr.xtb" lang="mr" />
- <file path="select_to_speak_strings_ms.xtb" lang="ms" />
- <file path="select_to_speak_strings_my.xtb" lang="my" />
- <file path="select_to_speak_strings_ne.xtb" lang="ne" />
- <file path="select_to_speak_strings_nl.xtb" lang="nl" />
- <file path="select_to_speak_strings_no.xtb" lang="no" />
- <file path="select_to_speak_strings_or.xtb" lang="or" />
- <file path="select_to_speak_strings_pa.xtb" lang="pa" />
- <file path="select_to_speak_strings_pl.xtb" lang="pl" />
- <file path="select_to_speak_strings_pt-BR.xtb" lang="pt-BR" />
- <file path="select_to_speak_strings_pt-PT.xtb" lang="pt-PT" />
- <file path="select_to_speak_strings_ro.xtb" lang="ro" />
- <file path="select_to_speak_strings_ru.xtb" lang="ru" />
- <file path="select_to_speak_strings_si.xtb" lang="si" />
- <file path="select_to_speak_strings_sk.xtb" lang="sk" />
- <file path="select_to_speak_strings_sl.xtb" lang="sl" />
- <file path="select_to_speak_strings_sq.xtb" lang="sq" />
- <file path="select_to_speak_strings_sr.xtb" lang="sr" />
- <file path="select_to_speak_strings_sv.xtb" lang="sv" />
- <file path="select_to_speak_strings_sw.xtb" lang="sw" />
- <file path="select_to_speak_strings_ta.xtb" lang="ta" />
- <file path="select_to_speak_strings_te.xtb" lang="te" />
- <file path="select_to_speak_strings_th.xtb" lang="th" />
- <file path="select_to_speak_strings_tr.xtb" lang="tr" />
- <file path="select_to_speak_strings_uk.xtb" lang="uk" />
- <file path="select_to_speak_strings_ur.xtb" lang="ur" />
- <file path="select_to_speak_strings_uz.xtb" lang="uz" />
- <file path="select_to_speak_strings_vi.xtb" lang="vi" />
- <file path="select_to_speak_strings_zh-CN.xtb" lang="zh-CN" />
- <file path="select_to_speak_strings_zh-HK.xtb" lang="zh-HK" />
- <file path="select_to_speak_strings_zh-TW.xtb" lang="zh-TW" />
- <file path="select_to_speak_strings_zu.xtb" lang="zu" />
- </translations>
- <release allow_pseudo="false" seq="1">
- <messages fallback_to_english="true">
- <message desc="The locale you're translating into. For use in URL to localized pages. e.g. http://www.google.com/?hl=en." name="IDS_LOCALE">
- en
- </message>
- <message desc="The product name for Select-to-speak." name="IDS_SELECT_TO_SPEAK_NAME">
- Select-to-speak
- </message>
- <message desc="The description for Select-to-speak." name="IDS_SELECT_TO_SPEAK_DESCRIPTION">
-
- </message>
- <message desc="The title of the Select-to-speak options page." name="IDS_SELECT_TO_SPEAK_OPTIONS_PAGE_TITLE">
- Select-to-speak Settings
- </message>
- <message desc="Section of the Select-to-speak options dialog where the user can adjust synthesized speech properties." name="IDS_SELECT_TO_SPEAK_OPTIONS_SPEECH">
- Speech
- </message>
- <message desc="Label for the control in the Select-to-speak options dialog where the user can choose a voice from a list." name="IDS_SELECT_TO_SPEAK_OPTIONS_VOICES_DESCRIPTION">
- Select a voice:
- </message>
- <message desc="Group of options controlling highlighting." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT">
- Highlighting
- </message>
- <message desc="Label for option to highlight spoken words rather than spoken nodes." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_DESCRIPTION">
- Highlight each word as it is spoken
- </message>
- <message desc="Label for option to pick word highlight color." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_DESCRIPTION">
- Color for word highlights:
- </message>
- <message desc="Label for a blue highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_BLUE">
- Blue
- </message>
- <message desc="Label for a orange highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_ORANGE">
- Orange
- </message>
- <message desc="Label for a yellow highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_YELLOW">
- Yellow
- </message>
- <message desc="Label for a green highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_GREEN">
- Green
- </message>
- <message desc="Label for a pink highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_PINK">
- Pink
- </message>
- <message desc="Example of a word highlight on a dark background in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_DARK">
- Dark background
- </message>
- <message desc="Example of a word highlight on a light background in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_LIGHT">
- Light background
- </message>
- <message desc="Link to the Text-to-Speech settings page." name="IDS_SELECT_TO_SPEAK_OPTIONS_TEXT_TO_SPEECH_SETTINGS">
- Personalize Text-to-Speech settings
- </message>
- <message desc="Link to the Text-to-Speech settings page." name="IDS_SELECT_TO_SPEAK_OPTIONS_TEXT_TO_SPEECH_SETTINGS_LINK">
- Text-to-Speech settings
- </message>
- <message desc="Voice name for the system default Text-to-Speech voice" name="IDS_SELECT_TO_SPEAK_SYSTEM_VOICE">
- System Text-to-Speech voice
- </message>
- <message desc="Description of a checkbox that is not checked" name="IDS_SELECT_TO_SPEAK_CHECKBOX_UNCHECKED">
- unchecked
- </message>
- <message desc="Description of a checkbox that is checked" name="IDS_SELECT_TO_SPEAK_CHECKBOX_CHECKED">
- checked
- </message>
- <message desc="Description of a checkbox that is a mixed selection" name="IDS_SELECT_TO_SPEAK_CHECKBOX_MIXED">
- partially checked
- </message>
- <message desc="Description of a radio button that is not selected" name="IDS_SELECT_TO_SPEAK_RADIOBUTTON_UNSELECTED">
- unselected
- </message>
- <message desc="Description of a radio button that is selected" name="IDS_SELECT_TO_SPEAK_RADIOBUTTON_SELECTED">
- selected
- </message>
- <message desc="Description of a radio button that is selected" name="IDS_SELECT_TO_SPEAK_RADIOBUTTON_MIXED">
- partially selected
- </message>
- </messages>
- </release>
-</grit>
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.gni b/chromium/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.gni
new file mode 100644
index 00000000000..95f07bafa9b
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.gni
@@ -0,0 +1,71 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chrome/common/features.gni")
+import("//tools/grit/grit_rule.gni")
+
+template("accessibility_strings") {
+ grit(target_name) {
+ source = "//chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.grd"
+ defines = chrome_grit_defines
+ outputs = [
+ "_locales/am/messages.json.gz",
+ "_locales/ar/messages.json.gz",
+ "_locales/bg/messages.json.gz",
+ "_locales/bn/messages.json.gz",
+ "_locales/ca/messages.json.gz",
+ "_locales/cs/messages.json.gz",
+ "_locales/da/messages.json.gz",
+ "_locales/de/messages.json.gz",
+ "_locales/el/messages.json.gz",
+ "_locales/en_GB/messages.json.gz",
+ "_locales/en/messages.json.gz",
+ "_locales/es/messages.json.gz",
+ "_locales/es_419/messages.json.gz",
+ "_locales/et/messages.json.gz",
+ "_locales/fa/messages.json.gz",
+ "_locales/fi/messages.json.gz",
+ "_locales/fil/messages.json.gz",
+ "_locales/fr/messages.json.gz",
+ "_locales/gu/messages.json.gz",
+ "_locales/he/messages.json.gz",
+ "_locales/hi/messages.json.gz",
+ "_locales/hr/messages.json.gz",
+ "_locales/hu/messages.json.gz",
+ "_locales/id/messages.json.gz",
+ "_locales/it/messages.json.gz",
+ "_locales/ja/messages.json.gz",
+ "_locales/kn/messages.json.gz",
+ "_locales/ko/messages.json.gz",
+ "_locales/lt/messages.json.gz",
+ "_locales/lv/messages.json.gz",
+ "_locales/ml/messages.json.gz",
+ "_locales/mr/messages.json.gz",
+ "_locales/ms/messages.json.gz",
+ "_locales/nl/messages.json.gz",
+ "_locales/nb/messages.json.gz",
+ "_locales/pl/messages.json.gz",
+ "_locales/pt_BR/messages.json.gz",
+ "_locales/pt_PT/messages.json.gz",
+ "_locales/ro/messages.json.gz",
+ "_locales/ru/messages.json.gz",
+ "_locales/sk/messages.json.gz",
+ "_locales/sl/messages.json.gz",
+ "_locales/sr/messages.json.gz",
+ "_locales/sv/messages.json.gz",
+ "_locales/sw/messages.json.gz",
+ "_locales/ta/messages.json.gz",
+ "_locales/te/messages.json.gz",
+ "_locales/th/messages.json.gz",
+ "_locales/tr/messages.json.gz",
+ "_locales/uk/messages.json.gz",
+ "_locales/vi/messages.json.gz",
+ "_locales/zh_CN/messages.json.gz",
+ "_locales/zh_TW/messages.json.gz",
+ ]
+ output_dir = invoker.out_dir
+
+ resource_ids = ""
+ }
+}
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.grd b/chromium/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.grd
new file mode 100644
index 00000000000..c96bb2cdd5f
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.grd
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<grit base_dir="." current_release="1" latest_public_release="0"
+ output_all_resource_defines="false" enc_check="möl" source_lang_id="en">
+ <outputs>
+ <output filename="_locales/am/messages.json.gz" type="chrome_messages_json_gzip" lang="am"/>
+ <output filename="_locales/ar/messages.json.gz" type="chrome_messages_json_gzip" lang="ar"/>
+ <output filename="_locales/bg/messages.json.gz" type="chrome_messages_json_gzip" lang="bg"/>
+ <output filename="_locales/bn/messages.json.gz" type="chrome_messages_json_gzip" lang="bn"/>
+ <output filename="_locales/ca/messages.json.gz" type="chrome_messages_json_gzip" lang="ca"/>
+ <output filename="_locales/cs/messages.json.gz" type="chrome_messages_json_gzip" lang="cs"/>
+ <output filename="_locales/da/messages.json.gz" type="chrome_messages_json_gzip" lang="da"/>
+ <output filename="_locales/de/messages.json.gz" type="chrome_messages_json_gzip" lang="de"/>
+ <output filename="_locales/el/messages.json.gz" type="chrome_messages_json_gzip" lang="el"/>
+ <output filename="_locales/en_GB/messages.json.gz" type="chrome_messages_json_gzip" lang="en-GB"/>
+ <output filename="_locales/en/messages.json.gz" type="chrome_messages_json_gzip" lang="en"/>
+ <output filename="_locales/es/messages.json.gz" type="chrome_messages_json_gzip" lang="es"/>
+ <output filename="_locales/es_419/messages.json.gz" type="chrome_messages_json_gzip" lang="es-419"/>
+ <output filename="_locales/et/messages.json.gz" type="chrome_messages_json_gzip" lang="et"/>
+ <output filename="_locales/fa/messages.json.gz" type="chrome_messages_json_gzip" lang="fa"/>
+ <output filename="_locales/fi/messages.json.gz" type="chrome_messages_json_gzip" lang="fi"/>
+ <output filename="_locales/fil/messages.json.gz" type="chrome_messages_json_gzip" lang="fil"/>
+ <output filename="_locales/fr/messages.json.gz" type="chrome_messages_json_gzip" lang="fr"/>
+ <output filename="_locales/gu/messages.json.gz" type="chrome_messages_json_gzip" lang="gu"/>
+ <output filename="_locales/he/messages.json.gz" type="chrome_messages_json_gzip" lang="he"/>
+ <output filename="_locales/hi/messages.json.gz" type="chrome_messages_json_gzip" lang="hi"/>
+ <output filename="_locales/hr/messages.json.gz" type="chrome_messages_json_gzip" lang="hr"/>
+ <output filename="_locales/hu/messages.json.gz" type="chrome_messages_json_gzip" lang="hu"/>
+ <output filename="_locales/id/messages.json.gz" type="chrome_messages_json_gzip" lang="id"/>
+ <output filename="_locales/it/messages.json.gz" type="chrome_messages_json_gzip" lang="it"/>
+ <output filename="_locales/ja/messages.json.gz" type="chrome_messages_json_gzip" lang="ja"/>
+ <output filename="_locales/kn/messages.json.gz" type="chrome_messages_json_gzip" lang="kn"/>
+ <output filename="_locales/ko/messages.json.gz" type="chrome_messages_json_gzip" lang="ko"/>
+ <output filename="_locales/lt/messages.json.gz" type="chrome_messages_json_gzip" lang="lt"/>
+ <output filename="_locales/lv/messages.json.gz" type="chrome_messages_json_gzip" lang="lv"/>
+ <output filename="_locales/ml/messages.json.gz" type="chrome_messages_json_gzip" lang="ml"/>
+ <output filename="_locales/mr/messages.json.gz" type="chrome_messages_json_gzip" lang="mr"/>
+ <output filename="_locales/ms/messages.json.gz" type="chrome_messages_json_gzip" lang="ms"/>
+ <output filename="_locales/nl/messages.json.gz" type="chrome_messages_json_gzip" lang="nl"/>
+ <output filename="_locales/nb/messages.json.gz" type="chrome_messages_json_gzip" lang="no"/>
+ <output filename="_locales/pl/messages.json.gz" type="chrome_messages_json_gzip" lang="pl"/>
+ <output filename="_locales/pt_BR/messages.json.gz" type="chrome_messages_json_gzip" lang="pt-BR"/>
+ <output filename="_locales/pt_PT/messages.json.gz" type="chrome_messages_json_gzip" lang="pt-PT"/>
+ <output filename="_locales/ro/messages.json.gz" type="chrome_messages_json_gzip" lang="ro"/>
+ <output filename="_locales/ru/messages.json.gz" type="chrome_messages_json_gzip" lang="ru"/>
+ <output filename="_locales/sk/messages.json.gz" type="chrome_messages_json_gzip" lang="sk"/>
+ <output filename="_locales/sl/messages.json.gz" type="chrome_messages_json_gzip" lang="sl"/>
+ <output filename="_locales/sr/messages.json.gz" type="chrome_messages_json_gzip" lang="sr"/>
+ <output filename="_locales/sv/messages.json.gz" type="chrome_messages_json_gzip" lang="sv"/>
+ <output filename="_locales/sw/messages.json.gz" type="chrome_messages_json_gzip" lang="sw"/>
+ <output filename="_locales/ta/messages.json.gz" type="chrome_messages_json_gzip" lang="ta"/>
+ <output filename="_locales/te/messages.json.gz" type="chrome_messages_json_gzip" lang="te"/>
+ <output filename="_locales/th/messages.json.gz" type="chrome_messages_json_gzip" lang="th"/>
+ <output filename="_locales/tr/messages.json.gz" type="chrome_messages_json_gzip" lang="tr"/>
+ <output filename="_locales/uk/messages.json.gz" type="chrome_messages_json_gzip" lang="uk"/>
+ <output filename="_locales/vi/messages.json.gz" type="chrome_messages_json_gzip" lang="vi"/>
+ <output filename="_locales/zh_CN/messages.json.gz" type="chrome_messages_json_gzip" lang="zh-CN"/>
+ <output filename="_locales/zh_TW/messages.json.gz" type="chrome_messages_json_gzip" lang="zh-TW"/>
+ </outputs>
+ <translations>
+ <file path="accessibility_strings_af.xtb" lang="af" />
+ <file path="accessibility_strings_am.xtb" lang="am" />
+ <file path="accessibility_strings_ar.xtb" lang="ar" />
+ <file path="accessibility_strings_as.xtb" lang="as" />
+ <file path="accessibility_strings_az.xtb" lang="az" />
+ <file path="accessibility_strings_be.xtb" lang="be" />
+ <file path="accessibility_strings_bg.xtb" lang="bg" />
+ <file path="accessibility_strings_bn.xtb" lang="bn" />
+ <file path="accessibility_strings_bs.xtb" lang="bs" />
+ <file path="accessibility_strings_ca.xtb" lang="ca" />
+ <file path="accessibility_strings_cs.xtb" lang="cs" />
+ <file path="accessibility_strings_da.xtb" lang="da" />
+ <file path="accessibility_strings_de.xtb" lang="de" />
+ <file path="accessibility_strings_el.xtb" lang="el" />
+ <file path="accessibility_strings_en-GB.xtb" lang="en-GB" />
+ <file path="accessibility_strings_es.xtb" lang="es" />
+ <file path="accessibility_strings_es-419.xtb" lang="es-419" />
+ <file path="accessibility_strings_et.xtb" lang="et" />
+ <file path="accessibility_strings_eu.xtb" lang="eu" />
+ <file path="accessibility_strings_fa.xtb" lang="fa" />
+ <file path="accessibility_strings_fi.xtb" lang="fi" />
+ <file path="accessibility_strings_fil.xtb" lang="fil" />
+ <file path="accessibility_strings_fr.xtb" lang="fr" />
+ <file path="accessibility_strings_fr-CA.xtb" lang="fr-CA" />
+ <file path="accessibility_strings_gl.xtb" lang="gl" />
+ <file path="accessibility_strings_gu.xtb" lang="gu" />
+ <file path="accessibility_strings_hi.xtb" lang="hi" />
+ <file path="accessibility_strings_hr.xtb" lang="hr" />
+ <file path="accessibility_strings_hu.xtb" lang="hu" />
+ <file path="accessibility_strings_hy.xtb" lang="hy" />
+ <file path="accessibility_strings_id.xtb" lang="id" />
+ <file path="accessibility_strings_is.xtb" lang="is" />
+ <file path="accessibility_strings_it.xtb" lang="it" />
+ <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
+ <file path="accessibility_strings_iw.xtb" lang="he" />
+ <file path="accessibility_strings_ja.xtb" lang="ja" />
+ <file path="accessibility_strings_ka.xtb" lang="ka" />
+ <file path="accessibility_strings_kk.xtb" lang="kk" />
+ <file path="accessibility_strings_km.xtb" lang="km" />
+ <file path="accessibility_strings_kn.xtb" lang="kn" />
+ <file path="accessibility_strings_ko.xtb" lang="ko" />
+ <file path="accessibility_strings_ky.xtb" lang="ky" />
+ <file path="accessibility_strings_lo.xtb" lang="lo" />
+ <file path="accessibility_strings_lt.xtb" lang="lt" />
+ <file path="accessibility_strings_lv.xtb" lang="lv" />
+ <file path="accessibility_strings_mk.xtb" lang="mk" />
+ <file path="accessibility_strings_ml.xtb" lang="ml" />
+ <file path="accessibility_strings_mn.xtb" lang="mn" />
+ <file path="accessibility_strings_mr.xtb" lang="mr" />
+ <file path="accessibility_strings_ms.xtb" lang="ms" />
+ <file path="accessibility_strings_my.xtb" lang="my" />
+ <file path="accessibility_strings_ne.xtb" lang="ne" />
+ <file path="accessibility_strings_nl.xtb" lang="nl" />
+ <file path="accessibility_strings_no.xtb" lang="no" />
+ <file path="accessibility_strings_or.xtb" lang="or" />
+ <file path="accessibility_strings_pa.xtb" lang="pa" />
+ <file path="accessibility_strings_pl.xtb" lang="pl" />
+ <file path="accessibility_strings_pt-BR.xtb" lang="pt-BR" />
+ <file path="accessibility_strings_pt-PT.xtb" lang="pt-PT" />
+ <file path="accessibility_strings_ro.xtb" lang="ro" />
+ <file path="accessibility_strings_ru.xtb" lang="ru" />
+ <file path="accessibility_strings_si.xtb" lang="si" />
+ <file path="accessibility_strings_sk.xtb" lang="sk" />
+ <file path="accessibility_strings_sl.xtb" lang="sl" />
+ <file path="accessibility_strings_sq.xtb" lang="sq" />
+ <file path="accessibility_strings_sr.xtb" lang="sr" />
+ <file path="accessibility_strings_sr-Latn.xtb" lang="sr-Latn" />
+ <file path="accessibility_strings_sv.xtb" lang="sv" />
+ <file path="accessibility_strings_sw.xtb" lang="sw" />
+ <file path="accessibility_strings_ta.xtb" lang="ta" />
+ <file path="accessibility_strings_te.xtb" lang="te" />
+ <file path="accessibility_strings_th.xtb" lang="th" />
+ <file path="accessibility_strings_tr.xtb" lang="tr" />
+ <file path="accessibility_strings_uk.xtb" lang="uk" />
+ <file path="accessibility_strings_ur.xtb" lang="ur" />
+ <file path="accessibility_strings_uz.xtb" lang="uz" />
+ <file path="accessibility_strings_vi.xtb" lang="vi" />
+ <file path="accessibility_strings_zh-CN.xtb" lang="zh-CN" />
+ <file path="accessibility_strings_zh-HK.xtb" lang="zh-HK" />
+ <file path="accessibility_strings_zh-TW.xtb" lang="zh-TW" />
+ <file path="accessibility_strings_zu.xtb" lang="zu" />
+ </translations>
+ <release allow_pseudo="false" seq="1">
+ <messages fallback_to_english="true">
+ <part file="chromevox_strings.grdp" />
+ <part file="select_to_speak_strings.grdp" />
+ <part file="switch_access_strings.grdp" />
+ </messages>
+ </release>
+</grit>
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp b/chromium/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
new file mode 100644
index 00000000000..c47fc91cede
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
@@ -0,0 +1,2916 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit-part>
+ <message desc="The locale you're translating into. For use in URL to localized pages. e.g. http://www.google.com/?hl=en." name="IDS_LOCALE">
+ en
+ </message>
+ <message desc="The product name for ChromeVox." name="IDS_CHROMEVOX_NAME">
+ ChromeVox
+ </message>
+ <message desc="The product description, displayed in the Chrome Extensions page." name="IDS_CHROMEVOX_DESCRIPTION">
+ ChromeVox - Giving Voice to Chrome
+ </message>
+ <message desc="The description of the stopSpeech key. Displayed in the Options page." name="IDS_CHROMEVOX_STOP_SPEECH_KEY">
+ Stop speech
+ </message>
+ <message desc="The description of the toggleStickyMode key. Displayed in the Options page." name="IDS_CHROMEVOX_TOGGLE_STICKY_MODE">
+ Enable/Disable sticky mode
+ </message>
+ <message desc="The description of the handleTab key. Displayed in the Options page." name="IDS_CHROMEVOX_HANDLE_TAB_NEXT">
+ Jump to next focusable item
+ </message>
+ <message desc="The description of the handleTab key. Displayed in the Options page." name="IDS_CHROMEVOX_HANDLE_TAB_PREV">
+ Jump to previous focusable item
+ </message>
+ <message desc="The description of the backward key. Displayed in the Options page." name="IDS_CHROMEVOX_BACKWARD">
+ Navigate backward
+ </message>
+ <message desc="The description of the forward key. Displayed in the Options page." name="IDS_CHROMEVOX_FORWARD">
+ Navigate forward
+ </message>
+ <message desc="The description of the left key. Displayed in the Options page." name="IDS_CHROMEVOX_LEFT">
+ Move left
+ </message>
+ <message desc="The description of the right key. Displayed in the Options page." name="IDS_CHROMEVOX_RIGHT">
+ Move right
+ </message>
+ <message desc="The description of the previousGranularity key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_GRANULARITY">
+ Decrease navigation granularity
+ </message>
+ <message desc="The description of the nextGranularity key. Navigation granularity can be e.g. &quot;sentence level&quot;, &quot;word level&quot;. Granularity is also referred as &quot;level of detail&quot;. c.f. http://chromevox.com/tutorial/text_navigation.html Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_GRANULARITY">
+ Increase navigation granularity
+ </message>
+ <message desc="The description of the previousAtGranularity gesture. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_AT_GRANULARITY">
+ Move to previous at granularity
+ </message>
+ <message desc="The description of the nextGranularity gesture. Navigation granularity can be e.g. &quot;word level&quot;. Granularity is also referred as &quot;level of detail&quot;. c.f. http://chromevox.com/tutorial/text_navigation.html Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_AT_GRANULARITY">
+ Move to next at granularity
+ </message>
+ <message desc="The description of the forceClickOnCurrentItem key. Displayed in the Options page." name="IDS_CHROMEVOX_FORCE_CLICK_ON_CURRENT_ITEM">
+ Click on current item
+ </message>
+ <message desc="The description of the readLinkURL key. Displayed in the Options page." name="IDS_CHROMEVOX_READ_LINK_URL">
+ Announce the URL behind a link
+ </message>
+ <message desc="The description of the readCurrentTitle key. Displayed in the Options page." name="IDS_CHROMEVOX_READ_CURRENT_TITLE">
+ Announce the title of the current page
+ </message>
+ <message desc="The description of the readCurrentURL key. Displayed in the Options page." name="IDS_CHROMEVOX_READ_CURRENT_URL">
+ Announce the URL of the current page
+ </message>
+ <message desc="The description of the readFromHere key. Displayed in the Options page." name="IDS_CHROMEVOX_READ_FROM_HERE">
+ Start reading from current location
+ </message>
+ <message desc="The description of the command to show the ChromeVox menu. This menu is the application menu for ChromeVox and contains commands, as well as other useful menu items such as help." name="IDS_CHROMEVOX_SHOW_PANEL_MENU">
+ Open ChromeVox menus
+ </message>
+ <message desc="The description of the help key. Displayed in the Options page." name="IDS_CHROMEVOX_HELP">
+ Open ChromeVox tutorial
+ </message>
+ <message desc="The description of the toggleSearchWidget key. Displayed in the Options page." name="IDS_CHROMEVOX_TOGGLE_SEARCH_WIDGET">
+ ChromeVox find in page
+ </message>
+ <message desc="The description of the showOptionsPage key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_OPTIONS_PAGE">
+ Open options page
+ </message>
+ <message desc="The description of the showLogPage key. Displayed in the ChromeVox panel." name="IDS_CHROMEVOX_SHOW_LOG_PAGE">
+ Open developer log page
+ </message>
+ <message desc="The description of the showKbExplorerPage key; this allows users to learn about their keyboard. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_KB_EXPLORER_PAGE">
+ Open learn mode
+ </message>
+ <message desc="The description of the decreaseTtsRate key. Displayed in the Options page." name="IDS_CHROMEVOX_DECREASE_TTS_RATE">
+ Decrease rate of speech
+ </message>
+ <message desc="The description of the increaseTtsRate key. Displayed in the Options page." name="IDS_CHROMEVOX_INCREASE_TTS_RATE">
+ Increase rate of speech
+ </message>
+ <message desc="The description of the decreaseTtsPitch key. This key's action is passed to the text-to-speech voice engine and controls the voice's pitch. c.f. http://en.wikipedia.org/wiki/Pitch_(music) Displayed in the Options page." name="IDS_CHROMEVOX_DECREASE_TTS_PITCH">
+ Decrease pitch
+ </message>
+ <message desc="The description of the increaseTtsPitch key. Displayed in the Options page." name="IDS_CHROMEVOX_INCREASE_TTS_PITCH">
+ Increase pitch
+ </message>
+ <message desc="The description of the decreaseTtsVolume key. Displayed in the Options page." name="IDS_CHROMEVOX_DECREASE_TTS_VOLUME">
+ Decrease speech volume
+ </message>
+ <message desc="The description of the increaseTtsVolume key. Displayed in the Options page." name="IDS_CHROMEVOX_INCREASE_TTS_VOLUME">
+ Increase speech volume
+ </message>
+ <message desc="The description of the showFormsList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_FORMS_LIST">
+ Show forms list
+ </message>
+ <message desc="The description of the showHeadingsList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_HEADINGS_LIST">
+ Show headings list
+ </message>
+ <message desc="The description of the showLinksList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_LINKS_LIST">
+ Show links list
+ </message>
+ <message desc="The description of the showTablesList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_TABLES_LIST">
+ Show tables list
+ </message>
+ <message desc="The description of the showLandmarksList key. Displayed in the Options page." name="IDS_CHROMEVOX_SHOW_LANDMARKS_LIST">
+ Show landmarks list
+ </message>
+ <message desc="The description of the announceHeaders key. Displayed in the Options page." name="IDS_CHROMEVOX_ANNOUNCE_HEADERS">
+ Announce the headers of the current cell
+ </message>
+ <message desc="The description of the speakTableLocation key. This key's action will describe where in the table the focus currently is. Displayed in the Options page." name="IDS_CHROMEVOX_SPEAK_TABLE_LOCATION">
+ Announce current cell coordinates
+ </message>
+ <message desc="The description of the skipToBeginning key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_BEGINNING">
+ Go to beginning of table
+ </message>
+ <message desc="The description of the skipToEnd key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_END">
+ Go to end of table
+ </message>
+ <message desc="The description of the skipToRowBeginning key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_ROW_BEGINNING">
+ Go to beginning of the current row
+ </message>
+ <message desc="The description of the skipToRowEnd key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_ROW_END">
+ Go to end of the current row
+ </message>
+ <message desc="The description of the skipToColBeginning key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_COL_BEGINNING">
+ Go to beginning of the current column
+ </message>
+ <message desc="The description of the skipToColEnd key. Displayed in the Options page." name="IDS_CHROMEVOX_SKIP_TO_COL_END">
+ Go to end of the current column
+ </message>
+ <message desc="Describes the command to move to the previous row. Displayed in a help menu." name="IDS_CHROMEVOX_SKIP_TO_PREV_ROW">
+ Go to the previous row
+ </message>
+ <message desc="Describes the command to move to the next row. Displayed in a help menu." name="IDS_CHROMEVOX_SKIP_TO_NEXT_ROW">
+ Go to the next row
+ </message>
+ <message desc="Describes the command to move to the previous column. Displayed in a help menu." name="IDS_CHROMEVOX_SKIP_TO_PREV_COL">
+ Go to the previous column
+ </message>
+ <message desc="Describes the command to move to the next column. Displayed in a help menu." name="IDS_CHROMEVOX_SKIP_TO_NEXT_COL">
+ Go to the next column
+ </message>
+ <message desc="The description of the nextHeading1 key. In most cases, &quot;level 1 heading&quot; is a H1 HTML tag. ChromeVox will search, from the current focus, for the next heading on the page. If a heading is found, ChromeVox will focus on the heading. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING1">
+ Next level 1 heading
+ </message>
+ <message desc="The description of the previousHeading1 key. Behaves like nextHeading1, but this key's action will search backwards (up the page). Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING1">
+ Previous level 1 heading
+ </message>
+ <message desc="The description of the nextHeading2 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING2">
+ Next level 2 heading
+ </message>
+ <message desc="The description of the previousHeading2 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING2">
+ Previous level 2 heading
+ </message>
+ <message desc="The description of the nextHeading3 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING3">
+ Next level 3 heading
+ </message>
+ <message desc="The description of the previousHeading3 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING3">
+ Previous level 3 heading
+ </message>
+ <message desc="The description of the nextHeading4 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING4">
+ Next level 4 heading
+ </message>
+ <message desc="The description of the previousHeading4 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING4">
+ Previous level 4 heading
+ </message>
+ <message desc="The description of the nextHeading5 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING5">
+ Next level 5 heading
+ </message>
+ <message desc="The description of the previousHeading5 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING5">
+ Previous level 5 heading
+ </message>
+ <message desc="The description of the nextHeading6 key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING6">
+ Next level 6 heading
+ </message>
+ <message desc="The description of the previousHeading6 key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING6">
+ Previous level 6 heading
+ </message>
+ <message desc="The description of the nextComboBox key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_COMBO_BOX">
+ Next combo box
+ </message>
+ <message desc="The description of the previousComboBox key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_COMBO_BOX">
+ Previous combo box
+ </message>
+ <message desc="The description of the nextEditText key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_EDIT_TEXT">
+ Next editable text area
+ </message>
+ <message desc="The description of the previousEditText key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_EDIT_TEXT">
+ Previous editable text area
+ </message>
+ <message desc="The description of the nextFormField key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_FORM_FIELD">
+ Next form field
+ </message>
+ <message desc="The description of the previousFormField key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_FORM_FIELD">
+ Previous form field
+ </message>
+ <message desc="The description of the nextGraphic key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_GRAPHIC">
+ Next graphic
+ </message>
+ <message desc="The description of the previousGraphic key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_GRAPHIC">
+ Previous graphic
+ </message>
+ <message desc="The description of the nextHeading key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_HEADING">
+ Next heading
+ </message>
+ <message desc="The description of the previousHeading key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_HEADING">
+ Previous heading
+ </message>
+ <message desc="The description of the nextListItem key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LIST_ITEM">
+ Next list item
+ </message>
+ <message desc="The description of the previousListItem key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LIST_ITEM">
+ Previous list item
+ </message>
+ <message desc="The description of the nextLink key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LINK">
+ Next link
+ </message>
+ <message desc="The description of the previousLink key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LINK">
+ Previous link
+ </message>
+ <message desc="The description of the nextList key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LIST">
+ Next list
+ </message>
+ <message desc="The description of the previousList key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LIST">
+ Previous list
+ </message>
+ <message desc="The description of the nextMath key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_MATH">
+ Next math
+ </message>
+ <message desc="The description of the previousMath key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_MATH">
+ Previous math
+ </message>
+ <message desc="The description of the nextMedia key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_MEDIA">
+ Next media
+ </message>
+ <message desc="The description of the previousMedia key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_MEDIA">
+ Previous media
+ </message>
+ <message desc="The description of the nextRadio key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_RADIO">
+ Next radio button
+ </message>
+ <message desc="The description of the previousRadio key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_RADIO">
+ Previous radio button
+ </message>
+ <message desc="The description of the nextTable key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_TABLE">
+ Next table
+ </message>
+ <message desc="The description of the nextVisitedLink key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_VISITED_LINK">
+ Next visited link
+ </message>
+ <message desc="The description of the previousTable key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_TABLE">
+ Previous table
+ </message>
+ <message desc="The description of the previousVisitedLink key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_VISITED_LINK">
+ Previous visited link
+ </message>
+ <message desc="The description of the nextButton key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_BUTTON">
+ Next button
+ </message>
+ <message desc="The description of the previousButton key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_BUTTON">
+ Previous button
+ </message>
+ <message desc="The description of the nextCheckbox key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_CHECKBOX">
+ Next checkbox
+ </message>
+ <message desc="The description of the previousCheckbox key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_CHECKBOX">
+ Previous checkbox
+ </message>
+ <message desc="The description of the nextLandmark key. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LANDMARK">
+ Next landmark
+ </message>
+ <message desc="The description of the previousLandmark key. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LANDMARK">
+ Previous landmark
+ </message>
+ <message desc="The description of the fullyDescribe key. Displayed in the Options page." name="IDS_CHROMEVOX_FULLY_DESCRIBE">
+ Announces a complete description of the current position
+ </message>
+ <message desc="The title of the extension's options page." name="IDS_CHROMEVOX_OPTIONS_PAGE_TITLE">
+ ChromeVox Options
+ </message>
+ <message desc="An options page section header for options about the ChromeVox virtual display. This section lets users change the rows, columns, and display style of the virtual braille display." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY">
+ Virtual Braille Display
+ </message>
+ <message desc="An explanatory paragraph as part of the ChromeVox options page. Explains that the section on virtual braille display allows the user to control a simulation of a refreshable braille display (a physical hardware device) in the panel at the top of the screen." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_DETAILS">
+ Simulates the output of a refreshable braille display
+ in the ChromeVox panel at the top of the screen
+ </message>
+ <message desc="The label for a numberic input field where the user can choose the number of lines of text in a grid." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_ROWS">
+ Lines:
+ </message>
+ <message desc="The label for a numberic input field where the user can choose the number of cells in each line of a grid." name="IDS_CHROMEVOX_OPTIONS_VIRTUAL_BRAILLE_DISPLAY_COLUMNS">
+ Cells in each line:
+ </message>
+ <message desc="A description that tells the user that the current display style of the virtual display interleaves braille and regular text, one on top of the other." name="IDS_CHROMEVOX_OPTIONS_CURRENT_DISPLAY_STYLE_INTERLEAVE">
+ Current display style is interleave
+ </message>
+ <message desc="A description that tells the user that the current display style of the virtual display is side by side, where regular text is on the left and braille is on the right." name="IDS_CHROMEVOX_OPTIONS_CURRENT_DISPLAY_STYLE_SIDE_BY_SIDE">
+ Current display style is side by side
+ </message>
+ <message desc="Labels the change display style button when the display style is side by side. Pressing the button would make the text interleave with the braille cells, one on top of the other." name="IDS_CHROMEVOX_OPTIONS_CHANGE_CURRENT_DISPLAY_STYLE_INTERLEAVE">
+ Change display style to interleave
+ </message>
+ <message desc="Labels the change display style button when the display style is interleave. Pressing the button would put all the text on the left side and all the braille cells on the right." name="IDS_CHROMEVOX_OPTIONS_CHANGE_CURRENT_DISPLAY_STYLE_SIDE_BY_SIDE">
+ Change display style to side by side
+ </message>
+ <message desc="An option to use more verbose feedback for the user." name="IDS_CHROMEVOX_OPTIONS_VERBOSITY_VERBOSE">
+ Enable verbose descriptions
+ </message>
+ <message desc="An option to automatically read the page after it loads." name="IDS_CHROMEVOX_OPTIONS_AUTO_READ">
+ Automatically read page after it finishes loading
+ </message>
+ <message desc="Describes the multi select option for how to play audio when ChromeVox speaks using text to speech." name="IDS_CHROMEVOX_OPTIONS_AUDIO_DESCRIPTION">
+ When playing audio...
+ </message>
+ <message desc="Sets audio playback to be at normal volume." name="IDS_CHROMEVOX_OPTIONS_AUDIO_NORMAL">
+ Play at normal volume even if ChromeVox is speaking
+ </message>
+ <message desc="An option to use audio ducking." name="IDS_CHROMEVOX_OPTIONS_AUDIO_duck">
+ Play at lower volume when ChromeVox is speaking
+ </message>
+ <message desc="An option to use audio suspension while text to speech is speaking." name="IDS_CHROMEVOX_OPTIONS_AUDIO_suspend">
+ Pause playback when ChromeVox is speaking
+ </message>
+ <message desc="An option to speak text under the mouse." name="IDS_CHROMEVOX_OPTIONS_SPEAK_MOUSE">
+ Speak text under the mouse
+ </message>
+ <message desc="An options page section header for options about the ChromeVox voice. This section lets users change the voice by selecting a different voice from a listbox." name="IDS_CHROMEVOX_OPTIONS_VOICES">
+ Voices
+ </message>
+ <message desc="Labels the voice selection list box." name="IDS_CHROMEVOX_OPTIONS_VOICES_DESCRIPTION">
+ Select current voice:
+ </message>
+ <message desc="An options page section header for options about the ChromeVox braille support. This section allows the user to customize varous aspects of the braille output and input support." name="IDS_CHROMEVOX_OPTIONS_BRAILLE">
+ Braille
+ </message>
+ <message desc="Labels the braille table type button when the current table is an 6 dot table. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_TABLE_TYPE_6">
+ Switch to 8 dot braille
+ </message>
+ <message desc="Labels the braille table type button when the current table is an 8 dot table. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_TABLE_TYPE_8">
+ Switch to 6 dot braille
+ </message>
+ <message desc="Labels the braille table selection list box. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_DESCRIPTION_6">
+ Select a 6-dot braille table:
+ </message>
+ <message desc="How to present the name of a braille table to the user. For example, a locale could be 'English (United States)' and a grade could be '2'. Together they would be 'English (UnitedStates), Grade 2'. A braille table describes how text gets converted from Unicode text into a pattern of braille dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_BRAILLE_TABLE_NAME_WITH_GRADE">
+ <ph name="locale">$1</ph>, Grade <ph name="grade">$2</ph>
+ </message>
+ <message desc="How to present the name of a braille table to the user. For example, a locale could be 'English' and a variant could be 'UEB' (for 'Unified English Braille'). Together they would be 'English (UEB)'. A braille table describes how text gets converted from Unicode text into a pattern of braille dots. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_BRAILLE_TABLE_NAME_WITH_VARIANT">
+ <ph name="locale">$1</ph> (<ph name="variant">$2</ph>)
+ </message>
+ <message desc="How to present the name of a braille table to the user. For example, a locale could be 'English', variant could be 'UEB' (for 'Unified English Braille') and a grade could be '2'. Together they would be 'English (UEB), Grade 2'. A braille table describes how text gets converted from Unicode text into a pattern of braille dots. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_BRAILLE_TABLE_NAME_WITH_VARIANT_AND_GRADE">
+ <ph name="locale">$1</ph> (<ph name="variant">$2</ph>), Grade <ph name="grade">$3</ph>
+ </message>
+ <message desc="Labels the braille table selection list box. A braille table describes how text gets converted from a unicode encoding into a pattern of dots. This varies based on locale and contraction. See http://en.wikipedia.org/wiki/Braille for a more in-depth discussion." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_DESCRIPTION_8">
+ Select an 8-dot braille table:
+ </message>
+ <message desc="Labels the checkbox that enables wrapping of words if a whole line doesn't fit on a braille display. When this option is enabled, an effort is made to keep the characters of words together on the display. Otherwise, as many characters as possible are put on each braille display line, possible splitting words between lines." name="IDS_CHROMEVOX_OPTIONS_BRAILLE_WORD_WRAP">
+ Enable word wrap
+ </message>
+ <message desc="Labels the checkbox that enables developer options for ChromeVox." name="IDS_CHROMEVOX_OPTIONS_DEVELOPER_OPTIONS">
+ Enable Developer Options
+ </message>
+ <message desc="Enable chromevox earcon logging." name="IDS_CHROMEVOX_OPTIONS_DEVELOPER_EARCON_LOGGING">
+ Enable earcon logging
+ </message>
+ <message desc="Enable chromevox speech logging." name="IDS_CHROMEVOX_OPTIONS_DEVELOPER_SPEECH_LOGGING">
+ Enable speech logging
+ </message>
+ <message desc="Enable event stream logging in chromevox for developer options." name="IDS_CHROMEVOX_OPTIONS_EVENT_STREAM_LOGGING">
+ Enable event stream logging
+ </message>
+ <message desc="Show ChromeVox Event Log." name="IDS_CHROMEVOX_OPTIONS_SHOW_LOG">
+ Show Log
+ </message>
+ <message desc="Keyboard shortcut to show the ChromeVox log." name="IDS_CHROMEVOX_OPTIONS_SHOW_LOG_KEY">
+ Search + O + W
+ </message>
+ <message desc="Show event stream filters options for event stream logging." name="IDS_CHROMEVOX_OPTIONS_SHOW_EVENT_STREAM_FILTERS">
+ Show event stream filters
+ </message>
+ <message desc="Hide event stream filters options for event stream logging." name="IDS_CHROMEVOX_OPTIONS_HIDE_EVENT_STREAM_FILTERS">
+ Hide event stream filters
+ </message>
+ <message desc="Set all event stream logging filters to on." name="IDS_CHROMEVOX_OPTIONS_ENABLE_ALL_EVENT_STREAM_FILTERS">
+ Enable all event filters
+ </message>
+ <message desc="Set all event stream logging filters to off." name="IDS_CHROMEVOX_OPTIONS_DISABLE_ALL_EVENT_STREAM_FILTERS">
+ Disable all event filters
+ </message>
+ <message desc="Enable chromevox braille logging." name="IDS_CHROMEVOX_OPTIONS_DEVELOPER_BRAILLE_LOGGING">
+ Enable braille logging
+ </message>
+ <message desc="The title of ChromeVox Learn Mode page. The keyboard explorer voices the name of each key when the user presses it." name="IDS_CHROMEVOX_KBEXPLORER_TITLE">
+ ChromeVox Learn Mode
+ </message>
+ <message desc="The title of ChromeVox Log page." name="IDS_CHROMEVOX_LOG_TITLE">
+ ChromeVox Log
+ </message>
+ <message desc="The instructions for ChromeVox Learn Mode. The keyboard explorer voices the name of each key when the user presses it. * These instructions describe how to use the keyboard explorer." name="IDS_CHROMEVOX_KBEXPLORER_INSTRUCTIONS">
+ Press any key to learn its name. Ctrl+W will close learn mode.
+ </message>
+ <message desc="Spoken when a new Chrome tab named 'title' is opened." name="IDS_CHROMEVOX_CHROME_TAB_CREATED">
+ tab created
+ </message>
+ <message desc="Spoken when the user changes to different tab showing the 'title' page." name="IDS_CHROMEVOX_CHROME_TAB_SELECTED">
+ <ph name="title">$1</ph>, tab
+ </message>
+ <message desc="Spoken when the user opens a Chrome menu named 'title'." name="IDS_CHROMEVOX_CHROME_MENU_OPENED">
+ <ph name="title">$1</ph> menu opened
+ </message>
+ <message desc="Spoken when the user closes any Chrome menu." name="IDS_CHROMEVOX_CHROME_MENU_CLOSED">
+ menu closed
+ </message>
+ <message desc="Describes a switch named 'name' in the on/checked state." name="IDS_CHROMEVOX_DESCRIBE_SWITCH_ON">
+ <ph name="name">$1</ph>, switch on
+ </message>
+ <message desc="Describes a switch named 'name' in the off/unchecked state." name="IDS_CHROMEVOX_DESCRIBE_SWITCH_OFF">
+ <ph name="name">$1</ph>, switch off
+ </message>
+ <message desc="Describes a HTML radio button named 'name' in the selected state." name="IDS_CHROMEVOX_DESCRIBE_RADIO_SELECTED">
+ <ph name="name">$1</ph>, radio button selected
+ </message>
+ <message desc="Describes a HTML radio button named 'name' in the unselected state." name="IDS_CHROMEVOX_DESCRIBE_RADIO_UNSELECTED">
+ <ph name="name">$1</ph>, radio button unselected
+ </message>
+ <message desc="Describes a window named 'name'." name="IDS_CHROMEVOX_DESCRIBE_WINDOW">
+ <ph name="name">$1</ph>, window
+ </message>
+ <message desc="Describes a Chrome tab named 'name'." name="IDS_CHROMEVOX_DESCRIBE_TAB">
+ <ph name="name">$1</ph>, tab
+ </message>
+ <message desc="Spoken through the a11y api after describing an element if it is part of a group." name="IDS_CHROMEVOX_DESCRIBE_INDEX">
+ ''' <ph name="index">$1</ph> of <ph name="total">$2</ph> '''
+ </message>
+ <message desc="Braille for describing an index of an element in a group." name="IDS_CHROMEVOX_DESCRIBE_INDEX_BRL">
+ <ph name="index">$1</ph>/<ph name="total">$2</ph>
+ </message>
+ <message desc="Spoken through the a11y api when moving between treeitems of differing depth." name="IDS_CHROMEVOX_DESCRIBE_DEPTH">
+ ''' level <ph name="depth">$1</ph> '''
+ </message>
+ <message desc="Describes the rate of synthesized speech as a percentage of the normal speaking rate, like 50% for slow speech or 200% for fast speech." name="IDS_CHROMEVOX_ANNOUNCE_RATE">
+ Rate <ph name="percent">$1</ph> percent
+ </message>
+ <message desc="Describes the pitch of synthesized speech as a percentage of the normal pitch, like 50% for low pitch or 150% for high pitch." name="IDS_CHROMEVOX_ANNOUNCE_PITCH">
+ Pitch <ph name="percent">$1</ph> percent
+ </message>
+ <message desc="Describes the volume of synthesized speech as a percentage where 100% is full volume." name="IDS_CHROMEVOX_ANNOUNCE_VOLUME">
+ Volume <ph name="percent">$1</ph> percent
+ </message>
+ <message desc="Spoken when the user exits a container." name="IDS_CHROMEVOX_EXITED_CONTAINER">
+ Exited <ph name="type">$1</ph>.
+ </message>
+ <message desc="Spoken before the list of elements when a live region of a page is removed." name="IDS_CHROMEVOX_LIVE_REGIONS_REMOVED">
+ removed:
+ </message>
+ <message desc="Tells the user that sticky mode is enabled. Sticky mode allows the user to navigate without pressing the modifier keys." name="IDS_CHROMEVOX_STICKY_MODE_ENABLED">
+ Sticky mode enabled
+ </message>
+ <message desc="Tells the user that sticky mode is disabled. Sticky mode allows the user to navigate without pressing the modifier keys." name="IDS_CHROMEVOX_STICKY_MODE_DISABLED">
+ Sticky mode disabled
+ </message>
+ <message desc="Spoken when the user reads a link without a URL." name="IDS_CHROMEVOX_NO_URL_FOUND">
+ No URL found
+ </message>
+ <message desc="Spoken, in table mode, when the user attempts to navigate to a non-existant next row." name="IDS_CHROMEVOX_NO_CELL_BELOW">
+ No cell below
+ </message>
+ <message desc="Spoken, in table mode, when the user attempts to navigate to a non-existant previous row." name="IDS_CHROMEVOX_NO_CELL_ABOVE">
+ No cell above
+ </message>
+ <message desc="Spoken, in table mode, when the user attempts to navigate to a non-existant row to the right." name="IDS_CHROMEVOX_NO_CELL_RIGHT">
+ No cell right
+ </message>
+ <message desc="Spoken, in table mode, when the user attempts to navigate to a non-existant row to the left." name="IDS_CHROMEVOX_NO_CELL_LEFT">
+ No cell left
+ </message>
+ <message desc="summarizes a table." name="IDS_CHROMEVOX_TABLE_SUMMARY">
+ Table <ph name="tableName">$1</ph>, <ph name="tableRows">$2</ph> by <ph name="tableCols">$3</ph>
+ </message>
+ <message desc="summarizes a html data table for braille. If the description for the table (and not the substitutions after the initial description) is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TABLE_SUMMARY_BRL">
+ tbl <ph name="tableName">$1</ph> <ph name="tableRows">$2</ph>x<ph name="tableCols">$3</ph>
+ </message>
+ <message desc="summarizes a table cell." name="IDS_CHROMEVOX_CELL_SUMMARY">
+ row <ph name="tableCellRowIndex">$1</ph> column <ph name="tableCellColumnIndex">$2</ph>
+ </message>
+ <message desc="summarizes a table cell for braille; for example, r1c2 means row 1, column 2. Try to localize the 'r' and 'c' to the first letter of something that would be recognizable." name="IDS_CHROMEVOX_CELL_SUMMARY_BRL">
+ r<ph name="tableCellRowIndex">$1</ph>c<ph name="tableCellColumnIndex">$2</ph>
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next checkbox when none exists." name="IDS_CHROMEVOX_NO_NEXT_CHECKBOX">
+ No next checkbox
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous checkbox when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_CHECKBOX">
+ No previous checkbox
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next editable text field when none exists." name="IDS_CHROMEVOX_NO_NEXT_EDIT_TEXT">
+ No next editable text field
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous editable text field when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_EDIT_TEXT">
+ No previous editable text field
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING">
+ No next heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING">
+ No previous heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next level 1 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_1">
+ No next level 1 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous level 1 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_1">
+ No previous level 1 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next level 2 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_2">
+ No next level 2 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous level 2 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_2">
+ No previous level 2 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next level 3 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_3">
+ No next level 3 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous level 3 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_3">
+ No previous level 3 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next level 4 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_4">
+ No next level 4 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous level 4 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_4">
+ No previous level 4 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next level 5 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_5">
+ No next level 5 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous level 5 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_5">
+ No previous level 5 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next level 6 heading when none exists." name="IDS_CHROMEVOX_NO_NEXT_HEADING_6">
+ No next level 6 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous level 6 heading when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_HEADING_6">
+ No previous level 6 heading
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next link when none exists." name="IDS_CHROMEVOX_NO_NEXT_LINK">
+ No next link
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous link when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_LINK">
+ No previous link
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next table when none exists." name="IDS_CHROMEVOX_NO_NEXT_TABLE">
+ No next table
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous table when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_TABLE">
+ No previous table
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next visited link when none exists." name="IDS_CHROMEVOX_NO_NEXT_VISITED_LINK">
+ No next visited link
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous visited link when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_VISITED_LINK">
+ No previous visited link
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next math expression when none exists." name="IDS_CHROMEVOX_NO_NEXT_MATH">
+ No next math expression
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous math expression when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_MATH">
+ No previous math expression
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next media widget (audio/video) when none exists." name="IDS_CHROMEVOX_NO_NEXT_MEDIA_WIDGET">
+ No next media widget
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous media widget (audio/video) when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_MEDIA_WIDGET">
+ No previous media widget
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next list when none exists." name="IDS_CHROMEVOX_NO_NEXT_LIST">
+ No next list
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous list when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_LIST">
+ No previous list
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next list item when none exists." name="IDS_CHROMEVOX_NO_NEXT_LIST_ITEM">
+ No next list item
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous list item when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_LIST_ITEM">
+ No previous list item
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next form field when none exists." name="IDS_CHROMEVOX_NO_NEXT_FORM_FIELD">
+ No next form field
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous form field when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_FORM_FIELD">
+ No previous form field
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next ARIA landmark when none exists." name="IDS_CHROMEVOX_NO_NEXT_LANDMARK">
+ No next ARIA landmark
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous ARIA landmark when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_LANDMARK">
+ No previous ARIA landmark
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next combo box when none exists." name="IDS_CHROMEVOX_NO_NEXT_COMBO_BOX">
+ No next combo box
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous combo box when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_COMBO_BOX">
+ No previous combo box
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next button when none exists." name="IDS_CHROMEVOX_NO_NEXT_BUTTON">
+ No next button
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous button when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_BUTTON">
+ No previous button
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next graphic when none exists." name="IDS_CHROMEVOX_NO_NEXT_GRAPHIC">
+ No next graphic
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous graphic when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_GRAPHIC">
+ No previous graphic
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next slider when none exists." name="IDS_CHROMEVOX_NO_NEXT_SLIDER">
+ No next slider
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous slider when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_SLIDER">
+ No previous slider
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next radio button when none exists." name="IDS_CHROMEVOX_NO_NEXT_RADIO_BUTTON">
+ No next radio button
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous radio button when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_RADIO_BUTTON">
+ No previous radio button
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next section when none exists." name="IDS_CHROMEVOX_NO_NEXT_SECTION">
+ No next section
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous section when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_SECTION">
+ No previous section
+ </message>
+ <message desc="Spoken if the user attempts to jump to the next control when none exists." name="IDS_CHROMEVOX_NO_NEXT_CONTROL">
+ No next control
+ </message>
+ <message desc="Spoken if the user attempts to jump to the previous control when none exists." name="IDS_CHROMEVOX_NO_PREVIOUS_CONTROL">
+ No previous control
+ </message>
+ <message desc="Spoken in PowerKey if there are no ARIA landmarks to display." name="IDS_CHROMEVOX_POWERKEY_NO_LANDMARKS">
+ No ARIA landmarks
+ </message>
+ <message desc="Spoken after an element is spoken if the element has a pop up. For example &quot;Button Add friends has pop up&quot;" name="IDS_CHROMEVOX_ARIA_HAS_POPUP">
+ has pop up
+ </message>
+ <message desc="This is a suffix shown on a braille display for a widget (such as a button) that opens some kind of popup. When translating, keep the plus sign and append the translated word for 'popup'. If it is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_HAS_POPUP_BRL">
+ +popup
+ </message>
+ <message desc="Spoken when describing an ARIA value minimun. For example &quot;Distance, in meters textbox 6, min 2, max 10&quot;" name="IDS_CHROMEVOX_ARIA_VALUE_MIN">
+ Min <ph name="x">$1</ph>
+ </message>
+ <message desc="Brailled when describing an ARIA value minimum. For example &quot;Distance, in meters: 6 min:6 max:10&quot;" name="IDS_CHROMEVOX_ARIA_VALUE_MIN_BRL">
+ min:<ph name="x">$1</ph>
+ </message>
+ <message desc="Spoken when describing an ARIA value maximum. For example &quot;Distance, in meters textbox 6, min 2, max 10&quot;" name="IDS_CHROMEVOX_ARIA_VALUE_MAX">
+ Max <ph name="x">$1</ph>
+ </message>
+ <message desc="Brailled when describing an ARIA value maximum. For example &quot;Distance, in meters: 6 min:2 max:10&quot;." name="IDS_CHROMEVOX_ARIA_VALUE_MAX_BRL">
+ max:<ph name="x">$1</ph>
+ </message>
+ <message desc="Describes an element with the ARIA role alert." name="IDS_CHROMEVOX_ROLE_ALERT">
+ Alert
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translated word 'alert' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_ALERT_BRL">
+ alrt
+ </message>
+ <message desc="Describes an element with the ARIA role alertdialog." name="IDS_CHROMEVOX_ROLE_ALERTDIALOG">
+ Alert dialog
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'alert dialog' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_ALERTDIALOG_BRL">
+ alrt dlg
+ </message>
+ <message desc="Describes an element with the ARIA role button." name="IDS_CHROMEVOX_ROLE_BUTTON">
+ Button
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translated word for 'button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_BUTTON_BRL">
+ btn
+ </message>
+ <message desc="Describes an element with the ARIA role checkbox." name="IDS_CHROMEVOX_ROLE_CHECKBOX">
+ Check box
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'check box' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_CHECKBOX_BRL">
+ chk
+ </message>
+ <message desc="Describes an element with the ARIA role combobox." name="IDS_CHROMEVOX_ROLE_COMBOBOX">
+ Combo box
+ </message>
+ <message desc="Accessibility role description for a single comment" name="IDS_CHROMEVOX_ROLE_COMMENT">
+ Comment
+ </message>
+ <message desc="Accessibility role description for content deletion, meaning content that is has been or is suggested to be removed from a document, such as in a revision review" name="IDS_CHROMEVOX_ROLE_CONTENT_DELETION">
+ Deletion
+ </message>
+ <message desc="Accessibility role description for content insertion, meaning content that is has been or is suggested to be inserted into a document, such as in a revision review" name="IDS_CHROMEVOX_ROLE_CONTENT_INSERTION">
+ Insertion
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'combo box' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_COMBOBOX_BRL">
+ cbo
+ </message>
+ <message desc="Describes an element with the ARIA role dialog." name="IDS_CHROMEVOX_ROLE_DIALOG">
+ Dialog
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'dialog' (as in dialog box on a computer screen) according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DIALOG_BRL">
+ dlg
+ </message>
+ <message desc="Accessibility role description for abstract" name="IDS_CHROMEVOX_ROLE_DOC_ABSTRACT">
+ Abstract
+ </message>
+ <message desc="Accessibility role description for acknowledgments" name="IDS_CHROMEVOX_ROLE_DOC_ACKNOWLEDGMENTS">
+ Acknowledgments
+ </message>
+ <message desc="Accessibility role description for afterword" name="IDS_CHROMEVOX_ROLE_DOC_AFTERWORD">
+ Afterword
+ </message>
+ <message desc="Accessibility role description for appendix" name="IDS_CHROMEVOX_ROLE_DOC_APPENDIX">
+ Appendix
+ </message>
+ <message desc="Accessibility role description for back link" name="IDS_CHROMEVOX_ROLE_DOC_BACK_LINK">
+ Back link
+ </message>
+ <message desc="Accessibility role description for bibliography entry" name="IDS_CHROMEVOX_ROLE_DOC_BIBLIO_ENTRY">
+ Bibliography entry
+ </message>
+ <message desc="Accessibility role description for bibliography" name="IDS_CHROMEVOX_ROLE_DOC_BIBLIOGRAPHY">
+ Bibliography
+ </message>
+ <message desc="Accessibility role description for bibliography reference" name="IDS_CHROMEVOX_ROLE_DOC_BIBLIO_REF">
+ Bibliography reference
+ </message>
+ <message desc="Accessibility role description for chapter" name="IDS_CHROMEVOX_ROLE_DOC_CHAPTER">
+ Chapter
+ </message>
+ <message desc="Accessibility role description for colophon" name="IDS_CHROMEVOX_ROLE_DOC_COLOPHON">
+ Colophon
+ </message>
+ <message desc="Accessibility role description for conclusion" name="IDS_CHROMEVOX_ROLE_DOC_CONCLUSION">
+ Conclusion
+ </message>
+ <message desc="Accessibility role description for cover" name="IDS_CHROMEVOX_ROLE_DOC_COVER">
+ Cover
+ </message>
+ <message desc="Accessibility role description for credit" name="IDS_CHROMEVOX_ROLE_DOC_CREDIT">
+ Credit
+ </message>
+ <message desc="Accessibility role description for credits" name="IDS_CHROMEVOX_ROLE_DOC_CREDITS">
+ Credits
+ </message>
+ <message desc="Accessibility role description for dedication" name="IDS_CHROMEVOX_ROLE_DOC_DEDICATION">
+ Dedication
+ </message>
+ <message desc="Accessibility role description for endnote" name="IDS_CHROMEVOX_ROLE_DOC_ENDNOTE">
+ Endnote
+ </message>
+ <message desc="Accessibility role description for endnotes" name="IDS_CHROMEVOX_ROLE_DOC_ENDNOTES">
+ Endnotes
+ </message>
+ <message desc="Accessibility role description for epigraph" name="IDS_CHROMEVOX_ROLE_DOC_EPIGRAPH">
+ Epigraph
+ </message>
+ <message desc="Accessibility role description for epilogue" name="IDS_CHROMEVOX_ROLE_DOC_EPILOGUE">
+ Epilogue
+ </message>
+ <message desc="Accessibility role description for errata" name="IDS_CHROMEVOX_ROLE_DOC_ERRATA">
+ Errata
+ </message>
+ <message desc="Accessibility role description for example" name="IDS_CHROMEVOX_ROLE_DOC_EXAMPLE">
+ Example
+ </message>
+ <message desc="Accessibility role description for footnote" name="IDS_CHROMEVOX_ROLE_DOC_FOOTNOTE">
+ Footnote
+ </message>
+ <message desc="Accessibility role description for foreword" name="IDS_CHROMEVOX_ROLE_DOC_FOREWORD">
+ Foreword
+ </message>
+ <message desc="Accessibility role description for glossary" name="IDS_CHROMEVOX_ROLE_DOC_GLOSSARY">
+ Glossary
+ </message>
+ <message desc="Accessibility role description for glossary reference" name="IDS_CHROMEVOX_ROLE_DOC_GLOSS_REF">
+ Glossary reference
+ </message>
+ <message desc="Accessibility role description for index" name="IDS_CHROMEVOX_ROLE_DOC_INDEX">
+ Index
+ </message>
+ <message desc="Accessibility role description for introduction" name="IDS_CHROMEVOX_ROLE_DOC_INTRODUCTION">
+ Introduction
+ </message>
+ <message desc="Accessibility role description for note reference" name="IDS_CHROMEVOX_ROLE_DOC_NOTE_REF">
+ Note reference
+ </message>
+ <message desc="Accessibility role description for notice" name="IDS_CHROMEVOX_ROLE_DOC_NOTICE">
+ Notice
+ </message>
+ <message desc="Accessibility role description for page break" name="IDS_CHROMEVOX_ROLE_DOC_PAGE_BREAK">
+ Page break
+ </message>
+ <message desc="Accessibility role description for page list" name="IDS_CHROMEVOX_ROLE_DOC_PAGE_LIST">
+ Page list
+ </message>
+ <message desc="Accessibility role description for part" name="IDS_CHROMEVOX_ROLE_DOC_PART">
+ Part
+ </message>
+ <message desc="Accessibility role description for preface" name="IDS_CHROMEVOX_ROLE_DOC_PREFACE">
+ Preface
+ </message>
+ <message desc="Accessibility role description for prologue" name="IDS_CHROMEVOX_ROLE_DOC_PROLOGUE">
+ Prologue
+ </message>
+ <message desc="Accessibility role description for pullquote" name="IDS_CHROMEVOX_ROLE_DOC_PULLQUOTE">
+ Pullquote
+ </message>
+ <message desc="Accessibility role description for Q+A (questions and answers)" name="IDS_CHROMEVOX_ROLE_DOC_QNA">
+ Q&amp;A
+ </message>
+ <message desc="Accessibility role description for subtitle" name="IDS_CHROMEVOX_ROLE_DOC_SUBTITLE">
+ Subtitle
+ </message>
+ <message desc="Accessibility role description for tip" name="IDS_CHROMEVOX_ROLE_DOC_TIP">
+ Tip
+ </message>
+ <message desc="Accessibility role description for table of contents" name="IDS_CHROMEVOX_ROLE_DOC_TOC">
+ Table of contents
+ </message>
+ <message desc="Accessibility role description for graphics document" name="IDS_CHROMEVOX_ROLE_GRAPHICS_DOCUMENT">
+ Graphics document
+ </message>
+ <message desc="Accessibility role description for graphics object" name="IDS_CHROMEVOX_ROLE_GRAPHICS_OBJECT">
+ Graphics object
+ </message>
+ <message desc="Accessibility role description for graphics symbol" name="IDS_CHROMEVOX_ROLE_GRAPHICS_SYMBOL">
+ Graphics symbol
+ </message>
+ <message desc="Describes an element with the ARIA role grid." name="IDS_CHROMEVOX_ROLE_GRID">
+ Grid
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'grid' (a kind of tabular layout) according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_GRID_BRL">
+ grd
+ </message>
+ <message desc="Describes an element with the ARIA role gridcell." name="IDS_CHROMEVOX_ROLE_GRIDCELL">
+ Cell
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'cell' (as a part of a grid or tabular layout) according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_GRIDCELL_BRL">
+ cll
+ </message>
+ <message desc="Describes the position of an element with the ARIA role gridcell." name="IDS_CHROMEVOX_ROLE_GRIDCELL_POS">
+ row <ph name="row">$1</ph> column <ph name="col">$2</ph>
+ </message>
+ <message desc="Spoken to describe a link in a document." name="IDS_CHROMEVOX_ROLE_LINK">
+ Link
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'link' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LINK_BRL">
+ lnk
+ </message>
+ <message desc="Describes an element with the ARIA role listbox." name="IDS_CHROMEVOX_ROLE_LISTBOX">
+ List box
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'list box' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LISTBOX_BRL">
+ lstbx
+ </message>
+ <message desc="Describes an element with the ARIA role log." name="IDS_CHROMEVOX_ROLE_LOG">
+ Log
+ </message>
+ <message desc="This is an ARIA widget role name shown on a braille display. If the translation is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LOG_BRL">
+ log
+ </message>
+ <message desc="Describes an element with the ARIA role marquee." name="IDS_CHROMEVOX_ROLE_MARQUEE">
+ Marquee
+ </message>
+ <message desc="This is an ARIA widget role name shown on a braille display. When translating, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MARQUEE_BRL">
+ marquee
+ </message>
+ <message desc="Describes an element with the ARIA role menu." name="IDS_CHROMEVOX_ROLE_MENU">
+ Menu
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENU_BRL">
+ mnu
+ </message>
+ <message desc="Describes an element with the ARIA role menubar." name="IDS_CHROMEVOX_ROLE_MENUBAR">
+ Menu bar
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu bar' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENUBAR_BRL">
+ mnubr
+ </message>
+ <message desc="Describes an element with the ARIA role menuitem." name="IDS_CHROMEVOX_ROLE_MENUITEM">
+ Menu item
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu item' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENUITEM_BRL">
+ mnuitm
+ </message>
+ <message desc="Describes an element with the ARIA role menuitemcheckbox." name="IDS_CHROMEVOX_ROLE_MENUITEMCHECKBOX">
+ Menu item check box
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu item with checkbox' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENUITEMCHECKBOX_BRL">
+ chkmnuitm
+ </message>
+ <message desc="Describes an element with the ARIA role menuitemradio." name="IDS_CHROMEVOX_ROLE_MENUITEMRADIO">
+ Menu item radio button
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'menu item with radio button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_MENUITEMRADIO_BRL">
+ rdmnuitm
+ </message>
+ <message desc="Describes an element with the ARIA role button, with a pop-up." name="IDS_CHROMEVOX_ROLE_POPUP_BUTTON">
+ Pop-up button
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'pop up button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_POPUP_BUTTON_BRL">
+ popbtn
+ </message>
+ <message desc="Describes an element with the ARIA role progressbar." name="IDS_CHROMEVOX_ROLE_PROGRESSBAR">
+ Progress bar
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'progress bar' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_PROGRESSBAR_BRL">
+ pgbar
+ </message>
+ <message desc="Describes a progress indicator widget." name="IDS_CHROMEVOX_ROLE_PROGRESS_INDICATOR">
+ Progress indicator
+ </message>
+ <message desc="This is an abbreviated widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'progress indicator' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_PROGRESS_INDICATOR_BRL">
+ pgbar
+ </message>
+ <message desc="Describes an element with the ARIA role radio." name="IDS_CHROMEVOX_ROLE_RADIO">
+ Radio button
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'radio button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_RADIO_BRL">
+ rbtn
+ </message>
+ <message desc="Describes an element with the ARIA role radiogroup." name="IDS_CHROMEVOX_ROLE_RADIOGROUP">
+ Radio button group
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'radio button group' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_RADIOGROUP_BRL">
+ rdgrp
+ </message>
+ <message desc="Describes an element with the ARIA role scrollbar." name="IDS_CHROMEVOX_ROLE_SCROLLBAR">
+ Scroll bar
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'scroll bar' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_SCROLLBAR_BRL">
+ scbr
+ </message>
+ <message desc="Describes an element with the ARIA role slider." name="IDS_CHROMEVOX_ROLE_SLIDER">
+ Slider
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'slider' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_SLIDER_BRL">
+ sldr
+ </message>
+ <message desc="Describes an element with the ARIA role spinbutton." name="IDS_CHROMEVOX_ROLE_SPINBUTTON">
+ Spin button
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'spin button' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_SPINBUTTON_BRL">
+ spnbtn
+ </message>
+ <message desc="Describes an element with the ARIA role status." name="IDS_CHROMEVOX_ROLE_STATUS">
+ Status
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'status' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_STATUS_BRL">
+ sts
+ </message>
+ <message desc="Accessibility role description for suggestion, meaning a suggested change to some content" name="IDS_CHROMEVOX_ROLE_SUGGESTION">
+ Suggestion
+ </message>
+ <message desc="Describes an element with the ARIA role tab." meaning="UI element" name="IDS_CHROMEVOX_ROLE_TAB">
+ Tab
+ </message>
+ <message desc="This is an ARIA widget role name shown on a braille display. If the translation is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TAB_BRL">
+ tab
+ </message>
+ <message desc="Describes an element with the ARIA role table." name="IDS_CHROMEVOX_ROLE_TABLE">
+ Table
+ </message>
+ <message desc="This is an ARIA widget role name shown on a braille display. If the translation is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TABLE_BRL">
+ table
+ </message>
+ <message desc="Describes an element with the ARIA role tablist." name="IDS_CHROMEVOX_ROLE_TABLIST">
+ Tab list
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tab list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TABLIST_BRL">
+ tablst
+ </message>
+ <message desc="Describes an element with the ARIA role tabpanel." name="IDS_CHROMEVOX_ROLE_TABPANEL">
+ Tab panel
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tab panel' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TABPANEL_BRL">
+ tabpnl
+ </message>
+ <message desc="Describes an element with the ARIA role textbox." name="IDS_CHROMEVOX_ROLE_TEXTBOX">
+ Text box
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'editable' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TEXTBOX_BRL">
+ ed
+ </message>
+ <message desc="Describes an element with the ARIA role timer." name="IDS_CHROMEVOX_ROLE_TIMER">
+ Timer
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'timer' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TIMER_BRL">
+ tmr
+ </message>
+ <message desc="Describes an element with the ARIA role toolbar." name="IDS_CHROMEVOX_ROLE_TOOLBAR">
+ Tool bar
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tool bar' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TOOLBAR_BRL">
+ tlbar
+ </message>
+ <message desc="Describes an element with the ARIA role tooltip." name="IDS_CHROMEVOX_ROLE_TOOLTIP">
+ Tool tip
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tool tip' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TOOLTIP_BRL">
+ tltip
+ </message>
+ <message desc="Describes an element with the ARIA role tree. Note that the word tree is used metaphorically and refers to a user interface widget." name="IDS_CHROMEVOX_ROLE_TREE">
+ Tree
+ </message>
+ <message desc="This is an ARIA widget role name shown on a braille display. If the translation is longer than 5 characters, try to abbreviate it according to local conventions, and when doing so, if reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible. Note that the word tree is used metaphorically and refers to a user interface widget." name="IDS_CHROMEVOX_ROLE_TREE_BRL">
+ tree
+ </message>
+ <message desc="Describes an element with the ARIA role treeitem." name="IDS_CHROMEVOX_ROLE_TREEITEM">
+ Tree item
+ </message>
+ <message desc="This is an abbreviated ARIA widget role name shown on a braille display. When translating, try to find a contracted form of the translation for 'tree item' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_TREEITEM_BRL">
+ tritm
+ </message>
+ <message desc="Describes an element with the ARIA role article." name="IDS_CHROMEVOX_ROLE_ARTICLE">
+ Article
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_ARTICLE_BRL">
+ article
+ </message>
+ <message desc="Describes an element with the ARIA role application." name="IDS_CHROMEVOX_ROLE_APPLICATION">
+ Application
+ </message>
+ <message desc="This is an ARIA navigational landmark role name shown on a braille display. When translating, try to find a contracted form of the translation for 'application' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_APPLICATION_BRL">
+ app
+ </message>
+ <message desc="Describes an element with the ARIA role banner." name="IDS_CHROMEVOX_ROLE_BANNER">
+ Banner
+ </message>
+ <message desc="This is an ARIA navigational landmark role name shown on a braille display. When translating, try to find a contracted form of the translation for 'banner' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_BANNER_BRL">
+ bnr
+ </message>
+ <message desc="Describes an element with the ARIA role columnheader." name="IDS_CHROMEVOX_ROLE_COLUMNHEADER">
+ Column header
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'column header' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_COLUMNHEADER_BRL">
+ colhdr
+ </message>
+ <message desc="Describes an element with the ARIA role complementary." name="IDS_CHROMEVOX_ROLE_COMPLEMENTARY">
+ Complementary
+ </message>
+ <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_COMPLEMENTARY_BRL">
+ complementary
+ </message>
+ <message desc="Describes an element with the ARIA role contentinfo." name="IDS_CHROMEVOX_ROLE_CONTENTINFO">
+ Content info
+ </message>
+ <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, try to find a contracted form of the translation for 'content info' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_CONTENTINFO_BRL">
+ cntntinfo
+ </message>
+ <message desc="Describes an element with the ARIA role definition." name="IDS_CHROMEVOX_ROLE_DEFINITION">
+ Definition
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'definition' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DEFINITION_BRL">
+ def
+ </message>
+ <message desc="Describes an element with the ARIA role directory." name="IDS_CHROMEVOX_ROLE_DIRECTORY">
+ Directory
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'directory' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DIRECTORY_BRL">
+ dir
+ </message>
+ <message desc="Describes an element with the ARIA role document." name="IDS_CHROMEVOX_ROLE_DOCUMENT">
+ Document
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'document' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DOCUMENT_BRL">
+ doc
+ </message>
+ <message desc="Describes an element with the ARIA role form." name="IDS_CHROMEVOX_ROLE_FORM">
+ Form
+ </message>
+ <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_FORM_BRL">
+ form
+ </message>
+ <message desc="Describes an element with the ARIA role group." name="IDS_CHROMEVOX_ROLE_GROUP">
+ Group
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'group' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_GROUP_BRL">
+ grp
+ </message>
+ <message desc="Describes an element with the ARIA role heading." name="IDS_CHROMEVOX_ROLE_HEADING">
+ Heading
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'heading' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_HEADING_BRL">
+ hdng
+ </message>
+ <message desc="Describes an element with the ARIA role img." name="IDS_CHROMEVOX_ROLE_IMG">
+ Image
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'image' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_IMG_BRL">
+ img
+ </message>
+ <message desc="Describes an element with the ARIA role list." name="IDS_CHROMEVOX_ROLE_LIST">
+ List
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LIST_BRL">
+ lst
+ </message>
+ <message desc="Describes an element with the internal role of listGrid. This is similar to an ARIA grid." name="IDS_CHROMEVOX_ROLE_LIST_GRID">
+ List grid
+ </message>
+ <message desc="This is the name of an internal role shown on a braille display. When translating, try to find a contracted form of the translation for 'list grid' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LIST_GRID_BRL">
+ lstgrd
+ </message>
+ <message desc="Describes an element with the ARIA role listitem." name="IDS_CHROMEVOX_ROLE_LISTITEM">
+ List item
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'list item' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_LISTITEM_BRL">
+ lstitm
+ </message>
+ <message desc="Describes an element with the ARIA role main." name="IDS_CHROMEVOX_ROLE_MAIN">
+ Main
+ </message>
+ <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_MAIN_BRL">
+ main
+ </message>
+ <message desc="Describes an element with the ARIA role math." name="IDS_CHROMEVOX_ROLE_MATH">
+ Math
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_MATH_BRL">
+ math
+ </message>
+ <message desc="Describes an element with the ARIA role navigation." name="IDS_CHROMEVOX_ROLE_NAVIGATION">
+ Navigation
+ </message>
+ <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, try to find a contracted form of the translation for 'navigation' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_NAVIGATION_BRL">
+ nav
+ </message>
+ <message desc="Describes an element with the ARIA role note." name="IDS_CHROMEVOX_ROLE_NOTE">
+ Note
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_NOTE_BRL">
+ note
+ </message>
+ <message desc="Describes an element with the ARIA role region." name="IDS_CHROMEVOX_ROLE_REGION">
+ Region
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'region' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_REGION_BRL">
+ rgn
+ </message>
+ <message desc="Describes an element with the ARIA role rowheader." name="IDS_CHROMEVOX_ROLE_ROWHEADER">
+ Row header
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'row header' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_ROWHEADER_BRL">
+ rwhdr
+ </message>
+ <message desc="Describes an element with the ARIA role search." name="IDS_CHROMEVOX_ROLE_SEARCH">
+ Search
+ </message>
+ <message desc="This is the name of an ARIA navigational landmark role shown on a braille display. When translating, stick to lowercase letters, if applicable." name="IDS_CHROMEVOX_ROLE_SEARCH_BRL">
+ search
+ </message>
+ <message desc="Describes an element with the ARIA role separator." name="IDS_CHROMEVOX_ROLE_SEPARATOR">
+ Separator
+ </message>
+ <message desc="This is the name of an ARIA document structure role shown on a braille display. When translating, try to find a contracted form of the translation for 'separator' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_SEPARATOR_BRL">
+ seprtr
+ </message>
+ <message desc="Describes an element with the ARIA role meter." name="IDS_CHROMEVOX_ROLE_METER">
+ Meter
+ </message>
+ <message desc="This is the name of an ARIA meter role shown on a braille display. When translating, try to find a contracted form of the translation for meter according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_METER_BRL">
+ meter
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-autocomplete=inline." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_INLINE">
+ Autocompletion inline
+ </message>
+ <message desc="Shown on a braille display as a suffix to text fields and combo boxes when suggestions on how to complete the field are shown as text after the caret. When translating, try to find a contracted form of the translation for 'autocomplete inline' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_INLINE_BRL">
+ autoinl
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-autocomplete=list." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_LIST">
+ Autocompletion list
+ </message>
+ <message desc="Shown on a braille display as a suffix to text fields and combo boxes when suggestions on how to complete the field are shown in a list. When translating, try to find a contracted form of the translation for 'autocomplete list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_LIST_BRL">
+ autolst
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-autocomplete=both." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_BOTH">
+ Autocompletion inline and list
+ </message>
+ <message desc="Shown on a braille display as a suffix to text fields and combo boxes when suggestions on how to complete the field are shown in a list and the currently selected value is shown as text after the caret in the input field. When translating, try to find a contracted form of the translation for 'autocomplete inline and list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_AUTOCOMPLETE_BOTH_BRL">
+ autoinl+lst
+ </message>
+ <message desc="Describes an element that is checked." name="IDS_CHROMEVOX_CHECKED_TRUE">
+ Checked
+ </message>
+ <message desc="Describes an element that is unchecked." name="IDS_CHROMEVOX_CHECKED_FALSE">
+ Not checked
+ </message>
+ <message desc="Describes an element where the checked state is mixed or indeterminate." name="IDS_CHROMEVOX_CHECKED_MIXED">
+ Partially checked
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-disabled=true." name="IDS_CHROMEVOX_ARIA_DISABLED_TRUE">
+ Disabled
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-expanded=true." name="IDS_CHROMEVOX_ARIA_EXPANDED_TRUE">
+ Expanded
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-expanded=false." name="IDS_CHROMEVOX_ARIA_EXPANDED_FALSE">
+ Collapsed
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-invalid=true." name="IDS_CHROMEVOX_ARIA_INVALID_TRUE">
+ Invalid input
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-invalid=grammar." name="IDS_CHROMEVOX_ARIA_INVALID_GRAMMAR">
+ Grammatical mistake detected
+ </message>
+ <message desc="Shown on a braille display as a suffix to text fields that are marked as containing a grammatical mistake. When translating, stick to lowercase." name="IDS_CHROMEVOX_ARIA_INVALID_GRAMMAR_BRL">
+ grammatical mistake
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-invalid=spelling." name="IDS_CHROMEVOX_ARIA_INVALID_SPELLING">
+ Spelling mistake detected
+ </message>
+ <message desc="Shown on a braille display as a suffix to text fields that are marked as containing a misspelling. When translating, stick to lowercase." name="IDS_CHROMEVOX_ARIA_INVALID_SPELLING_BRL">
+ misspelled
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-multiline=true." name="IDS_CHROMEVOX_ARIA_MULTILINE_TRUE">
+ Multi line
+ </message>
+ <message desc="Shown on a braille display as a suffix to text fields that accept multiline input. When translating, try to find a contracted form of the translation for 'multiple lines' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_MULTILINE_TRUE_BRL">
+ multln
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-multiselectable=true." name="IDS_CHROMEVOX_ARIA_MULTISELECTABLE_TRUE">
+ Multi select
+ </message>
+ <message desc="Shown on a braille display for list boxes that allow more than one selected list item. When translating, try to find a contracted form of the translation for 'multiple selections' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_MULTISELECTABLE_TRUE_BRL">
+ multsel
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-pressed=true." name="IDS_CHROMEVOX_ARIA_PRESSED_TRUE">
+ Pressed
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-pressed=false." name="IDS_CHROMEVOX_ARIA_PRESSED_FALSE">
+ Not pressed
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-pressed=mixed." name="IDS_CHROMEVOX_ARIA_PRESSED_MIXED">
+ Partially pressed
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-readonly=true." name="IDS_CHROMEVOX_ARIA_READONLY_TRUE">
+ Read only
+ </message>
+ <message desc="Shown on a braille display for read-only controls. When translating, try to find a contracted form of the translation for 'read only' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_READONLY_TRUE_BRL">
+ rdonly
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-required=true." name="IDS_CHROMEVOX_ARIA_REQUIRED_TRUE">
+ Required
+ </message>
+ <message desc="Shown on a braille display for required fields. When translating, try to find a contracted form of the translation for 'required' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ARIA_REQUIRED_TRUE_BRL">
+ rq
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-selected=true." name="IDS_CHROMEVOX_ARIA_SELECTED_TRUE">
+ Selected
+ </message>
+ <message desc="Describes an element with the ARIA attribute aria-selected=false." name="IDS_CHROMEVOX_ARIA_SELECTED_FALSE">
+ Not selected
+ </message>
+ <message desc="Spoken to describe the visited state (e.g. for links)." name="IDS_CHROMEVOX_VISITED_STATE">
+ Visited
+ </message>
+ <message desc="Shown on a braille display for widget in the visited state (e.g. for links). When translating, try to find a contracted form of the translation for 'visited' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_VISITED_STATE_BRL">
+ vtd
+ </message>
+ <message desc="Spoken to describe a &lt;h1&gt; tag." name="IDS_CHROMEVOX_TAG_H1">
+ Heading 1
+ </message>
+ <message desc="Shown on a braille display to describe a heading on level 1 in a document. When translating, try to find a contracted form of the translation for 'heading 1' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H1_BRL">
+ h1
+ </message>
+ <message desc="Spoken to describe a &lt;h2&gt; tag." name="IDS_CHROMEVOX_TAG_H2">
+ Heading 2
+ </message>
+ <message desc="Shown on a braille display to describe a heading on level 2 in a document. When translating, try to find a contracted form of the translation for 'heading 2' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H2_BRL">
+ h2
+ </message>
+ <message desc="Spoken to describe a &lt;h3&gt; tag." name="IDS_CHROMEVOX_TAG_H3">
+ Heading 3
+ </message>
+ <message desc="Shown on a braille display to describe a heading on level 3 in a document. When translating, try to find a contracted form of the translation for 'heading 3' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H3_BRL">
+ h3
+ </message>
+ <message desc="Spoken to describe a &lt;h4&gt; tag." name="IDS_CHROMEVOX_TAG_H4">
+ Heading 4
+ </message>
+ <message desc="Shown on a braille display to describe a heading on level 4 in a document. When translating, try to find a contracted form of the translation for 'heading 4' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H4_BRL">
+ h4
+ </message>
+ <message desc="Spoken to describe a &lt;h5&gt; tag." name="IDS_CHROMEVOX_TAG_H5">
+ Heading 5
+ </message>
+ <message desc="Shown on a braille display to describe a heading on level 5 in a document. When translating, try to find a contracted form of the translation for 'heading 5' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H5_BRL">
+ h5
+ </message>
+ <message desc="Spoken to describe a &lt;h6&gt; tag." name="IDS_CHROMEVOX_TAG_H6">
+ Heading 6
+ </message>
+ <message desc="Shown on a braille display to describe a heading on level 6 in a document. When translating, try to find a contracted form of the translation for 'heading 6' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_TAG_H6_BRL">
+ h6
+ </message>
+ <message desc="Spoken to describe a &lt;li&gt; tag." name="IDS_CHROMEVOX_TAG_LI">
+ List item
+ </message>
+ <message desc="Brailled to describe a &lt;li&gt; tag." name="IDS_CHROMEVOX_TAG_LI_BRL">
+ lstitm
+ </message>
+ <message desc="Spoken to describe a &lt;ol&gt; tag." name="IDS_CHROMEVOX_TAG_OL">
+ Ordered List
+ </message>
+ <message desc="Brailled to describe a &lt;ol&gt; tag." name="IDS_CHROMEVOX_TAG_OL_BRL">
+ lst
+ </message>
+ <message desc="Spoken to describe a &lt;select&gt; tag." name="IDS_CHROMEVOX_TAG_SELECT">
+ Combo box
+ </message>
+ <message desc="Brailled to describe a &lt;select&gt; tag." name="IDS_CHROMEVOX_TAG_SELECT_BRL">
+ cbo
+ </message>
+ <message desc="Spoken to describe a &lt;textarea&gt; tag." name="IDS_CHROMEVOX_TAG_TEXTAREA">
+ Text area
+ </message>
+ <message desc="Brailled to describe a &lt;textarea&gt; tag." name="IDS_CHROMEVOX_TAG_TEXTAREA_BRL">
+ mled
+ </message>
+ <message desc="Spoken to describe a &lt;table&gt; tag." name="IDS_CHROMEVOX_TAG_TABLE">
+ table
+ </message>
+ <message desc="Brailled to describe a &lt;table&gt; tag." name="IDS_CHROMEVOX_TAG_TABLE_BRL">
+ tbl
+ </message>
+ <message desc="Spoken to describe a &lt;ul&gt; tag." name="IDS_CHROMEVOX_TAG_UL">
+ List
+ </message>
+ <message desc="Brailled to describe a &lt;ul&gt; tag." name="IDS_CHROMEVOX_TAG_UL_BRL">
+ lst
+ </message>
+ <message desc="Spoken to describe a &lt;section&gt; tag." name="IDS_CHROMEVOX_TAG_SECTION">
+ Section
+ </message>
+ <message desc="Brailled to describe a &lt;section&gt; tag." name="IDS_CHROMEVOX_TAG_SECTION_BRL">
+ sctn
+ </message>
+ <message desc="Spoken to describe a &lt;nav&gt; tag." name="IDS_CHROMEVOX_TAG_NAV">
+ Navigation
+ </message>
+ <message desc="Brailled to describe a &lt;nav&gt; tag." name="IDS_CHROMEVOX_TAG_NAV_BRL">
+ nav
+ </message>
+ <message desc="Spoken to describe a &lt;article&gt; tag." name="IDS_CHROMEVOX_TAG_ARTICLE">
+ Article
+ </message>
+ <message desc="Brailled to describe a &lt;article&gt; tag." name="IDS_CHROMEVOX_TAG_ARTICLE_BRL">
+ article
+ </message>
+ <message desc="Spoken to describe a &lt;aside&gt; tag." name="IDS_CHROMEVOX_TAG_ASIDE">
+ Aside
+ </message>
+ <message desc="Brailled to describe a &lt;aside&gt; tag." name="IDS_CHROMEVOX_TAG_ASIDE_BRL">
+ aside
+ </message>
+ <message desc="Spoken to describe a &lt;hgroup&gt; tag." name="IDS_CHROMEVOX_TAG_HGROUP">
+ Heading group
+ </message>
+ <message desc="Brailled to describe a &lt;hgroup&gt; tag." name="IDS_CHROMEVOX_TAG_HGROUP_BRL">
+ hdnggrp
+ </message>
+ <message desc="Spoken to describe a &lt;header&gt; tag." name="IDS_CHROMEVOX_TAG_HEADER">
+ Header
+ </message>
+ <message desc="Brailled to describe a &lt;header&gt; tag." name="IDS_CHROMEVOX_TAG_HEADER_BRL">
+ hdr
+ </message>
+ <message desc="Spoken to describe a &lt;footer&gt; tag." name="IDS_CHROMEVOX_TAG_FOOTER">
+ Footer
+ </message>
+ <message desc="Brailled to describe a &lt;footer&gt; tag." name="IDS_CHROMEVOX_TAG_FOOTER_BRL">
+ ftr
+ </message>
+ <message desc="Spoken to describe a &lt;time&gt; tag." name="IDS_CHROMEVOX_TAG_TIME">
+ Time
+ </message>
+ <message desc="Spoken to describe a &lt;mark&gt; tag." name="IDS_CHROMEVOX_TAG_MARK">
+ Mark
+ </message>
+ <message desc="Brailled to describe a &lt;mark&gt; tag." name="IDS_CHROMEVOX_TAG_MARK_BRL">
+ mark
+ </message>
+ <message desc="Spoken to describe a &lt;video&gt; tag." name="IDS_CHROMEVOX_TAG_VIDEO">
+ Video
+ </message>
+ <message desc="Brailled to describe a &lt;video&gt; tag." name="IDS_CHROMEVOX_TAG_VIDEO_BRL">
+ video
+ </message>
+ <message desc="Spoken to describe a &lt;audio&gt; tag." name="IDS_CHROMEVOX_TAG_AUDIO">
+ Audio
+ </message>
+ <message desc="Brailled to describe a &lt;audio&gt; tag." name="IDS_CHROMEVOX_TAG_AUDIO_BRL">
+ audio
+ </message>
+ <message desc="Describes an &lt;input&gt; element with type=time." name="IDS_CHROMEVOX_INPUT_TYPE_TIME">
+ Time control
+ </message>
+ <message desc="Brailles an &lt;input&gt; element with type=datetime." name="IDS_CHROMEVOX_INPUT_TYPE_TIME_BRL">
+ time
+ </message>
+ <message desc="Describes an &lt;input&gt; element with type=date." name="IDS_CHROMEVOX_INPUT_TYPE_DATE">
+ Date control
+ </message>
+ <message desc="Brailles an &lt;input&gt; element with type=date." name="IDS_CHROMEVOX_INPUT_TYPE_DATE_BRL">
+ date
+ </message>
+ <message desc="Describes an &lt;input&gt; element with type=email." name="IDS_CHROMEVOX_INPUT_TYPE_EMAIL">
+ Edit text, email entry
+ </message>
+ <message desc="Shown on a braille display for a text field that accept an email address as input. When translating, keep the @ sign and try to find an abbreviation for 'edit field 8 dot' according to local conventions; 8 dot refers to the braille table chosen by the user that includes 8 dots in a braille cell appropriate for writing computer symbols. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_EMAIL_BRL">
+ @ed 8dot
+ </message>
+ <message desc="Describes an &lt;input&gt; element with type=number." name="IDS_CHROMEVOX_INPUT_TYPE_NUMBER">
+ Edit text numeric only
+ </message>
+ <message desc="Shown on a braille display for a text field that accept numeric input only. When translating, keep the # sign, if it can be used to represent numbers in the target language and try to find an abbreviation for 'edit field'. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_NUMBER_BRL">
+ #ed
+ </message>
+ <message desc="Describes an &lt;input&gt; element with type=password." name="IDS_CHROMEVOX_INPUT_TYPE_PASSWORD">
+ Password edit text
+ </message>
+ <message desc="Shown on a braille display for a password text field. When translating, try to find a contracted form of the translation of 'password edit' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_PASSWORD_BRL">
+ pwded
+ </message>
+ <message desc="Describes an &lt;input&gt; element with type=search." name="IDS_CHROMEVOX_INPUT_TYPE_SEARCH">
+ Edit text, search entry
+ </message>
+ <message desc="Shown on a braille display for an input field of type search. When translating, try to find a contracted form of the translation for 'search edit field' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_SEARCH_BRL">
+ srched
+ </message>
+ <message desc="Describes an &lt;input&gt; element with type=text." name="IDS_CHROMEVOX_INPUT_TYPE_TEXT">
+ Edit text
+ </message>
+ <message desc="Shown on a braille display to describe a text field. When translating, try to find a contracted form of the translation for 'edit field' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_TEXT_BRL">
+ ed
+ </message>
+ <message desc="Describes an &lt;input&gt; element with type=url." name="IDS_CHROMEVOX_INPUT_TYPE_URL">
+ Edit text, URL entry
+ </message>
+ <message desc="Shown on a braille display to describe a text field for entering a URL. When translating, try to find a contracted form of the translation for 'url edit field 8 dot' according to local conventions; 8 dot refers to the braille table chosen by the user that includes 8 dots in a braille cell appropriate for writing computer symbols. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INPUT_TYPE_URL_BRL">
+ urled 8dot
+ </message>
+ <message desc="Spoken to describe a &lt;a&gt; tag with a link to an internal anchor." name="IDS_CHROMEVOX_INTERNAL_LINK">
+ Internal link
+ </message>
+ <message desc="Shown on a braille display to describe a link to a different part of the same web page. When translating, try to find a contracted form of the translation for 'internal link' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_INTERNAL_LINK_BRL">
+ intlnk
+ </message>
+ <message desc="In an editable text box, describes a blank line." name="IDS_CHROMEVOX_TEXT_BOX_BLANK">
+ Blank
+ </message>
+ <message desc="In an editable text box, describes a line with only whitespace." meaning="UI element" name="IDS_CHROMEVOX_TEXT_BOX_WHITESPACE">
+ Space
+ </message>
+ <message desc="Further describes a list-like element with a number of items. e.g. This will be combined with other messages to produce: List with 3 items." name="IDS_CHROMEVOX_LIST_WITH_ITEMS">
+ {COUNT, plural, =1{with # item} other{with # items}}
+ </message>
+ <!-- TODO(crbug.com/999781): This should not need ICU msg format. Fix where the message is used. --> <message desc="Further describes a list-like element with a number of items in braille." name="IDS_CHROMEVOX_LIST_WITH_ITEMS_BRL">
+ {COUNT, plural, =1{+#} other{+#}}
+ </message>
+ <message desc="Phrase indicating a menu item has a submenu." name="IDS_CHROMEVOX_HAS_SUBMENU">
+ with submenu
+ </message>
+ <message desc="Describes a collection of tags. e.g. A 'link collection'." name="IDS_CHROMEVOX_COLLECTION">
+ <ph name="tag">$1</ph> collection with <ph name="num">$2</ph> items
+ </message>
+ <message desc="The indicator of a pause to tts." name="IDS_CHROMEVOX_PAUSE">
+ , '''
+ </message>
+ <message desc="A message spoken when the user switches to the table granularity, which allows users to navigate within a group." name="IDS_CHROMEVOX_TABLE_STRATEGY">
+ Table
+ </message>
+ <message desc="Describes rows within tables on the web." name="IDS_CHROMEVOX_ROLE_ROW">
+ Row
+ </message>
+ <message desc="Describes columns within tables on the web." name="IDS_CHROMEVOX_ROLE_COLUMN">
+ Column
+ </message>
+ <message desc="Describes rows within tables on the web." name="IDS_CHROMEVOX_ROLE_ROW_BRL">
+ row
+ </message>
+ <message desc="Describes columns within tables on the web." name="IDS_CHROMEVOX_ROLE_COLUMN_BRL">
+ col
+ </message>
+ <message desc="A message spoken when the user switches to the line granularity, which allows users to navigate the page one line at a time." name="IDS_CHROMEVOX_LINE_GRANULARITY">
+ Line
+ </message>
+ <message desc="A message spoken when the user switches to the word granularity, which allows users to navigate the page one word at a time." name="IDS_CHROMEVOX_WORD_GRANULARITY">
+ Word
+ </message>
+ <message desc="A message spoken when the user switches to the character granularity, which allows users to navigate the page one character at a time." name="IDS_CHROMEVOX_CHARACTER_GRANULARITY">
+ Character
+ </message>
+ <message desc="Spoken when the search widget first shows." name="IDS_CHROMEVOX_SEARCH_WIDGET_INTRO">
+ Find in page
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_MODIFIER_KEYS">
+ Modifier Keys
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_NAVIGATION">
+ ChromeVox Navigation
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_INFORMATION">
+ Information
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_HELP_COMMANDS">
+ Help Commands
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_CONTROLLING_SPEECH">
+ Controlling Speech
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_OVERVIEW">
+ Overview
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_TABLES">
+ Tables
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_JUMP_COMMANDS">
+ Jump Commands
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_BRAILLE">
+ Braille
+ </message>
+ <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_DEVELOPER">
+ Developer
+ </message>
+ <message desc="Description of the TTS console logging command. Displayed in the options page." name="IDS_CHROMEVOX_ENABLE_TTS_LOG">
+ Enable TTS logging
+ </message>
+ <message desc="Spoken when a user ends a selection on a webpage." name="IDS_CHROMEVOX_END_SELECTION">
+ End selection
+ </message>
+ <message desc="Describes the toggle selection command. Displayed in the options page." name="IDS_CHROMEVOX_TOGGLE_SELECTION">
+ Start or end selection
+ </message>
+ <message desc="Spoken when the browser's copy command is invoked." name="IDS_CHROMEVOX_COPY">
+ copy <ph name="TEXT">$1</ph>.
+ </message>
+ <message desc="Spoken when the browser's cut command is invoked." name="IDS_CHROMEVOX_CUT">
+ cut <ph name="TEXT">$1</ph>.
+ </message>
+ <message desc="Spoken when the browser's paste command is invoked." name="IDS_CHROMEVOX_PASTE">
+ paste <ph name="TEXT">$1</ph>.
+ </message>
+ <message desc="Spoken when additional characters are selected in editable text." name="IDS_CHROMEVOX_SELECTED">
+ selected
+ </message>
+ <message desc="Spoken in editable text when text is unselected." name="IDS_CHROMEVOX_UNSELECTED">
+ unselected
+ </message>
+ <message desc="Spoken when more than one character gets added to selection in editable text." name="IDS_CHROMEVOX_ADDED_TO_SELECTION">
+ added to selection
+ </message>
+ <message desc="Spoken when more than one character gets removed from selection in editable text." name="IDS_CHROMEVOX_REMOVED_FROM_SELECTION">
+ removed from selection
+ </message>
+ <message desc="Spoken as the conjunction between hotkey combinations like ctrl then alt followed by a." name="IDS_CHROMEVOX_THEN">
+ then
+ </message>
+ <message desc="Spoken to describe the ChromeVox modifier keys when describing a key combination." name="IDS_CHROMEVOX_MODIFIER_KEY">
+ ChromeVox modifier
+ </message>
+ <message desc="Spoken to describe the current selection is a Math object." name="IDS_CHROMEVOX_MATH_EXPR">
+ Math
+ </message>
+ <message desc="Brailled phrase indicating the current selection is a Math object. When translating, stick to lowercase." name="IDS_CHROMEVOX_MATH_EXPR_BRL">
+ math
+ </message>
+ <message desc="Describes an element with the ARIA role math." name="IDS_CHROMEVOX_NOT_INSIDE_MATH">
+ Not inside math
+ </message>
+ <message desc="Spoken when a user switches to a mode announcing no punctuation." name="IDS_CHROMEVOX_NO_PUNCTUATION">
+ No punctuation
+ </message>
+ <message desc="Spoken when a user switches to a mode announcing some punctuation." name="IDS_CHROMEVOX_SOME_PUNCTUATION">
+ Some punctuation
+ </message>
+ <message desc="Spoken when a user switches to a mode announcing all punctuation." name="IDS_CHROMEVOX_ALL_PUNCTUATION">
+ All punctuation
+ </message>
+ <message desc="Spoken to describe a clickable element." name="IDS_CHROMEVOX_CLICKABLE">
+ clickable
+ </message>
+ <message desc="Brailled to describe a clickable element." name="IDS_CHROMEVOX_CLICKABLE_BRL">
+ clk
+ </message>
+ <message desc="The description of the previous character command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_CHARACTER">
+ Previous Character
+ </message>
+ <message desc="The description of the next character command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_CHARACTER">
+ Next Character
+ </message>
+ <message desc="The description of the previous word command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_WORD">
+ Previous Word
+ </message>
+ <message desc="The description of the next word command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_WORD">
+ Next Word
+ </message>
+ <message desc="The description of the previous sentence command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_SENTENCE">
+ Previous Sentence
+ </message>
+ <message desc="The description of the next sentence command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_SENTENCE">
+ Next Sentence
+ </message>
+ <message desc="The description of the previous line command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_LINE">
+ Previous Line
+ </message>
+ <message desc="The description of the next line command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_LINE">
+ Next Line
+ </message>
+ <message desc="The description of the previous object command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_OBJECT">
+ Previous Object
+ </message>
+ <message desc="The description of the next object command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_OBJECT">
+ Next Object
+ </message>
+ <message desc="The description of the previous group command. Displayed in the Options page." name="IDS_CHROMEVOX_PREVIOUS_GROUP">
+ Previous Group
+ </message>
+ <message desc="The description of the next group command. Displayed in the Options page." name="IDS_CHROMEVOX_NEXT_GROUP">
+ Next Group
+ </message>
+ <message desc="The description of the previous similar command." name="IDS_CHROMEVOX_PREVIOUS_SIMILAR_ITEM">
+ Previous similar item
+ </message>
+ <message desc="The description of the next similar item command." name="IDS_CHROMEVOX_NEXT_SIMILAR_ITEM">
+ Next similar item
+ </message>
+ <message desc="Describes nodes or anything describing them as a landmark." name="IDS_CHROMEVOX_ROLE_LANDMARK">
+ Landmark
+ </message>
+ <message desc="Describes a button that can be pressed/toggled." name="IDS_CHROMEVOX_ROLE_TOGGLE_BUTTON">
+ Toggle Button
+ </message>
+ <message desc="Brailles a button that can be pressed/toggled." name="IDS_CHROMEVOX_ROLE_TOGGLE_BUTTON_BRL">
+ tgl btn
+ </message>
+ <message desc="The description of the key to move to the beginning of the page. Displayed in the Options page." name="IDS_CHROMEVOX_JUMP_TO_TOP">
+ Jump to the top of the page
+ </message>
+ <message desc="The description of the key to move to the end of the page. Displayed in the Options page." name="IDS_CHROMEVOX_JUMP_TO_BOTTOM">
+ Jump to the bottom of the page
+ </message>
+ <message desc="Description of the cycle punctuation echo key. Shown in options page." name="IDS_CHROMEVOX_CYCLE_PUNCTUATION_ECHO">
+ Cycle punctuation echo
+ </message>
+ <message desc="Description of the cycle typing echo key. Shown in options page." name="IDS_CHROMEVOX_CYCLE_TYPING_ECHO">
+ Cycle typing echo
+ </message>
+ <message desc="The description of the pauseAllMedia key. Shown in options page." name="IDS_CHROMEVOX_PAUSE_ALL_MEDIA">
+ Pauses all currently playing media widgets
+ </message>
+ <message desc="The description of the openLongDesc key. Shown in options page." name="IDS_CHROMEVOX_OPEN_LONG_DESC">
+ Open long description in a new tab
+ </message>
+ <message desc="Spoken to describe character echo (a setting to speak characters while typing into editable text fields)." name="IDS_CHROMEVOX_CHARACTER_ECHO">
+ character echo
+ </message>
+ <message desc="Spoken to describe word echo (a setting to speak words while typing into editable text fields)." name="IDS_CHROMEVOX_WORD_ECHO">
+ word echo
+ </message>
+ <message desc="Spoken to describe character and word echo (a setting to speak characters and words while typing into editable text fields)." name="IDS_CHROMEVOX_CHARACTER_AND_WORD_ECHO">
+ character and word echo
+ </message>
+ <message desc="Spoken to describe no echo (a setting to not speak characters or words while typing into editable text fields)." name="IDS_CHROMEVOX_NONE_ECHO">
+ no typing echo
+ </message>
+ <message desc="Describes the enter content command in the options page. Content refers to any special structure on the page such as tables or math." name="IDS_CHROMEVOX_ENTER_CONTENT">
+ enter structured content, such as tables
+ </message>
+ <message desc="Describes the exit content command in the options page. Content refers to any special structure on the page such as tables or math." name="IDS_CHROMEVOX_EXIT_CONTENT">
+ exit structured content, such as tables
+ </message>
+ <message desc="Displayed to describes the key that toggles semantic interpretation of mathematical formulas." name="IDS_CHROMEVOX_TOGGLE_SEMANTICS">
+ Toggle interpretation of math expressions between structural and semantic
+ </message>
+ <message desc="Used as a phonetic word hint for a particular letter. The word is used to clarify similarly sounding letters like m and n. This mapping is taken directly from the NATO phonetic standard: https://en.wikipedia.org/wiki/NATO_phonetic_alphabet Please retain the structure of this string. The structure is of the form {&quot;letter&quot;: &quot;phonetic word equivalent&quot;, ..., &quot;letter&quot;: &quot;phonetic word equivalent&quot;}. The first part of the mapping (letter) should be all letters of the localization in lower case. The second part (phonetic word equivalent) should be the word that describes the letter." name="IDS_CHROMEVOX_PHONETIC_MAP">
+ {"a": "alpha", "b": "bravo", "c": "charlie", "d": "delta", "e": "echo", "f": "foxtrot", "g": "golf", "h": "hotel", "i": "india", "j": "juliet","k": "kilo", "l": "lima", "m": "mike", "n": "november", "o": "oscar","p": "papa", "q": "quebec", "r": "romeo", "s": "sierra", "t": "tango", "u": "uniform", "v": "victor", "w": "whiskey","x": "xray", "y": "yankee", "z": "zulu"}
+ </message>
+ <message desc="Spoken when the browser first starts and ChromeVox is active." name="IDS_CHROMEVOX_CHROMEVOX_INTRO">
+ ChromeVox spoken feedback is ready
+ </message>
+ <message desc="Brailled when ChromeVox is connected to a braille display." name="IDS_CHROMEVOX_INTRO_BRL">
+ ChromeVox ready
+ </message>
+ <message desc="Spoken when earcons are on." name="IDS_CHROMEVOX_EARCONS_ON">
+ Earcons on
+ </message>
+ <message desc="Spoken when earcons are off." name="IDS_CHROMEVOX_EARCONS_OFF">
+ Earcons off
+ </message>
+ <message desc="Description of the toggle earcons key. Shown in options page." name="IDS_CHROMEVOX_TOGGLE_EARCONS">
+ Turn sound feedback (earcons) on or off
+ </message>
+ <message desc="Description of the speak time and date key. Shown in options page." name="IDS_CHROMEVOX_SPEAK_TIME_AND_DATE">
+ Speak the current time and date
+ </message>
+ <message desc="Abbreviation indicating following text is an incremental search result. For example, in English, the abbreviation might be 'S:' for 'Search'." name="IDS_CHROMEVOX_MARK_AS_SEARCH_RESULT_BRL">
+ S:<ph name="result">$1</ph>
+ </message>
+ <message desc="Announced when text within an editable text field gets deleted." name="IDS_CHROMEVOX_TEXT_DELETED">
+ Deleted
+ </message>
+ <message desc="Describes the perform default action command. This is usually triggered by hitting the enter key over a control. Shown in options page." name="IDS_CHROMEVOX_PERFORM_DEFAULT_ACTION">
+ Perform default action
+ </message>
+ <message desc="Exclamation (!) character description." name="IDS_CHROMEVOX_EXCLAMATION">
+ {COUNT, plural, =1 {exclamation}other {# exclamations}}
+ </message>
+ <message desc="Space ( ) character description." name="IDS_CHROMEVOX_SPACE">
+ {COUNT, plural, =1 {space}other {# spaces}}
+ </message>
+ <message desc="Backtcik (`) character description." name="IDS_CHROMEVOX_BACKTICK">
+ {COUNT, plural, =1 {backtick}other {# backticks}}
+ </message>
+ <message desc="Tilde (~) character description." name="IDS_CHROMEVOX_TILDE">
+ {COUNT, plural, =1 {TILDE}other {# tildes}}
+ </message>
+ <message desc="At (@) character description." name="IDS_CHROMEVOX_AT">
+ {COUNT, plural, =1 {at}other {# at signs}}
+ </message>
+ <message desc="Pound (#) character description." name="IDS_CHROMEVOX_POUND">
+ {COUNT, plural, =1 {pound}other {# pound signs}}
+ </message>
+ <message desc="Dollar ($) character description." name="IDS_CHROMEVOX_DOLLAR">
+ {COUNT, plural, =1 {dollar}other {# dollar signs}}
+ </message>
+ <message desc="Percent (%) character description." name="IDS_CHROMEVOX_PERCENT">
+ {COUNT, plural, =1 {percent}other {# percent signs}}
+ </message>
+ <message desc="Caret (^) character description." name="IDS_CHROMEVOX_CARET">
+ {COUNT, plural, =1 {caret}other {# carets}}
+ </message>
+ <message desc="Ampersand (&amp;) character description." name="IDS_CHROMEVOX_AMPERSAND">
+ {COUNT, plural, =1 {ampersand}other {# ampersands}}
+ </message>
+ <message desc="Asterisk (*) character description." name="IDS_CHROMEVOX_ASTERISK">
+ {COUNT, plural, =1 {asterisk}other {# asterisks}}
+ </message>
+ <message desc="Left parenthesis (() character description." name="IDS_CHROMEVOX_OPEN_PAREN">
+ {COUNT, plural, =1 {open paren}other {# open parens}}
+ </message>
+ <message desc="Right parenthesis ()) character description." name="IDS_CHROMEVOX_CLOSE_PAREN">
+ {COUNT, plural, =1 {close paren}other {# close parens}}
+ </message>
+ <message desc="Dash (-) character description." name="IDS_CHROMEVOX_DASH">
+ {COUNT, plural, =1 {dash}other {# dashes}}
+ </message>
+ <message desc="Underscore (_) character description." name="IDS_CHROMEVOX_UNDERSCORE">
+ {COUNT, plural, =1 {underscore}other {# underscores}}
+ </message>
+ <message desc="Equals (=) character description." name="IDS_CHROMEVOX_EQUALS">
+ {COUNT, plural, =1 {equal}other {# equal signs}}
+ </message>
+ <message desc="Plus (+) character description." name="IDS_CHROMEVOX_PLUS">
+ {COUNT, plural, =1 {plus}other {# plus signs}}
+ </message>
+ <message desc="Left bracket ([) character description." name="IDS_CHROMEVOX_LEFT_BRACKET">
+ {COUNT, plural, =1 {left bracket}other {# left brackets}}
+ </message>
+ <message desc="Right bracket (]) character description." name="IDS_CHROMEVOX_RIGHT_BRACKET">
+ {COUNT, plural, =1 {right bracket}other {# right brackets}}
+ </message>
+ <message desc="Left brace ({) character description." name="IDS_CHROMEVOX_LEFT_BRACE">
+ {COUNT, plural, =1 {left brace}other {# left braces}}
+ </message>
+ <message desc="Right brace (}) character description." name="IDS_CHROMEVOX_RIGHT_BRACE">
+ {COUNT, plural, =1 {right brace}other {# right braces}}
+ </message>
+ <message desc="Pipe (|) character description." name="IDS_CHROMEVOX_PIPE">
+ {COUNT, plural, =1 {pipe}other {# vertical pipes}}
+ </message>
+ <message desc="Semicolon (;) character description." name="IDS_CHROMEVOX_SEMICOLON">
+ {COUNT, plural, =1 {semicolon}other {# semicolons}}
+ </message>
+ <message desc="Colon (:) character description." name="IDS_CHROMEVOX_COLON">
+ {COUNT, plural, =1 {colon}other {# colons}}
+ </message>
+ <message desc="Comma (,) character description." name="IDS_CHROMEVOX_COMMA">
+ {COUNT, plural, =1 {comma}other {# commas}}
+ </message>
+ <message desc="Dot (.) character description." name="IDS_CHROMEVOX_DOT">
+ {COUNT, plural, =1 {dot}=3 {ellipsis}other {# dots}}
+ </message>
+ <message desc="Less than (&lt;) character description." name="IDS_CHROMEVOX_LESS_THAN">
+ {COUNT, plural, =1 {less than}other {# less than signs}}
+ </message>
+ <message desc="Greater than (&gt;) character description." name="IDS_CHROMEVOX_GREATER_THAN">
+ {COUNT, plural, =1 {greater than}other {# greater than signs}}
+ </message>
+ <message desc="Slash (/) character description." name="IDS_CHROMEVOX_SLASH">
+ {COUNT, plural, =1 {slash}other {# slashes}}
+ </message>
+ <message desc="Question mark (?) character description." name="IDS_CHROMEVOX_QUESTION_MARK">
+ {COUNT, plural, =1 {question mark}other {# question marks}}
+ </message>
+ <message desc="Quote (&quot;) character description." name="IDS_CHROMEVOX_QUOTE">
+ {COUNT, plural, =1 {quote}other {# quotes}}
+ </message>
+ <message desc="Apostrophe (') character description." name="IDS_CHROMEVOX_APOSTROPHE">
+ {COUNT, plural, =1 {apostrophe}other {# apostrophes}}
+ </message>
+ <message desc="Tab (\t) character description." name="IDS_CHROMEVOX_TAB">
+ {COUNT, plural, =1 {tab}other {# tabs}}
+ </message>
+ <message desc="Backslash (\) character description." name="IDS_CHROMEVOX_BACKSLASH">
+ {COUNT, plural, =1 {backslash}other {# backslashes}}
+ </message>
+ <message desc="BULLET (•) character description." name="IDS_CHROMEVOX_BULLET">
+ {COUNT, plural, =1 {bullet}other {# bullets}}
+ </message>
+ <message desc="Describes the braille click command. Displayed in the options page." name="IDS_CHROMEVOX_BRAILLE_ROUTING">
+ Click the item under routing key <ph name="ROUTING_KEY_NUMBER">$1</ph>
+ </message>
+ <message desc="Describes the braille pan backward command. Displayed in the options page." name="IDS_CHROMEVOX_BRAILLE_PAN_LEFT">
+ Pan backward
+ </message>
+ <message desc="Describes the braille pan forward command. Displayed in the options page." name="IDS_CHROMEVOX_BRAILLE_PAN_RIGHT">
+ Pan forward
+ </message>
+ <message desc="The description of the braille previous line command. Displayed in the Options page." name="IDS_CHROMEVOX_BRAILLE_LINE_UP">
+ Braille previous Line
+ </message>
+ <message desc="The description of the braille next line command. Displayed in the Options page." name="IDS_CHROMEVOX_BRAILLE_LINE_DOWN">
+ Braille next Line
+ </message>
+ <message desc="The description of the braille top command. Displayed in the Options page." name="IDS_CHROMEVOX_BRAILLE_TOP">
+ Move braille display to top of page
+ </message>
+ <message desc="The description of the braille bottom command. Displayed in the Options page." name="IDS_CHROMEVOX_BRAILLE_BOTTOM">
+ Move braille display to bottom of page
+ </message>
+ <message desc="Describes a single physical braille dot on a refreshable braille display. Will usually be followed with numbers to describe the layout of a braille cell. For example, dot 8" name="IDS_CHROMEVOX_BRAILLE_DOT">
+ dot <ph name="dot">$1</ph>
+ </message>
+ <message desc="Describes multiple physical braille dots on a refreshable braille display. Will usually be followed with numbers to describe the layout of a braille cell. For example, dots 1 2 3 4 8" name="IDS_CHROMEVOX_BRAILLE_DOTS">
+ dots <ph name="dot">$1</ph>
+ </message>
+ <message desc="Describes dots on a refreshable braille display pressed with the space key. For example, dots 1 2 3 4 8 chord" name="IDS_CHROMEVOX_BRAILLE_CHORD">
+ <ph name="dot">$1</ph> chord
+ </message>
+ <message desc="The description of the command that allows the user to view a graphic as a dot pattern on a refreshable braille display." name="IDS_CHROMEVOX_VIEW_GRAPHIC_AS_BRAILLE">
+ View Graphic As Braille
+ </message>
+ <message desc="Spoken to describe an access key. An access key consists of a single letter. When pressed along with a modifier (usually alt, but depends on platform), a targetted node will be activated." name="IDS_CHROMEVOX_ACCESS_KEY">
+ has access key, <ph name="key">$1</ph>
+ </message>
+ <message desc="Brailled to describe an access key. An access key consists of a single letter. When pressed along with a modifier (usually alt, but depends on platform), a targetted node will be activated. When translating, stick to lower case." name="IDS_CHROMEVOX_ACCESS_KEY_BRL">
+ access key:<ph name="key">$1</ph>
+ </message>
+ <message desc="The text to speak when the user moves their cursor to the end of a block of editable text, in verbose mode." name="IDS_CHROMEVOX_END_OF_TEXT_VERBOSE">
+ End of text
+ </message>
+ <message desc="The text to speak when the user moves their cursor to the end of a block of editable text, in brief mode." name="IDS_CHROMEVOX_END_OF_TEXT_BRIEF">
+ End
+ </message>
+ <message desc="Spoken to describe a new line ('\n')." name="IDS_CHROMEVOX_NEW_LINE">
+ new line
+ </message>
+ <message desc="Spoken to describe a carriage return ('\r')." name="IDS_CHROMEVOX_RETURN">
+ return
+ </message>
+ <message desc="Spoken after pressing the pass through key command." name="IDS_CHROMEVOX_PASS_THROUGH_KEY">
+ Ignoring next key press
+ </message>
+ <message desc="Describes the pass through key command. Shown in options page." name="IDS_CHROMEVOX_PASS_THROUGH_KEY_DESCRIPTION">
+ Pass through key
+ </message>
+ <message desc="Describes the show context menu command. Shown in options page." name="IDS_CHROMEVOX_SHOW_CONTEXT_MENU">
+ Show context menu
+ </message>
+ <message desc="Describes the braille caption feature. Braille captioning provides an overlay showing both text and braille of what ChromeVox would show on a refreshable braille display. Shown in the options page as a label." name="IDS_CHROMEVOX_BRAILLE_CAPTIONS">
+ Toggle braille captions
+ </message>
+ <message desc="Spoken and brailled when the braille captions feature is enabled. This feature shows the braille output in a small overlay on the screen for development and demonstration purposes." name="IDS_CHROMEVOX_BRAILLE_CAPTIONS_ENABLED">
+ Braille captions enabled
+ </message>
+ <message desc="Spoken and brailled when the braille captions feature is disabled. This feature shows the braille output in a small overlay on the screen for development and demonstration purposes." name="IDS_CHROMEVOX_BRAILLE_CAPTIONS_DISABLED">
+ Braille captions disabled
+ </message>
+ <message desc="Describes the back key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_BACK_KEY">
+ back
+ </message>
+ <message desc="Describes the forward key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_FORWARD_KEY">
+ forward
+ </message>
+ <message desc="Describes the refresh key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_REFRESH_KEY">
+ refresh
+ </message>
+ <message desc="Describes the key to toggle full screen in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_TOGGLE_FULL_SCREEN_KEY">
+ toggle full screen
+ </message>
+ <message desc="Describes the key to toggle window overview in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_WINDOW_OVERVIEW_KEY">
+ window overview
+ </message>
+ <message desc="Describes the brightness down key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_BRIGHTNESS_DOWN_KEY">
+ Brightness down
+ </message>
+ <message desc="Describes the brightness up key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_BRIGHTNESS_UP_KEY">
+ Brightness up
+ </message>
+ <message desc="Describes the volume mute key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_MUTE_KEY">
+ volume mute
+ </message>
+ <message desc="Describes the volume down key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_DOWN_KEY">
+ volume down
+ </message>
+ <message desc="Describes the volume up key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_VOLUME_UP_KEY">
+ volume up
+ </message>
+ <message desc="Describes the Assistant key in the ChromeVox keyboard explorer." name="IDS_CHROMEVOX_ASSISTANT_KEY">
+ Google Assistant
+ </message>
+
+
+ <message desc="Title of the ChromeVox panel, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_TITLE">
+ ChromeVox Panel
+ </message>
+ <message desc="Title of the ChromeVox panel when menus are open, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_MENUS_TITLE">
+ ChromeVox Menus
+ </message>
+ <message desc="Title of the ChromeVox panel when the tutorial is open, a window that displays the text ChromeVox is speaking and contains controls to manipulate ChromeVox." name="IDS_CHROMEVOX_PANEL_TUTORIAL_TITLE">
+ ChromeVox Tutorial
+ </message>
+ <message desc="Title of the button that opens up the ChromeVox menus." name="IDS_CHROMEVOX_MENUS_TITLE">
+ ChromeVox Menus
+ </message>
+ <message desc="Title of the button that opens up ChromeVox options." name="IDS_CHROMEVOX_OPTIONS">
+ ChromeVox Options
+ </message>
+ <message desc="Title of the button that disables ChromeVox." name="IDS_CHROMEVOX_DISABLE_CHROMEVOX">
+ Disable ChromeVox
+ </message>
+ <message desc="Text in parentheses to be appended next to a tab that's currently active." name="IDS_CHROMEVOX_ACTIVE_TAB">
+ (active)
+ </message>
+ <message desc="Title displayed in the panel for the jump menu." name="IDS_CHROMEVOX_PANEL_MENU_JUMP">
+ Jump
+ </message>
+ <message desc="Title displayed in the panel for the speech menu." name="IDS_CHROMEVOX_PANEL_MENU_SPEECH">
+ Speech
+ </message>
+ <message desc="Title displayed in the panel for the tabs menu." name="IDS_CHROMEVOX_PANEL_MENU_TABS">
+ Tabs
+ </message>
+ <message desc="Title displayed in the panel for the ChromeVox menu." name="IDS_CHROMEVOX_PANEL_MENU_CHROMEVOX">
+ ChromeVox
+ </message>
+ <message desc="Title displayed in the panel for the actions menu." name="IDS_CHROMEVOX_PANEL_MENU_ACTIONS">
+ Actions
+ </message>
+ <message desc="Title displayed in the panel when there are no menu items." name="IDS_CHROMEVOX_PANEL_MENU_ITEM_NONE">
+ No items
+ </message>
+ <message desc="Title displayed in the panel for the menuitem to report an issue." name="IDS_CHROMEVOX_PANEL_MENU_ITEM_REPORT_ISSUE">
+ Report an issue
+ </message>
+ <message desc="Title of a notification that ChromeVox has been updated." name="IDS_CHROMEVOX_UPDATE_TITLE">
+ ChromeVox Updated
+ </message>
+ <message desc="Message text for a notification that ChromeVox has been updated for a new release." name="IDS_CHROMEVOX_UPDATE_MESSAGE_NEW">
+ Press ChromeVox o, n to find out what's new
+ </message>
+ <message desc="Description of button that closes the ChromeVox Tutorial" name="IDS_CHROMEVOX_CLOSE_TUTORIAL">
+ Close ChromeVox Tutorial
+ </message>
+ <message desc="Button that goes to the previous page in the ChromeVox Tutorial" name="IDS_CHROMEVOX_TUTORIAL_PREVIOUS">
+ Previous
+ </message>
+ <message desc="Button that goes to the next page in the ChromeVox Tutorial" name="IDS_CHROMEVOX_TUTORIAL_NEXT">
+ Next
+ </message>
+ <message desc="Heading that welcomes users to the ChromeVox tutorial" name="IDS_CHROMEVOX_TUTORIAL_WELCOME_HEADING">
+ Welcome to ChromeVox!
+ </message>
+ <message desc="Introductory text for the 'ChromeVox' tutorial" name="IDS_CHROMEVOX_TUTORIAL_WELCOME_TEXT">
+ Are you using ChromeVox spoken feedback for the first time? This quick tutorial explains the essentials for getting started with ChromeVox.
+ </message>
+ <message desc="Text that tells users to press the enter key to move to the next page or backspace to move to the previous page in the tutorial" name="IDS_CHROMEVOX_TUTORIAL_ENTER_TO_ADVANCE">
+ To advance, press enter; to go back, press backspace.
+ </message>
+ <message desc="Heading that talks about turning ChromeVox on, off, and stopping it from speaking" name="IDS_CHROMEVOX_TUTORIAL_ON_OFF_HEADING">
+ On, Off, and Stop
+ </message>
+ <message desc="Part of ChromeVox tutorial, explains that pressing Control on the keyboard stops it from speaking" name="IDS_CHROMEVOX_TUTORIAL_CONTROL">
+ To temporarily stop ChromeVox from speaking, press the Control key.
+ </message>
+ <message desc="Part of ChromeVox tutorial, explains that you can turn ChromeVox on or turn it off, by pressing Control+Alt+Z on the keyboard" name="IDS_CHROMEVOX_TUTORIAL_ON_OFF">
+ To turn ChromeVox on or off, use Control+Alt+Z.
+ </message>
+ <message desc="Heading for a section of the ChromeVox tutorial talking about the ChromeVox modifier key" name="IDS_CHROMEVOX_TUTORIAL_MODIFIER_HEADING">
+ The ChromeVox modifier key
+ </message>
+ <message desc="Text explaining that the Search key on the keyboard will be held down for most ChromeVox shortcuts" name="IDS_CHROMEVOX_TUTORIAL_MODIFIER">
+ In ChromeVox, the Search key is the modifier key. Most ChromeVox shortcuts start with the Search key. You’ll also use the arrow keys for navigation.
+ </message>
+ <message desc="Text explaining where to find the Search key on a Chromebook keyboard" name="IDS_CHROMEVOX_TUTORIAL_CHROMEBOOK_SEARCH">
+ On the Chromebook, the Search key is immediately above the left Shift key.
+ </message>
+ <message desc="Text explaining that while the ChromeVox tutorial is open, users can press any key to hear the key's name" name="IDS_CHROMEVOX_TUTORIAL_ANY_KEY">
+ During this tutorial, press any key to hear its name.
+ </message>
+ <message desc="Heading as part of the ChromeVox tutorial for a section on how to navigate within a webpage" name="IDS_CHROMEVOX_TUTORIAL_BASIC_NAVIGATION_HEADING">
+ Basic Navigation
+ </message>
+ <message desc="Part of the ChromeVox tutorial, explanation of keystrokes to navigate a webpage." name="IDS_CHROMEVOX_TUTORIAL_BASIC_NAVIGATION">
+ To move forward between items on a page, press Search + Right Arrow, or Search + Left Arrow to jump back. To go to the next line, press Search + Down Arrow. To get to the previous line, use Search + Up Arrow. If you reach an item you want to click, press Search + Space.
+ </message>
+ <message desc="Part of the ChromeVox tutorial, instructs the user to use key combinations to find and click a button titled 'Next' on the page and click it." name="IDS_CHROMEVOX_TUTORIAL_CLICK_NEXT">
+ Try using Search + Right Arrow now to find the Next button, then press Search + Space to click it.
+ </message>
+ <message desc="Heading for a section of the ChromeVox tutorial on commands to jump" name="IDS_CHROMEVOX_TUTORIAL_JUMP_HEADING">
+ Jump Commands
+ </message>
+ <message desc="Part of the ChromeVox tutorial, explains two keystrokes to jump to the next or previous heading." name="IDS_CHROMEVOX_TUTORIAL_JUMP">
+ Use jump commands to skip to specific types of elements. To jump forward between headings, press Search + H, or to jump backward, press Search + Shift + H.
+ </message>
+ <message desc="Part of the ChromeVox tutorial, heading used to illustrate jumping." name="IDS_CHROMEVOX_TUTORIAL_JUMP_SECOND_HEADING">
+ This is the second heading. Keep going; either press Search+H or Search+Shift+H
+ </message>
+ <message desc="Part of the ChromeVox tutorial, heading used to illustrate jumping from last heading." name="IDS_CHROMEVOX_TUTORIAL_JUMP_WRAP_HEADING">
+ This is the last heading. Press Search+H to wrap to the first heading, or Search+Shift+H to go to the second heading on this page.
+ </message>
+ <message desc="Heading for a section of the ChromeVox tutorial on menus of ChromeVox commands to press" name="IDS_CHROMEVOX_TUTORIAL_MENUS_HEADING">
+ Command Menus
+ </message>
+ <message desc="Part of the ChromeVox tutorial, explains the keystrokes to press to open and use a menu of commands." name="IDS_CHROMEVOX_TUTORIAL_MENUS">
+ To explore all ChromeVox commands and shortcuts, press Search + Period, then use the Arrow keys to navigate the menus, and Enter to activate a command. Return here by pressing Search+o then t.
+ </message>
+ <message desc="Heading for a section of the ChromeVox tutorial on Chrome shortcuts" name="IDS_CHROMEVOX_TUTORIAL_CHROME_SHORTCUTS_HEADING">
+ Helpful Chrome Shortcuts
+ </message>
+ <message desc="Part of the ChromeVox tutorial, explains some common Chrome keyboard shortcuts" name="IDS_CHROMEVOX_TUTORIAL_CHROME_SHORTCUTS">
+ The next few shortcuts aren’t ChromeVox commands, but they’re still very useful for getting the most out of Chrome.
+ To navigate forward through actionable items like buttons and links, press the Tab key. To navigate backwards, press Shift+Tab.
+ To enter the Chrome browser address box, also called the omnibox, press Control + L.
+ To open and go to a new tab automatically, press Control+T. Your cursor will be in the omnibox.
+ To close a tab, press Control+W.
+ To move forward between open tabs, use Control+Tab.
+ To open the Chrome browser menu, press Alt+F.
+ </message>
+ <message desc="Part of the ChromeVox tutorial, explains a keyboard shortcut to press on Chromebook keyboards" name="IDS_CHROMEVOX_TUTORIAL_CHROMEBOOK_CTRL_FORWARD">
+ To jump to other parts of the screen, like toolbars or the system tray, press Control+Forward. On a Chromebook, the Forward key is immediately above the number 2 key.
+ </message>
+ <message desc="Heading for a section of the ChromeVox tutorial where the user can learn more" name="IDS_CHROMEVOX_TUTORIAL_LEARN_MORE_HEADING">
+ Learn More
+ </message>
+ <message desc="Part of the ChromeVox tutorial, explaining that this is the end of the tutorial and that there are links to more information." name="IDS_CHROMEVOX_TUTORIAL_LEARN_MORE">
+ Congratulations! You’ve learned the essentials to use ChromeVox successfully. Remember that you can open the ChromeVox command menu at any time by pressing Search+Period. To learn even more about ChromeVox and Chrome OS, visit the following articles.
+ If you're done with the tutorial, use ChromeVox to navigate to the Close button and click it.
+ </message>
+ <message desc="Part of the ChromeVox update notes for m63, title." name="IDS_CHROMEVOX_UPDATE_63_TITLE">
+ You've been updated to ChromeVox 63!
+ </message>
+ <message desc="Part of the ChromeVox update notes for m63, introductory text." name="IDS_CHROMEVOX_UPDATE_63_INTRO">
+ We have some exciting changes in this new release; here's what's new:
+ </message>
+ <message desc="Part of the ChromeVox update notes for 63, new items 1." name="IDS_CHROMEVOX_UPDATE_63_ITEM_1">
+ Classic removed. The keyboard toggle to switch back into ChromeVox Classic has been removed.
+ </message>
+ <message desc="Part of the ChromeVox update notes for m63, new items 2." name="IDS_CHROMEVOX_UPDATE_63_ITEM_2">
+ Rich text support. ChromeVox now supports rich text fields including jump commands, braille cursor routing, selection, and more.
+ </message>
+ <message desc="Part of the ChromeVox update notes for m63, new items 3." name="IDS_CHROMEVOX_UPDATE_63_ITEM_3">
+ Android apps for Chrome. If you have Play Store on your device, get a sneak peek at ChromeVox with Android apps. Try the experimental support by downloading Google Chrome Canary from the Play Store.
+ </message>
+ <message desc="Title of an article on the command reference for 'ChromeVox'" name="IDS_CHROMEVOX_NEXT_COMMAND_REFERENCE">
+ ChromeVox Command Reference
+ </message>
+ <message desc="Title of an article on keyboard shortcuts for Chromebooks" name="IDS_CHROMEVOX_CHROME_KEYBOARD_SHORTCUTS">
+ Chromebook keyboard shortcuts
+ </message>
+ <message desc="Title of an article on how to use accessibility features of the Chromebook touch screen" name="IDS_CHROMEVOX_TOUCHSCREEN_ACCESSIBILITY">
+ Use Chromebook touch screen accessibility features
+ </message>
+ <message desc="Describes a UI element invoked after pressing enter such as an ok button in a dialog" name="IDS_CHROMEVOX_DEFAULT_STATE">
+ default
+ </message>
+ <message desc="Brailles for a UI element invoked after pressing enter such as an ok button in a dialog" name="IDS_CHROMEVOX_DEFAULT_STATE_BRL">
+ default
+ </message>
+ <message desc="Title of the earcon page in the ChromeVox tutorial" name="IDS_CHROMEVOX_TUTORIAL_EARCON_PAGE_TITLE">
+ Sounds
+ </message>
+ <message desc="Body text of the earcon page in the ChromeVox tutorial" name="IDS_CHROMEVOX_TUTORIAL_EARCON_PAGE_BODY">
+ ChromeVox uses sounds to give you essential and additional information. You can use these sounds to navigate more quickly by learning what each sound means. Once you get more comfortable, you can turn off verbose descriptions in speech and rely on them for essential information about the page. Here's a complete list of sounds and what they mean.
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_ALERT_MODAL_EARCON_DESCRIPTION">
+ A modal alert
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_ALERT_NONMODAL_EARCON_DESCRIPTION">
+ A non modal alert
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_BUTTON_EARCON_DESCRIPTION">
+ A button
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_CHECK_OFF_EARCON_DESCRIPTION">
+ An unchecked checkbox
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_CHECK_ON_EARCON_DESCRIPTION">
+ A checked checkbox
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_EDITABLE_TEXT_EARCON_DESCRIPTION">
+ An editable text field
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_INVALID_KEYPRESS_EARCON_DESCRIPTION">
+ An invalid key press
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_LINK_EARCON_DESCRIPTION">
+ A link
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_LISTBOX_EARCON_DESCRIPTION">
+ A listbox or combo box
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_PAGE_START_LOADING_EARCON_DESCRIPTION">
+ A page load in progress
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_POP_UP_BUTTON_EARCON_DESCRIPTION">
+ A pop up button
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_SLIDER_EARCON_DESCRIPTION">
+ A slider
+ </message>
+ <message desc="Describes an audio clip that gets played for a specific event or control type. Use the default string as a guide to what the audio clip represents or conveys." name="IDS_CHROMEVOX_WRAP_EARCON_DESCRIPTION">
+ Wrap from beginning to end or end to beginning inside of a page, dialog, or other container
+ </message>
+ <message desc="Describes a command to turn off the visual display for accessibility without impacting usage of the machine." name="IDS_CHROMEVOX_DARKEN_SCREEN">
+ Darken screen
+ </message>
+ <message desc="Describes a command to turn the visual display on for accessibility undoing any previous request to turn off the visual display." name="IDS_CHROMEVOX_UNDARKEN_SCREEN">
+ Undarken screen
+ </message>
+ <message desc="Describes a command to toggle on/off the visual display for accessibility." name="IDS_CHROMEVOX_TOGGLE_DARK_SCREEN">
+ Toggle dark screen
+ </message>
+ <message desc="Describes a command that turns text to speech feedback off." name="IDS_CHROMEVOX_SPEECH_OFF">
+ Speech off
+ </message>
+ <message desc="Describes a command that turns text to speech feedback on." name="IDS_CHROMEVOX_SPEECH_ON">
+ Speech on
+ </message>
+ <message desc="Description of a command that toggles text to speech feedback on or off." name="IDS_CHROMEVOX_SPEECH_ON_OFF_DESCRIPTION">
+ Toggle speech on or off
+ </message>
+ <message desc="Description of a command that toggles between 6 and 8 dot braille." name="IDS_CHROMEVOX_TOGGLE_BRAILLE_TABLE">
+ Toggle between 6 and 8 dot braille
+ </message>
+ <message desc="Spoken when a user navigates into a misspelled word." name="IDS_CHROMEVOX_MISSPELLING_START">
+ Misspelled
+ </message>
+ <message desc="Spoken when a user navigates out of a misspelled word." name="IDS_CHROMEVOX_MISSPELLING_END">
+ Leaving misspelled
+ </message>
+ <message desc="Spoken when a user navigates into a grammar error." name="IDS_CHROMEVOX_GRAMMAR_START">
+ Grammar error
+ </message>
+ <message desc="Spoken when a user navigates out of a grammar error." name="IDS_CHROMEVOX_GRAMMAR_END">
+ Leaving grammar error
+ </message>
+ <message desc="Spoken to describe text that is superscript." name="IDS_CHROMEVOX_SUPERSCRIPT">
+ Superscript
+ </message>
+ <message desc="Spoken to describe text that is not superscript." name="IDS_CHROMEVOX_NOT_SUPERSCRIPT">
+ Not superscript
+ </message>
+ <message desc="Spoken to describe text that is subscript." name="IDS_CHROMEVOX_SUBSCRIPT">
+ Subscript
+ </message>
+ <message desc="Spoken to describe text that is not subscript." name="IDS_CHROMEVOX_NOT_SUBSCRIPT">
+ Not subscript
+ </message>
+ <message desc="Spoken to describe bolded text." name="IDS_CHROMEVOX_BOLD">
+ Bold
+ </message>
+ <message desc="Spoken to describe non bolded text." name="IDS_CHROMEVOX_NOT_BOLD">
+ Not bold
+ </message>
+ <message desc="Spoken to describe italicized text." name="IDS_CHROMEVOX_ITALIC">
+ Italic
+ </message>
+ <message desc="Spoken to describe non italicized text." name="IDS_CHROMEVOX_NOT_ITALIC">
+ Not italic
+ </message>
+ <message desc="Spoken to describe underlined text." name="IDS_CHROMEVOX_UNDERLINE">
+ Underline
+ </message>
+ <message desc="Spoken to describe non underlined text." name="IDS_CHROMEVOX_NOT_UNDERLINE">
+ Not underline
+ </message>
+ <message desc="Spoken to describe line-through text." name="IDS_CHROMEVOX_LINETHROUGH">
+ Line through
+ </message>
+ <message desc="Spoken to describe non line-through text." name="IDS_CHROMEVOX_NOT_LINETHROUGH">
+ Not line through
+ </message>
+ <message desc="Spoken when a user navigates to text and the link state changes" name="IDS_CHROMEVOX_LINK">
+ Link
+ </message>
+ <message desc="Spoken to describe non-linked text." name="IDS_CHROMEVOX_NOT_LINK">
+ Not link
+ </message>
+ <message desc="Spoken when a user navigates to text and the font family changes, e.g. 'Font Arial'" name="IDS_CHROMEVOX_FONT_FAMILY">
+ Font <ph name="font_family">$1<ex>Arial</ex></ph>
+ </message>
+ <message desc="Spoken when a user navigates to text and the font size changes, e.g. 'Size 12'" name="IDS_CHROMEVOX_FONT_SIZE">
+ Size <ph name="font_size">$1<ex>12</ex></ph>
+ </message>
+ <message desc="Spoken when a user navigates to text and the font color changes, e.g. 'Red, 100% opacity'" name="IDS_CHROMEVOX_FONT_COLOR">
+ <ph name="font_color">$1<ex>Red, 100% opacity</ex></ph>
+ </message>
+ <message desc="Shown to a user when they invoke the read current title command in a context without a title." name="IDS_CHROMEVOX_NO_TITLE">
+ No title
+ </message>
+ <message desc="A hint to the user that the current control is checkable." name="IDS_CHROMEVOX_HINT_CHECKABLE">
+ Press Search+Space to toggle
+ </message>
+ <message desc="A hint to the user that the current control is clickable." name="IDS_CHROMEVOX_HINT_CLICKABLE">
+ Press Search+Space to activate
+ </message>
+ <message desc="A hint to the user that the current control has a list of auto completions." name="IDS_CHROMEVOX_HINT_AUTOCOMPLETE_LIST">
+ Press up or down arrow for auto completions
+ </message>
+ <message desc="A hint to the user that the current control has inline auto completions." name="IDS_CHROMEVOX_HINT_AUTOCOMPLETE_INLINE">
+ Type to auto complete
+ </message>
+ <message desc="A hint to the user for interacting with the table control." name="IDS_CHROMEVOX_HINT_TABLE">
+ Press Search+Ctrl+Alt with arrows to navigate by cell
+ </message>
+ <message desc="A hint to the user for interacting with the menu control." name="IDS_CHROMEVOX_HINT_MENU">
+ Press up or down arrow to navigate; enter to activate
+ </message>
+ <message desc="A hint to the user that there are details associated with this element." name="IDS_CHROMEVOX_HINT_DETAILS">
+ Press Search+A, J to jump to details
+ </message>
+ <message desc="The display name of the command that will jump to more details about an item." name="IDS_CHROMEVOX_JUMP_TO_DETAILS">
+ Jump to Details
+ </message>
+ <message desc="Describes the action of decrementing a control." name="IDS_CHROMEVOX_ACTION_DECREMENT_DESCRIPTION">
+ Decrease value
+ </message>
+ <message desc="Describes the action of incrementing a control." name="IDS_CHROMEVOX_ACTION_INCREMENT_DESCRIPTION">
+ Increase value
+ </message>
+ <message desc="Describes the action of scrolling backward." name="IDS_CHROMEVOX_ACTION_SCROLL_BACKWARD_DESCRIPTION">
+ Scroll back
+ </message>
+ <message desc="Describes the action of scrolling forward." name="IDS_CHROMEVOX_ACTION_SCROLL_FORWARD_DESCRIPTION">
+ Scroll forward
+ </message>
+ <message desc="A hint to the user that they are editing text within a text field. This text will be spoken using text to speech along with a description of the text field's name and value" name="IDS_CHROMEVOX_HINT_IS_EDITING">
+ is editing
+ </message>
+ <message desc="A hint to the user about the special behavior of the Search key with arrows within a text field. This text will be spoken using text to speech along with a description of the text field's name and value. The text is intentionally in fragments to reduce the time needed to convey this information via text to speech. Keys are capitalized and do not contain plus separators because it adds to the spoken announcement's duration. As a general guide, try to read the string aloud." name="IDS_CHROMEVOX_HINT_SEARCH_WITHIN_TEXT_FIELD">
+ Use Search Left or Right for Home or End, Search Control Left or Right for Control Home or End, Search Up or Down for Page Up or Down
+ </message>
+ <message desc="A hint to the user controls that can be double tapped." name="IDS_CHROMEVOX_HINT_DOUBLE_TAP">
+ Double tap to activate
+ </message>
+ <message desc="Shown to the user in braille and speech when the device goes into landscape orientation." name="IDS_CHROMEVOX_DEVICE_LANDSCAPE">
+ landscape
+ </message>
+ <message desc="Shown to the user in braille and speech when the device goes into portrait orientation." name="IDS_CHROMEVOX_DEVICE_PORTRAIT">
+ portrait
+ </message>
+ <message desc="A hint to the user for how to interact with math content using the keyboard." name="IDS_CHROMEVOX_HINT_MATH_KEYBOARD">
+ Press up, down, left, or right to explore math
+ </message>
+ <message desc="Voice name for the system default Text-to-Speech voice" name="IDS_CHROMEVOX_SYSTEM_VOICE">
+ System Text-to-Speech voice
+ </message>
+ <message desc="Menu item text for a command to open the text to speech settings page" name="IDS_CHROMEVOX_SHOW_TTS_SETTINGS">
+ Open text-to-speech settings
+ </message>
+ <message desc="A hint to the user on how to interact with the virtual on screen keyboard." name="IDS_CHROMEVOX_HINT_TOUCH_TYPE">
+ Find a key, then lift to type
+ </message>
+ <message desc="Hint for how to start editing a text field while exploring the screen using touch exploration." name="IDS_CHROMEVOX_HINT_DOUBLE_TAP_TO_EDIT">
+ Double tap to start editing
+ </message>
+ <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_TAP2_GESTURE">
+ Tap with two fingers
+ </message>
+ <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_TAP4_GESTURE">
+ Tap with four fingers
+ </message>
+ <message desc="Describes a gesture to be performed on a touch screen." name="IDS_CHROMEVOX_CLICK_GESTURE">
+ Double tap with one finger
+ </message>
+ <message desc="Describes Learn Mode when the mode is initially entered." name="IDS_CHROMEVOX_LEARN_MODE_INTRO">
+ Starting Learn Mode. Press a qwerty key, refreshable braille key, or touch gesture to learn its function. Press control with w or escape to exit.
+ </message>
+ <message desc="Output when leaving Learn Mode." name="IDS_CHROMEVOX_LEARN_MODE_OUTTRO">
+ Stopping Learn Mode
+ </message>
+ <message desc="Part of the ChromeVox touch tutorial page. Title of the tutorial page for touch support." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_HEADING">
+ Touch
+ </message>
+ <message desc="Part of the ChromeVox touch tutorial page. Introduces this page." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_INTRO">
+ You can use ChromeVox with the touchscreen
+ </message>
+ <message desc="Part of the ChromeVox touch tutorial page. Describes dragging a finger on the touch screen to get spoken feedback." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_DRAG_ONE_FINGER">
+ Drag one finger to hear what you touch
+ </message>
+ <message desc="Part of the ChromeVox touch tutorial page. Describes swiping left or right with one finger to move item by item." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_SWIPE_LEFT_RIGHT">
+ Swipe left or right to move by item
+ </message>
+
+ <message desc="Part of the ChromeVox touch tutorial page. Describes swiping up or down with one finger to move line by line." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_SWIPE_UP_DOWN">
+ Swipe up or down to move by line
+ </message>
+ <message desc="Part of the ChromeVox touch tutorial page. Describes double tapping with one finger to activate an item." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_DOUBLE_TAP">
+ Double-tap to activate what is focused
+ </message>
+ <message desc="Part of the ChromeVox touch tutorial page. Describes a single tap of four fingers to enter the ChromeVox menus." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_FOUR_FINGER_TAP">
+ Tap with 4 fingers to enter the ChromeVox menus
+ </message>
+ <message desc="Part of the ChromeVox touch tutorial page. Describes a two finger tap to stop speech." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_TWO_FINGER_TAP">
+ Tap with 2 fingers to temporarily stop speech
+ </message>
+ <message desc="Part of the ChromeVox touch tutorial page. Concludes this page." name="IDS_CHROMEVOX_TUTORIAL_TOUCH_LEARN_MORE">
+ Explore more gestures in Learn Mode and the Chromebook Help Center
+ </message>
+ <message desc="Title of the bluetooth braille display section in ChromeVox options." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_TITLE">
+ Bluetooth Braille Display
+ </message>
+ <message desc="Labels a button which when pressed, connects to a selected braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_CONNECT">
+ Connect
+ </message>
+ <message desc="Labels a button which when pressed, disconnects from a selected braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_DISCONNECT">
+ Disconnect
+ </message>
+ <message desc="Labels a button which is disabled and indicates the system is connecting to a braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_CONNECTING">
+ Connecting
+ </message>
+ <message desc="Labels a button which when pressed, forgets the selected braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_FORGET">
+ Forget
+ </message>
+ <message desc="Labels a text field which prompts the user for a pincode when pairing a braille display." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_PINCODE_LABEL">
+ Please enter a pin
+ </message>
+ <message desc="Labels a select control which lists all bluetooth braille displays." name="IDS_CHROMEVOX_OPTIONS_BLUETOOTH_BRAILLE_DISPLAY_SELECT_LABEL">
+ Select a bluetooth braille display
+ </message>
+ <message desc="Describes web content that has no title." name="IDS_CHROMEVOX_WEB_CONTENT">
+ Web Content
+ </message>
+ <message desc="The text label for ChromeVox language switching checkbox." name="IDS_CHROMEVOX_OPTIONS_LANG_SWITCHING_CHECKBOX_LABEL">
+ Automatically switch ChromeVox voice based on language
+ </message>
+ <message desc="Spoken to describe all rich text attributes of a node." name="IDS_CHROMEVOX_RICH_TEXT_ATTRIBUTES">
+ Text formatting
+ <ph name="font_size_string">$1<ex>Size 12</ex></ph>
+ <ph name="color_string">$2<ex>Red, 100% opacity.</ex></ph>
+ <ph name="bold_string">$3<ex>Bold</ex></ph>
+ <ph name="italic_string">$4<ex>Italic</ex></ph>
+ <ph name="underline_string">$5<ex>Unerline</ex></ph>
+ <ph name="line_through_string">$6<ex>Line through</ex></ph>
+ <ph name="font_family_string">$7<ex>Arial</ex></ph>
+ </message>
+
+
+ <message desc="Spoken to describe color and opacity of text" name="IDS_CHROMEVOX_COLOR_DESCRIPTION">
+ <ph name="color">$1<ex>Red</ex></ph>, <ph name="opacity_percentage">$2<ex>50</ex></ph>% opacity.
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLACK">
+ Black
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_GREEN">
+ Dark Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GREEN">
+ Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PURPLE">
+ Purple
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_GOLDEN_ROD">
+ Dark Golden Rod
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LEMON_CHIFFON">
+ Lemon Chiffon
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SIENNA">
+ Sienna
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ORANGE">
+ Orange
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SADDLE_BROWN">
+ Saddle Brown
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CYAN">
+ Cyan
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GREEN_YELLOW">
+ Green Yellow
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CHOCOLATE">
+ Chocolate
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MAROON">
+ Maroon
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GOLDEN_ROD">
+ Golden Rod
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_FOREST_GREEN">
+ Forest Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_OLIVE_DRAB">
+ Olive Drab
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_IVORY">
+ Ivory
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BEIGE">
+ Beige
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BROWN">
+ Brown
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_YELLOW_GREEN">
+ Yellow Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ORANGE_RED">
+ Orange Red
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_OLIVE_GREEN">
+ Dark Olive Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIME_GREEN">
+ Lime Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIME">
+ Lime
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_GOLDEN_ROD">
+ Pale Golden Rod
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_HOT_PINK">
+ Hot Pink
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CRIMSON">
+ Crimson
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_POWDER_BLUE">
+ Powder Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_OLIVE">
+ Olive
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_YELLOW">
+ Light Yellow
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LINEN">
+ Linen
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_BLUE">
+ Dark Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GHOST_WHITE">
+ Ghost White
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TOMATO">
+ Tomato
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_KHAKI">
+ Khaki
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SLATE_GREY">
+ Dark Slate Grey
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CORAL">
+ Coral
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MINT_CREAM">
+ Mint Cream
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TEAL">
+ Teal
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_MAGENTA">
+ Dark Magenta
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SALMON">
+ Light Salmon
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SEA_GREEN">
+ Sea Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_RED">
+ Red
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ROSY_BROWN">
+ Rosy Brown
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_INDIAN_RED">
+ Indian Red
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_GREY">
+ Light Grey
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SANDY_BROWN">
+ Sandy Brown
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_GREEN">
+ Light Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_BLUE">
+ Light Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_ORANGE">
+ Dark Orange
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DIM_GREY">
+ Dim Grey
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLANCHED_ALMOND">
+ Blanched Almond
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_KHAKI">
+ Dark Khaki
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MAGENTA">
+ Magenta
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MIDNIGHT_BLUE">
+ Midnight Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_SEA_GREEN">
+ Medium Sea Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SALMON">
+ Salmon
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DEEP_PINK">
+ Deep Pink
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SALMON">
+ Dark Salmon
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PERU">
+ Peru
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SPRING_GREEN">
+ Spring Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_NAVY">
+ Navy
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_CORAL">
+ Light Coral
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_INDIGO">
+ Indigo
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_WHITE">
+ White
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_VIOLET_RED">
+ Medium Violet Red
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BURLY_WOOD">
+ Burly Wood
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LAVENDER">
+ Lavender
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SLATE_BLUE">
+ Dark Slate Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TAN">
+ Tan
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_SEA_GREEN">
+ Dark Sea Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SLATE_GREY">
+ Slate Grey
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_VIOLET_RED">
+ Pale Violet Red
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CORNSILK">
+ Cornsilk
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_TURQUOISE">
+ Pale Turquoise
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SLATE_GREY">
+ Light Slate Grey
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PALE_GREEN">
+ Pale Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_REBECCA_PURPLE">
+ Rebecca Purple
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_SPRING_GREEN">
+ Medium Spring Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PINK">
+ Pink
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CADET_BLUE">
+ Cadet Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GREY">
+ Grey
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_VIOLET">
+ Violet
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_GREY">
+ Dark Grey
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SEA_GREEN">
+ Light Sea Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_CYAN">
+ Dark Cyan
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_NAVAJO_WHITE">
+ Navajo White
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ALICE_BLUE">
+ Alice Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_FLORAL_WHITE">
+ Floral White
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MISTY_ROSE">
+ Misty Rose
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_WHEAT">
+ Wheat
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_STEEL_BLUE">
+ Steel Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MOCCASIN">
+ Moccasin
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PEACH_PUFF">
+ Peach Puff
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GOLD">
+ Gold
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LAVENDER_BLUSH">
+ Lavender Blush
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SILVER">
+ Silver
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_PINK">
+ Light Pink
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_AZURE">
+ Azure
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BISQUE">
+ Bisque
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_ORCHID">
+ Dark Orchid
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_OLD_LACE">
+ Old Lace
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_TURQUOISE">
+ Medium Turquoise
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SLATE_BLUE">
+ Slate Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_BLUE">
+ Medium Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_TURQUOISE">
+ Turquoise
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_TURQUOISE">
+ Dark Turquoise
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_GOLDEN_ROD_YELLOW">
+ Light Golden Rod Yellow
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_VIOLET">
+ Dark Violet
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_AQUAMARINE">
+ Aquamarine
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PAPAYA_WHIP">
+ Papaya Whip
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ORCHID">
+ Orchid
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ANTIQUE_WHITE">
+ Antique White
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_THISTLE">
+ Thistle
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_PURPLE">
+ Medium Purple
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_GAINSBORO">
+ Gainsboro
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_PLUM">
+ Plum
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_STEEL_BLUE">
+ Light Steel Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DARK_RED">
+ Dark Red
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SEA_SHELL">
+ Sea Shell
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_ROYAL_BLUE">
+ Royal Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLUE_VIOLET">
+ Blue Violet
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LAWN_GREEN">
+ Lawn Green
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_CYAN">
+ Light Cyan
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_FIRE_BRICK">
+ Fire Brick
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SKY_BLUE">
+ Sky Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CORNFLOWER_BLUE">
+ Cornflower Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_SLATE_BLUE">
+ Medium Slate Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_BLUE">
+ Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_HONEYDEW">
+ HoneyDew
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_ORCHID">
+ Medium Orchid
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_WHITE_SMOKE">
+ White Smoke
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_YELLOW">
+ Yellow
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_LIGHT_SKY_BLUE">
+ Light Sky Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DEEP_SKY_BLUE">
+ Deep Sky Blue
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_SNOW">
+ Snow
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_MEDIUM_AQUA_MARINE">
+ Medium Aqua Marine
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_CHARTREUSE">
+ Chartreuse
+ </message>
+ <message desc="Spoken to describe color of text" name="IDS_CHROMEVOX_COLOR_DODGER_BLUE">
+ Dodger Blue
+ </message>
+ <message desc="An options page section header for options about ChromeVox rich text behavior. This section lets users set preferences on how rich text attributes should be indicated." name="IDS_CHROMEVOX_OPTIONS_RICH_TEXT_HEADER">
+ Formatting
+ </message>
+ <message desc="The text label for ChromeVox automatic rich text indication checkbox." name="IDS_CHROMEVOX_OPTIONS_RICH_TEXT_CHECKBOX_LABEL">
+ Announce text styling
+ </message>
+ <message desc="An option to announce download notifications." name="IDS_CHROMEVOX_OPTIONS_ANNOUNCE_DOWNLOAD">
+ Announce download notifications
+ </message>
+ <message desc="Spoken when a download is started" name="IDS_CHROMEVOX_DOWNLOAD_STARTED">
+ Download started <ph name="file_name">$1<ex>test.pdf</ex></ph>
+ </message>
+ <message desc="Spoken when a download is completed" name="IDS_CHROMEVOX_DOWNLOAD_COMPLETED">
+ Download completed <ph name="file_name">$1<ex>test.pdf</ex></ph>
+ </message>
+ <message desc="Spoken when a download is stopped" name="IDS_CHROMEVOX_DOWNLOAD_STOPPED">
+ Download stopped <ph name="file_name">$1<ex>test.pdf</ex></ph>
+ </message>
+ <message desc="Spoken when a download is paused" name="IDS_CHROMEVOX_DOWNLOAD_PAUSED">
+ Download paused <ph name="file_name">$1<ex>test.pdf</ex></ph>
+ </message>
+ <message desc="Spoken when a download is resumed" name="IDS_CHROMEVOX_DOWNLOAD_RESUMED">
+ Download resumed <ph name="file_name">$1<ex>test.pdf</ex></ph>
+ </message>
+ <message desc="Spoken to give progress on a current download, specifying percent complete and time remaining." name="IDS_CHROMEVOX_DOWNLOAD_PROGRESS">
+ Download <ph name="progress">$1<ex>50</ex></ph>% complete <ph name="file_name">$2<ex>test.pdf</ex></ph>. About <ph name="time">$3<ex>30</ex></ph> <ph name="units">$4<ex>minutes</ex></ph> remaining.
+ </message>
+ <message desc="A string to specify time units in seconds." name="IDS_CHROMEVOX_SECONDS">
+ {COUNT, plural, =1 {second}other {seconds}}
+ </message>
+ <message desc="A string to specify time units in minutes." name="IDS_CHROMEVOX_MINUTES">
+ {COUNT, plural, =1 {minute}other {minutes}}
+ </message>
+ <message desc="A string to specify time units in hours." name="IDS_CHROMEVOX_HOURS">
+ {COUNT, plural, =1 {hour}other {hours}}
+ </message>
+ <message desc="Appends language in front of content." name="IDS_CHROMEVOX_LANGUAGE_SWITCH">
+ <ph name="language">$1<ex>English</ex></ph>: <ph name="content">$2<ex>This is example content</ex></ph>
+ </message>
+ <message desc="The description of the readPhoneticPronunciation key. Displayed in the ChromeVox menu." name="IDS_CHROMEVOX_READ_PHONETIC_PRONUNCIATION">
+ Announce phonetic pronunciation for word
+ </message>
+ <message desc="Spoken to inform the user that the node's name is empty" name="IDS_CHROMEVOX_EMPTY_NAME">
+ No available text for this item
+ </message>
+ <message desc="The description of the announceBatteryDescription key. Displayed in the ChromeVox menu." name="IDS_CHROMEVOX_ANNOUNCE_BATTERY_DESCRIPTION">
+ Announce current battery status
+ </message>
+ <message desc="The description of the announceRichTextDescription key. Displayed in the ChromeVox menu." name="IDS_CHROMEVOX_ANNOUNCE_RICH_TEXT_DESCRIPTION">
+ Announce formatting for current item
+ </message>
+ <message desc="Announced when there is no available voice for a language." name="IDS_CHROMEVOX_VOICE_UNAVAILABLE_FOR_LANGUAGE">
+ No voice available for language: <ph name="language">$1<ex>English</ex></ph>
+ </message>
+ <message desc="Used to describe the link behind a url." name="IDS_CHROMEVOX_URL_BEHIND_LINK">
+ Link URL: <ph name="link_url">$1</ph>
+ </message>
+ <message desc="Describes an HTML description list element." name="IDS_CHROMEVOX_ROLE_DESCRIPTION_LIST">
+ Description list
+ </message>
+ <message desc="Describes an HTML description list detail element." name="IDS_CHROMEVOX_ROLE_DESCRIPTION_LIST_DETAIL">
+ Description list detail
+ </message>
+ <message desc="This is an abbreviated HTML description list element shown on a braille display. When translating, try to find a contracted form of the translation for 'description list' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DESCRIPTION_LIST_BRL">
+ dscrplst
+ </message>
+ <message desc="This is an abbreviated HTML description list detail element shown on a braille display. When translating, try to find a contracted form of the translation for 'description list detail' according to local conventions. If reasonable, use all lowercase and avoid punctuation to keep the number of characters as low as possible." name="IDS_CHROMEVOX_ROLE_DESCRIPTION_LIST_DETAIL_BRL">
+ dscrplst dtl
+ </message>
+ <message desc="Spoken when the user resets text to speech settings back to their default values" name="IDS_CHROMEVOX_ANNOUNCE_TTS_DEFAULT_SETTINGS">
+ Reset text to speech settings to default values
+ </message>
+ <message desc="The description of the resetTextToSpeechSettings key. Displayed in the Options page." name="IDS_CHROMEVOX_RESET_TTS_SETTINGS">
+ Reset text to speech settings
+ </message>
+ <message desc="The description of the openKeyboardShortcutsMenu key. Displayed in the ChromeVox menu" name="IDS_CHROMEVOX_OPEN_KEYBOARD_SHORTCUTS_MENU">
+ Open keyboard shortcuts menu
+ </message>
+ <message desc="Describes the multi select option for how to describe capital letters." name="IDS_CHROMEVOX_OPTIONS_CAPITAL_STRATEGY_SELECT_LABEL">
+ When reading capitals:
+ </message>
+ <message desc="Sets capital description strategy to announce presence of capital letters" name="IDS_CHROMEVOX_OPTIONS_ANNOUNCE_CAPITALS">
+ Speak "cap" before letter
+ </message>
+ <message desc="Sets capital description strategy to increase pitch" name="IDS_CHROMEVOX_OPTIONS_INCREASE_PITCH">
+ Increase pitch
+ </message>
+ <message desc="Used to describe capital letters" name="IDS_CHROMEVOX_ANNOUNCE_CAPITAL_LETTER">
+ Cap <ph name="letter">$1<ex>A</ex></ph>
+ </message>
+ <message desc="The hint text and label for the search bar in the ChromeVox menus" name="IDS_CHROMEVOX_SEARCH_CHROMEVOX_MENUS">
+ Search the menus
+ </message>
+ <message desc="Title displayed in the panel for the search menu." name="IDS_CHROMEVOX_PANEL_SEARCH_MENU">
+ Search
+ </message>
+ <message desc="Hint text for the input in the ChromeVox panel used for creating annotations." name="IDS_CHROMEVOX_ANNOTATIONS_WIDGET_INTRO">
+ Enter a custom label
+ </message>
+ <message desc="A label for the button in the ChromeVox panel used to discard annotations and leave the UI." name="IDS_CHROMEVOX_DISCARD_ANNOTATION">
+ Discard label
+ </message>
+ <message desc="A label for the button in the ChromeVox panel used to save annotations." name="IDS_CHROMEVOX_SAVE_ANNOTATION">
+ Save label
+ </message>
+ <message desc="Labels the select for choosing how ChromeVox reads numbers." name="IDS_CHROMEVOX_OPTIONS_NUMBER_READING_STYLE_SELECT_LABEL">
+ Read numbers as:
+ </message>
+ <message desc="Describes an option for ChromeVox to read numbers as words." name="IDS_CHROMEVOX_OPTIONS_NUMBER_READING_STYLE_WORDS">
+ Words
+ </message>
+ <message desc="Describes an option for ChromeVox to read numbers as digits." name="IDS_CHROMEVOX_OPTIONS_NUMBER_READING_STYLE_DIGITS">
+ Digits
+ </message>
+ <message desc="Labels the checkbox on the options page that enables displaying Perkins Brailler commands in the ChromeVox menus." name="IDS_CHROMEVOX_OPTIONS_MENU_BRAILLE_COMMANDS">
+ Show braille commands in the ChromeVox menus
+ </message>
+ <message desc="Title displayed in the panel for the form controls node menu." name="IDS_CHROMEVOX_PANEL_MENU_FORM_CONTROLS">
+ Form Controls
+ </message>
+ <message desc="Announced to alert the user that ChromeVox has no current focus." name="IDS_CHROMEVOX_NO_FOCUS">
+ No current ChromeVox focus. Press Alt+Shift+L to go to the launcher.
+ </message>
+
+</grit-part>
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp b/chromium/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp
new file mode 100644
index 00000000000..fa31306e16b
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit-part>
+<message desc="The product name for Select-to-speak." name="IDS_SELECT_TO_SPEAK_NAME">
+ Select-to-speak
+</message>
+<message desc="The description for Select-to-speak." name="IDS_SELECT_TO_SPEAK_DESCRIPTION">
+
+</message>
+<message desc="The title of the Select-to-speak options page." name="IDS_SELECT_TO_SPEAK_OPTIONS_PAGE_TITLE">
+ Select-to-speak Settings
+</message>
+<message desc="Section of the Select-to-speak options dialog where the user can adjust synthesized speech properties." name="IDS_SELECT_TO_SPEAK_OPTIONS_SPEECH">
+ Speech
+</message>
+<message desc="Label for the control in the Select-to-speak options dialog where the user can choose a voice from a list." name="IDS_SELECT_TO_SPEAK_OPTIONS_VOICES_DESCRIPTION">
+ Select a voice:
+</message>
+<message desc="Group of options controlling highlighting." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT">
+ Highlighting
+</message>
+<message desc="Label for option to highlight spoken words rather than spoken nodes." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_DESCRIPTION">
+ Highlight each word as it is spoken
+</message>
+<message desc="Label for option to pick word highlight color." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_DESCRIPTION">
+ Color for word highlights:
+</message>
+<message desc="Label for a blue highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_BLUE">
+ Blue
+</message>
+<message desc="Label for a orange highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_ORANGE">
+ Orange
+</message>
+<message desc="Label for a yellow highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_YELLOW">
+ Yellow
+</message>
+<message desc="Label for a green highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_GREEN">
+ Green
+</message>
+<message desc="Label for a pink highlight color in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_COLOR_PINK">
+ Pink
+</message>
+<message desc="Example of a word highlight on a dark background in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_DARK">
+ Dark background
+</message>
+<message desc="Example of a word highlight on a light background in the Select-to-speak options dialog." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT_LIGHT">
+ Light background
+</message>
+<message desc="Link to the Text-to-Speech settings page." name="IDS_SELECT_TO_SPEAK_OPTIONS_TEXT_TO_SPEECH_SETTINGS">
+ Personalize Text-to-Speech settings
+</message>
+<message desc="Link to the Text-to-Speech settings page." name="IDS_SELECT_TO_SPEAK_OPTIONS_TEXT_TO_SPEECH_SETTINGS_LINK">
+ Text-to-Speech settings
+</message>
+<message desc="Voice name for the system default Text-to-Speech voice" name="IDS_SELECT_TO_SPEAK_SYSTEM_VOICE">
+ System Text-to-Speech voice
+</message>
+<message desc="Description of a checkbox that is not checked" name="IDS_SELECT_TO_SPEAK_CHECKBOX_UNCHECKED">
+ unchecked
+</message>
+<message desc="Description of a checkbox that is checked" name="IDS_SELECT_TO_SPEAK_CHECKBOX_CHECKED">
+ checked
+</message>
+<message desc="Description of a checkbox that is a mixed selection" name="IDS_SELECT_TO_SPEAK_CHECKBOX_MIXED">
+ partially checked
+</message>
+<message desc="Description of a radio button that is not selected" name="IDS_SELECT_TO_SPEAK_RADIOBUTTON_UNSELECTED">
+ unselected
+</message>
+<message desc="Description of a radio button that is selected" name="IDS_SELECT_TO_SPEAK_RADIOBUTTON_SELECTED">
+ selected
+</message>
+<message desc="Description of a radio button that is selected" name="IDS_SELECT_TO_SPEAK_RADIOBUTTON_MIXED">
+ partially selected
+</message>
+</grit-part>
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/strings/switch_access_strings.grdp b/chromium/chrome/browser/resources/chromeos/accessibility/strings/switch_access_strings.grdp
new file mode 100644
index 00000000000..f53d2e1d63a
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/strings/switch_access_strings.grdp
@@ -0,0 +1,93 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<grit-part>
+ <message desc="The product name for Switch Access." name="IDS_SWITCH_ACCESS_NAME">
+ Switch Access
+ </message>
+ <message desc="The description for Switch Access." name="IDS_SWITCH_ACCESS_DESCRIPTION">
+ Control the device with just 1 or 2 switches
+ </message>
+ <message desc="The title of the Switch Access menu to select which action to perform on an element." name="IDS_SWITCH_ACCESS_MENU_TITLE">
+ Switch Access Menu
+ </message>
+ <message desc="The Switch Access action to perform the default action on the current element, similar to a click or tap. Should be short." name="IDS_SWITCH_ACCESS_SELECT">
+ Select
+ </message>
+ <message desc="The Switch Access action to open the onscreen keyboard and begin entering text in the selected text input element. Should be short." name="IDS_SWITCH_ACCESS_OPEN_KEYBOARD">
+ Keyboard
+ </message>
+ <message desc="The Switch Access action to increment the selected input element. Should be short." name="IDS_SWITCH_ACCESS_INCREMENT">
+ Increment
+ </message>
+ <message desc="The Switch Access action to decrement the selected input element. Should be short." name="IDS_SWITCH_ACCESS_DECREMENT">
+ Decrement
+ </message>
+ <message desc="The Switch Access action to scroll the selected element down. Should be short." name="IDS_SWITCH_ACCESS_SCROLL_DOWN">
+ Scroll down
+ </message>
+ <message desc="The Switch Access action to scroll the selected element up. Should be short." name="IDS_SWITCH_ACCESS_SCROLL_UP">
+ Scroll up
+ </message>
+ <message desc="The Switch Access action to scroll the selected element right. Should be short." name="IDS_SWITCH_ACCESS_SCROLL_RIGHT">
+ Scroll right
+ </message>
+ <message desc="The Switch Access action to scroll the selected element left. Should be short." name="IDS_SWITCH_ACCESS_SCROLL_LEFT">
+ Scroll left
+ </message>
+ <message desc="The Switch Access action to scroll the selected element logically forward (generally either down or right, depending on the context). Should be short." name="IDS_SWITCH_ACCESS_SCROLL_FORWARD">
+ Scroll forward
+ </message>
+ <message desc="The Switch Access action to scroll the selected element logically backward (generally either up or left, depending on the context). Should be short." name="IDS_SWITCH_ACCESS_SCROLL_BACKWARD">
+ Scroll backward
+ </message>
+ <message desc="The Switch Access action to speak to type in the selected text input element. Ideally the same as the name of the standalone Dictation feature (IDS_ASH_STATUS_TRAY_ACCESSIBILITY_DICTATION). Should be short." name="IDS_SWITCH_ACCESS_DICTATION">
+ Dictation
+ </message>
+ <message desc="The Switch Access action to show the system context menu, as when a user right-clicks on the focused element. Should be short." name="IDS_SWITCH_ACCESS_SHOW_CONTEXT_MENU">
+ Context menu
+ </message>
+ <message desc="The Switch Access action to open the Switch Access settings page. Should be short." name="IDS_SWITCH_ACCESS_SETTINGS_ACTION">
+ Settings
+ </message>
+ <message desc="The Switch Access action to show the text navigation menu for moving the text caret within a text element." name="IDS_SWITCH_ACCESS_MOVE_CURSOR">
+ Move cursor
+ </message>
+ <message desc="The Switch Access action for moving the text caret to the beginning of the text element." name="IDS_SWITCH_ACCESS_JUMP_TO_BEGINNING_OF_TEXT">
+ Jump to beginning
+ </message>
+ <message desc="The Switch Access action for moving the text caret to the end of the text element." name="IDS_SWITCH_ACCESS_JUMP_TO_END_OF_TEXT">
+ Jump to end
+ </message>
+ <message desc="The Switch Access action for moving the text caret backward one character." name="IDS_SWITCH_ACCESS_MOVE_BACKWARD_ONE_CHAR_OF_TEXT">
+ Move backward one char
+ </message>
+ <message desc="The Switch Access action for moving the text caret backward one word." name="IDS_SWITCH_ACCESS_MOVE_BACKWARD_ONE_WORD_OF_TEXT">
+ Move backward one word
+ </message>
+ <message desc="The Switch Access action for moving the text caret forward one character." name="IDS_SWITCH_ACCESS_MOVE_FORWARD_ONE_CHAR_OF_TEXT">
+ Move forward one char
+ </message>
+ <message desc="The Switch Access action for moving the text caret forward one word." name="IDS_SWITCH_ACCESS_MOVE_FORWARD_ONE_WORD_OF_TEXT">
+ Move forward one word
+ </message>
+ <message desc="The Switch Access action for moving the text caret down one line." name="IDS_SWITCH_ACCESS_MOVE_DOWN_ONE_LINE_OF_TEXT">
+ Move down one line
+ </message>
+ <message desc="The Switch Access action for moving the text caret up one line." name="IDS_SWITCH_ACCESS_MOVE_UP_ONE_LINE_OF_TEXT">
+ Move up one line
+ </message>
+ <message desc="The Switch Access action to set the beginning of a text selection area." name="IDS_SWITCH_ACCESS_SELECTION_START">
+ Selection start
+ </message>
+ <message desc="The Switch Access action to set the end of a text selection area." name="IDS_SWITCH_ACCESS_SELECTION_END">
+ Selection end
+ </message>
+ <message desc="The Switch Access action to cut text." name="IDS_SWITCH_ACCESS_CUT">
+ Cut
+ </message>
+ <message desc="The Switch Access action to copy text." name="IDS_SWITCH_ACCESS_COPY">
+ Copy
+ </message>
+ <message desc="The Switch Access action to paste text." name="IDS_SWITCH_ACCESS_PASTE">
+ Paste
+ </message>
+</grit-part>
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
index d8cf485bf4f..2ee94a9bb36 100644
--- a/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
@@ -16,12 +16,7 @@ switch_access_dir =
"$root_out_dir/resources/chromeos/accessibility/switch_access"
group("build") {
- deps = [
- ":switch_access_copied_files",
- ":switch_access_guest_manifest",
- ":switch_access_manifest",
- "strings:switch_access_strings",
- ]
+ deps = [ ":switch_access_copied_files" ]
}
# Instead of setting up one copy target for each subdirectory, use a script
@@ -30,10 +25,6 @@ run_jsbundler("switch_access_copied_files") {
mode = "copy"
dest_dir = switch_access_dir
sources = [
- "../chromevox/background/constants.js",
- "../chromevox/background/tree_walker.js",
- "../select_to_speak/closure_shim.js",
- "//third_party/chromevox/third_party/closure-library/closure/goog/base.js",
"auto_scan_manager.js",
"background.js",
"commands.js",
@@ -73,11 +64,14 @@ run_jsbundler("switch_access_copied_files") {
"metrics.js",
"navigation_manager.js",
"nodes/back_button_node.js",
+ "nodes/desktop_node.js",
+ "nodes/editable_text_node.js",
"nodes/group_node.js",
"nodes/keyboard_node.js",
"nodes/node_wrapper.js",
"nodes/switch_access_node.js",
"nodes/system_menu_node.js",
+ "nodes/tab_node.js",
"preferences.js",
"rect_helper.js",
"switch_access.js",
@@ -88,8 +82,6 @@ run_jsbundler("switch_access_copied_files") {
rewrite_rules = [
rebase_path(".", root_build_dir) + ":",
rebase_path(closure_library_dir, root_build_dir) + ":closure",
- rebase_path("../chromevox/background", root_build_dir) + ":",
- rebase_path("../select_to_speak", root_build_dir) + ":",
]
}
@@ -97,9 +89,7 @@ source_set("browser_tests") {
testonly = true
assert(enable_extensions)
- deps = [
- ":switch_access_extjs_tests",
- ]
+ deps = [ ":switch_access_extjs_tests" ]
data = [
"//chrome/browser/resources/chromeos/accessibility/chromevox/",
@@ -112,11 +102,13 @@ source_set("browser_tests") {
js2gtest("switch_access_extjs_tests") {
test_type = "extension"
sources = [
- "auto_scan_manager_test.extjs",
- "navigation_manager_test.extjs",
- "nodes/node_wrapper_test.extjs",
- "switch_access_predicate_test.extjs",
- "text_navigation_manager_test.extjs",
+ "auto_scan_manager_test.js",
+ "navigation_manager_test.js",
+ "nodes/desktop_node_test.js",
+ "nodes/node_wrapper_test.js",
+ "nodes/tab_node_test.js",
+ "switch_access_predicate_test.js",
+ "text_navigation_manager_test.js",
]
gen_include_files = [
"../chromevox/testing/callback_helper.js",
@@ -135,53 +127,14 @@ js2gtest("switch_access_extjs_tests") {
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
}
-# TODO(crbug/978200): refactor this into another file like generate_manifest.gni
-# to share with other extensions.
-template("manifest") {
- version_file = "//chrome/VERSION"
- version_script = "//build/util/version.py"
- template_file = "manifest.json.jinja2"
- output_file = invoker.output_file
- key = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVWTYdXNGhIG6FJKIhaohRRrYYGwg9cR2jea2NRBSEg+T7E3EvUyFy0ouez0N0omeSAL/xlvQtCjZJ72eCqDBgON/49SRtUdLS5TQ2U9cHYcIwI86llKMqqws6uMSwlWXldyNwKx5LVT1nR0+x3J744E2mymCSip2Y+NrGEA2yCUFL8D+O/uS+d5pVFb3NNjPTVbNOlhIs5ZUVX3FBij86ILivoSfRZMIZqK7MU8XDT1zolpFPiSYvDh1Qivwqar0pVYmNbCSjEgbGIuQh7zMaMdHC1HtvjbI20XFzWHyP/cW2YKszlfqawH+kdHSp4ANIjc7GCAjGJNxm33iMNwcFAgMBAAECggEAL47YakkzjZheKp3U6mAGDSAXHV6BQrkBY1yPXGstq7B/DZzy4RrF3QOkDf2jys8dCUXTg7YjrhqVqXuNdmmphvmGq8dxnFDeDxb6wZWE3GdlUzfYK77rdGp2cVuYtMhI05LwOmPSN/bDXk9eK4bDhTTy+lgomOH/aYcntXkEpIfVQ1kVs7RLvBs3tF3QfsL7t+aqphUlbyVRxCzogK3EDnLD0NODrydx5xB2UMKcxrQD8mVl8IhyBUeluWmcqVkIv7z9C9Y6s9HgcQdxsxhClymAsXtjkZVyP/xst9iwIxOyTijffcqbQOPtB9w1d7GWUrdpwCys0TveJslU7zo6jQKBgQD3VOJSiJuENck71q2Sg4yP0ytBNWVO7xLeTDc6OPEuhqtennWYFeprdplL8aejHqPFiNi7L2QVguP1JDLWPPu+RHHsZDtvG+stssE9Z+oVzBowDJZO1EvBH7nvqgxFz4utoDIrQmkbCcsBqOqwv1i7UdJ0DPIofZE/u0G8wONriwKBgQDc02xS5HZ8ysxEdhL9dC8FSvd12lHocEuBML5ufCkK4SUo8EFeg8k+2UVwd0xXwFNv3nKRPfr/yOQ0CRlKTo3IXXj4Uie+ww3j1jWIMPzC5Oo7IUHRd69KfLvG5N9byGv4wdsPKsXsGrUlvP4meD1U9fujxJdE9RC9evZss33prwKBgAQE7BydPbG7UgbX6UAtRRZ9PwGzRW8v8WWNZYRbsoeoBpbmClErYgDXD4ytY6UB9XVbUPJRxdWXp+6u5OiYWxrvb86AnnqiwIKgmgVOb/5kr7RCMBsd1hFQW6wqXkKwKbvrk4UiciTPVu4y+YVfxqhcnwflwfWofLjFaT8Q/2EbAoGANkdtr+5iRYhfr1BKmKwvRqDHtNtGGNlJZecCWAwC1p7C0I5FsyK3m9AyJlPcmxE2MSA/jv3qLWdG2JeH9ODcLuzy6C7hgB1X07H6lJBeANXd0Uz6ba96kdeZHGlzkY7xI0MbQl4kKkXiUvVijzgs8y5HfVi8SgHm7HxGCDASehcCgYEAnw1yu4eaWqsq7ECyjEBM7sQcMVGypiG3VupzLKA75iPkg/E+peUZyDRg7LPCiX/UcW22bliUw1ASRzY+thuVlGWC2CPah95Z4m+H4cJVSEEqKUbYRGfsDlDIJNxPihGvhoTniKZwvpUacbAhop7rbiAVGx+RJ+tFG8P56AbvBVE="
- action(target_name) {
- script = "//chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_manifest.py"
- inputs = [
- version_file,
- version_script,
- ]
- sources = [
- template_file,
- ]
- outputs = [
- output_file,
- ]
- args = [
- "--key=$key",
- "--version_file=" + rebase_path(version_file, root_build_dir),
- "--output_manifest=" + rebase_path(output_file, root_build_dir),
- ]
- if (defined(invoker.is_guest_manifest) && invoker.is_guest_manifest) {
- args += [ "--is_guest_manifest=1" ]
- }
- args += rebase_path(sources, root_build_dir)
- }
-}
-
-manifest("switch_access_manifest") {
- output_file = "$switch_access_dir/manifest.json"
-}
-
-manifest("switch_access_guest_manifest") {
- output_file = "$switch_access_dir/manifest_guest.json"
- is_guest_manifest = true
-}
-
js_type_check("closure_compile") {
deps = [
":auto_scan_manager",
":back_button_node",
":background",
":commands",
+ ":desktop_node",
+ ":editable_text_node",
":event_helper",
":focus_ring_manager",
":group_node",
@@ -196,35 +149,28 @@ js_type_check("closure_compile") {
":rect_helper",
":switch_access",
":switch_access_constants",
- ":switch_access_interface",
":switch_access_node",
":switch_access_predicate",
":system_menu_node",
+ ":tab_node",
":text_navigation_manager",
- "../chromevox:constants",
- "../chromevox:tree_walker",
- "../select_to_speak:closure_shim",
+ "../common:closure_shim",
+ "../common:constants",
+ "../common:tree_walker",
]
}
js_library("auto_scan_manager") {
- deps = [
- ":switch_access_constants",
- ":switch_access_interface",
- ]
+ deps = [ ":switch_access_constants" ]
}
js_library("background") {
- deps = [
- ":switch_access",
- ]
+ deps = [ ":switch_access" ]
externs_list = [ "$externs_path/chrome_extensions.js" ]
}
js_library("back_button_node") {
- sources = [
- "nodes/back_button_node.js",
- ]
+ sources = [ "nodes/back_button_node.js" ]
deps = [
":rect_helper",
":switch_access_constants",
@@ -237,10 +183,26 @@ js_library("back_button_node") {
}
js_library("commands") {
+ externs_list = [ "$externs_path/accessibility_private.js" ]
+}
+
+js_library("desktop_node") {
+ sources = [ "nodes/desktop_node.js" ]
+ deps = [ ":node_wrapper" ]
+ externs_list = [ "$externs_path/automation.js" ]
+}
+
+js_library("editable_text_node") {
+ sources = [ "nodes/editable_text_node.js" ]
deps = [
- ":switch_access_interface",
+ ":node_wrapper",
+ ":switch_access_constants",
+ ":switch_access_node",
+ ]
+ externs_list = [
+ "$externs_path/accessibility_private.js",
+ "$externs_path/automation.js",
]
- externs_list = [ "$externs_path/accessibility_private.js" ]
}
js_library("event_helper") {
@@ -257,9 +219,7 @@ js_library("focus_ring_manager") {
}
js_library("group_node") {
- sources = [
- "nodes/group_node.js",
- ]
+ sources = [ "nodes/group_node.js" ]
deps = [
":back_button_node",
":node_wrapper",
@@ -274,9 +234,7 @@ js_library("group_node") {
}
js_library("keyboard_node") {
- sources = [
- "nodes/keyboard_node.js",
- ]
+ sources = [ "nodes/keyboard_node.js" ]
deps = [
":event_helper",
":group_node",
@@ -285,8 +243,8 @@ js_library("keyboard_node") {
":switch_access_constants",
":switch_access_node",
":switch_access_predicate",
- "../chromevox:constants",
- "../chromevox:tree_walker",
+ "../common:constants",
+ "../common:tree_walker",
]
externs_list = [
"$externs_path/accessibility_private.js",
@@ -305,8 +263,8 @@ js_library("menu_manager") {
":switch_access_node",
":switch_access_predicate",
":text_navigation_manager",
- "../chromevox:constants",
- "../chromevox:tree_walker",
+ "../common:constants",
+ "../common:tree_walker",
]
externs_list = [
"$externs_path/accessibility_private.js",
@@ -319,7 +277,6 @@ js_library("menu_panel") {
deps = [
":menu_manager",
":switch_access_constants",
- ":switch_access_interface",
]
externs_list = [ "$externs_path/chrome_extensions.js" ]
}
@@ -328,14 +285,13 @@ js_library("menu_panel_interface") {
}
js_library("metrics") {
- deps = [
- ":switch_access_constants",
- ]
+ deps = [ ":switch_access_constants" ]
externs_list = [ "$externs_path/metrics_private.js" ]
}
js_library("navigation_manager") {
deps = [
+ ":desktop_node",
":focus_ring_manager",
":keyboard_node",
":menu_manager",
@@ -354,16 +310,14 @@ js_library("navigation_manager") {
}
js_library("node_wrapper") {
- sources = [
- "nodes/node_wrapper.js",
- ]
+ sources = [ "nodes/node_wrapper.js" ]
deps = [
":back_button_node",
":switch_access_constants",
":switch_access_node",
":switch_access_predicate",
- "../chromevox:constants",
- "../chromevox:tree_walker",
+ "../common:constants",
+ "../common:tree_walker",
]
externs_list = [
"$externs_path/accessibility_private.js",
@@ -372,10 +326,7 @@ js_library("node_wrapper") {
}
js_library("preferences") {
- deps = [
- ":switch_access_constants",
- ":switch_access_interface",
- ]
+ deps = [ ":switch_access_constants" ]
externs_list = [ "$externs_path/settings_private.js" ]
}
@@ -392,9 +343,8 @@ js_library("switch_access") {
":navigation_manager",
":preferences",
":switch_access_constants",
- ":switch_access_interface",
- "../chromevox:constants",
- "../chromevox:tree_walker",
+ "../common:constants",
+ "../common:tree_walker",
]
externs_list = [
"$externs_path/automation.js",
@@ -406,19 +356,9 @@ js_library("switch_access") {
js_library("switch_access_constants") {
}
-js_library("switch_access_interface") {
- deps = [
- ":menu_panel_interface",
- ]
-}
-
js_library("switch_access_node") {
- sources = [
- "nodes/switch_access_node.js",
- ]
- deps = [
- ":switch_access_constants",
- ]
+ sources = [ "nodes/switch_access_node.js" ]
+ deps = [ ":switch_access_constants" ]
externs_list = [
"$externs_path/accessibility_private.js",
"$externs_path/automation.js",
@@ -434,9 +374,7 @@ js_library("switch_access_predicate") {
}
js_library("system_menu_node") {
- sources = [
- "nodes/system_menu_node.js",
- ]
+ sources = [ "nodes/system_menu_node.js" ]
deps = [
":event_helper",
":node_wrapper",
@@ -446,10 +384,19 @@ js_library("system_menu_node") {
externs_list = [ "$externs_path/automation.js" ]
}
-js_library("text_navigation_manager") {
+js_library("tab_node") {
+ sources = [ "nodes/tab_node.js" ]
deps = [
- ":event_helper",
+ ":node_wrapper",
+ ":rect_helper",
+ ":switch_access_constants",
+ ":switch_access_node",
]
+ externs_list = [ "$externs_path/automation.js" ]
+}
+
+js_library("text_navigation_manager") {
+ deps = [ ":event_helper" ]
externs_list = [
"$externs_path/accessibility_private.js",
"$externs_path/automation.js",
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/strings/BUILD.gn b/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/strings/BUILD.gn
deleted file mode 100644
index 15a643c6fb2..00000000000
--- a/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/strings/BUILD.gn
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//chrome/common/features.gni")
-import("//tools/grit/grit_rule.gni")
-
-switch_access_out_dir =
- "$root_out_dir/resources/chromeos/accessibility/switch_access"
-
-grit("switch_access_strings") {
- source = "switch_access_strings.grd"
- defines = chrome_grit_defines
- outputs = [
- "_locales/am/messages.json",
- "_locales/ar/messages.json",
- "_locales/bg/messages.json",
- "_locales/bn/messages.json",
- "_locales/ca/messages.json",
- "_locales/cs/messages.json",
- "_locales/da/messages.json",
- "_locales/de/messages.json",
- "_locales/el/messages.json",
- "_locales/en_GB/messages.json",
- "_locales/en/messages.json",
- "_locales/es/messages.json",
- "_locales/es_419/messages.json",
- "_locales/et/messages.json",
- "_locales/fa/messages.json",
- "_locales/fi/messages.json",
- "_locales/fil/messages.json",
- "_locales/fr/messages.json",
- "_locales/gu/messages.json",
- "_locales/he/messages.json",
- "_locales/hi/messages.json",
- "_locales/hr/messages.json",
- "_locales/hu/messages.json",
- "_locales/id/messages.json",
- "_locales/it/messages.json",
- "_locales/ja/messages.json",
- "_locales/kn/messages.json",
- "_locales/ko/messages.json",
- "_locales/lt/messages.json",
- "_locales/lv/messages.json",
- "_locales/ml/messages.json",
- "_locales/mr/messages.json",
- "_locales/ms/messages.json",
- "_locales/nl/messages.json",
- "_locales/nb/messages.json",
- "_locales/pl/messages.json",
- "_locales/pt_BR/messages.json",
- "_locales/pt_PT/messages.json",
- "_locales/ro/messages.json",
- "_locales/ru/messages.json",
- "_locales/sk/messages.json",
- "_locales/sl/messages.json",
- "_locales/sr/messages.json",
- "_locales/sv/messages.json",
- "_locales/sw/messages.json",
- "_locales/ta/messages.json",
- "_locales/te/messages.json",
- "_locales/th/messages.json",
- "_locales/tr/messages.json",
- "_locales/uk/messages.json",
- "_locales/vi/messages.json",
- "_locales/zh_CN/messages.json",
- "_locales/zh_TW/messages.json",
- ]
- output_dir = switch_access_out_dir
-
- # Don't pollute the extension directory with stamp and .d files.
- depfile_dir = target_out_dir
- resource_ids = ""
-}
diff --git a/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/strings/switch_access_strings.grd b/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/strings/switch_access_strings.grd
deleted file mode 100644
index 80123f64f1f..00000000000
--- a/chromium/chrome/browser/resources/chromeos/accessibility/switch_access/strings/switch_access_strings.grd
+++ /dev/null
@@ -1,236 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<grit base_dir="." current_release="1" latest_public_release="0"
- output_all_resource_defines="false" enc_check="möl" source_lang_id="en">
- <outputs>
- <output filename="_locales/am/messages.json" type="chrome_messages_json" lang="am"/>
- <output filename="_locales/ar/messages.json" type="chrome_messages_json" lang="ar"/>
- <output filename="_locales/bg/messages.json" type="chrome_messages_json" lang="bg"/>
- <output filename="_locales/bn/messages.json" type="chrome_messages_json" lang="bn"/>
- <output filename="_locales/ca/messages.json" type="chrome_messages_json" lang="ca"/>
- <output filename="_locales/cs/messages.json" type="chrome_messages_json" lang="cs"/>
- <output filename="_locales/da/messages.json" type="chrome_messages_json" lang="da"/>
- <output filename="_locales/de/messages.json" type="chrome_messages_json" lang="de"/>
- <output filename="_locales/el/messages.json" type="chrome_messages_json" lang="el"/>
- <output filename="_locales/en_GB/messages.json" type="chrome_messages_json" lang="en-GB"/>
- <output filename="_locales/en/messages.json" type="chrome_messages_json" lang="en"/>
- <output filename="_locales/es/messages.json" type="chrome_messages_json" lang="es"/>
- <output filename="_locales/es_419/messages.json" type="chrome_messages_json" lang="es-419"/>
- <output filename="_locales/et/messages.json" type="chrome_messages_json" lang="et"/>
- <output filename="_locales/fa/messages.json" type="chrome_messages_json" lang="fa"/>
- <output filename="_locales/fi/messages.json" type="chrome_messages_json" lang="fi"/>
- <output filename="_locales/fil/messages.json" type="chrome_messages_json" lang="fil"/>
- <output filename="_locales/fr/messages.json" type="chrome_messages_json" lang="fr"/>
- <output filename="_locales/gu/messages.json" type="chrome_messages_json" lang="gu"/>
- <output filename="_locales/he/messages.json" type="chrome_messages_json" lang="he"/>
- <output filename="_locales/hi/messages.json" type="chrome_messages_json" lang="hi"/>
- <output filename="_locales/hr/messages.json" type="chrome_messages_json" lang="hr"/>
- <output filename="_locales/hu/messages.json" type="chrome_messages_json" lang="hu"/>
- <output filename="_locales/id/messages.json" type="chrome_messages_json" lang="id"/>
- <output filename="_locales/it/messages.json" type="chrome_messages_json" lang="it"/>
- <output filename="_locales/ja/messages.json" type="chrome_messages_json" lang="ja"/>
- <output filename="_locales/kn/messages.json" type="chrome_messages_json" lang="kn"/>
- <output filename="_locales/ko/messages.json" type="chrome_messages_json" lang="ko"/>
- <output filename="_locales/lt/messages.json" type="chrome_messages_json" lang="lt"/>
- <output filename="_locales/lv/messages.json" type="chrome_messages_json" lang="lv"/>
- <output filename="_locales/ml/messages.json" type="chrome_messages_json" lang="ml"/>
- <output filename="_locales/mr/messages.json" type="chrome_messages_json" lang="mr"/>
- <output filename="_locales/ms/messages.json" type="chrome_messages_json" lang="ms"/>
- <output filename="_locales/nl/messages.json" type="chrome_messages_json" lang="nl"/>
- <output filename="_locales/nb/messages.json" type="chrome_messages_json" lang="no"/>
- <output filename="_locales/pl/messages.json" type="chrome_messages_json" lang="pl"/>
- <output filename="_locales/pt_BR/messages.json" type="chrome_messages_json" lang="pt-BR"/>
- <output filename="_locales/pt_PT/messages.json" type="chrome_messages_json" lang="pt-PT"/>
- <output filename="_locales/ro/messages.json" type="chrome_messages_json" lang="ro"/>
- <output filename="_locales/ru/messages.json" type="chrome_messages_json" lang="ru"/>
- <output filename="_locales/sk/messages.json" type="chrome_messages_json" lang="sk"/>
- <output filename="_locales/sl/messages.json" type="chrome_messages_json" lang="sl"/>
- <output filename="_locales/sr/messages.json" type="chrome_messages_json" lang="sr"/>
- <output filename="_locales/sv/messages.json" type="chrome_messages_json" lang="sv"/>
- <output filename="_locales/sw/messages.json" type="chrome_messages_json" lang="sw"/>
- <output filename="_locales/ta/messages.json" type="chrome_messages_json" lang="ta"/>
- <output filename="_locales/te/messages.json" type="chrome_messages_json" lang="te"/>
- <output filename="_locales/th/messages.json" type="chrome_messages_json" lang="th"/>
- <output filename="_locales/tr/messages.json" type="chrome_messages_json" lang="tr"/>
- <output filename="_locales/uk/messages.json" type="chrome_messages_json" lang="uk"/>
- <output filename="_locales/vi/messages.json" type="chrome_messages_json" lang="vi"/>
- <output filename="_locales/zh_CN/messages.json" type="chrome_messages_json" lang="zh-CN"/>
- <output filename="_locales/zh_TW/messages.json" type="chrome_messages_json" lang="zh-TW"/>
- </outputs>
- <translations>
- <file path="switch_access_strings_af.xtb" lang="af" />
- <file path="switch_access_strings_am.xtb" lang="am" />
- <file path="switch_access_strings_ar.xtb" lang="ar" />
- <file path="switch_access_strings_as.xtb" lang="as" />
- <file path="switch_access_strings_az.xtb" lang="az" />
- <file path="switch_access_strings_be.xtb" lang="be" />
- <file path="switch_access_strings_bg.xtb" lang="bg" />
- <file path="switch_access_strings_bn.xtb" lang="bn" />
- <file path="switch_access_strings_bs.xtb" lang="bs" />
- <file path="switch_access_strings_ca.xtb" lang="ca" />
- <file path="switch_access_strings_cs.xtb" lang="cs" />
- <file path="switch_access_strings_da.xtb" lang="da" />
- <file path="switch_access_strings_de.xtb" lang="de" />
- <file path="switch_access_strings_el.xtb" lang="el" />
- <file path="switch_access_strings_en-GB.xtb" lang="en-GB" />
- <file path="switch_access_strings_es.xtb" lang="es" />
- <file path="switch_access_strings_es-419.xtb" lang="es-419" />
- <file path="switch_access_strings_et.xtb" lang="et" />
- <file path="switch_access_strings_eu.xtb" lang="eu" />
- <file path="switch_access_strings_fa.xtb" lang="fa" />
- <file path="switch_access_strings_fi.xtb" lang="fi" />
- <file path="switch_access_strings_fil.xtb" lang="fil" />
- <file path="switch_access_strings_fr.xtb" lang="fr" />
- <file path="switch_access_strings_fr-CA.xtb" lang="fr-CA" />
- <file path="switch_access_strings_gl.xtb" lang="gl" />
- <file path="switch_access_strings_gu.xtb" lang="gu" />
- <file path="switch_access_strings_hi.xtb" lang="hi" />
- <file path="switch_access_strings_hr.xtb" lang="hr" />
- <file path="switch_access_strings_hu.xtb" lang="hu" />
- <file path="switch_access_strings_hy.xtb" lang="hy" />
- <file path="switch_access_strings_id.xtb" lang="id" />
- <file path="switch_access_strings_is.xtb" lang="is" />
- <file path="switch_access_strings_it.xtb" lang="it" />
- <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
- <file path="switch_access_strings_iw.xtb" lang="he" />
- <file path="switch_access_strings_ja.xtb" lang="ja" />
- <file path="switch_access_strings_ka.xtb" lang="ka" />
- <file path="switch_access_strings_kk.xtb" lang="kk" />
- <file path="switch_access_strings_km.xtb" lang="km" />
- <file path="switch_access_strings_kn.xtb" lang="kn" />
- <file path="switch_access_strings_ko.xtb" lang="ko" />
- <file path="switch_access_strings_ky.xtb" lang="ky" />
- <file path="switch_access_strings_lo.xtb" lang="lo" />
- <file path="switch_access_strings_lt.xtb" lang="lt" />
- <file path="switch_access_strings_lv.xtb" lang="lv" />
- <file path="switch_access_strings_mk.xtb" lang="mk" />
- <file path="switch_access_strings_ml.xtb" lang="ml" />
- <file path="switch_access_strings_mn.xtb" lang="mn" />
- <file path="switch_access_strings_mr.xtb" lang="mr" />
- <file path="switch_access_strings_ms.xtb" lang="ms" />
- <file path="switch_access_strings_my.xtb" lang="my" />
- <file path="switch_access_strings_ne.xtb" lang="ne" />
- <file path="switch_access_strings_nl.xtb" lang="nl" />
- <file path="switch_access_strings_no.xtb" lang="no" />
- <file path="switch_access_strings_or.xtb" lang="or" />
- <file path="switch_access_strings_pa.xtb" lang="pa" />
- <file path="switch_access_strings_pl.xtb" lang="pl" />
- <file path="switch_access_strings_pt-BR.xtb" lang="pt-BR" />
- <file path="switch_access_strings_pt-PT.xtb" lang="pt-PT" />
- <file path="switch_access_strings_ro.xtb" lang="ro" />
- <file path="switch_access_strings_ru.xtb" lang="ru" />
- <file path="switch_access_strings_si.xtb" lang="si" />
- <file path="switch_access_strings_sk.xtb" lang="sk" />
- <file path="switch_access_strings_sl.xtb" lang="sl" />
- <file path="switch_access_strings_sq.xtb" lang="sq" />
- <file path="switch_access_strings_sr.xtb" lang="sr" />
- <file path="switch_access_strings_sv.xtb" lang="sv" />
- <file path="switch_access_strings_sw.xtb" lang="sw" />
- <file path="switch_access_strings_ta.xtb" lang="ta" />
- <file path="switch_access_strings_te.xtb" lang="te" />
- <file path="switch_access_strings_th.xtb" lang="th" />
- <file path="switch_access_strings_tr.xtb" lang="tr" />
- <file path="switch_access_strings_uk.xtb" lang="uk" />
- <file path="switch_access_strings_ur.xtb" lang="ur" />
- <file path="switch_access_strings_uz.xtb" lang="uz" />
- <file path="switch_access_strings_vi.xtb" lang="vi" />
- <file path="switch_access_strings_zh-CN.xtb" lang="zh-CN" />
- <file path="switch_access_strings_zh-HK.xtb" lang="zh-HK" />
- <file path="switch_access_strings_zh-TW.xtb" lang="zh-TW" />
- <file path="switch_access_strings_zu.xtb" lang="zu" />
- </translations>
- <release allow_pseudo="false" seq="1">
- <messages fallback_to_english="true">
- <message desc="The product name for Switch Access." name="IDS_SWITCH_ACCESS_NAME">
- Switch Access
- </message>
- <message desc="The description for Switch Access." name="IDS_SWITCH_ACCESS_DESCRIPTION">
- Control the device with just 1 or 2 switches.
- </message>
- <message desc="The title of the Switch Access menu to select which action to perform on an element." name="IDS_SWITCH_ACCESS_MENU_TITLE">
- Switch Access Menu
- </message>
- <message desc="The Switch Access action to perform the default action on the current element, similar to a click or tap. Should be short." name="IDS_SWITCH_ACCESS_SELECT">
- Select
- </message>
- <message desc="The Switch Access action to open the onscreen keyboard and begin entering text in the selected text input element. Should be short." name="IDS_SWITCH_ACCESS_OPEN_KEYBOARD">
- Keyboard
- </message>
- <message desc="The Switch Access action to increment the selected input element. Should be short." name="IDS_SWITCH_ACCESS_INCREMENT">
- Increment
- </message>
- <message desc="The Switch Access action to decrement the selected input element. Should be short." name="IDS_SWITCH_ACCESS_DECREMENT">
- Decrement
- </message>
- <message desc="The Switch Access action to scroll the selected element down. Should be short." name="IDS_SWITCH_ACCESS_SCROLL_DOWN">
- Scroll down
- </message>
- <message desc="The Switch Access action to scroll the selected element up. Should be short." name="IDS_SWITCH_ACCESS_SCROLL_UP">
- Scroll up
- </message>
- <message desc="The Switch Access action to scroll the selected element right. Should be short." name="IDS_SWITCH_ACCESS_SCROLL_RIGHT">
- Scroll right
- </message>
- <message desc="The Switch Access action to scroll the selected element left. Should be short." name="IDS_SWITCH_ACCESS_SCROLL_LEFT">
- Scroll left
- </message>
- <message desc="The Switch Access action to scroll the selected element logically forward (generally either down or right, depending on the context). Should be short." name="IDS_SWITCH_ACCESS_SCROLL_FORWARD">
- Scroll forward
- </message>
- <message desc="The Switch Access action to scroll the selected element logically backward (generally either up or left, depending on the context). Should be short." name="IDS_SWITCH_ACCESS_SCROLL_BACKWARD">
- Scroll backward
- </message>
- <message desc="The Switch Access action to speak to type in the selected text input element. Ideally the same as the name of the standalone Dictation feature (IDS_ASH_STATUS_TRAY_ACCESSIBILITY_DICTATION). Should be short." name="IDS_SWITCH_ACCESS_DICTATION">
- Dictation
- </message>
- <message desc="The Switch Access action to show the system context menu, as when a user right-clicks on the focused element. Should be short." name="IDS_SWITCH_ACCESS_SHOW_CONTEXT_MENU">
- Context menu
- </message>
- <message desc="The Switch Access action to open the Switch Access settings page. Should be short." name="IDS_SWITCH_ACCESS_SETTINGS_ACTION">
- Settings
- </message>
- <message desc="The Switch Access action to show the text navigation menu for moving the text caret within a text element." name="IDS_SWITCH_ACCESS_MOVE_CURSOR">
- Move cursor
- </message>
- <message desc="The Switch Access action for moving the text caret to the beginning of the text element." name="IDS_SWITCH_ACCESS_JUMP_TO_BEGINNING_OF_TEXT">
- Jump to beginning
- </message>
- <message desc="The Switch Access action for moving the text caret to the end of the text element." name="IDS_SWITCH_ACCESS_JUMP_TO_END_OF_TEXT">
- Jump to end
- </message>
- <message desc="The Switch Access action for moving the text caret backward one character." name="IDS_SWITCH_ACCESS_MOVE_BACKWARD_ONE_CHAR_OF_TEXT">
- Move backward one char
- </message>
- <message desc="The Switch Access action for moving the text caret backward one word." name="IDS_SWITCH_ACCESS_MOVE_BACKWARD_ONE_WORD_OF_TEXT">
- Move backward one word
- </message>
- <message desc="The Switch Access action for moving the text caret forward one character." name="IDS_SWITCH_ACCESS_MOVE_FORWARD_ONE_CHAR_OF_TEXT">
- Move forward one char
- </message>
- <message desc="The Switch Access action for moving the text caret forward one word." name="IDS_SWITCH_ACCESS_MOVE_FORWARD_ONE_WORD_OF_TEXT">
- Move forward one word
- </message>
- <message desc="The Switch Access action for moving the text caret down one line." name="IDS_SWITCH_ACCESS_MOVE_DOWN_ONE_LINE_OF_TEXT">
- Move down one line
- </message>
- <message desc="The Switch Access action for moving the text caret up one line." name="IDS_SWITCH_ACCESS_MOVE_UP_ONE_LINE_OF_TEXT">
- Move up one line
- </message>
- <message desc="The Switch Access action to set the beginning of a text selection area." name="IDS_SWITCH_ACCESS_SELECTION_START">
- Selection start
- </message>
- <message desc="The Switch Access action to set the end of a text selection area." name="IDS_SWITCH_ACCESS_SELECTION_END">
- Selection end
- </message>
- <message desc="The Switch Access action to cut text." name="IDS_SWITCH_ACCESS_CUT">
- Cut
- </message>
- <message desc="The Switch Access action to copy text." name="IDS_SWITCH_ACCESS_COPY">
- Copy
- </message>
- <message desc="The Switch Access action to paste text." name="IDS_SWITCH_ACCESS_PASTE">
- Paste
- </message>
- </messages>
- </release>
-</grit>
diff --git a/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn b/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
index f529c8d5041..e7e7cc85086 100644
--- a/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/bluetooth_pairing_dialog/BUILD.gn
@@ -17,9 +17,7 @@ optimize_webui("build") {
}
js_type_check("closure_compile") {
- deps = [
- ":bluetooth_pairing_dialog",
- ]
+ deps = [ ":bluetooth_pairing_dialog" ]
}
js_library("bluetooth_pairing_dialog") {
diff --git a/chromium/chrome/browser/resources/chromeos/camera/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/BUILD.gn
index 02f976656cf..af8c9e69867 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/BUILD.gn
@@ -5,9 +5,7 @@
chrome_camera_app_dir = "$root_out_dir/resources/chromeos/camera"
group("closure_compile") {
- deps = [
- "src/js:closure_compile",
- ]
+ deps = [ "src/js:closure_compile" ]
}
group("chrome_camera_app") {
@@ -25,6 +23,7 @@ group("chrome_camera_app") {
":chrome_camera_app_js",
":chrome_camera_app_js_browser_proxy",
":chrome_camera_app_js_device",
+ ":chrome_camera_app_js_lib",
":chrome_camera_app_js_models",
":chrome_camera_app_js_mojo",
":chrome_camera_app_js_views",
@@ -36,23 +35,15 @@ group("chrome_camera_app") {
}
copy("chrome_camera_app_base") {
- sources = [
- "src/manifest.json",
- ]
+ sources = [ "src/manifest.json" ]
- outputs = [
- "$chrome_camera_app_dir/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/{{source_file_part}}" ]
}
copy("chrome_camera_app_css") {
- sources = [
- "src/css/main.css",
- ]
+ sources = [ "src/css/main.css" ]
- outputs = [
- "$chrome_camera_app_dir/css/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/css/{{source_file_part}}" ]
}
copy("chrome_camera_app_images") {
@@ -101,21 +92,20 @@ copy("chrome_camera_app_images") {
"src/images/spinner.svg",
]
- outputs = [
- "$chrome_camera_app_dir/images/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/images/{{source_file_part}}" ]
}
copy("chrome_camera_app_js") {
sources = [
"src/js/background.js",
+ "src/js/background_ops.js",
"src/js/chrome_util.js",
"src/js/gallerybutton.js",
- "src/js/google-analytics-bundle.js",
"src/js/intent.js",
"src/js/main.js",
"src/js/metrics.js",
"src/js/nav.js",
+ "src/js/perf.js",
"src/js/sound.js",
"src/js/state.js",
"src/js/toast.js",
@@ -124,19 +114,17 @@ copy("chrome_camera_app_js") {
"src/js/util.js",
]
- outputs = [
- "$chrome_camera_app_dir/js/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/js/{{source_file_part}}" ]
}
copy("chrome_camera_app_js_browser_proxy") {
sources = [
+ # TODO(b/129956426): Remove dependency used only in closure compiler check.
"src/js/browser_proxy/browser_proxy.js",
+ "src/js/browser_proxy/browser_proxy_interface.js",
]
- outputs = [
- "$chrome_camera_app_dir/js/browser_proxy/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/js/browser_proxy/{{source_file_part}}" ]
}
copy("chrome_camera_app_js_device") {
@@ -147,25 +135,29 @@ copy("chrome_camera_app_js_device") {
"src/js/device/error.js",
]
- outputs = [
- "$chrome_camera_app_dir/js/device/{{source_file_part}}",
+ outputs = [ "$chrome_camera_app_dir/js/device/{{source_file_part}}" ]
+}
+
+copy("chrome_camera_app_js_lib") {
+ sources = [
+ "src/js/lib/comlink.js",
+ "src/js/lib/google-analytics-bundle.js",
]
+
+ outputs = [ "$chrome_camera_app_dir/js/lib/{{source_file_part}}" ]
}
copy("chrome_camera_app_js_models") {
sources = [
- "src/js/models/file_video_saver.js",
+ "src/js/models/async_writer.js",
"src/js/models/filenamer.js",
"src/js/models/filesystem.js",
- "src/js/models/gallery.js",
- "src/js/models/intent_video_saver.js",
"src/js/models/result_saver.js",
- "src/js/models/video_saver_interface.js",
+ "src/js/models/video_processor.js",
+ "src/js/models/video_saver.js",
]
- outputs = [
- "$chrome_camera_app_dir/js/models/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/js/models/{{source_file_part}}" ]
}
copy("chrome_camera_app_js_mojo") {
@@ -175,9 +167,7 @@ copy("chrome_camera_app_js_mojo") {
"src/js/mojo/image_capture.js",
]
- outputs = [
- "$chrome_camera_app_dir/js/mojo/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/js/mojo/{{source_file_part}}" ]
}
copy("chrome_camera_app_js_views") {
@@ -190,9 +180,7 @@ copy("chrome_camera_app_js_views") {
"src/js/views/warning.js",
]
- outputs = [
- "$chrome_camera_app_dir/js/views/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/js/views/{{source_file_part}}" ]
}
copy("chrome_camera_app_js_views_camera") {
@@ -206,9 +194,7 @@ copy("chrome_camera_app_js_views_camera") {
"src/js/views/camera/timertick.js",
]
- outputs = [
- "$chrome_camera_app_dir/js/views/camera/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/js/views/camera/{{source_file_part}}" ]
}
copy("chrome_camera_app_sounds") {
@@ -221,19 +207,16 @@ copy("chrome_camera_app_sounds") {
"src/sounds/tick_start.ogg",
]
- outputs = [
- "$chrome_camera_app_dir/sounds/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/sounds/{{source_file_part}}" ]
}
copy("chrome_camera_app_views") {
sources = [
+ "src/views/background.html",
"src/views/main.html",
]
- outputs = [
- "$chrome_camera_app_dir/views/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/views/{{source_file_part}}" ]
}
copy("chrome_camera_app_mojo_generated") {
@@ -246,6 +229,8 @@ copy("chrome_camera_app_mojo_generated") {
"$root_gen_dir/media/capture/video/chromeos/mojom/camera_metadata.mojom-lite.js",
"$root_gen_dir/media/capture/video/chromeos/mojom/camera_metadata_tags.mojom-lite.js",
"$root_gen_dir/mojo/public/js/mojo_bindings_lite.js",
+ "$root_gen_dir/mojo/public/mojom/base/time.mojom-lite.js",
+ "$root_gen_dir/third_party/blink/public/mojom/idle/idle_manager.mojom-lite.js",
"$root_gen_dir/ui/gfx/geometry/mojom/geometry.mojom-lite.js",
"$root_gen_dir/ui/gfx/range/mojom/range.mojom-lite.js",
]
@@ -257,11 +242,10 @@ copy("chrome_camera_app_mojo_generated") {
"//media/capture/mojom:image_capture_js",
"//media/capture/video/chromeos/mojom:cros_camera_js",
"//mojo/public/js:bindings_lite",
+ "//third_party/blink/public/mojom:mojom_platform_js",
"//ui/gfx/geometry/mojom:mojom_js",
"//ui/gfx/range/mojom:mojom_js",
]
- outputs = [
- "$chrome_camera_app_dir/js/mojo/{{source_file_part}}",
- ]
+ outputs = [ "$chrome_camera_app_dir/js/mojo/{{source_file_part}}" ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/camera/camera_resources.grd b/chromium/chrome/browser/resources/chromeos/camera/camera_resources.grd
index 9bf9333cb40..eacbf35d140 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/camera_resources.grd
+++ b/chromium/chrome/browser/resources/chromeos/camera/camera_resources.grd
@@ -12,21 +12,23 @@
</outputs>
<release seq="1">
<structures>
+ <structure name="IDR_CAMERA_ASYNC_WRITER_JS" file="src/js/models/async_writer.js" type="chrome_html" />
<structure name="IDR_CAMERA_BACKGROUND_JS" file="src/js/background.js" type="chrome_html" />
- <structure name="IDR_CAMERA_BUNDLE_JS" file="src/js/google-analytics-bundle.js" type="chrome_html" />
+ <structure name="IDR_CAMERA_BUNDLE_JS" file="src/js/lib/google-analytics-bundle.js" type="chrome_html" />
<structure name="IDR_CAMERA_CAMERA3_DEVICE_INFO_JS" file="src/js/device/camera3_device_info.js" type="chrome_html" />
<structure name="IDR_CAMERA_CAMERA_JS" file="src/js/views/camera.js" type="chrome_html" />
<structure name="IDR_CAMERA_CAMERA_INTENT_JS" file="src/js/views/camera_intent.js" type="chrome_html" />
+ <structure name="IDR_CAMERA_COMLINK_JS" file="src/js/lib/comlink.js" type="chrome_html" />
<structure name="IDR_CAMERA_CONSTRAINTS_PREFERRER_JS" file="src/js/device/constraints_preferrer.js" type="chrome_html" />
<structure name="IDR_CAMERA_CHROME_HELPER_JS" file="src/js/mojo/chrome_helper.js" type="chrome_html" />
<structure name="IDR_CAMERA_CHROME_UTIL_JS" file="src/js/chrome_util.js" type="chrome_html" />
+ <structure name="IDR_CAMERA_BACKGROUND_OPS_JS" file="src/js/background_ops.js" type="chrome_html" />
<structure name="IDR_CAMERA_DEVICE_OPERATOR_JS" file="src/js/mojo/device_operator.js" type="chrome_html" />
<structure name="IDR_CAMERA_DEVICE_INFO_UPDATER_JS" file="src/js/device/device_info_updater.js" type="chrome_html" />
<structure name="IDR_CAMERA_DIALOG_JS" file="src/js/views/dialog.js" type="chrome_html" />
<structure name="IDR_CAMERA_ERROR_JS" file="src/js/device/error.js" type="chrome_html" />
<structure name="IDR_CAMERA_FILENAMER_JS" file="src/js/models/filenamer.js" type="chrome_html" />
<structure name="IDR_CAMERA_FILESYSTEM_JS" file="src/js/models/filesystem.js" type="chrome_html" />
- <structure name="IDR_CAMERA_GALLERY_JS" file="src/js/models/gallery.js" type="chrome_html" />
<structure name="IDR_CAMERA_GALLERYBUTTON_JS" file="src/js/gallerybutton.js" type="chrome_html" />
<structure name="IDR_CAMERA_IMAGECAPTURE_JS" file="src/js/mojo/image_capture.js" type="chrome_html" />
<structure name="IDR_CAMERA_INTENT_JS" file="src/js/intent.js" type="chrome_html" />
@@ -39,6 +41,7 @@
<structure name="IDR_CAMERA_MODES_JS" file="src/js/views/camera/modes.js" type="chrome_html" />
<structure name="IDR_CAMERA_NAV_JS" file="src/js/nav.js" type="chrome_html" />
<structure name="IDR_CAMERA_OPTIONS_JS" file="src/js/views/camera/options.js" type="chrome_html" />
+ <structure name="IDR_CAMERA_PERF_JS" file="src/js/perf.js" type="chrome_html" />
<structure name="IDR_CAMERA_PREVIEW_JS" file="src/js/views/camera/preview.js" type="chrome_html" />
<structure name="IDR_CAMERA_RECORDTIME_JS" file="src/js/views/camera/recordtime.js" type="chrome_html" />
<structure name="IDR_CAMERA_RESULT_SAVER_JS" file="src/js/models/result_saver.js" type="chrome_html" />
@@ -51,9 +54,8 @@
<structure name="IDR_CAMERA_TOOLTIP_JS" file="src/js/tooltip.js" type="chrome_html" />
<structure name="IDR_CAMERA_TYPE_JS" file="src/js/type.js" type="chrome_html" />
<structure name="IDR_CAMERA_UTIL_JS" file="src/js/util.js" type="chrome_html" />
- <structure name="IDR_CAMERA_VIDEO_SAVER_INTERFACE_JS" file="src/js/models/video_saver_interface.js" type="chrome_html" />
- <structure name="IDR_CAMERA_INTENT_VIDEO_SAVER_JS" file="src/js/models/file_video_saver.js" type="chrome_html" />
- <structure name="IDR_CAMERA_FILE_VIDEO_SAVER_JS" file="src/js/models/intent_video_saver.js" type="chrome_html" />
+ <structure name="IDR_CAMERA_VIDEO_SAVER_JS" file="src/js/models/video_saver.js" type="chrome_html" />
+ <structure name="IDR_CAMERA_VIDEO_PROCESSOR_JS" file="src/js/models/video_processor.js" type="chrome_html" />
<structure name="IDR_CAMERA_VIEW_JS" file="src/js/views/view.js" type="chrome_html" />
<structure name="IDR_CAMERA_WARNING_JS" file="src/js/views/warning.js" type="chrome_html" />
<structure name="IDR_CAMERA_WEBUI_BROWSER_PROXY" file="src/js/browser_proxy/webui_browser_proxy.js" type="chrome_html" />
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
index 703e8951e28..eaf9be78d83 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
@@ -18,12 +18,14 @@ group("closure_compile") {
js_type_check("compile_resources") {
deps = [
":background",
+ ":background_ops",
":chrome_util",
":gallerybutton",
":intent",
":main",
":metrics",
":nav",
+ ":perf",
":sound",
":state",
":toast",
@@ -38,6 +40,9 @@ js_library("chrome_util") {
js_library("intent") {
deps = [
+ ":chrome_util",
+ ":metrics",
+ ":type",
"mojo:chrome_helper",
]
}
@@ -45,7 +50,9 @@ js_library("intent") {
js_library("gallerybutton") {
deps = [
":chrome_util",
- "models:gallery",
+ "models:filesystem",
+ "models:result_saver",
+ "models:video_saver",
]
externs_list = [
"$externs_path/file_manager_private.js",
@@ -55,6 +62,7 @@ js_library("gallerybutton") {
js_library("metrics") {
deps = [
+ ":state",
"externs:chrome_platform_analytics",
]
}
@@ -67,13 +75,14 @@ js_library("type") {
js_library("main") {
deps = [
+ ":background_ops",
":chrome_util",
":gallerybutton",
":intent",
":state",
+ ":type",
"device:constraints_preferrer",
"device:device_info_updater",
- "models:gallery",
"views:camera",
"views:camera_intent",
"views:dialog",
@@ -89,28 +98,46 @@ js_library("nav") {
]
}
+js_library("perf") {
+}
+
js_library("state") {
+ deps = [
+ ":perf",
+ ":type",
+ "views:view",
+ ]
}
js_library("background") {
deps = [
+ ":background_ops",
":intent",
]
}
-js_library("toast") {
+js_library("background_ops") {
deps = [
- ":util",
+ ":chrome_util",
+ ":intent",
+ ":perf",
]
}
+js_library("toast") {
+ deps = [ ":util" ]
+}
+
js_library("tooltip") {
+ deps = [ ":chrome_util" ]
}
js_library("util") {
deps = [
":tooltip",
+ ":type",
"browser_proxy:browser_proxy",
+ "externs:w3c_fileapi",
"mojo:chrome_helper",
]
externs_list = [ "$externs_path/chrome_extensions.js" ]
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn
index aa71df45125..909b9b4aea2 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn
@@ -5,16 +5,24 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":browser_proxy",
- ]
+ deps = [ ":browser_proxy" ]
}
js_library("browser_proxy") {
+ deps = [
+ "..:chrome_util",
+ "../mojo:chrome_helper",
+ ]
sources = [
"browser_proxy.js",
"browser_proxy_interface.js",
"webui_browser_proxy.js",
]
- externs_list = [ "$externs_path/chrome_extensions.js" ]
+ externs_list = [
+ "../externs/chrome.js",
+ "$externs_path/chrome_extensions.js",
+ "$externs_path/file_manager_private.js",
+ "$externs_path/file_system_provider.js",
+ "$externs_path/metrics_private.js",
+ ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn
index 0a43ce9d653..f4b59b69732 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn
@@ -23,6 +23,7 @@ js_library("camera3_device_info") {
js_library("constraints_preferrer") {
deps = [
":camera3_device_info",
+ "..:chrome_util",
"..:state",
"..:type",
"../browser_proxy:browser_proxy",
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn
index e41499011b1..7db53bae1d7 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn
@@ -9,3 +9,9 @@ js_library("chrome_platform_analytics") {
externs_list = [ "chrome_platform_analytics.js" ]
}
+
+js_library("w3c_fileapi") {
+ sources = []
+
+ externs_list = [ "w3c_fileapi.js" ]
+}
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/lib/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/lib/BUILD.gn
new file mode 100644
index 00000000000..b9241fdf28c
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/js/lib/BUILD.gn
@@ -0,0 +1,9 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_library("comlink") {
+ sources = [ "comlink.js" ]
+}
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn
index 39e60221b1d..ec38d8a722b 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn
@@ -8,7 +8,6 @@ js_type_check("closure_compile") {
deps = [
":filenamer",
":filesystem",
- ":gallery",
":result_saver",
":video_saver",
]
@@ -19,13 +18,8 @@ js_library("filenamer") {
js_library("filesystem") {
deps = [
- "..:util",
- ]
-}
-
-js_library("gallery") {
- deps = [
- ":filesystem",
+ ":filenamer",
+ "../browser_proxy:browser_proxy",
]
}
@@ -34,11 +28,13 @@ js_library("result_saver") {
js_library("video_saver") {
sources = [
- "file_video_saver.js",
- "intent_video_saver.js",
- "video_saver_interface.js",
+ "async_writer.js",
+ "video_processor.js",
+ "video_saver.js",
]
deps = [
"..:intent",
+ "../externs:w3c_fileapi",
+ "../lib:comlink",
]
}
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn
index 65264576c4d..b1bdcd32ae1 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn
@@ -16,6 +16,7 @@ js_library("chrome_helper") {
deps = [
"//components/arc/mojom:camera_intent_js_library_for_compile",
"//components/chromeos_camera/common:camera_app_helper_js_library_for_compile",
+ "//third_party/blink/public/mojom:mojom_platform_js_library_for_compile",
]
externs_list = [ "$externs_path/pending.js" ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn
index c77f3a005e9..59804f3efa5 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn
@@ -24,6 +24,7 @@ js_type_check("compile_resources") {
js_library("camera") {
deps = [
+ "..:background_ops",
"..:chrome_util",
"..:metrics",
"..:type",
@@ -59,9 +60,7 @@ js_library("settings") {
}
js_library("view") {
- deps = [
- "..:toast",
- ]
+ deps = [ "..:toast" ]
externs_list = [ "../externs/chrome.js" ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn
index b610cd28173..97fdd2dce89 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
group("closure_compile") {
- deps = [
- ":compile_resources",
- ]
+ deps = [ ":compile_resources" ]
}
js_type_check("compile_resources") {
@@ -36,7 +34,6 @@ js_library("modes") {
"../..:sound",
"../..:toast",
"../..:type",
- "../..:type",
"../..:util",
"../../device:constraints_preferrer",
"../../models:filenamer",
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn b/chromium/chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn
index bfd9210b776..6535e9e8673 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn
@@ -67,7 +67,5 @@ grit("camera_strings") {
]
output_dir = chrome_camera_app_dir
- # Don't pollute the extension directory with stamp and .d files.
- depfile_dir = target_out_dir
resource_ids = ""
}
diff --git a/chromium/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd b/chromium/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd
index 2068ed0af0f..f22c312b325 100644
--- a/chromium/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd
+++ b/chromium/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd
@@ -124,6 +124,7 @@
<file path="camera_strings_sl.xtb" lang="sl" />
<file path="camera_strings_sq.xtb" lang="sq" />
<file path="camera_strings_sr.xtb" lang="sr" />
+ <file path="camera_strings_sr-Latn.xtb" lang="sr-Latn" />
<file path="camera_strings_sv.xtb" lang="sv" />
<file path="camera_strings_sw.xtb" lang="sw" />
<file path="camera_strings_ta.xtb" lang="ta" />
@@ -258,6 +259,9 @@
<message desc="Label for expert mode option: save metadata." name="IDS_EXPERT_SAVE_METADATA">
Save metadata
</message>
+ <message desc="Label for expert mode option: print performance logs." name="IDS_EXPERT_PRINT_PERFORMANCE_LOGS">
+ Print performance logs
+ </message>
<message desc="Error message when the device does not support expert mode but tries to enable it." name="IDS_ERROR_MSG_EXPERT_MODE_NOT_SUPPORTED">
Expert mode is not supported on this device
</message>
diff --git a/chromium/chrome/browser/resources/chromeos/crostini_installer/BUILD.gn b/chromium/chrome/browser/resources/chromeos/crostini_installer/BUILD.gn
index 7b3fd4c854a..d2b10cc2eb7 100644
--- a/chromium/chrome/browser/resources/chromeos/crostini_installer/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/crostini_installer/BUILD.gn
@@ -39,7 +39,5 @@ polymer_modulizer("app") {
}
group("polymer3_elements") {
- deps = [
- ":app_module",
- ]
+ public_deps = [ ":app_module" ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/crostini_upgrader/BUILD.gn b/chromium/chrome/browser/resources/chromeos/crostini_upgrader/BUILD.gn
index 0d27180e1c7..8c14961d7cd 100644
--- a/chromium/chrome/browser/resources/chromeos/crostini_upgrader/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/crostini_upgrader/BUILD.gn
@@ -39,7 +39,5 @@ polymer_modulizer("app") {
}
group("polymer3_elements") {
- deps = [
- ":app_module",
- ]
+ public_deps = [ ":app_module" ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/edu_login/BUILD.gn b/chromium/chrome/browser/resources/chromeos/edu_login/BUILD.gn
new file mode 100644
index 00000000000..7f88acdfd7b
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/edu_login/BUILD.gn
@@ -0,0 +1,191 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+
+js_type_check("closure_compile") {
+ is_polymer3 = true
+ closure_flags =
+ default_closure_args + [
+ "js_module_root=../../chrome/browser/resources/gaia_auth_host/",
+ "js_module_root=./gen/chrome/browser/resources/gaia_auth_host/",
+ ]
+ deps = [
+ ":app",
+ ":browser_proxy",
+ ":edu_login_button",
+ ":edu_login_parent_info",
+ ":edu_login_parent_signin",
+ ":edu_login_parents",
+ ":edu_login_signin",
+ ":edu_login_template",
+ ":edu_login_util",
+ ":edu_login_welcome",
+ ]
+}
+
+js_library("app") {
+ deps = [
+ ":edu_login_parent_info",
+ ":edu_login_parent_signin",
+ ":edu_login_parents",
+ ":edu_login_signin",
+ ":edu_login_util",
+ ":edu_login_welcome",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager.m",
+ "//ui/webui/resources/js:assert.m",
+ ]
+}
+
+js_library("edu_login_button") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:util.m",
+ ]
+}
+
+js_library("edu_login_template") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements:cr_scrollable_behavior.m",
+ ]
+}
+
+js_library("browser_proxy") {
+ deps = [
+ ":edu_login_util",
+ "//chrome/browser/resources/gaia_auth_host:authenticator.m",
+ "//ui/webui/resources/js:cr.m",
+ ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+}
+
+js_library("edu_login_util") {
+}
+
+js_library("edu_login_welcome") {
+ deps = [
+ ":edu_login_button",
+ ":edu_login_template",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+}
+
+js_library("edu_login_parents") {
+ deps = [
+ ":edu_login_button",
+ ":edu_login_template",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:icon.m",
+ ]
+}
+
+js_library("edu_login_parent_signin") {
+ deps = [
+ ":browser_proxy",
+ ":edu_login_button",
+ ":edu_login_template",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+}
+
+js_library("edu_login_parent_info") {
+ deps = [
+ ":edu_login_button",
+ ":edu_login_template",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:icon.m",
+ ]
+}
+
+js_library("edu_login_signin") {
+ deps = [
+ ":edu_login_button",
+ ":edu_login_template",
+ "//chrome/browser/resources/gaia_auth_host:authenticator.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+}
+
+polymer_modulizer("app") {
+ js_file = "app.js"
+ html_file = "app.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("edu_login_button") {
+ js_file = "edu_login_button.js"
+ html_file = "edu_login_button.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("edu_login_template") {
+ js_file = "edu_login_template.js"
+ html_file = "edu_login_template.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("edu_login_css") {
+ js_file = "edu_login_css.js"
+ html_file = "edu_login_css.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("icons") {
+ js_file = "icons.js"
+ html_file = "icons.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("edu_login_welcome") {
+ js_file = "edu_login_welcome.js"
+ html_file = "edu_login_welcome.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("edu_login_parents") {
+ js_file = "edu_login_parents.js"
+ html_file = "edu_login_parents.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("edu_login_parent_signin") {
+ js_file = "edu_login_parent_signin.js"
+ html_file = "edu_login_parent_signin.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("edu_login_parent_info") {
+ js_file = "edu_login_parent_info.js"
+ html_file = "edu_login_parent_info.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("edu_login_signin") {
+ js_file = "edu_login_signin.js"
+ html_file = "edu_login_signin.html"
+ html_type = "v3-ready"
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":app_module",
+ ":edu_login_button_module",
+ ":edu_login_css_module",
+ ":edu_login_parent_info_module",
+ ":edu_login_parent_signin_module",
+ ":edu_login_parents_module",
+ ":edu_login_signin_module",
+ ":edu_login_template_module",
+ ":edu_login_welcome_module",
+ ":icons_module",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/chromeos/emulator/BUILD.gn b/chromium/chrome/browser/resources/chromeos/emulator/BUILD.gn
index 248fc9c931a..609772768f3 100644
--- a/chromium/chrome/browser/resources/chromeos/emulator/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/emulator/BUILD.gn
@@ -98,7 +98,7 @@ polymer_modulizer("shared_styles") {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":audio_settings_module",
":battery_settings_module",
":bluetooth_settings_module",
diff --git a/chromium/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn b/chromium/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn
index 6d5812421dd..f899962417a 100644
--- a/chromium/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn
@@ -18,9 +18,7 @@ optimize_webui("build") {
}
js_type_check("closure_compile") {
- deps = [
- ":internet_config_dialog",
- ]
+ deps = [ ":internet_config_dialog" ]
}
js_library("internet_config_dialog") {
diff --git a/chromium/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn b/chromium/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn
index 980be603b64..a4dd8090983 100644
--- a/chromium/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn
@@ -18,9 +18,7 @@ optimize_webui("build") {
}
js_type_check("closure_compile") {
- deps = [
- ":internet_detail_dialog",
- ]
+ deps = [ ":internet_detail_dialog" ]
}
js_library("internet_detail_dialog") {
diff --git a/chromium/chrome/browser/resources/chromeos/login/BUILD.gn b/chromium/chrome/browser/resources/chromeos/login/BUILD.gn
index 65b1907ba2c..df3e3c5d5ac 100644
--- a/chromium/chrome/browser/resources/chromeos/login/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -13,7 +13,6 @@ js_type_check("closure_compile") {
":demo_preferences",
":demo_setup",
":encryption_migration",
- ":enrollment_license_card",
":fingerprint_setup",
":gaia_buttons",
":gaia_card",
@@ -21,6 +20,7 @@ js_type_check("closure_compile") {
":gaia_input",
":gaia_input_form",
":gaia_password_changed",
+ ":gesture_navigation",
":hd-iron-icon",
":html-echo",
":marketing_opt_in",
@@ -35,10 +35,11 @@ js_type_check("closure_compile") {
":oobe_dialog",
":oobe_enable_kiosk",
":oobe_eula",
+ ":oobe_help_dialog",
+ ":oobe_i18n_behavior",
":oobe_i18n_dropdown",
":oobe_network",
":oobe_reset",
- ":oobe_reset_confirmation_overlay",
":oobe_select",
":oobe_supervision_transition",
":oobe_update",
@@ -51,29 +52,6 @@ js_type_check("closure_compile") {
]
}
-js2gtest("login_unitjs_tests") {
- # These could be unit tests, except they need a browser context in order
- # to construct a DOMParser object - so they are webui tests.
- test_type = "webui"
- sources = [
- "saml_password_attributes_test.unitjs",
- "saml_timestamps_test.unitjs",
- ]
- gen_include_files = [
- "saml_password_attributes.js",
- "saml_timestamps.js",
- "//ui/webui/resources/js/cr.js",
- ]
- defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
-}
-
-source_set("browser_tests") {
- testonly = true
- deps = [
- ":login_unitjs_tests",
- ]
-}
-
###############################
# Closure compiler libraries below
@@ -98,6 +76,10 @@ js_library("login_screen_behavior") {
]
}
+js_library("oobe_i18n_behavior") {
+ deps = [ "//ui/webui/resources/js:i18n_behavior" ]
+}
+
js_library("oobe_dialog_host_behavior") {
}
@@ -109,39 +91,37 @@ js_library("oobe_welcome") {
":fake_oobe",
":login_screen_behavior",
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("offline_ad_login") {
deps = [
":oobe_dialog_host_behavior",
+ ":oobe_i18n_behavior",
":oobe_select",
"//ui/webui/resources/cr_elements/cr_input:cr_input",
- "//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:load_time_data",
]
}
js_library("multidevice_setup_first_run") {
deps = [
+ ":oobe_i18n_behavior",
"//ui/webui/resources/cr_components/chromeos/multidevice_setup:mojo_api",
"//ui/webui/resources/cr_components/chromeos/multidevice_setup:multidevice_setup",
"//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
]
}
js_library("active_directory_password_change") {
- deps = [
- "//ui/webui/resources/js:i18n_behavior",
- ]
+ deps = [ ":oobe_i18n_behavior" ]
}
js_library("app_downloading") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
@@ -149,44 +129,37 @@ js_library("arc_terms_of_service") {
deps = [
":html-echo",
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("demo_preferences") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("demo_setup") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("encryption_migration") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
- ]
-}
-
-js_library("enrollment_license_card") {
- deps = [
- ":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("fingerprint_setup") {
deps = [
":oobe_dialog_host_behavior",
+ ":oobe_i18n_behavior",
"//ui/webui/resources/cr_elements/chromeos/cr_lottie:cr_lottie",
"//ui/webui/resources/cr_elements/cr_fingerprint:cr_fingerprint_progress_arc",
- "//ui/webui/resources/js:i18n_behavior",
]
}
@@ -206,8 +179,14 @@ js_library("gaia_input") {
}
js_library("gaia_password_changed") {
+ deps = [ ":oobe_i18n_behavior" ]
+}
+
+js_library("gesture_navigation") {
deps = [
- "//ui/webui/resources/js:i18n_behavior",
+ ":login_screen_behavior",
+ ":oobe_dialog_host_behavior",
+ ":oobe_i18n_behavior",
]
}
@@ -220,7 +199,7 @@ js_library("html-echo") {
js_library("marketing_opt_in") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
@@ -240,7 +219,7 @@ js_library("notification_card") {
js_library("offline_gaia") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
@@ -251,80 +230,75 @@ js_library("oobe_buttons") {
}
js_library("oobe_dialog") {
- deps = [
- "//ui/webui/resources/cr_elements:cr_scrollable_behavior",
- ]
+ deps = [ "//ui/webui/resources/cr_elements:cr_scrollable_behavior" ]
}
js_library("oobe_enable_kiosk") {
deps = [
":login_screen_behavior",
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("oobe_eula") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
+js_library("oobe_help_dialog") {
+ deps = [ ":oobe_i18n_behavior" ]
+}
+
js_library("oobe_i18n_dropdown") {
- deps = [
- ":oobe_types",
- ]
+ deps = [ ":oobe_types" ]
}
js_library("oobe_network") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
- ]
-}
-
-js_library("oobe_reset_confirmation_overlay") {
- deps = [
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("oobe_reset") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("oobe_supervision_transition") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("oobe_update") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("recommend_apps") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
js_library("saml_confirm_password") {
+ deps = [ ":oobe_i18n_behavior" ]
}
js_library("sync_consent") {
deps = [
":oobe_dialog_host_behavior",
- "//ui/webui/resources/js:i18n_behavior",
+ ":oobe_i18n_behavior",
]
}
diff --git a/chromium/chrome/browser/resources/chromeos/login/components/BUILD.gn b/chromium/chrome/browser/resources/chromeos/login/components/BUILD.gn
new file mode 100644
index 00000000000..96ebbf270c0
--- /dev/null
+++ b/chromium/chrome/browser/resources/chromeos/login/components/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chrome/test/base/js2gtest.gni")
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+ deps = [ ":progress_list_item" ]
+}
+
+###############################
+# Closure compiler libraries below
+
+js_library("progress_list_item") {
+ deps = [ "../:oobe_i18n_behavior" ]
+}
diff --git a/chromium/chrome/browser/resources/chromeos/machine_learning/BUILD.gn b/chromium/chrome/browser/resources/chromeos/machine_learning/BUILD.gn
index bca7700d77d..a4f22168e19 100644
--- a/chromium/chrome/browser/resources/chromeos/machine_learning/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/machine_learning/BUILD.gn
@@ -14,9 +14,7 @@ js_type_check("closure_compile") {
}
js_library("test_model_tab") {
- deps = [
- ":machine_learning_internals_utils",
- ]
+ deps = [ ":machine_learning_internals_utils" ]
}
js_library("machine_learning_internals") {
diff --git a/chromium/chrome/browser/resources/chromeos/network_ui/BUILD.gn b/chromium/chrome/browser/resources/chromeos/network_ui/BUILD.gn
index fafbe28decd..6060563b75e 100644
--- a/chromium/chrome/browser/resources/chromeos/network_ui/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/network_ui/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":network_ui",
- ]
+ deps = [ ":network_ui" ]
}
js_library("network_ui") {
diff --git a/chromium/chrome/browser/resources/chromeos/set_time_dialog/BUILD.gn b/chromium/chrome/browser/resources/chromeos/set_time_dialog/BUILD.gn
index ce57213b9dc..7cb59f79254 100644
--- a/chromium/chrome/browser/resources/chromeos/set_time_dialog/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/set_time_dialog/BUILD.gn
@@ -25,9 +25,7 @@ js_library("set_time_dialog") {
}
js_library("set_time_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
externs_list = [ "$externs_path/chrome_send.js" ]
}
@@ -38,7 +36,5 @@ polymer_modulizer("set_time_dialog") {
}
group("polymer3_elements") {
- deps = [
- ":set_time_dialog_module",
- ]
+ public_deps = [ ":set_time_dialog_module" ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/smb_shares/BUILD.gn b/chromium/chrome/browser/resources/chromeos/smb_shares/BUILD.gn
index 99a7d9fd23b..ef5886a1842 100644
--- a/chromium/chrome/browser/resources/chromeos/smb_shares/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/smb_shares/BUILD.gn
@@ -3,8 +3,10 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
js_type_check("closure_compile") {
+ is_polymer3 = true
deps = [
":smb_credentials_dialog",
":smb_share_dialog",
@@ -13,19 +15,38 @@ js_type_check("closure_compile") {
js_library("smb_share_dialog") {
deps = [
- "//ui/webui/resources/cr_components/chromeos/smb_shares:add_smb_share_dialog",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/cr_components/chromeos/smb_shares:add_smb_share_dialog.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
]
}
js_library("smb_credentials_dialog") {
deps = [
- "//ui/webui/resources/cr_components/chromeos/smb_shares:smb_browser_proxy",
- "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
- "//ui/webui/resources/cr_elements/cr_input:cr_input",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/cr_components/chromeos/smb_shares:smb_browser_proxy.m",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+}
+
+polymer_modulizer("smb_share_dialog") {
+ js_file = "smb_share_dialog.js"
+ html_file = "smb_share_dialog.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("smb_credentials_dialog") {
+ js_file = "smb_credentials_dialog.js"
+ html_file = "smb_credentials_dialog.html"
+ html_type = "v3-ready"
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":smb_credentials_dialog_module",
+ ":smb_share_dialog_module",
]
}
diff --git a/chromium/chrome/browser/resources/chromeos/sys_internals/BUILD.gn b/chromium/chrome/browser/resources/chromeos/sys_internals/BUILD.gn
index 0e3b81047a0..b365621c31e 100644
--- a/chromium/chrome/browser/resources/chromeos/sys_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/sys_internals/BUILD.gn
@@ -24,13 +24,9 @@ js_library("index") {
}
js_library("constants") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("types") {
- deps = [
- "line_chart:data_series",
- ]
+ deps = [ "line_chart:data_series" ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/sys_internals/line_chart/BUILD.gn b/chromium/chrome/browser/resources/chromeos/sys_internals/line_chart/BUILD.gn
index 817f99cb978..a43a83423ce 100644
--- a/chromium/chrome/browser/resources/chromeos/sys_internals/line_chart/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/sys_internals/line_chart/BUILD.gn
@@ -43,9 +43,7 @@ js_library("scrollbar") {
}
js_library("unit_label") {
- deps = [
- ":constants",
- ]
+ deps = [ ":constants" ]
}
js_library("menu") {
@@ -57,9 +55,7 @@ js_library("menu") {
}
js_library("data_series") {
- deps = [
- ":constants",
- ]
+ deps = [ ":constants" ]
}
js_library("constants") {
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn b/chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn
index cda784402f3..642f6bd097a 100644
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/zip_archiver/BUILD.gn
@@ -15,13 +15,9 @@ group("zip_archiver") {
zip_archiver_dir = "$root_out_dir/resources/chromeos/zip_archiver"
copy("zip_archiver_css") {
- sources = [
- "css/passphrase.css",
- ]
+ sources = [ "css/passphrase.css" ]
- outputs = [
- "$zip_archiver_dir/css/{{source_file_part}}",
- ]
+ outputs = [ "$zip_archiver_dir/css/{{source_file_part}}" ]
}
copy("zip_archiver_html") {
@@ -30,9 +26,7 @@ copy("zip_archiver_html") {
"html/passphrase.html",
]
- outputs = [
- "$zip_archiver_dir/html/{{source_file_part}}",
- ]
+ outputs = [ "$zip_archiver_dir/html/{{source_file_part}}" ]
}
copy("zip_archiver_icons") {
@@ -44,9 +38,7 @@ copy("zip_archiver_icons") {
"icons/icon96.png",
]
- outputs = [
- "$zip_archiver_dir/icons/{{source_file_part}}",
- ]
+ outputs = [ "$zip_archiver_dir/icons/{{source_file_part}}" ]
}
copy("zip_archiver_js") {
@@ -66,9 +58,7 @@ copy("zip_archiver_js") {
"js/volume.js",
]
- outputs = [
- "$zip_archiver_dir/js/{{source_file_part}}",
- ]
+ outputs = [ "$zip_archiver_dir/js/{{source_file_part}}" ]
}
copy("zip_archiver_root") {
@@ -76,9 +66,7 @@ copy("zip_archiver_root") {
"//chrome/browser/resources/chromeos/zip_archiver/cpp:zip_archiver_pnacl(//build/toolchain/nacl:newlib_pnacl)",
"root_out_dir")
- deps = [
- "//chrome/browser/resources/chromeos/zip_archiver/cpp:zip_archiver_pnacl(//build/toolchain/nacl:newlib_pnacl)",
- ]
+ deps = [ "//chrome/browser/resources/chromeos/zip_archiver/cpp:zip_archiver_pnacl(//build/toolchain/nacl:newlib_pnacl)" ]
sources = [
"$pexe_dir/zip_archiver_pnacl.pexe",
@@ -86,9 +74,7 @@ copy("zip_archiver_root") {
"module.nmf",
]
- outputs = [
- "$zip_archiver_dir/{{source_file_part}}",
- ]
+ outputs = [ "$zip_archiver_dir/{{source_file_part}}" ]
}
static_library("char_coding") {
@@ -97,7 +83,5 @@ static_library("char_coding") {
"cpp/char_coding.h",
]
- deps = [
- "//base",
- ]
+ deps = [ "//base" ]
}
diff --git a/chromium/chrome/browser/resources/chromeos/zip_archiver/cpp/BUILD.gn b/chromium/chrome/browser/resources/chromeos/zip_archiver/cpp/BUILD.gn
index 688f339dd71..d925f456976 100644
--- a/chromium/chrome/browser/resources/chromeos/zip_archiver/cpp/BUILD.gn
+++ b/chromium/chrome/browser/resources/chromeos/zip_archiver/cpp/BUILD.gn
@@ -55,16 +55,12 @@ source_set("ziparchiver_unittests") {
"//testing/gtest",
]
- data = [
- "//chrome/browser/resources/chromeos/zip_archiver/test/data/",
- ]
+ data = [ "//chrome/browser/resources/chromeos/zip_archiver/test/data/" ]
}
if (is_nacl) {
executable("zip_archiver_pnacl") {
- sources = [
- "module.cc",
- ]
+ sources = [ "module.cc" ]
deps = [
":zip_archiver_library",
diff --git a/chromium/chrome/browser/resources/component_extension_resources.grd b/chromium/chrome/browser/resources/component_extension_resources.grd
index b25e2d366cf..c737ee855ac 100644
--- a/chromium/chrome/browser/resources/component_extension_resources.grd
+++ b/chromium/chrome/browser/resources/component_extension_resources.grd
@@ -59,6 +59,7 @@
<include name="IDR_IDENTITY_API_SCOPE_APPROVAL_DIALOG_CSS" file="identity_scope_approval_dialog/scope_approval_dialog.css" type="BINDATA" />
<include name="IDR_IDENTITY_API_SCOPE_APPROVAL_DIALOG" file="identity_scope_approval_dialog/scope_approval_dialog.html" type="BINDATA" />
<include name="IDR_IDENTITY_API_SCOPE_APPROVAL_DIALOG_JS" file="identity_scope_approval_dialog/scope_approval_dialog.js" type="BINDATA" />
+ <include name="IDR_IDENTITY_API_SCOPE_APPROVAL_INJECT_JS" file="identity_scope_approval_dialog/inject.js" type="BINDATA" />
<if expr="chromeos">
<include name="IDR_WALLPAPER_MANAGER_CONSTANTS_JS" file="chromeos/wallpaper_manager/js/constants.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_WALLPAPER_MANAGER_EVENT_JS" file="chromeos/wallpaper_manager/js/event_page.js" flattenhtml="true" type="BINDATA" />
@@ -101,9 +102,9 @@
<include name="IDR_PDF_INDEX_CSS" file="pdf/index.css" allowexternalscript="true" type="BINDATA" />
<include name="IDR_PDF_MAIN_JS" file="pdf/main.js" type="BINDATA" preprocess="true" />
<include name="IDR_PDF_PDF_VIEWER_JS" file="pdf/pdf_viewer.js" type="BINDATA" />
+ <include name="IDR_PDF_CONSTANTS_JS" file="pdf/constants.js" type="BINDATA" />
<include name="IDR_PDF_CONTROLLER_JS" file="pdf/controller.js" type="BINDATA" />
<include name="IDR_PDF_TOOLBAR_MANAGER_JS" file="pdf/toolbar_manager.js" type="BINDATA" />
- <include name="IDR_PDF_PDF_FITTING_TYPE_JS" file="pdf/pdf_fitting_type.js" type="BINDATA" />
<include name="IDR_PDF_VIEWPORT_JS" file="pdf/viewport.js" type="BINDATA" />
<include name="IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS" file="pdf/open_pdf_params_parser.js" type="BINDATA" />
<include name="IDR_PDF_NAVIGATOR_JS" file="pdf/navigator.js" type="BINDATA" />
diff --git a/chromium/chrome/browser/resources/components/BUILD.gn b/chromium/chrome/browser/resources/components/BUILD.gn
index d62c4b0188f..5f65e311b26 100644
--- a/chromium/chrome/browser/resources/components/BUILD.gn
+++ b/chromium/chrome/browser/resources/components/BUILD.gn
@@ -5,16 +5,15 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":components",
- ]
+ uses_js_modules = true
+ deps = [ ":components" ]
}
js_library("components") {
deps = [
"//third_party/jstemplate:jstemplate",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:util",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:util.m",
]
}
diff --git a/chromium/chrome/browser/resources/components/components.html b/chromium/chrome/browser/resources/components/components.html
index a6e144fb2ad..7361019927a 100644
--- a/chromium/chrome/browser/resources/components/components.html
+++ b/chromium/chrome/browser/resources/components/components.html
@@ -66,11 +66,8 @@
</div>
</div>
</div>
-<script src="chrome://resources/js/util.js"></script>
-<script src="chrome://resources/js/cr.js"></script>
-<script src="chrome://components/components.js"></script>
-<script src="chrome://resources/js/load_time_data.js"></script>
+
+<script type="module" src="components.js"></script>
<script src="chrome://resources/js/jstemplate_compiled.js"></script>
-<script src="chrome://components/strings.js"></script>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/components/components.js b/chromium/chrome/browser/resources/components/components.js
index 9636e829963..f50d4b36097 100644
--- a/chromium/chrome/browser/resources/components/components.js
+++ b/chromium/chrome/browser/resources/components/components.js
@@ -2,7 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-'use strict';
+import './strings.m.js';
+
+import {addWebUIListener, isChromeOS, sendWithPromise} from 'chrome://resources/js/cr.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
/**
* An array of the latest component data including ID, name, status and
@@ -31,10 +35,9 @@ function renderTemplate(componentsData) {
/**
* Asks the C++ ComponentsDOMHandler to get details about the installed
* components.
- * The ComponentsDOMHandler should reply to returnComponentsData() (below).
*/
function requestComponentsData() {
- chrome.send('requestComponentsData');
+ sendWithPromise('requestComponentsData').then(returnComponentsData);
}
/**
@@ -82,7 +85,7 @@ function returnComponentsData(componentsData) {
}
// Disable some controls for Guest mode in ChromeOS.
- if (cr.isChromeOS && loadTimeData.getBoolean('isGuest')) {
+ if (isChromeOS && loadTimeData.getBoolean('isGuest')) {
document.querySelectorAll('[guest-disabled]').forEach(function(element) {
element.disabled = true;
});
@@ -93,8 +96,7 @@ function returnComponentsData(componentsData) {
}
/**
- * This event function is called from component UI indicating changed state
- * of component updater service.
+ * Listener called when state of component updater service changes.
* @param {Object} eventArgs Contains event and component ID. Component ID is
* optional.
*/
@@ -108,6 +110,13 @@ function onComponentEvent(eventArgs) {
const filteredComponents = currentComponentsData.filter(function(entry) {
return entry.id === id;
});
+
+ // A component may be added from another page so the status and version
+ // should only be updated if the component is listed on this page.
+ if (filteredComponents.length === 0) {
+ return;
+ }
+
const component = filteredComponents[0];
const status = eventArgs['event'];
@@ -135,4 +144,7 @@ function handleCheckUpdate(node) {
}
// Get data and have it displayed upon loading.
-document.addEventListener('DOMContentLoaded', requestComponentsData);
+document.addEventListener('DOMContentLoaded', function() {
+ addWebUIListener('component-event', onComponentEvent);
+ requestComponentsData();
+});
diff --git a/chromium/chrome/browser/resources/conflicts/BUILD.gn b/chromium/chrome/browser/resources/conflicts/BUILD.gn
new file mode 100644
index 00000000000..a9939157d1c
--- /dev/null
+++ b/chromium/chrome/browser/resources/conflicts/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+ uses_js_modules = true
+ deps = [ ":about_conflicts" ]
+}
+
+js_library("about_conflicts") {
+ deps = [
+ "//third_party/jstemplate:jstemplate",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:util.m",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/conflicts/about_conflicts.html b/chromium/chrome/browser/resources/conflicts/about_conflicts.html
index c8da460f8c8..83c277a0bbe 100644
--- a/chromium/chrome/browser/resources/conflicts/about_conflicts.html
+++ b/chromium/chrome/browser/resources/conflicts/about_conflicts.html
@@ -1,5 +1,9 @@
+<!--
+This is an internal only page meant for debugging. It is not intended for
+general use and is not localized.
+-->
<!doctype html>
-<html lang="en">
+<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
@@ -254,11 +258,7 @@ html[dir=rtl] .clearing {
</div>
</div>
</div>
-<script src="chrome://resources/js/cr.js"></script>
<script src="chrome://resources/js/jstemplate_compiled.js"></script>
-<script src="chrome://resources/js/promise_resolver.js"></script>
-<script src="chrome://resources/js/util.js"></script>
-
-<script src="chrome://conflicts/conflicts.js"></script>
+<script type="module" src="chrome://conflicts/conflicts.js"></script>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/conflicts/about_conflicts.js b/chromium/chrome/browser/resources/conflicts/about_conflicts.js
index f44af07a016..0e435313c85 100644
--- a/chromium/chrome/browser/resources/conflicts/about_conflicts.js
+++ b/chromium/chrome/browser/resources/conflicts/about_conflicts.js
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
+
/**
* This variable structure is here to document the structure that the template
* expects to correctly populate the page.
@@ -39,7 +42,7 @@ function renderTemplate(moduleListData) {
* and return detailed data about the configuration.
*/
function requestModuleListData() {
- cr.sendWithPromise('requestModuleList').then(returnModuleList);
+ sendWithPromise('requestModuleList').then(returnModuleList);
}
/**
@@ -52,9 +55,9 @@ function filterModuleListData() {
const modules = document.getElementsByClassName('module');
// Loop through all modules, and hide all that don't match the filter.
- for (i = 0; i < modules.length; ++i) {
- modules[i].style.display =
- modules[i].dataset.process.includes(filter) ? '' : 'none';
+ for (const module of modules) {
+ module.style.display =
+ module.dataset['process'].includes(filter) ? '' : 'none';
}
}
diff --git a/chromium/chrome/browser/resources/cryptotoken/cryptotokenbackground.js b/chromium/chrome/browser/resources/cryptotoken/cryptotokenbackground.js
index 977b3804a0d..caeb698a9af 100644
--- a/chromium/chrome/browser/resources/cryptotoken/cryptotokenbackground.js
+++ b/chromium/chrome/browser/resources/cryptotoken/cryptotokenbackground.js
@@ -13,6 +13,7 @@ var HTTP_ORIGINS_ALLOWED = false;
/** @const */
var LOG_SAVER_EXTENSION_ID = 'fjajfjhkeibgmiggdfehjplbhmfkialk';
+var LOG_SAVER_EXTENSION_ORIGIN = 'chrome-extension://' + LOG_SAVER_EXTENSION_ID;
var FACTORY_REGISTRY = (function() {
var windowTimer = new WindowTimer();
@@ -105,7 +106,7 @@ function messageHandler(request, sender, sendResponse) {
}
/**
- * Listen to individual messages sent from (whitelisted) webpages via
+ * Listen to individual messages sent from (allowlisted) extensions/apps via
* chrome.runtime.sendMessage
* @param {*} request The received request
* @param {!MessageSender} sender The message sender
@@ -113,7 +114,7 @@ function messageHandler(request, sender, sendResponse) {
* @return {boolean}
*/
function messageHandlerExternal(request, sender, sendResponse) {
- if (sender.id && sender.id === LOG_SAVER_EXTENSION_ID) {
+ if (sender.origin && sender.origin === LOG_SAVER_EXTENSION_ORIGIN) {
return handleLogSaverMessage(request);
}
diff --git a/chromium/chrome/browser/resources/cryptotoken/enroller.js b/chromium/chrome/browser/resources/cryptotoken/enroller.js
index fd81423f478..4088338c9e8 100644
--- a/chromium/chrome/browser/resources/cryptotoken/enroller.js
+++ b/chromium/chrome/browser/resources/cryptotoken/enroller.js
@@ -492,6 +492,8 @@ function handleU2fEnrollRequest(messageSender, request, sendResponse) {
return null;
}
+ chrome.cryptotokenPrivate.recordRegisterRequest(sender.tabId, sender.frameId);
+
var timeoutValueSeconds = getTimeoutValueFromRequest(request);
// Attenuate watchdog timeout value less than the enroller's timeout, so the
// watchdog only fires after the enroller could reasonably have called back,
diff --git a/chromium/chrome/browser/resources/cryptotoken/signer.js b/chromium/chrome/browser/resources/cryptotoken/signer.js
index 30cd3ca9097..725e8ee66cb 100644
--- a/chromium/chrome/browser/resources/cryptotoken/signer.js
+++ b/chromium/chrome/browser/resources/cryptotoken/signer.js
@@ -58,6 +58,9 @@ function handleU2fSignRequest(messageSender, request, sendResponse) {
queuedSignRequest = validateAndEnqueueSignRequest(
sender, request, sendErrorResponse, sendSuccessResponse);
+ if (queuedSignRequest) {
+ chrome.cryptotokenPrivate.recordSignRequest(sender.tabId, sender.frameId);
+ }
return queuedSignRequest;
}
diff --git a/chromium/chrome/browser/resources/cryptotoken/webrequestsender.js b/chromium/chrome/browser/resources/cryptotoken/webrequestsender.js
index 9630de47e9d..734abbbf313 100644
--- a/chromium/chrome/browser/resources/cryptotoken/webrequestsender.js
+++ b/chromium/chrome/browser/resources/cryptotoken/webrequestsender.js
@@ -12,6 +12,7 @@
* @typedef {{
* origin: string,
* tabId: (number|undefined)
+ * frameId: (number|undefined)
* }}
*/
var WebRequestSender;
@@ -31,6 +32,7 @@ function createSenderFromMessageSender(messageSender) {
var sender = {origin: origin};
if (messageSender.tab) {
sender.tabId = messageSender.tab.id;
+ sender.frameId = messageSender.frameId;
}
return sender;
}
diff --git a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.css b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.css
index ff0510a1b18..0944dac060e 100644
--- a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.css
+++ b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.css
@@ -13,16 +13,16 @@ body {
margin: 0;
}
-#header {
+div {
margin: 5px;
}
-/* Checkboxes */
-
-#log-checkbox-container {
- margin: 5px;
+button {
+ margin-inline-end: 5px;
}
+/* Header */
+
#log-checkbox-container button {
margin-inline-end: 8px;
}
@@ -31,24 +31,23 @@ body {
vertical-align: middle;
}
-#log-checkbox-show {
- font-weight: bold;
-}
-
#log-checkbox-container input {
margin-bottom: 1px;
vertical-align: middle;
}
+#log-level-select {
+ padding: 0 5px;
+}
+
/* Log */
#log-container {
border: 1px solid rgb(220, 220, 220);
flex: 1 1 100%;
font-size: 12px;
- margin: 5px;
overflow: auto;
- padding: 10px;
+ padding: 5px;
}
#log-container p {
diff --git a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.html b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.html
index d0724135998..1360c4d93b0 100644
--- a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.html
+++ b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.html
@@ -12,28 +12,30 @@
</head>
<body>
<div id="header">
- <p>$i18n{autoRefreshText}</p>
+ <span>$i18n{autoRefreshText}</span>
</div>
- <div id="log-checkbox-container">
+ <div>
<button id="log-refresh">$i18n{logRefreshText}</button>
<button id="log-clear">$i18n{logClearText}</button>
- <label id="log-checkbox-show">$i18n{logLevelShowText}</label>
- <label>
- <input id="log-level-error" type="checkbox">
- <span>$i18n{logLevelErrorText}</span>
- </label>
- <label>
- <input id="log-level-user" type="checkbox">
- <span>$i18n{logLevelUserText}</span>
- </label>
+ <span>$i18n{logLevelLabel}</span>
+ <select id="log-level-select">
+ <option value="Error">$i18n{logLevelErrorText}</option>
+ <option value="User">$i18n{logLevelUserText}</option>
+ <option value="Event">$i18n{logLevelEventText}</option>
+ <option value="Debug">$i18n{logLevelDebugText}</option>
+ </select>
<label>
- <input id="log-level-event" type="checkbox">
- <span>$i18n{logLevelEventText}</span>
+ <input id="log-fileinfo" type="checkbox">
+ <span>$i18n{logLevelFileinfoText}</span>
</label>
<label>
- <input id="log-level-debug" type="checkbox">
- <span>$i18n{logLevelDebugText}</span>
+ <input id="log-timedetail" type="checkbox">
+ <span>$i18n{logLevelTimeDetailText}</span>
</label>
+ </div>
+
+ <div id="log-checkbox-container">
+ <button id="log-clear-types">$i18n{logClearTypesText}</button>
<label>
<input id="log-type-login" type="checkbox">
<span>$i18n{logTypeLoginText}</span>
@@ -66,14 +68,6 @@
<input id="log-type-fido" type="checkbox">
<span>$i18n{logTypeFidoText}</span>
</label>
- <label>
- <input id="log-fileinfo" type="checkbox">
- <span>$i18n{logLevelFileinfoText}</span>
- </label>
- <label>
- <input id="log-timedetail" type="checkbox">
- <span>$i18n{logLevelTimeDetailText}</span>
- </label>
</div>
<div id="log-container"></div>
</body>
diff --git a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.js b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.js
index 2e4181171db..c4a211ecff1 100644
--- a/chromium/chrome/browser/resources/device_log_ui/device_log_ui.js
+++ b/chromium/chrome/browser/resources/device_log_ui/device_log_ui.js
@@ -5,6 +5,9 @@
const DeviceLogUI = (function() {
'use strict';
+ // List of log levels in priority order.
+ const logLevels = ['Debug', 'Event', 'User', 'Error'];
+
/**
* Creates a tag for the log level.
*
@@ -43,8 +46,9 @@ const DeviceLogUI = (function() {
*/
const createLogEntryText = function(logEntry) {
const level = logEntry['level'];
- const levelCheckbox = 'log-level-' + level.toLowerCase();
- if ($(levelCheckbox) && !$(levelCheckbox).checked) {
+ const levelIndex = logLevels.indexOf(level);
+ const levelSelectIndex = logLevels.indexOf($('log-level-select').value);
+ if (levelIndex < levelSelectIndex) {
return null;
}
@@ -120,6 +124,14 @@ const DeviceLogUI = (function() {
requestLog();
};
+ const clearLogTypes = function() {
+ const checkboxes = document.querySelectorAll(
+ '#log-checkbox-container input[type="checkbox"]');
+ for (let i = 0; i < checkboxes.length; ++i) {
+ checkboxes[i].checked = false;
+ }
+ };
+
/**
* Sets refresh rate if the interval is found in the url.
*/
@@ -134,24 +146,26 @@ const DeviceLogUI = (function() {
* Gets log information from WebUI.
*/
document.addEventListener('DOMContentLoaded', function() {
- // Show all levels except 'debug' by default.
- $('log-level-error').checked = true;
- $('log-level-user').checked = true;
- $('log-level-event').checked = true;
- $('log-level-debug').checked = false;
+ // Show all levels except 'Debug' by default.
+ $('log-level-select').value = 'Event';
+ $('log-level-select').onchange = requestLog;
// Show all types by default.
let checkboxes = document.querySelectorAll(
- '#log-checkbox-container input[type="checkbox"][id*="log-type"]');
+ '#log-checkbox-container input[type="checkbox"]');
for (let i = 0; i < checkboxes.length; ++i) {
checkboxes[i].checked = true;
}
$('log-fileinfo').checked = false;
+ $('log-fileinfo').onclick = requestLog;
$('log-timedetail').checked = false;
+ $('log-timedetail').onclick = requestLog;
$('log-refresh').onclick = requestLog;
$('log-clear').onclick = clearLog;
+ $('log-clear-types').onclick = clearLogTypes;
+
checkboxes = document.querySelectorAll(
'#log-checkbox-container input[type="checkbox"]');
for (let i = 0; i < checkboxes.length; ++i) {
diff --git a/chromium/chrome/browser/resources/discards/BUILD.gn b/chromium/chrome/browser/resources/discards/BUILD.gn
index 4c44f557b82..e5181983e38 100644
--- a/chromium/chrome/browser/resources/discards/BUILD.gn
+++ b/chromium/chrome/browser/resources/discards/BUILD.gn
@@ -82,30 +82,26 @@ action("generate_graph_tab") {
"graph_doc_template.html",
"graph_tab_template.html",
]
- outputs = [
- "$target_gen_dir/graph_tab.js",
- ]
+ outputs = [ "$target_gen_dir/graph_tab.js" ]
args = rebase_path(outputs) + rebase_path([
"graph_doc_template.html",
"graph_doc.js",
]) +
rebase_path([ "$target_gen_dir/graph_tab_template.js" ])
- deps = [
- ":graph_tab_module",
- ]
+ deps = [ ":graph_tab_module" ]
}
# Action with a transparent name.
group("discards_resources_gen") {
- deps = [
+ public_deps = [
":generate_graph_tab",
":polymer3_elements",
]
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":database_tab_module",
":discards_main_module",
":discards_tab_module",
diff --git a/chromium/chrome/browser/resources/discards/database_tab.html b/chromium/chrome/browser/resources/discards/database_tab.html
index a011dcf5b07..b5905014f5b 100644
--- a/chromium/chrome/browser/resources/discards/database_tab.html
+++ b/chromium/chrome/browser/resources/discards/database_tab.html
@@ -1,4 +1,10 @@
<style>
+ @media (prefers-color-scheme: dark) {
+ :host {
+ color: var(--cr-secondary-text-color);
+ }
+ }
+
.add-origin-container {
display: flex;
padding-top: 10px;
@@ -17,6 +23,7 @@
table th {
background: rgb(224, 236, 255);
+ color: black;
padding-bottom: 4px;
padding-inline-end: 16px;
padding-top: 4px;
diff --git a/chromium/chrome/browser/resources/discards/database_tab.js b/chromium/chrome/browser/resources/discards/database_tab.js
index e110244ad72..93367e2adf3 100644
--- a/chromium/chrome/browser/resources/discards/database_tab.js
+++ b/chromium/chrome/browser/resources/discards/database_tab.js
@@ -10,7 +10,7 @@ import './mojo_api.js';
import {assertNotReached} from 'chrome://resources/js/assert.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {boolToString, durationToString, getOrCreateDetailsProvider, secondsToString} from './discards.js';
+import {boolToString, durationToString, getOrCreateSiteDataProvider, secondsToString} from './discards.js';
import {SortedTableBehavior} from './sorted_table_behavior.js';
/**
@@ -229,14 +229,14 @@ Polymer({
/** @private {!Object} */
requestedOrigins_: {},
- /** @private {?discards.mojom.DetailsProviderRemote} */
- discardsDetailsProvider_: null,
+ /** @private {?discards.mojom.SiteDataProviderRemote} */
+ siteDataProvider_: null,
/** @override */
- ready: function() {
+ ready() {
this.setSortKey('origin');
this.requestedOrigins_ = {};
- this.discardsDetailsProvider_ = getOrCreateDetailsProvider();
+ this.siteDataProvider_ = getOrCreateSiteDataProvider();
// Specifies the update interval of the table, in ms.
const UPDATE_INTERVAL_MS = 1000;
@@ -256,7 +256,7 @@ Polymer({
},
/** @override */
- detached: function() {
+ detached() {
// Clear the update timers to avoid memory leaks.
clearInterval(this.updateTableTimer_);
this.updateTableTimer_ = 0;
@@ -268,8 +268,8 @@ Polymer({
* Issues a request for the data and renders on response.
* @private
*/
- updateDbRows_: function() {
- this.discardsDetailsProvider_
+ updateDbRows_() {
+ this.siteDataProvider_
.getSiteCharacteristicsDatabase(Object.keys(this.requestedOrigins_))
.then(response => {
// Bail if the SiteCharacteristicsDatabase is turned off.
@@ -291,7 +291,7 @@ Polymer({
* Adds the current new origin to requested origins and starts an update.
* @private
*/
- addNewOrigin_: function() {
+ addNewOrigin_() {
this.requestedOrigins_[this.newOrigin_] = true;
this.newOrigin_ = '';
this.updateDbRows_();
@@ -302,7 +302,7 @@ Polymer({
* origins.
* @private
*/
- onAddOriginClick_: function() {
+ onAddOriginClick_() {
this.addNewOrigin_();
// Set the focus back to the input field for convenience.
@@ -313,7 +313,7 @@ Polymer({
* A key-down handler that adds the current new origin to requested origins.
* @private
*/
- onOriginKeydown_: function(e) {
+ onOriginKeydown_(e) {
if (e.key === 'Enter' && this.isValidOrigin_(this.newOrigin_)) {
this.addNewOrigin_();
e.stopPropagation();
@@ -324,8 +324,8 @@ Polymer({
* Issues a request for the database sizes and renders on response.
* @private
*/
- updateDbSizes_: function() {
- this.discardsDetailsProvider_.getSiteCharacteristicsDatabaseSize().then(
+ updateDbSizes_() {
+ this.siteDataProvider_.getSiteCharacteristicsDatabaseSize().then(
response => {
// Bail if the SiteCharacteristicsDatabase is turned off.
if (!response.dbSize) {
@@ -346,7 +346,7 @@ Polymer({
* number if a > b.
* @private
*/
- computeSortFunction_: function(sortKey, sortReverse) {
+ computeSortFunction_(sortKey, sortReverse) {
// Polymer 2 may invoke multi-property observers before all properties
// are defined.
if (!sortKey) {
@@ -365,7 +365,7 @@ Polymer({
* @return {boolean} Whether the origin is valid.
* @private
*/
- isValidOrigin_: function(origin) {
+ isValidOrigin_(origin) {
const re = /(https?|ftp):\/\/[a-z+.]/;
return re.test(origin);
@@ -376,7 +376,7 @@ Polymer({
* @return {boolean} Whether the origin is valid or empty.
* @private
*/
- isEmptyOrValidOrigin_: function(origin) {
+ isEmptyOrValidOrigin_(origin) {
return !origin || this.isValidOrigin_(origin);
},
@@ -385,7 +385,7 @@ Polymer({
* @return {string} A display string representing value.
* @private
*/
- boolToString_: function(value) {
+ boolToString_(value) {
return boolToString(value);
},
@@ -396,7 +396,7 @@ Polymer({
* occurred.
* @private
*/
- lastUseToString_: function(time) {
+ lastUseToString_(time) {
const nowSecondsFromEpoch = Math.round(Date.now() / 1000);
return durationToString(nowSecondsFromEpoch - time);
},
@@ -407,7 +407,7 @@ Polymer({
* @return {string} A human-readable string representing the feature.
* @private
*/
- featureToString_: function(feature) {
+ featureToString_(feature) {
if (!feature) {
return 'N/A';
}
@@ -432,7 +432,7 @@ Polymer({
* unavailable.
* @private
*/
- getLoadTimeEstimate_: function(item, propertyName) {
+ getLoadTimeEstimate_(item, propertyName) {
return formatLoadTimeEstimate(item, propertyName);
},
@@ -442,7 +442,7 @@ Polymer({
* @return {string} A human readable string representing value.
* @private
*/
- kilobytesToString_: function(value) {
+ kilobytesToString_(value) {
return value == -1 ? 'N/A' : kilobytesToString(value);
},
@@ -451,7 +451,7 @@ Polymer({
* @return {string} A human readable string representing value.
* @private
*/
- optionalIntegerToString_: function(value) {
+ optionalIntegerToString_(value) {
return value == -1 ? 'N/A' : value.toString();
},
});
diff --git a/chromium/chrome/browser/resources/discards/discards.html b/chromium/chrome/browser/resources/discards/discards.html
index 9874bc61a3e..c4519e0594f 100644
--- a/chromium/chrome/browser/resources/discards/discards.html
+++ b/chromium/chrome/browser/resources/discards/discards.html
@@ -10,6 +10,7 @@ general use and is not localized.-->
<head>
<title>Discards</title>
<meta charset="utf-8">
+ <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
<style>
html,
@@ -18,12 +19,18 @@ general use and is not localized.-->
overflow: hidden;
}
+ @media (prefers-color-scheme: dark) {
+ body {
+ background-color: var(--md-background-color);
+ }
+ }
+
body {
margin: 0;
}
</style>
</head>
- <body>
+ <body dir="ltr">
<discards-main></discards-main>
<script type="module" src="discards_main.js"></script>
</body>
diff --git a/chromium/chrome/browser/resources/discards/discards.js b/chromium/chrome/browser/resources/discards/discards.js
index 9d8a9571a45..b93201c96f2 100644
--- a/chromium/chrome/browser/resources/discards/discards.js
+++ b/chromium/chrome/browser/resources/discards/discards.js
@@ -16,6 +16,18 @@
return discardsDetailsProvider;
}
+ let siteDataProvider;
+
+ /**
+ * @return {!discards.mojom.SiteDataProviderRemote} Provides site data info.
+ */
+ export function getOrCreateSiteDataProvider() {
+ if (!siteDataProvider) {
+ siteDataProvider = discards.mojom.SiteDataProvider.getRemote();
+ }
+ return siteDataProvider;
+ }
+
/**
* Pluralizes a string according to the given count. Assumes that appending an
* 's' is sufficient to make a string plural.
diff --git a/chromium/chrome/browser/resources/discards/discards_tab.html b/chromium/chrome/browser/resources/discards/discards_tab.html
index 9eb2fac2ed8..b91684d1b52 100644
--- a/chromium/chrome/browser/resources/discards/discards_tab.html
+++ b/chromium/chrome/browser/resources/discards/discards_tab.html
@@ -7,8 +7,15 @@
table td,
table th {
border: 1px solid #777;
- padding-left: 4px;
- padding-right: 4px;
+ padding-inline-end: 4px;
+ padding-inline-start: 4px;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ table td,
+ table th {
+ border-color: var(--cr-separator-color);
+ }
}
table th {
@@ -29,6 +36,13 @@
justify-content: flex-start;
}
+ @media (prefers-color-scheme: dark) {
+ table td {
+ background-color: var(--google-grey-900);
+ color: var(--cr-secondary-text-color);
+ }
+ }
+
table td.title-cell {
max-width: 200px;
overflow: hidden;
@@ -87,6 +101,12 @@
background: rgb(255, 255, 187);
}
+ @media (prefers-color-scheme: dark) {
+ table tr:hover td {
+ background: var(--google-grey-800);
+ }
+ }
+
th div.header-cell-container::after {
content: '▲';
opacity: 0;
@@ -112,7 +132,7 @@
display: none;
font-size: 0.75rem;
left: 50%;
- margin-left: -100px;
+ margin-inline-start: -100px;
margin-top: 4px;
padding: 4px;
position: absolute;
@@ -126,9 +146,6 @@
}
</style>
<div id="discards">
- <div is="action-link" on-click="discardNow_">
- [Discard a tab now]
- </div>
<div is="action-link" on-click="discardUrgentNow_">
[Urgent discard a tab now]
</div>
@@ -194,11 +211,6 @@
Can freeze?
</div>
</th>
- <th data-sort-key="canDiscard" on-click="onSortClick">
- <div class="header-cell-container">
- Can discard?
- </div>
- </th>
<th data-sort-key="discardCount" on-click="onSortClick">
<div class="header-cell-container">
<div>
@@ -259,19 +271,6 @@
</div>
</div>
</td>
- <td class="boolean-cell">
- <div>[[boolToString_(item.canDiscard)]]</div>
- <div is="action-link" class="tooltip-container"
- disabled$="[[!hasCannotDiscardReasons_(item)]]">
- [View Reason]
- <div class="tooltip">
- <template is="dom-repeat"
- items="[[item.cannotDiscardReasons]]">
- <div>[[item]]</div>
- </template>
- </div>
- </div>
- </td>
<td>[[item.discardCount]]</td>
<td class="boolean-cell">
<div>[[boolToString_(item.isAutoDiscardable)]]</div>
@@ -289,8 +288,6 @@
[Load]</div>
<div is="action-link" on-click="freezeTab_"
disabled$="[[!canFreeze_(item)]]">[Freeze]</div>
- <div is="action-link" on-click="discardTab_"
- disabled$="[[!canDiscard_(item)]]">[Discard]</div>
<div is="action-link" on-click="urgentDiscardTab_"
disabled$="[[!canDiscard_(item)]]">
[Urgent Discard]
diff --git a/chromium/chrome/browser/resources/discards/discards_tab.js b/chromium/chrome/browser/resources/discards/discards_tab.js
index c3bb0da93c9..d0adab8a334 100644
--- a/chromium/chrome/browser/resources/discards/discards_tab.js
+++ b/chromium/chrome/browser/resources/discards/discards_tab.js
@@ -14,15 +14,6 @@ import {boolToString, durationToString, getOrCreateDetailsProvider} from './disc
import {SortedTableBehavior} from './sorted_table_behavior.js';
/**
- * @param {mojom.LifecycleUnitState} state The discard state.
- * @return {boolean} Whether the state is related to discarding.
- */
-function isDiscardRelatedState(state) {
- return state == mojom.LifecycleUnitState.PENDING_DISCARD ||
- state == mojom.LifecycleUnitState.DISCARDED;
-}
-
-/**
* Compares two TabDiscardsInfos based on the data in the provided sort-key.
* @param {string} sortKey The key of the sort. See the "data-sort-key"
* attribute of the table headers for valid sort-keys.
@@ -46,7 +37,7 @@ export function compareTabDiscardsInfos(sortKey, a, b) {
}
// Compares boolean fields.
- if (['canFreeze', 'canDiscard', 'isAutoDiscardable'].includes(sortKey)) {
+ if (['canFreeze', 'isAutoDiscardable'].includes(sortKey)) {
if (val1 == val2) {
return 0;
}
@@ -57,7 +48,7 @@ export function compareTabDiscardsInfos(sortKey, a, b) {
if (sortKey == 'state') {
// If the keys are discarding state, then break ties using the discard
// reason.
- if (val1 == val2 && isDiscardRelatedState(val1)) {
+ if (val1 == val2 && val1 == mojom.LifecycleUnitState.DISCARDED) {
val1 = a['discardReason'];
val2 = b['discardReason'];
}
@@ -108,7 +99,7 @@ Polymer({
discardsDetailsProvider_: null,
/** @override */
- ready: function() {
+ ready() {
this.setSortKey('utilityRank');
this.discardsDetailsProvider_ = getOrCreateDetailsProvider();
@@ -126,7 +117,7 @@ Polymer({
* number if a > b.
* @private
*/
- computeSortFunction_: function(sortKey, sortReverse) {
+ computeSortFunction_(sortKey, sortReverse) {
// Polymer 2.0 may invoke multi-property observers before all properties
// are defined.
if (!sortKey) {
@@ -147,7 +138,7 @@ Polymer({
* @return {string} A string representation of the visibility.
* @private
*/
- visibilityToString_: function(visibility) {
+ visibilityToString_(visibility) {
switch (visibility) {
case discards.mojom.LifecycleUnitVisibility.HIDDEN:
return 'hidden';
@@ -167,7 +158,7 @@ Polymer({
* @return {string} A string representation of the loading state.
* @private
*/
- loadingStateToString_: function(loadingState) {
+ loadingStateToString_(loadingState) {
switch (loadingState) {
case mojom.LifecycleUnitLoadingState.UNLOADED:
return 'unloaded';
@@ -185,12 +176,10 @@ Polymer({
* @return {string} A string representation of the discarding reason.
* @private
*/
- discardReasonToString_: function(reason) {
+ discardReasonToString_(reason) {
switch (reason) {
case mojom.LifecycleUnitDiscardReason.EXTERNAL:
return 'external';
- case mojom.LifecycleUnitDiscardReason.PROACTIVE:
- return 'proactive';
case mojom.LifecycleUnitDiscardReason.URGENT:
return 'urgent';
}
@@ -211,7 +200,7 @@ Polymer({
* augmented with the discard reason if appropriate.
* @private
*/
- lifecycleStateToString_: function(
+ lifecycleStateToString_(
state, reason, visibility, hasFocus, stateChangeTime) {
const pageLifecycleStateFromVisibilityAndFocus = function() {
switch (visibility) {
@@ -234,9 +223,6 @@ Polymer({
return pageLifecycleStateFromVisibilityAndFocus() + ' (pending frozen)';
case mojom.LifecycleUnitState.FROZEN:
return 'frozen';
- case mojom.LifecycleUnitState.PENDING_DISCARD:
- return pageLifecycleStateFromVisibilityAndFocus() +
- ' (pending discard (' + this.discardReasonToString_(reason) + '))';
case mojom.LifecycleUnitState.DISCARDED:
return 'discarded (' + this.discardReasonToString_(reason) + ')' +
((reason == mojom.LifecycleUnitDiscardReason.URGENT) ? ' at ' +
@@ -255,7 +241,7 @@ Polymer({
* Dispatches a request to update tabInfos_.
* @private
*/
- updateTableImpl_: function() {
+ updateTableImpl_() {
this.discardsDetailsProvider_.getTabDiscardsInfo().then(response => {
this.tabInfos_ = response.infos;
});
@@ -267,7 +253,7 @@ Polymer({
* it after rendering instantaneously.
* @private
*/
- updateTable_: function() {
+ updateTable_() {
if (this.updateTimer_) {
clearInterval(this.updateTimer_);
}
@@ -281,7 +267,7 @@ Polymer({
* @return {string} The formatted reactivation score.
* @private
*/
- getReactivationScore_: function(item) {
+ getReactivationScore_(item) {
return item.hasReactivationScore ? item.reactivationScore.toFixed(4) :
'N/A';
},
@@ -292,7 +278,7 @@ Polymer({
* @return {string} The formatted site engagemetn score.
* @private
*/
- getSiteEngagementScore_: function(item) {
+ getSiteEngagementScore_(item) {
return item.siteEngagementScore.toFixed(1);
},
@@ -302,7 +288,7 @@ Polymer({
* @return {string} A style to retrieve and display the item's favicon.
* @private
*/
- getFavIconStyle_: function(item) {
+ getFavIconStyle_(item) {
return 'background-image:' + getFaviconForPageURL(item.tabUrl, false);
},
@@ -312,7 +298,7 @@ Polymer({
* @return {string} A human readable lifecycle state.
* @private
*/
- getLifeCycleState_: function(item) {
+ getLifeCycleState_(item) {
if (item.loadingState != mojom.LifecycleUnitLoadingState.UNLOADED ||
item.discardCount > 0) {
return this.lifecycleStateToString_(
@@ -330,7 +316,7 @@ Polymer({
* @return {string} A string representing the bool.
* @private
*/
- boolToString_: function(value) {
+ boolToString_(value) {
return boolToString(value);
},
@@ -340,7 +326,7 @@ Polymer({
* @return {string} An English string representing the duration.
* @private
*/
- durationToString_: function(secondsAgo) {
+ durationToString_(secondsAgo) {
return durationToString(secondsAgo);
},
@@ -351,7 +337,7 @@ Polymer({
* frozen.
* @private
*/
- hasCannotFreezeReasons_: function(item) {
+ hasCannotFreezeReasons_(item) {
return item.cannotFreezeReasons.length != 0;
},
/**
@@ -361,7 +347,7 @@ Polymer({
* discarded.
* @private
*/
- hasCannotDiscardReasons_: function(item) {
+ hasCannotDiscardReasons_(item) {
return item.cannotDiscardReasons.length != 0;
},
@@ -371,7 +357,7 @@ Polymer({
* @return {boolean} true iff the item can be loaded.
* @private
*/
- canLoad_: function(item) {
+ canLoad_(item) {
return item.loadingState == mojom.LifecycleUnitLoadingState.UNLOADED;
},
@@ -381,13 +367,12 @@ Polymer({
* @return {boolean} true iff the item can be frozen.
* @private
*/
- canFreeze_: function(item) {
+ canFreeze_(item) {
if (item.visibility == discards.mojom.LifecycleUnitVisibility.HIDDEN ||
item.visibility == discards.mojom.LifecycleUnitVisibility.OCCLUDED) {
// Only tabs that aren't visible can be frozen for now.
switch (item.state) {
case mojom.LifecycleUnitState.DISCARDED:
- case mojom.LifecycleUnitState.PENDING_DISCARD:
case mojom.LifecycleUnitState.FROZEN:
case mojom.LifecycleUnitState.PENDING_FREEZE:
return false;
@@ -403,13 +388,12 @@ Polymer({
* @return {boolean} true iff the item can be discarded.
* @private
*/
- canDiscard_: function(item) {
+ canDiscard_(item) {
if (item.visibility == discards.mojom.LifecycleUnitVisibility.HIDDEN ||
item.visibility == discards.mojom.LifecycleUnitVisibility.OCCLUDED) {
// Only tabs that aren't visible can be discarded for now.
switch (item.state) {
case mojom.LifecycleUnitState.DISCARDED:
- case mojom.LifecycleUnitState.PENDING_DISCARD:
return false;
}
return true;
@@ -422,7 +406,7 @@ Polymer({
* @param {Event} e The event.
* @private
*/
- toggleAutoDiscardable_: function(e) {
+ toggleAutoDiscardable_(e) {
const item = e.model.item;
this.discardsDetailsProvider_
.setAutoDiscardable(item.id, !item.isAutoDiscardable)
@@ -434,7 +418,7 @@ Polymer({
* @param {Event} e The event.
* @private
*/
- loadTab_: function(e) {
+ loadTab_(e) {
this.discardsDetailsProvider_.loadById(e.model.item.id);
},
@@ -443,65 +427,36 @@ Polymer({
* @param {Event} e The event.
* @private
*/
- freezeTab_: function(e) {
+ freezeTab_(e) {
this.discardsDetailsProvider_.freezeById(e.model.item.id);
},
/**
- * Implementation function for tab discarding.
- * @param {Event} e The event.
- * @param {boolean} urgent True if tab should be urgently discarded.
- * @private
- */
- discardTabImpl_: function(e, urgent) {
- this.discardsDetailsProvider_.discardById(e.model.item.id, urgent)
- .then(this.updateTable_.bind(this));
- },
-
- /**
- * Event handler that discards a given tab.
- * @param {Event} e The event.
- * @private
- */
- discardTab_: function(e) {
- this.discardTabImpl_(e, false);
- },
-
- /**
* Event handler that discards a given tab urgently.
* @param {Event} e The event.
* @private
*/
- urgentDiscardTab_: function(e) {
- this.discardTabImpl_(e, true);
+ urgentDiscardTab_(e) {
+ this.discardsDetailsProvider_.discardById(e.model.item.id)
+ .then(this.updateTable_.bind(this));
},
/**
* Implementation function to discard the next discardable tab.
- * @param {boolean} urgent True if tab should be urgently discarded.
* @private
*/
- discardImpl_: function(urgent) {
- this.discardsDetailsProvider_.discard(urgent).then(() => {
+ discardImpl_: function() {
+ this.discardsDetailsProvider_.discard().then(() => {
this.updateTable_();
});
},
/**
- * Event handler that discards the next discardable tab.
- * @param {Event} e The event.
- * @private
- */
- discardNow_: function(e) {
- this.discardImpl_(false);
- },
-
- /**
* Event handler that discards the next discardable tab urgently.
* @param {Event} e The event.
* @private
*/
- discardUrgentNow_: function(e) {
- this.discardImpl_(true);
+ discardUrgentNow_(e) {
+ this.discardImpl_();
},
});
diff --git a/chromium/chrome/browser/resources/discards/graph_tab_template.js b/chromium/chrome/browser/resources/discards/graph_tab_template.js
index d4ce2f9917a..7a1585912d0 100644
--- a/chromium/chrome/browser/resources/discards/graph_tab_template.js
+++ b/chromium/chrome/browser/resources/discards/graph_tab_template.js
@@ -93,19 +93,19 @@ Polymer({
changeListener_: null,
/** @override */
- ready: function() {
+ ready() {
this.graphDump_ = discards.mojom.GraphDump.getRemote();
},
/** @override */
- detached: function() {
+ detached() {
// TODO(siggi): Is there a way to tear down the binding explicitly?
this.graphDump_ = null;
this.changeListener_ = null;
},
/** @private */
- onWebViewReady_: function() {
+ onWebViewReady_() {
this.changeListener_ =
new DiscardsGraphChangeStreamImpl(this.$.webView.contentWindow);
this.client_ =
diff --git a/chromium/chrome/browser/resources/discards/mojo_api.js b/chromium/chrome/browser/resources/discards/mojo_api.js
index 35f80987bc1..312839302fe 100644
--- a/chromium/chrome/browser/resources/discards/mojo_api.js
+++ b/chromium/chrome/browser/resources/discards/mojo_api.js
@@ -8,3 +8,4 @@ import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
import './mojo/public/mojom/base/process_id.mojom-lite.js';
import './chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-lite.js';
import './chrome/browser/ui/webui/discards/discards.mojom-lite.js';
+import './chrome/browser/ui/webui/discards/site_data.mojom-lite.js';
diff --git a/chromium/chrome/browser/resources/discards/sorted_table_behavior.js b/chromium/chrome/browser/resources/discards/sorted_table_behavior.js
index dd703c1f4e8..26fc907647f 100644
--- a/chromium/chrome/browser/resources/discards/sorted_table_behavior.js
+++ b/chromium/chrome/browser/resources/discards/sorted_table_behavior.js
@@ -31,7 +31,7 @@ export const SortedTableBehavior = {
* @param {string} sortKey The new sort key.
* @public
*/
- setSortKey: function(sortKey) {
+ setSortKey(sortKey) {
this.sortKey = sortKey;
},
@@ -41,7 +41,7 @@ export const SortedTableBehavior = {
* @param {Event} e The event.
* @public
*/
- onSortClick: function(e) {
+ onSortClick(e) {
// Remove the presentation style on the old sort header.
const oldElement = this.$$('.sort-column, .sort-column-reverse');
if (oldElement) {
diff --git a/chromium/chrome/browser/resources/download_internals/BUILD.gn b/chromium/chrome/browser/resources/download_internals/BUILD.gn
index 1d0ff828cdb..52b8603a5f9 100644
--- a/chromium/chrome/browser/resources/download_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/download_internals/BUILD.gn
@@ -5,6 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
+ uses_js_modules = true
deps = [
":download_internals",
":download_internals_browser_proxy",
@@ -16,21 +17,15 @@ js_library("download_internals") {
deps = [
":download_internals_browser_proxy",
"//third_party/jstemplate:jstemplate",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:util",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:util.m",
]
}
js_library("download_internals_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
}
js_library("download_internals_visuals") {
- deps = [
- ":download_internals_browser_proxy",
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ ":download_internals_browser_proxy" ]
}
diff --git a/chromium/chrome/browser/resources/download_internals/download_internals.html b/chromium/chrome/browser/resources/download_internals/download_internals.html
index 9c60f4f637b..80cfdacf97b 100644
--- a/chromium/chrome/browser/resources/download_internals/download_internals.html
+++ b/chromium/chrome/browser/resources/download_internals/download_internals.html
@@ -7,13 +7,8 @@
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<link rel="stylesheet" href="download_internals.css">
- <script src="chrome://resources/js/promise_resolver.js"></script>
- <script src="chrome://resources/js/cr.js"></script>
- <script src="chrome://resources/js/util.js"></script>
-
- <script src="download_internals_browser_proxy.js"></script>
- <script src="download_internals.js"></script>
- <script src="download_internals_visuals.js"></script>
+ <script type="module" src="download_internals.js"></script>
+ <script type="module" src="download_internals_visuals.js"></script>
</head>
<body>
<h1>Download Internals</h1>
diff --git a/chromium/chrome/browser/resources/download_internals/download_internals.js b/chromium/chrome/browser/resources/download_internals/download_internals.js
index b69190f4463..aaed39139d6 100644
--- a/chromium/chrome/browser/resources/download_internals/download_internals.js
+++ b/chromium/chrome/browser/resources/download_internals/download_internals.js
@@ -2,140 +2,135 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-cr.define('downloadInternals', function() {
- 'use strict';
-
- /** @type {!downloadInternals.DownloadInternalsBrowserProxy} */
- const browserProxy =
- downloadInternals.DownloadInternalsBrowserProxyImpl.getInstance();
-
- /** @type {!Array<ServiceEntry>} */
- const ongoingServiceEntries = [];
-
- /** @type {!Array<ServiceEntry>} */
- const finishedServiceEntries = [];
-
- /** @type {!Array<ServiceRequest>} */
- const serviceRequests = [];
-
- /**
- * @param {!Array<ServiceEntry>} list A list to remove the entry from.
- * @param {string} guid The guid to remove from the list.
- */
- function removeGuidFromList(list, guid) {
- const index = list.findIndex(entry => entry.guid == guid);
- if (index != -1) {
- list.splice(index, 1);
- }
- }
+import {addWebUIListener} from 'chrome://resources/js/cr.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
- /**
- * Replaces the ServiceEntry specified by guid in the list or, if it's not
- * found, adds a new entry.
- * @param {!Array<ServiceEntry>} list A list to update.
- * @param {!ServiceEntry} newEntry The new entry.
- */
- function addOrUpdateEntryByGuid(list, newEntry) {
- const index = list.findIndex(entry => entry.guid == newEntry.guid);
- if (index != -1) {
- list[index] = newEntry;
- } else {
- list.unshift(newEntry);
- }
- }
+import {DownloadInternalsBrowserProxy, DownloadInternalsBrowserProxyImpl, ServiceEntry, ServiceEntryState, ServiceRequest, ServiceStatus} from './download_internals_browser_proxy.js';
- function updateEntryTables() {
- const ongoingInput = new JsEvalContext({entries: ongoingServiceEntries});
- jstProcess(ongoingInput, $('download-service-ongoing-entries-info'));
+/** @type {!DownloadInternalsBrowserProxy} */
+const browserProxy = DownloadInternalsBrowserProxyImpl.getInstance();
- const finishedInput = new JsEvalContext({entries: finishedServiceEntries});
- jstProcess(finishedInput, $('download-service-finished-entries-info'));
- }
+/** @type {!Array<ServiceEntry>} */
+const ongoingServiceEntries = [];
- /**
- * @param {!ServiceStatus} state The current status of the download service.
- */
- function onServiceStatusChanged(state) {
- $('service-state').textContent = state.serviceState;
- $('service-status-model').textContent = state.modelStatus;
- $('service-status-driver').textContent = state.driverStatus;
- $('service-status-file').textContent = state.fileMonitorStatus;
- }
+/** @type {!Array<ServiceEntry>} */
+const finishedServiceEntries = [];
- /**
- * @param {!Array<!ServiceEntry>} entries A list entries currently tracked by
- * the download service.
- */
- function onServiceDownloadsAvailable(entries) {
- for (let i = 0; i < entries.length; i++) {
- const entry = entries[i];
- if (entry.state == ServiceEntryState.COMPLETE) {
- finishedServiceEntries.unshift(entry);
- } else {
- ongoingServiceEntries.unshift(entry);
- }
- }
+/** @type {!Array<ServiceRequest>} */
+const serviceRequests = [];
- updateEntryTables();
+/**
+ * @param {!Array<ServiceEntry>} list A list to remove the entry from.
+ * @param {string} guid The guid to remove from the list.
+ */
+function removeGuidFromList(list, guid) {
+ const index = list.findIndex(entry => entry.guid == guid);
+ if (index != -1) {
+ list.splice(index, 1);
}
-
- /**
- * @param {!ServiceEntry} entry The new state for a particular download
- * service entry.
- */
- function onServiceDownloadChanged(entry) {
+}
+
+/**
+ * Replaces the ServiceEntry specified by guid in the list or, if it's not
+ * found, adds a new entry.
+ * @param {!Array<ServiceEntry>} list A list to update.
+ * @param {!ServiceEntry} newEntry The new entry.
+ */
+function addOrUpdateEntryByGuid(list, newEntry) {
+ const index = list.findIndex(entry => entry.guid == newEntry.guid);
+ if (index != -1) {
+ list[index] = newEntry;
+ } else {
+ list.unshift(newEntry);
+ }
+}
+
+function updateEntryTables() {
+ const ongoingInput = new JsEvalContext({entries: ongoingServiceEntries});
+ jstProcess(ongoingInput, $('download-service-ongoing-entries-info'));
+
+ const finishedInput = new JsEvalContext({entries: finishedServiceEntries});
+ jstProcess(finishedInput, $('download-service-finished-entries-info'));
+}
+
+/**
+ * @param {!ServiceStatus} state The current status of the download service.
+ */
+function onServiceStatusChanged(state) {
+ $('service-state').textContent = state.serviceState;
+ $('service-status-model').textContent = state.modelStatus;
+ $('service-status-driver').textContent = state.driverStatus;
+ $('service-status-file').textContent = state.fileMonitorStatus;
+}
+
+/**
+ * @param {!Array<!ServiceEntry>} entries A list entries currently tracked by
+ * the download service.
+ */
+function onServiceDownloadsAvailable(entries) {
+ for (let i = 0; i < entries.length; i++) {
+ const entry = entries[i];
if (entry.state == ServiceEntryState.COMPLETE) {
- removeGuidFromList(ongoingServiceEntries, entry.guid);
- addOrUpdateEntryByGuid(finishedServiceEntries, entry);
+ finishedServiceEntries.unshift(entry);
} else {
- addOrUpdateEntryByGuid(ongoingServiceEntries, entry);
+ ongoingServiceEntries.unshift(entry);
}
-
- updateEntryTables();
}
- /**
- * @param {!ServiceEntry} entry The new state for a failed download service
- * entry.
- */
- function onServiceDownloadFailed(entry) {
+ updateEntryTables();
+}
+
+/**
+ * @param {!ServiceEntry} entry The new state for a particular download
+ * service entry.
+ */
+function onServiceDownloadChanged(entry) {
+ if (entry.state == ServiceEntryState.COMPLETE) {
removeGuidFromList(ongoingServiceEntries, entry.guid);
addOrUpdateEntryByGuid(finishedServiceEntries, entry);
-
- updateEntryTables();
+ } else {
+ addOrUpdateEntryByGuid(ongoingServiceEntries, entry);
}
- /**
- * @param {!ServiceRequest} request The state for a newly issued download
- * service request.
- */
- function onServiceRequestMade(request) {
- serviceRequests.unshift(request);
- const input = new JsEvalContext({requests: serviceRequests});
- jstProcess(input, $('download-service-request-info'));
- }
-
- function initialize() {
- // Register all event listeners.
- cr.addWebUIListener('service-status-changed', onServiceStatusChanged);
- cr.addWebUIListener(
- 'service-downloads-available', onServiceDownloadsAvailable);
- cr.addWebUIListener('service-download-changed', onServiceDownloadChanged);
- cr.addWebUIListener('service-download-failed', onServiceDownloadFailed);
- cr.addWebUIListener('service-request-made', onServiceRequestMade);
-
- $('start-download').onclick = function() {
- browserProxy.startDownload($('download-url').value);
- };
-
- // Kick off requests for the current system state.
- browserProxy.getServiceStatus().then(onServiceStatusChanged);
- browserProxy.getServiceDownloads().then(onServiceDownloadsAvailable);
- }
-
- return {
- initialize: initialize,
+ updateEntryTables();
+}
+
+/**
+ * @param {!ServiceEntry} entry The new state for a failed download service
+ * entry.
+ */
+function onServiceDownloadFailed(entry) {
+ removeGuidFromList(ongoingServiceEntries, entry.guid);
+ addOrUpdateEntryByGuid(finishedServiceEntries, entry);
+
+ updateEntryTables();
+}
+
+/**
+ * @param {!ServiceRequest} request The state for a newly issued download
+ * service request.
+ */
+function onServiceRequestMade(request) {
+ serviceRequests.unshift(request);
+ const input = new JsEvalContext({requests: serviceRequests});
+ jstProcess(input, $('download-service-request-info'));
+}
+
+function initialize() {
+ // Register all event listeners.
+ addWebUIListener('service-status-changed', onServiceStatusChanged);
+ addWebUIListener('service-downloads-available', onServiceDownloadsAvailable);
+ addWebUIListener('service-download-changed', onServiceDownloadChanged);
+ addWebUIListener('service-download-failed', onServiceDownloadFailed);
+ addWebUIListener('service-request-made', onServiceRequestMade);
+
+ $('start-download').onclick = function() {
+ browserProxy.startDownload($('download-url').value);
};
-});
-document.addEventListener('DOMContentLoaded', downloadInternals.initialize);
+ // Kick off requests for the current system state.
+ browserProxy.getServiceStatus().then(onServiceStatusChanged);
+ browserProxy.getServiceDownloads().then(onServiceDownloadsAvailable);
+}
+
+document.addEventListener('DOMContentLoaded', initialize);
diff --git a/chromium/chrome/browser/resources/download_internals/download_internals_browser_proxy.js b/chromium/chrome/browser/resources/download_internals/download_internals_browser_proxy.js
index 0d870c7818d..27f7534e0f0 100644
--- a/chromium/chrome/browser/resources/download_internals/download_internals_browser_proxy.js
+++ b/chromium/chrome/browser/resources/download_internals/download_internals_browser_proxy.js
@@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
+
/**
* Contains the possible states a ServiceEntry can be in.
* @enum {string}
*/
-const ServiceEntryState = {
+export const ServiceEntryState = {
NEW: 'NEW',
AVAILABLE: 'AVAILABLE',
ACTIVE: 'ACTIVE',
@@ -18,7 +20,7 @@ const ServiceEntryState = {
* Contains the possible states a ServiceEntry's driver can be in.
* @enum {string}
*/
-const DriverEntryState = {
+export const DriverEntryState = {
IN_PROGRESS: 'IN_PROGRESS',
COMPLETE: 'COMPLETE',
CANCELLED: 'CANCELLED',
@@ -29,7 +31,7 @@ const DriverEntryState = {
* Contains the possible results a ServiceEntry can have.
* @enum {string}
*/
-const ServiceEntryResult = {
+export const ServiceEntryResult = {
SUCCEED: 'SUCCEED',
FAIL: 'FAIL',
ABORT: 'ABORT',
@@ -44,7 +46,7 @@ const ServiceEntryResult = {
* Contains the possible results of a ServiceRequest.
* @enum {string}
*/
-const ServiceRequestResult = {
+export const ServiceRequestResult = {
ACCEPTED: 'ACCEPTED',
BACKOFF: 'BACKOFF',
UNEXPECTED_CLIENT: 'UNEXPECTED_CLIENT',
@@ -61,7 +63,7 @@ const ServiceRequestResult = {
* fileMonitorStatus: string
* }}
*/
-let ServiceStatus;
+export let ServiceStatus;
/**
* @typedef {{
@@ -78,7 +80,7 @@ let ServiceStatus;
* }
* }}
*/
-let ServiceEntry;
+export let ServiceEntry;
/**
* @typedef {{
@@ -87,56 +89,50 @@ let ServiceEntry;
* result: !ServiceRequestResult
* }}
*/
-let ServiceRequest;
-
-cr.define('downloadInternals', function() {
- /** @interface */
- class DownloadInternalsBrowserProxy {
- /**
- * Gets the current status of the Download Service.
- * @return {!Promise<ServiceStatus>} A promise firing when the service
- * status is fetched.
- */
- getServiceStatus() {}
+export let ServiceRequest;
- /**
- * Gets the current list of downloads the Download Service is aware of.
- * @return {!Promise<!Array<!ServiceEntry>>} A promise firing when the list
- * of downloads is fetched.
- */
- getServiceDownloads() {}
+/** @interface */
+export class DownloadInternalsBrowserProxy {
+ /**
+ * Gets the current status of the Download Service.
+ * @return {!Promise<ServiceStatus>} A promise firing when the service
+ * status is fetched.
+ */
+ getServiceStatus() {}
- /**
- * Starts a download with the Download Service.
- * @param {string} url The download URL.
- */
- startDownload(url) {}
- }
+ /**
+ * Gets the current list of downloads the Download Service is aware of.
+ * @return {!Promise<!Array<!ServiceEntry>>} A promise firing when the list
+ * of downloads is fetched.
+ */
+ getServiceDownloads() {}
/**
- * @implements {downloadInternals.DownloadInternalsBrowserProxy}
+ * Starts a download with the Download Service.
+ * @param {string} url The download URL.
+ * @return {!Promise}
*/
- class DownloadInternalsBrowserProxyImpl {
- /** @override */
- getServiceStatus() {
- return cr.sendWithPromise('getServiceStatus');
- }
+ startDownload(url) {}
+}
- /** @override */
- getServiceDownloads() {
- return cr.sendWithPromise('getServiceDownloads');
- }
+/**
+ * @implements {DownloadInternalsBrowserProxy}
+ */
+export class DownloadInternalsBrowserProxyImpl {
+ /** @override */
+ getServiceStatus() {
+ return sendWithPromise('getServiceStatus');
+ }
- /** @override */
- startDownload(url) {
- return cr.sendWithPromise('startDownload', url);
- }
+ /** @override */
+ getServiceDownloads() {
+ return sendWithPromise('getServiceDownloads');
}
- cr.addSingletonGetter(DownloadInternalsBrowserProxyImpl);
+ /** @override */
+ startDownload(url) {
+ return sendWithPromise('startDownload', url);
+ }
+}
- return {
- DownloadInternalsBrowserProxy: DownloadInternalsBrowserProxy,
- DownloadInternalsBrowserProxyImpl: DownloadInternalsBrowserProxyImpl
- };
-});
+addSingletonGetter(DownloadInternalsBrowserProxyImpl);
diff --git a/chromium/chrome/browser/resources/download_internals/download_internals_visuals.js b/chromium/chrome/browser/resources/download_internals/download_internals_visuals.js
index c9467b7cc50..51d37324b07 100644
--- a/chromium/chrome/browser/resources/download_internals/download_internals_visuals.js
+++ b/chromium/chrome/browser/resources/download_internals/download_internals_visuals.js
@@ -2,55 +2,56 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-cr.define('downloadInternalsVisuals', function() {
- 'use strict';
+import {DriverEntryState, ServiceEntryResult, ServiceEntryState, ServiceRequestResult} from './download_internals_browser_proxy.js';
- function getOngoingServiceEntryClass(entry) {
- switch (entry.state) {
- case ServiceEntryState.NEW:
- return 'service-entry-new';
- case ServiceEntryState.AVAILABLE:
- return 'service-entry-available';
- case ServiceEntryState.ACTIVE:
- if (entry.driver == undefined || !entry.driver.paused ||
- entry.driver.state == DriverEntryState.INTERRUPTED) {
- return 'service-entry-active';
- } else {
- return 'service-entry-blocked';
- }
- case ServiceEntryState.PAUSED:
- return 'service-entry-paused';
- case ServiceEntryState.COMPLETE:
- return 'service-entry-success';
- default:
- return '';
- }
- }
+// Expose these on |window| because they need to be accessed by jstemplate code
+// in download_internals.html
+window.downloadInternalsVisuals = {};
- function getFinishedServiceEntryClass(entry) {
- switch (entry.result) {
- case ServiceEntryResult.SUCCEED:
- return 'service-entry-success';
- default:
- return 'service-entry-fail';
- }
+function getOngoingServiceEntryClass(entry) {
+ switch (entry.state) {
+ case ServiceEntryState.NEW:
+ return 'service-entry-new';
+ case ServiceEntryState.AVAILABLE:
+ return 'service-entry-available';
+ case ServiceEntryState.ACTIVE:
+ if (entry.driver == undefined || !entry.driver.paused ||
+ entry.driver.state == DriverEntryState.INTERRUPTED) {
+ return 'service-entry-active';
+ } else {
+ return 'service-entry-blocked';
+ }
+ case ServiceEntryState.PAUSED:
+ return 'service-entry-paused';
+ case ServiceEntryState.COMPLETE:
+ return 'service-entry-success';
+ default:
+ return '';
}
+}
+window.downloadInternalsVisuals.getOngoingServiceEntryClass =
+ getOngoingServiceEntryClass;
- function getServiceRequestClass(request) {
- switch (request.result) {
- case ServiceRequestResult.ACCEPTED:
- return 'service-entry-success';
- case ServiceRequestResult.BACKOFF:
- case ServiceRequestResult.CLIENT_CANCELLED:
- return 'service-entry-blocked';
- default:
- return 'service-entry-fail';
- }
+function getFinishedServiceEntryClass(entry) {
+ switch (entry.result) {
+ case ServiceEntryResult.SUCCEED:
+ return 'service-entry-success';
+ default:
+ return 'service-entry-fail';
}
+}
+window.downloadInternalsVisuals.getFinishedServiceEntryClass =
+ getFinishedServiceEntryClass;
- return {
- getOngoingServiceEntryClass: getOngoingServiceEntryClass,
- getFinishedServiceEntryClass: getFinishedServiceEntryClass,
- getServiceRequestClass: getServiceRequestClass
- };
-}); \ No newline at end of file
+function getServiceRequestClass(request) {
+ switch (request.result) {
+ case ServiceRequestResult.ACCEPTED:
+ return 'service-entry-success';
+ case ServiceRequestResult.BACKOFF:
+ case ServiceRequestResult.CLIENT_CANCELLED:
+ return 'service-entry-blocked';
+ default:
+ return 'service-entry-fail';
+ }
+}
+window.downloadInternalsVisuals.getServiceRequestClass = getServiceRequestClass;
diff --git a/chromium/chrome/browser/resources/downloads/.eslintrc.js b/chromium/chrome/browser/resources/downloads/.eslintrc.js
new file mode 100644
index 00000000000..9c84e103640
--- /dev/null
+++ b/chromium/chrome/browser/resources/downloads/.eslintrc.js
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/downloads/BUILD.gn b/chromium/chrome/browser/resources/downloads/BUILD.gn
index d1bcb37fe64..ea1077ddcd0 100644
--- a/chromium/chrome/browser/resources/downloads/BUILD.gn
+++ b/chromium/chrome/browser/resources/downloads/BUILD.gn
@@ -33,17 +33,12 @@ if (optimize_webui) {
pak_file = downloads_pak_file
out_folder = unpak_folder
- deps = [
- ":flattened_resources",
- ]
+ deps = [ ":flattened_resources" ]
}
grit("flattened_resources") {
source = "downloads_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
-
defines = chrome_grit_defines
outputs = [
"grit/downloads_resources.h",
@@ -149,7 +144,7 @@ js_library("toolbar") {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":icons_module",
":item_module",
":manager_module",
diff --git a/chromium/chrome/browser/resources/downloads/OWNERS b/chromium/chrome/browser/resources/downloads/OWNERS
index 455bfb52fad..cb00587830d 100644
--- a/chromium/chrome/browser/resources/downloads/OWNERS
+++ b/chromium/chrome/browser/resources/downloads/OWNERS
@@ -1,3 +1 @@
-dbeam@chromium.org
-
# COMPONENT: UI>Browser>Downloads
diff --git a/chromium/chrome/browser/resources/downloads/constants.js b/chromium/chrome/browser/resources/downloads/constants.js
index 1a0401c118c..ed08b723888 100644
--- a/chromium/chrome/browser/resources/downloads/constants.js
+++ b/chromium/chrome/browser/resources/downloads/constants.js
@@ -34,4 +34,6 @@ export const States = {
PAUSED: 'PAUSED',
DANGEROUS: 'DANGEROUS',
INTERRUPTED: 'INTERRUPTED',
+ MIXED_CONTENT: 'MIXED_CONTENT',
+ ASYNC_SCANNING: 'ASYNC_SCANNING',
};
diff --git a/chromium/chrome/browser/resources/downloads/icon_loader.js b/chromium/chrome/browser/resources/downloads/icon_loader.js
index 667c268a467..44a6b6d0ed9 100644
--- a/chromium/chrome/browser/resources/downloads/icon_loader.js
+++ b/chromium/chrome/browser/resources/downloads/icon_loader.js
@@ -46,7 +46,7 @@ export class IconLoader {
finishedLoading_(e) {
const resolver = assert(this.iconResolvers_[e.currentTarget.src]);
if (!resolver.isFulfilled) {
- resolver.resolve(e.type == 'load');
+ resolver.resolve(e.type === 'load');
}
}
}
diff --git a/chromium/chrome/browser/resources/downloads/item.html b/chromium/chrome/browser/resources/downloads/item.html
index cd940178258..9e23df600dc 100644
--- a/chromium/chrome/browser/resources/downloads/item.html
+++ b/chromium/chrome/browser/resources/downloads/item.html
@@ -47,7 +47,7 @@
}
#content.is-active {
- @apply --cr-card-elevation;
+ box-shadow: var(--cr-card-shadow);
}
@media (prefers-color-scheme: light) {
@@ -135,27 +135,34 @@
opacity: .5;
}
- #file-icon-wrapper iron-icon[icon='cr:insert-drive-file'] {
+ #file-icon-wrapper iron-icon[icon-color='paper-grey'] {
color: var(--paper-grey-400);
}
- #file-icon-wrapper iron-icon[icon='cr:warning'],
- .dangerous #description {
+ #file-icon-wrapper iron-icon[icon-color='red'] {
color: var(--google-red-700);
}
- #file-icon-wrapper iron-icon[icon='cr:error'],
- .dangerous #description {
+ #file-icon-wrapper iron-icon[icon-color='yellow'] {
color: var(--google-yellow-500);
}
@media (prefers-color-scheme: dark) {
- #file-icon-wrapper iron-icon[icon='cr:warning'],
- .dangerous #description {
+ #file-icon-wrapper iron-icon[icon-color='red'] {
color: var(--google-red-refresh-300);
}
}
+ #file-icon-wrapper iron-icon[icon-color='grey'] {
+ color: var(--google-grey-700);
+ }
+
+ @media (prefers-color-scheme: dark) {
+ #file-icon-wrapper iron-icon[icon-color='grey'] {
+ color: var(--google-grey-500);
+ }
+ }
+
#name,
#file-link,
#url {
@@ -269,7 +276,8 @@
}
#pauseOrResume,
- #dangerous .action-button {
+ #dangerous .action-button,
+ #openNow {
margin-inline-end: 8px;
}
</style>
@@ -286,10 +294,13 @@
attribute and remove aria-hidden="true" from #file-icon-wrapper
-->
<div id="file-icon-wrapper" class="icon-wrapper" aria-hidden="true">
- <img class="icon" id="file-icon" alt="" hidden="[[!useFileIcon_]]">
+ <img class="icon" id="file-icon" alt="" hidden="[[!useFileIcon_]]"
+ icon-color$="[[computeIconColor_(isDangerous_, data.dangerType,
+ useFileIcon_)]]">
<iron-icon class="icon" icon$="[[computeIcon_(
isDangerous_, data.dangerType, useFileIcon_)]]"
- hidden="[[useFileIcon_]]"></iron-icon>
+ hidden="[[useFileIcon_]]" icon-color$="[[computeIconColor_(isDangerous_,
+ data.dangerType, useFileIcon_)]]"></iron-icon>
</div>
<div id="details">
@@ -351,6 +362,14 @@
</cr-button>
</div>
</template>
+ <template is="dom-if" if="[[showOpenNow_]]">
+ <div role="gridcell">
+ <cr-button on-click="onOpenNowTap_" id="openNow" class="action-button"
+ focus-row-control focus-type="open">
+ $i18n{controlOpenNow}
+ </cr-button>
+ </div>
+ </template>
<template is="dom-if" if="[[showCancel_]]">
<div role="gridcell">
<cr-button on-click="onCancelTap_" focus-row-control
diff --git a/chromium/chrome/browser/resources/downloads/item.js b/chromium/chrome/browser/resources/downloads/item.js
index 592f13fff24..e5d8ca93ccb 100644
--- a/chromium/chrome/browser/resources/downloads/item.js
+++ b/chromium/chrome/browser/resources/downloads/item.js
@@ -116,6 +116,13 @@ Polymer({
value: false,
},
+ /** @private */
+ showOpenNow_: {
+ computed: 'computeShowOpenNow_(data.state)',
+ type: Boolean,
+ value: false,
+ },
+
useFileIcon_: Boolean,
},
@@ -138,35 +145,35 @@ Polymer({
restoreFocusAfterCancel_: false,
/** @override */
- attached: function() {
+ attached() {
afterNextRender(this, function() {
IronA11yAnnouncer.requestAvailability();
});
},
/** @override */
- ready: function() {
+ ready() {
this.mojoHandler_ = BrowserProxy.getInstance().handler;
this.content = this.$.content;
},
- focusOnRemoveButton: function() {
+ focusOnRemoveButton() {
focusWithoutInk(this.$.remove);
},
/** Overrides FocusRowBehavior. */
- getCustomEquivalent: function(sampleElement) {
- if (sampleElement.getAttribute('focus-type') == 'cancel') {
+ getCustomEquivalent(sampleElement) {
+ if (sampleElement.getAttribute('focus-type') === 'cancel') {
return this.$$('[focus-type="retry"]');
}
- if (sampleElement.getAttribute('focus-type') == 'retry') {
+ if (sampleElement.getAttribute('focus-type') === 'retry') {
return this.$$('[focus-type="pauseOrResume"]');
}
return null;
},
/** @return {!HTMLElement} */
- getFileIcon: function() {
+ getFileIcon() {
return /** @type {!HTMLElement} */ (this.$['file-icon']);
},
@@ -175,12 +182,12 @@ Polymer({
* @return {string} A reasonably long URL.
* @private
*/
- chopUrl_: function(url) {
+ chopUrl_(url) {
return url.slice(0, 300);
},
/** @private */
- computeClass_: function() {
+ computeClass_() {
const classes = [];
if (this.isActive_) {
@@ -202,8 +209,8 @@ Polymer({
* @return {boolean}
* @private
*/
- computeCompletelyOnDisk_: function() {
- return this.data.state == States.COMPLETE &&
+ computeCompletelyOnDisk_() {
+ return this.data.state === States.COMPLETE &&
!this.data.fileExternallyRemoved;
},
@@ -211,7 +218,7 @@ Polymer({
* @return {string}
* @private
*/
- computeControlledBy_: function() {
+ computeControlledBy_() {
if (!this.data.byExtId || !this.data.byExtName) {
return '';
}
@@ -225,7 +232,7 @@ Polymer({
* @return {string}
* @private
*/
- computeControlRemoveFromListAriaLabel_: function() {
+ computeControlRemoveFromListAriaLabel_() {
return loadTimeData.getStringF(
'controlRemoveFromListAriaLabel', this.data.fileName);
},
@@ -234,8 +241,8 @@ Polymer({
* @return {string}
* @private
*/
- computeDate_: function() {
- assert(typeof this.data.hideDate == 'boolean');
+ computeDate_() {
+ assert(typeof this.data.hideDate === 'boolean');
if (this.data.hideDate) {
return '';
}
@@ -243,15 +250,15 @@ Polymer({
},
/** @private @return {boolean} */
- computeDescriptionVisible_: function() {
- return this.computeDescription_() != '';
+ computeDescriptionVisible_() {
+ return this.computeDescription_() !== '';
},
/**
* @return {string}
* @private
*/
- computeDescription_: function() {
+ computeDescription_() {
const data = this.data;
switch (data.state) {
@@ -264,6 +271,9 @@ Polymer({
}
break;
+ case States.MIXED_CONTENT:
+ return loadTimeData.getString('mixedContentDownloadDesc');
+
case States.DANGEROUS:
const fileName = data.fileName;
switch (data.dangerType) {
@@ -286,6 +296,9 @@ Polymer({
}
break;
+ case States.ASYNC_SCANNING:
+ return loadTimeData.getString('asyncScanningDownloadDesc');
+
case States.IN_PROGRESS:
case States.PAUSED: // Fallthrough.
return data.progressStatusText;
@@ -308,13 +321,12 @@ Polymer({
* @return {string}
* @private
*/
- computeIcon_: function() {
+ computeIcon_() {
if (this.data) {
const dangerType = this.data.dangerType;
-
if ((loadTimeData.getBoolean('requestsApVerdicts') &&
- dangerType == DangerType.UNCOMMON_CONTENT) ||
- dangerType == DangerType.SENSITIVE_CONTENT_WARNING) {
+ dangerType === DangerType.UNCOMMON_CONTENT) ||
+ dangerType === DangerType.SENSITIVE_CONTENT_WARNING) {
return 'cr:error';
}
@@ -326,6 +338,10 @@ Polymer({
if (WARNING_TYPES.includes(dangerType)) {
return 'cr:warning';
}
+
+ if (this.data.state === States.ASYNC_SCANNING) {
+ return 'cr:error';
+ }
}
if (this.isDangerous_) {
return 'cr:warning';
@@ -337,12 +353,47 @@ Polymer({
},
/**
+ * @return {string}
+ * @private
+ */
+ computeIconColor_() {
+ if (this.data) {
+ const dangerType = this.data.dangerType;
+ if ((loadTimeData.getBoolean('requestsApVerdicts') &&
+ dangerType === DangerType.UNCOMMON_CONTENT) ||
+ dangerType === DangerType.SENSITIVE_CONTENT_WARNING) {
+ return 'yellow';
+ }
+
+ const WARNING_TYPES = [
+ DangerType.SENSITIVE_CONTENT_BLOCK,
+ DangerType.BLOCKED_TOO_LARGE,
+ DangerType.BLOCKED_PASSWORD_PROTECTED,
+ ];
+ if (WARNING_TYPES.includes(dangerType)) {
+ return 'red';
+ }
+
+ if (this.data.state === States.ASYNC_SCANNING) {
+ return 'grey';
+ }
+ }
+ if (this.isDangerous_) {
+ return 'red';
+ }
+ if (!this.useFileIcon_) {
+ return 'paper-grey';
+ }
+ return '';
+ },
+
+ /**
* @return {boolean}
* @private
*/
- computeIsActive_: function() {
- return this.data.state != States.CANCELLED &&
- this.data.state != States.INTERRUPTED &&
+ computeIsActive_() {
+ return this.data.state !== States.CANCELLED &&
+ this.data.state !== States.INTERRUPTED &&
!this.data.fileExternallyRemoved;
},
@@ -350,32 +401,33 @@ Polymer({
* @return {boolean}
* @private
*/
- computeIsDangerous_: function() {
- return this.data.state == States.DANGEROUS;
+ computeIsDangerous_() {
+ return this.data.state === States.DANGEROUS ||
+ this.data.state === States.MIXED_CONTENT;
},
/**
* @return {boolean}
* @private
*/
- computeIsInProgress_: function() {
- return this.data.state == States.IN_PROGRESS;
+ computeIsInProgress_() {
+ return this.data.state === States.IN_PROGRESS;
},
/**
* @return {boolean}
* @private
*/
- computeIsMalware_: function() {
+ computeIsMalware_() {
return this.isDangerous_ &&
- (this.data.dangerType == DangerType.DANGEROUS_CONTENT ||
- this.data.dangerType == DangerType.DANGEROUS_HOST ||
- this.data.dangerType == DangerType.DANGEROUS_URL ||
- this.data.dangerType == DangerType.POTENTIALLY_UNWANTED);
+ (this.data.dangerType === DangerType.DANGEROUS_CONTENT ||
+ this.data.dangerType === DangerType.DANGEROUS_HOST ||
+ this.data.dangerType === DangerType.DANGEROUS_URL ||
+ this.data.dangerType === DangerType.POTENTIALLY_UNWANTED);
},
/** @private */
- toggleButtonClass_: function() {
+ toggleButtonClass_() {
this.$$('#pauseOrResume')
.classList.toggle(
'action-button',
@@ -384,7 +436,7 @@ Polymer({
},
/** @private */
- updatePauseOrResumeClass_: function() {
+ updatePauseOrResumeClass_() {
if (!this.pauseOrResumeText_) {
return;
}
@@ -398,7 +450,7 @@ Polymer({
* @return {string}
* @private
*/
- computePauseOrResumeText_: function() {
+ computePauseOrResumeText_() {
if (this.data === undefined) {
return '';
}
@@ -416,7 +468,7 @@ Polymer({
* @return {string}
* @private
*/
- computeRemoveStyle_: function() {
+ computeRemoveStyle_() {
const canDelete = loadTimeData.getBoolean('allowDeletingHistory');
const hideRemove = this.isDangerous_ || this.showCancel_ || !canDelete;
return hideRemove ? 'visibility: hidden' : '';
@@ -426,24 +478,34 @@ Polymer({
* @return {boolean}
* @private
*/
- computeShowCancel_: function() {
- return this.data.state == States.IN_PROGRESS ||
- this.data.state == States.PAUSED;
+ computeShowCancel_() {
+ return this.data.state === States.IN_PROGRESS ||
+ this.data.state === States.PAUSED ||
+ this.data.state === States.ASYNC_SCANNING;
},
/**
* @return {boolean}
* @private
*/
- computeShowProgress_: function() {
- return this.showCancel_ && this.data.percent >= -1;
+ computeShowProgress_() {
+ return this.showCancel_ && this.data.percent >= -1 &&
+ this.data.state !== States.ASYNC_SCANNING;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeShowOpenNow_() {
+ return this.data.state === States.ASYNC_SCANNING;
},
/**
* @return {string}
* @private
*/
- computeTag_: function() {
+ computeTag_() {
switch (this.data.state) {
case States.CANCELLED:
return loadTimeData.getString('statusCancelled');
@@ -464,12 +526,12 @@ Polymer({
* @return {boolean}
* @private
*/
- isIndeterminate_: function() {
- return this.data.percent == -1;
+ isIndeterminate_() {
+ return this.data.percent === -1;
},
/** @private */
- observeControlledBy_: function() {
+ observeControlledBy_() {
this.$['controlled-by'].innerHTML = this.controlledBy_;
if (this.controlledBy_) {
const link = this.$$('#controlled-by a');
@@ -479,7 +541,7 @@ Polymer({
},
/** @private */
- observeIsDangerous_: function() {
+ observeIsDangerous_() {
if (!this.data) {
return;
}
@@ -495,13 +557,16 @@ Polymer({
this.useFileIcon_ = false;
} else if (OVERRIDDEN_ICON_TYPES.includes(this.data.dangerType)) {
this.useFileIcon_ = false;
+ } else if (this.data.state === States.ASYNC_SCANNING) {
+ this.useFileIcon_ = false;
} else {
this.$.url.href = assert(this.data.url);
const path = this.data.filePath;
IconLoader.getInstance()
.loadIcon(this.$['file-icon'], path)
.then(success => {
- if (path == this.data.filePath) {
+ if (path === this.data.filePath && this.data.state !==
+ States.ASYNC_SCANNING) {
this.useFileIcon_ = success;
}
});
@@ -509,21 +574,26 @@ Polymer({
},
/** @private */
- onCancelTap_: function() {
+ onCancelTap_() {
this.restoreFocusAfterCancel_ = true;
this.mojoHandler_.cancel(this.data.id);
},
/** @private */
- onDiscardDangerousTap_: function() {
+ onDiscardDangerousTap_() {
this.mojoHandler_.discardDangerous(this.data.id);
},
+ /** @private */
+ onOpenNowTap_() {
+ this.mojoHandler_.openDuringScanningRequiringGesture(this.data.id);
+ },
+
/**
* @private
* @param {Event} e
*/
- onDragStart_: function(e) {
+ onDragStart_(e) {
e.preventDefault();
this.mojoHandler_.drag(this.data.id);
},
@@ -532,19 +602,19 @@ Polymer({
* @param {Event} e
* @private
*/
- onFileLinkTap_: function(e) {
+ onFileLinkTap_(e) {
e.preventDefault();
this.mojoHandler_.openFileRequiringGesture(this.data.id);
},
/** @private */
- onUrlTap_: function() {
+ onUrlTap_() {
chrome.send('metricsHandler:recordAction',
['Downloads_OpenUrlOfDownloadedItem']);
},
/** @private */
- onPauseOrResumeTap_: function() {
+ onPauseOrResumeTap_() {
if (this.isInProgress_) {
this.mojoHandler_.pause(this.data.id);
} else {
@@ -553,7 +623,7 @@ Polymer({
},
/** @private */
- onRemoveTap_: function() {
+ onRemoveTap_() {
const pieces = loadTimeData.getSubstitutedStringPieces(
loadTimeData.getString('toastRemovedFromList'), this.data.fileName);
pieces.forEach(p => {
@@ -574,22 +644,22 @@ Polymer({
},
/** @private */
- onRetryTap_: function() {
+ onRetryTap_() {
this.mojoHandler_.retryDownload(this.data.id);
},
/** @private */
- onSaveDangerousTap_: function() {
+ onSaveDangerousTap_() {
this.mojoHandler_.saveDangerousRequiringGesture(this.data.id);
},
/** @private */
- onShowTap_: function() {
+ onShowTap_() {
this.mojoHandler_.show(this.data.id);
},
/** @private */
- restoreFocusAfterCancelIfNeeded_: function() {
+ restoreFocusAfterCancelIfNeeded_() {
if (!this.restoreFocusAfterCancel_) {
return;
}
diff --git a/chromium/chrome/browser/resources/downloads/manager.js b/chromium/chrome/browser/resources/downloads/manager.js
index 353cfe771d2..0770f851785 100644
--- a/chromium/chrome/browser/resources/downloads/manager.js
+++ b/chromium/chrome/browser/resources/downloads/manager.js
@@ -58,7 +58,7 @@ Polymer({
/** @private {!Array<!downloads.Data>} */
items_: {
type: Array,
- value: function() {
+ value() {
return [];
},
},
@@ -104,7 +104,7 @@ Polymer({
boundOnKeyDown_: null,
/** @override */
- created: function() {
+ created() {
const browserProxy = BrowserProxy.getInstance();
this.mojoEventTarget_ = browserProxy.callbackRouter;
this.mojoHandler_ = browserProxy.handler;
@@ -120,7 +120,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
document.documentElement.classList.remove('loading');
this.listenerIds_ = [
this.mojoEventTarget_.clearAll.addListener(this.clearAll_.bind(this)),
@@ -150,7 +150,7 @@ Polymer({
},
/** @override */
- detached: function() {
+ detached() {
this.listenerIds_.forEach(
id => assert(this.mojoEventTarget_.removeListener(id)));
@@ -159,12 +159,12 @@ Polymer({
},
/** @private */
- clearAll_: function() {
+ clearAll_() {
this.set('items_', []);
},
/** @private */
- hasDownloadsChanged_: function() {
+ hasDownloadsChanged_() {
if (this.hasDownloads_) {
this.$.downloadsList.fire('iron-resize');
}
@@ -175,7 +175,7 @@ Polymer({
* @param {!Array<downloads.Data>} items
* @private
*/
- insertItems_: function(index, items) {
+ insertItems_(index, items) {
// Insert |items| at the given |index| via Array#splice().
if (items.length > 0) {
this.items_.splice.apply(this.items_, [index, 0].concat(items));
@@ -198,19 +198,20 @@ Polymer({
},
/** @private */
- itemsChanged_: function() {
+ itemsChanged_() {
this.hasDownloads_ = this.items_.length > 0;
this.$.toolbar.hasClearableDownloads =
loadTimeData.getBoolean('allowDeletingHistory') &&
this.items_.some(
- ({state}) => state != States.DANGEROUS &&
- state != States.IN_PROGRESS && state != States.PAUSED);
+ ({state}) => state !== States.DANGEROUS &&
+ state !== States.MIXED_CONTENT &&
+ state !== States.IN_PROGRESS && state !== States.PAUSED);
if (this.inSearchMode_) {
this.fire('iron-announce', {
- text: this.items_.length == 0 ?
+ text: this.items_.length === 0 ?
this.noDownloadsText_() :
- (this.items_.length == 1 ?
+ (this.items_.length === 1 ?
loadTimeData.getStringF(
'searchResultsSingular', this.$.toolbar.getSearchText()) :
loadTimeData.getStringF(
@@ -224,7 +225,7 @@ Polymer({
* @return {string} The text to show when no download items are showing.
* @private
*/
- noDownloadsText_: function() {
+ noDownloadsText_() {
return loadTimeData.getString(
this.inSearchMode_ ? 'noSearchResults' : 'noDownloads');
},
@@ -233,7 +234,7 @@ Polymer({
* @param {!KeyboardEvent} e
* @private
*/
- onKeyDown_: function(e) {
+ onKeyDown_(e) {
let clearAllKey = 'c';
// <if expr="is_macosx">
// On Mac, pressing alt+c produces 'ç' as |event.key|.
@@ -282,7 +283,7 @@ Polymer({
},
/** @private */
- onScroll_: function() {
+ onScroll_() {
const container = this.$.downloadsList.scrollTarget;
const distanceToBottom =
container.scrollHeight - container.scrollTop - container.offsetHeight;
@@ -294,7 +295,7 @@ Polymer({
},
/** @private */
- onSearchChanged_: function() {
+ onSearchChanged_() {
this.inSearchMode_ = this.searchService_.isSearching();
},
@@ -302,7 +303,7 @@ Polymer({
* @param {number} index
* @private
*/
- removeItem_: function(index) {
+ removeItem_(index) {
const removed = this.items_.splice(index, 1);
this.updateHideDates_(index, index);
this.notifySplices('items_', [{
@@ -316,7 +317,7 @@ Polymer({
},
/** @private */
- onUndoClick_: function() {
+ onUndoClick_() {
getToastManager().hide();
this.mojoHandler_.undo();
},
@@ -329,14 +330,14 @@ Polymer({
* @param {number} end
* @private
*/
- updateHideDates_: function(start, end) {
+ updateHideDates_(start, end) {
for (let i = start; i <= end; ++i) {
const current = this.items_[i];
if (!current) {
continue;
}
const prev = this.items_[i - 1];
- current.hideDate = !!prev && prev.dateString == current.dateString;
+ current.hideDate = !!prev && prev.dateString === current.dateString;
}
},
@@ -345,7 +346,7 @@ Polymer({
* @param {!downloads.Data} data
* @private
*/
- updateItem_: function(index, data) {
+ updateItem_(index, data) {
this.items_[index] = data;
this.updateHideDates_(index, index);
@@ -357,7 +358,7 @@ Polymer({
},
// Override FindShortcutBehavior methods.
- handleFindShortcut: function(modalContextOpen) {
+ handleFindShortcut(modalContextOpen) {
if (modalContextOpen) {
return false;
}
@@ -366,7 +367,7 @@ Polymer({
},
// Override FindShortcutBehavior methods.
- searchInputHasFocus: function() {
+ searchInputHasFocus() {
return this.$.toolbar.isSearchFocused();
},
});
diff --git a/chromium/chrome/browser/resources/downloads/search_service.js b/chromium/chrome/browser/resources/downloads/search_service.js
index f1af2cae264..5a92fa29ad7 100644
--- a/chromium/chrome/browser/resources/downloads/search_service.js
+++ b/chromium/chrome/browser/resources/downloads/search_service.js
@@ -52,10 +52,10 @@ export class SearchService {
*/
search(searchText) {
const searchTerms = SearchService.splitTerms(searchText);
- let sameTerms = searchTerms.length == this.searchTerms_.length;
+ let sameTerms = searchTerms.length === this.searchTerms_.length;
for (let i = 0; sameTerms && i < searchTerms.length; ++i) {
- if (searchTerms[i] != this.searchTerms_[i]) {
+ if (searchTerms[i] !== this.searchTerms_[i]) {
sameTerms = false;
}
}
diff --git a/chromium/chrome/browser/resources/downloads/toolbar.js b/chromium/chrome/browser/resources/downloads/toolbar.js
index 4e674024d6f..d7219c061c6 100644
--- a/chromium/chrome/browser/resources/downloads/toolbar.js
+++ b/chromium/chrome/browser/resources/downloads/toolbar.js
@@ -42,41 +42,41 @@ Polymer({
mojoHandler_: null,
/** @override */
- ready: function() {
+ ready() {
this.mojoHandler_ = BrowserProxy.getInstance().handler;
},
/** @return {boolean} Whether removal can be undone. */
- canUndo: function() {
+ canUndo() {
return !this.isSearchFocused();
},
/** @return {boolean} Whether "Clear all" should be allowed. */
- canClearAll: function() {
- return this.getSearchText().length == 0 && this.hasClearableDownloads;
+ canClearAll() {
+ return this.getSearchText().length === 0 && this.hasClearableDownloads;
},
/** @return {string} The full text being searched. */
- getSearchText: function() {
+ getSearchText() {
return /** @type {!CrToolbarElement} */ (this.$.toolbar)
.getSearchField()
.getValue();
},
- focusOnSearchInput: function() {
+ focusOnSearchInput() {
return /** @type {!CrToolbarElement} */ (this.$.toolbar)
.getSearchField()
.showAndFocus();
},
- isSearchFocused: function() {
+ isSearchFocused() {
return /** @type {!CrToolbarElement} */ (this.$.toolbar)
.getSearchField()
.isSearchFocused();
},
/** @private */
- onClearAllTap_: function() {
+ onClearAllTap_() {
assert(this.canClearAll());
this.mojoHandler_.clearAll();
this.$.moreActionsMenu.close();
@@ -87,7 +87,7 @@ Polymer({
},
/** @private */
- onMoreActionsTap_: function() {
+ onMoreActionsTap_() {
this.$.moreActionsMenu.showAt(this.$.moreActions);
},
@@ -95,7 +95,7 @@ Polymer({
* @param {!CustomEvent<string>} event
* @private
*/
- onSearchChanged_: function(event) {
+ onSearchChanged_(event) {
const searchService = SearchService.getInstance();
if (searchService.search(event.detail)) {
this.spinnerActive = searchService.isSearching();
@@ -104,13 +104,13 @@ Polymer({
},
/** @private */
- onOpenDownloadsFolderTap_: function() {
+ onOpenDownloadsFolderTap_() {
this.mojoHandler_.openDownloadsFolderRequiringGesture();
this.$.moreActionsMenu.close();
},
/** @private */
- updateClearAll_: function() {
+ updateClearAll_() {
this.$$('.clear-all').hidden = !this.canClearAll();
},
});
diff --git a/chromium/chrome/browser/resources/engagement/BUILD.gn b/chromium/chrome/browser/resources/engagement/BUILD.gn
index 56a3ba2bd61..8fd5dfdc040 100644
--- a/chromium/chrome/browser/resources/engagement/BUILD.gn
+++ b/chromium/chrome/browser/resources/engagement/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":site_engagement",
- ]
+ deps = [ ":site_engagement" ]
}
js_library("site_engagement") {
diff --git a/chromium/chrome/browser/resources/explore_sites_internals/BUILD.gn b/chromium/chrome/browser/resources/explore_sites_internals/BUILD.gn
index a308c70d74b..2b09c615370 100644
--- a/chromium/chrome/browser/resources/explore_sites_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/explore_sites_internals/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":explore_sites_internals",
- ]
+ deps = [ ":explore_sites_internals" ]
}
js_library("explore_sites_internals") {
diff --git a/chromium/chrome/browser/resources/extensions/.eslintrc.js b/chromium/chrome/browser/resources/extensions/.eslintrc.js
new file mode 100644
index 00000000000..0b691a4dcc5
--- /dev/null
+++ b/chromium/chrome/browser/resources/extensions/.eslintrc.js
@@ -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.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/extensions/BUILD.gn b/chromium/chrome/browser/resources/extensions/BUILD.gn
index 49c26aa9c38..6b89fa93ad2 100644
--- a/chromium/chrome/browser/resources/extensions/BUILD.gn
+++ b/chromium/chrome/browser/resources/extensions/BUILD.gn
@@ -29,24 +29,18 @@ if (optimize_webui) {
pak_file = extensions_pak_file
out_folder = unpak_folder
- deps = [
- ":flattened_resources",
- ]
+ deps = [ ":flattened_resources" ]
}
grit("flattened_resources") {
source = "extensions_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
- deps = [
- ":polymer3_elements",
- ]
+ deps = [ ":polymer3_elements" ]
defines = chrome_grit_defines
outputs = [
"grit/extensions_resources.h",
@@ -66,7 +60,8 @@ group("closure_compile") {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
+ ":checkup_module",
":code_section_module",
":detail_view_module",
":drop_overlay_module",
@@ -93,10 +88,16 @@ group("polymer3_elements") {
"activity_log:polymer3_elements",
]
if (is_chromeos) {
- deps += [ ":kiosk_dialog_module" ]
+ public_deps += [ ":kiosk_dialog_module" ]
}
}
+polymer_modulizer("checkup") {
+ js_file = "checkup.js"
+ html_file = "checkup.html"
+ html_type = "v3-ready"
+}
+
polymer_modulizer("code_section") {
js_file = "code_section.js"
html_file = "code_section.html"
@@ -250,6 +251,7 @@ js_type_check("extensions_module_resources") {
]
is_polymer3 = true
deps = [
+ ":checkup",
":code_section",
":detail_view",
":drag_and_drop_handler",
@@ -284,6 +286,12 @@ js_type_check("extensions_module_resources") {
}
}
+js_library("checkup") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
js_library("code_section") {
deps = [
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
@@ -338,16 +346,12 @@ js_library("error_page") {
}
js_library("host_permissions_toggle_list") {
- deps = [
- ":item",
- ]
+ deps = [ ":item" ]
externs_list = [ "$externs_path/developer_private.js" ]
}
js_library("install_warnings_dialog") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
- ]
+ deps = [ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m" ]
externs_list = [ "$externs_path/developer_private.js" ]
}
@@ -366,18 +370,18 @@ js_library("item") {
}
js_library("item_behavior") {
- deps = [
- "//ui/webui/resources/js:load_time_data.m",
- ]
+ deps = [ "//ui/webui/resources/js:load_time_data.m" ]
externs_list = [ "$externs_path/developer_private.js" ]
}
js_library("item_list") {
deps = [
+ ":checkup",
":item",
"//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
"//ui/webui/resources/cr_elements:cr_container_shadow_behavior.m",
"//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
]
externs_list = [
"$externs_path/developer_private.js",
@@ -412,9 +416,7 @@ js_library("keyboard_shortcuts") {
}
js_library("kiosk_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
}
if (is_chromeos) {
@@ -533,7 +535,9 @@ js_library("shortcut_input") {
deps = [
":keyboard_shortcut_delegate",
":shortcut_util",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
"//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
]
externs_list = [ "$externs_path/developer_private.js" ]
}
diff --git a/chromium/chrome/browser/resources/extensions/activity_log/BUILD.gn b/chromium/chrome/browser/resources/extensions/activity_log/BUILD.gn
index d562aa8ca3d..af6d5b02f3d 100644
--- a/chromium/chrome/browser/resources/extensions/activity_log/BUILD.gn
+++ b/chromium/chrome/browser/resources/extensions/activity_log/BUILD.gn
@@ -36,7 +36,7 @@ polymer_modulizer("activity_log_stream_item") {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":activity_log_history_item_module",
":activity_log_history_module",
":activity_log_module",
diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log.js
index 6bf480f9927..694b67f7864 100644
--- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log.js
+++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log.js
@@ -97,7 +97,7 @@ Polymer({
* be HISTORY when we navigate to the page.
* @private
*/
- onViewEnterStart_: function() {
+ onViewEnterStart_() {
this.selectedSubpage_ = ActivityLogSubpage.HISTORY;
afterNextRender(this, () => focusWithoutInk(this.$.closeButton));
},
@@ -106,7 +106,7 @@ Polymer({
* Set |selectedSubpage_| to NONE to remove the active view from the DOM.
* @private
*/
- onViewExitFinish_: function() {
+ onViewExitFinish_() {
this.selectedSubpage_ = ActivityLogSubpage.NONE;
// clear the stream if the user is exiting the activity log page.
const activityLogStream = this.$$('activity-log-stream');
@@ -119,7 +119,7 @@ Polymer({
* @private
* @return {string}
*/
- getActivityLogHeading_: function() {
+ getActivityLogHeading_() {
const headingName = this.extensionInfo.isPlaceholder ?
this.i18n('missingOrUninstalledExtension') :
this.extensionInfo.name;
@@ -130,7 +130,7 @@ Polymer({
* @private
* @return {boolean}
*/
- isHistoryTabSelected_: function() {
+ isHistoryTabSelected_() {
return this.selectedSubpage_ === ActivityLogSubpage.HISTORY;
},
@@ -138,7 +138,7 @@ Polymer({
* @private
* @return {boolean}
*/
- isStreamTabSelected_: function() {
+ isStreamTabSelected_() {
return this.selectedSubpage_ === ActivityLogSubpage.STREAM;
},
@@ -147,7 +147,7 @@ Polymer({
* @param {!ActivityLogSubpage} newTab
* @param {!ActivityLogSubpage} oldTab
*/
- onSelectedSubpageChanged_: function(newTab, oldTab) {
+ onSelectedSubpageChanged_(newTab, oldTab) {
const activityLogStream = this.$$('activity-log-stream');
if (activityLogStream) {
if (newTab === ActivityLogSubpage.STREAM) {
@@ -165,7 +165,7 @@ Polymer({
},
/** @private */
- onCloseButtonTap_: function() {
+ onCloseButtonTap_() {
if (this.extensionInfo.isPlaceholder) {
navigation.navigateTo({page: Page.LIST});
} else {
diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history.js
index a28281eaa9d..dbd4412f6b2 100644
--- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history.js
+++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history.js
@@ -179,7 +179,7 @@ function groupActivities(activityData) {
*/
function sortActivitiesByCallCount(groupedActivities) {
return Array.from(groupedActivities.values()).sort((a, b) => {
- if (a.count != b.count) {
+ if (a.count !== b.count) {
return b.count - a.count;
}
if (a.key < b.key) {
@@ -252,12 +252,12 @@ Polymer({
* Expose only the promise of dataFetchedResolver_.
* @return {!Promise<void>}
*/
- whenDataFetched: function() {
+ whenDataFetched() {
return this.dataFetchedResolver_.promise;
},
/** @override */
- attached: function() {
+ attached() {
this.dataFetchedResolver_ = new PromiseResolver();
this.refreshActivities_();
},
@@ -266,7 +266,7 @@ Polymer({
* @private
* @return {boolean}
*/
- shouldShowEmptyActivityLogMessage_: function() {
+ shouldShowEmptyActivityLogMessage_() {
return this.pageState_ === ActivityLogPageState.LOADED &&
this.activityData_.length === 0;
},
@@ -275,7 +275,7 @@ Polymer({
* @private
* @return {boolean}
*/
- shouldShowLoadingMessage_: function() {
+ shouldShowLoadingMessage_() {
return this.pageState_ === ActivityLogPageState.LOADING;
},
@@ -283,20 +283,20 @@ Polymer({
* @private
* @return {boolean}
*/
- shouldShowActivities_: function() {
+ shouldShowActivities_() {
return this.pageState_ === ActivityLogPageState.LOADED &&
this.activityData_.length > 0;
},
/** @private */
- onClearActivitiesClick_: function() {
+ onClearActivitiesClick_() {
this.delegate.deleteActivitiesFromExtension(this.extensionId).then(() => {
this.processActivities_([]);
});
},
/** @private */
- onMoreActionsClick_: function() {
+ onMoreActionsClick_() {
this.$$('cr-action-menu').showAt(assert(this.$$('cr-icon-button')));
},
@@ -304,7 +304,7 @@ Polymer({
* @private
* @param {boolean} expanded
*/
- expandItems_: function(expanded) {
+ expandItems_(expanded) {
// Do not use .filter here as we need the original index of the item
// in |activityData_|.
this.activityData_.forEach((item, index) => {
@@ -316,17 +316,17 @@ Polymer({
},
/** @private */
- onExpandAllClick_: function() {
+ onExpandAllClick_() {
this.expandItems_(true);
},
/** @private */
- onCollapseAllClick_: function() {
+ onCollapseAllClick_() {
this.expandItems_(false);
},
/** @private */
- onExportClick_: function() {
+ onExportClick_() {
const fileName = `exported_activity_log_${this.extensionId}.json`;
this.delegate.downloadActivities(this.rawActivities_, fileName);
},
@@ -335,7 +335,7 @@ Polymer({
* @private
* @param {!CustomEvent<!Array<string>>} e
*/
- deleteItem_: function(e) {
+ deleteItem_(e) {
const activityIds = e.detail;
this.delegate.deleteActivitiesById(activityIds).then(() => {
// It is possible for multiple activities displayed to have the same
@@ -351,7 +351,7 @@ Polymer({
* @param {!Array<!chrome.activityLogPrivate.ExtensionActivity>}
* activityData
*/
- processActivities_: function(activityData) {
+ processActivities_(activityData) {
this.pageState_ = ActivityLogPageState.LOADED;
// Sort |activityData| in ascending order based on the activity's
@@ -370,7 +370,7 @@ Polymer({
* @private
* @return {!Promise<void>}
*/
- refreshActivities_: function() {
+ refreshActivities_() {
if (this.lastSearch_ === '') {
return this.getActivityLog_();
}
@@ -382,7 +382,7 @@ Polymer({
* @private
* @return {!Promise<void>}
*/
- getActivityLog_: function() {
+ getActivityLog_() {
this.pageState_ = ActivityLogPageState.LOADING;
return this.delegate.getExtensionActivityLog(this.extensionId)
.then(result => {
@@ -395,7 +395,7 @@ Polymer({
* @param {string} searchTerm
* @return {!Promise<void>}
*/
- getFilteredActivityLog_: function(searchTerm) {
+ getFilteredActivityLog_(searchTerm) {
this.pageState_ = ActivityLogPageState.LOADING;
return this.delegate
.getFilteredExtensionActivityLog(this.extensionId, searchTerm)
@@ -408,7 +408,7 @@ Polymer({
* @private
* @param {!CustomEvent<string>} e
*/
- onSearchChanged_: function(e) {
+ onSearchChanged_(e) {
// Remove all whitespaces from the search term, as API call names and
// urls should not contain any whitespace. As of now, only single term
// search queries are allowed.
diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history_item.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history_item.js
index 1ed2d728fcd..94a5ce67fd9 100644
--- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history_item.js
+++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_history_item.js
@@ -57,7 +57,7 @@ Polymer({
* @private
* @return {boolean}
*/
- computeIsExpandable_: function() {
+ computeIsExpandable_() {
return this.data.countsByUrl.size > 0;
},
@@ -68,11 +68,11 @@ Polymer({
* @private
* @return {!Array<PageUrlItem>}
*/
- getPageUrls_: function() {
+ getPageUrls_() {
return Array.from(this.data.countsByUrl.entries())
.map(e => ({page: e[0], count: e[1]}))
.sort(function(a, b) {
- if (a.count != b.count) {
+ if (a.count !== b.count) {
return b.count - a.count;
}
return a.page < b.page ? -1 : (a.page > b.page ? 1 : 0);
@@ -80,14 +80,14 @@ Polymer({
},
/** @private */
- onDeleteTap_: function(e) {
+ onDeleteTap_(e) {
e.stopPropagation();
this.fire(
'delete-activity-log-item', Array.from(this.data.activityIds.values()));
},
/** @private */
- onExpandTap_: function() {
+ onExpandTap_() {
if (this.isExpandable_) {
this.set('data.expanded', !this.data.expanded);
}
@@ -99,7 +99,7 @@ Polymer({
* @private
* @return {boolean}
*/
- shouldShowPageUrlCount_: function() {
+ shouldShowPageUrlCount_() {
return this.data.countsByUrl.size > 1;
},
});
diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream.js
index 7b74faf5714..14a324e01e3 100644
--- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream.js
+++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream.js
@@ -107,7 +107,7 @@ Polymer({
listenerInstance_: () => {},
/** @override */
- attached: function() {
+ attached() {
// Since this component is not restamped, this will only be called once
// in its lifecycle.
this.listenerInstance_ = this.extensionActivityListener_.bind(this);
@@ -115,15 +115,15 @@ Polymer({
},
/** @private */
- onResizeStream_: function(e) {
+ onResizeStream_(e) {
this.$$('iron-list').notifyResize();
},
- clearStream: function() {
+ clearStream() {
this.splice('activityStream_', 0, this.activityStream_.length);
},
- startStream: function() {
+ startStream() {
if (this.isStreamOn_) {
return;
}
@@ -132,7 +132,7 @@ Polymer({
this.delegate.getOnExtensionActivity().addListener(this.listenerInstance_);
},
- pauseStream: function() {
+ pauseStream() {
if (!this.isStreamOn_) {
return;
}
@@ -143,7 +143,7 @@ Polymer({
},
/** @private */
- onToggleButtonClick_: function() {
+ onToggleButtonClick_() {
if (this.isStreamOn_) {
this.pauseStream();
} else {
@@ -155,23 +155,23 @@ Polymer({
* @private
* @return {boolean}
*/
- isStreamEmpty_: function() {
- return this.activityStream_.length == 0;
+ isStreamEmpty_() {
+ return this.activityStream_.length === 0;
},
/**
* @private
* @return {boolean}
*/
- isFilteredStreamEmpty_: function() {
- return this.filteredActivityStream_.length == 0;
+ isFilteredStreamEmpty_() {
+ return this.filteredActivityStream_.length === 0;
},
/**
* @private
* @return {boolean}
*/
- shouldShowEmptySearchMessage_: function() {
+ shouldShowEmptySearchMessage_() {
return !this.isStreamEmpty_() && this.isFilteredStreamEmpty_();
},
@@ -179,8 +179,8 @@ Polymer({
* @private
* @param {!chrome.activityLogPrivate.ExtensionActivity} activity
*/
- extensionActivityListener_: function(activity) {
- if (activity.extensionId != this.extensionId) {
+ extensionActivityListener_(activity) {
+ if (activity.extensionId !== this.extensionId) {
return;
}
@@ -196,7 +196,7 @@ Polymer({
* @private
* @param {!CustomEvent<string>} e
*/
- onSearchChanged_: function(e) {
+ onSearchChanged_(e) {
// Remove all whitespaces from the search term, as API call names and
// URLs should not contain any whitespace. As of now, only single term
// search queries are allowed.
@@ -212,7 +212,7 @@ Polymer({
* @private
* @return {!Array<!StreamItem>}
*/
- computeFilteredActivityStream_: function() {
+ computeFilteredActivityStream_() {
if (!this.lastSearch_) {
return this.activityStream_.slice();
}
diff --git a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js
index e7025078fbc..82c04c600dd 100644
--- a/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js
+++ b/chromium/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js
@@ -82,7 +82,7 @@ Polymer({
* @private
* @return {boolean}
*/
- computeIsExpandable_: function() {
+ computeIsExpandable_() {
return this.hasPageUrl_() || this.hasArgs_() || this.hasWebRequestInfo_();
},
@@ -90,7 +90,7 @@ Polymer({
* @private
* @return {string}
*/
- getFormattedTime_: function() {
+ getFormattedTime_() {
// Format the activity's time to HH:MM:SS.mmm format. Use ToLocaleString
// for HH:MM:SS and padLeft for milliseconds.
const activityDate = new Date(this.data.timestamp);
@@ -109,7 +109,7 @@ Polymer({
* @private
* @return {boolean}
*/
- hasPageUrl_: function() {
+ hasPageUrl_() {
return !!this.data.pageUrl;
},
@@ -117,7 +117,7 @@ Polymer({
* @private
* @return {boolean}
*/
- hasArgs_: function() {
+ hasArgs_() {
return this.argsList_.length > 0;
},
@@ -125,15 +125,15 @@ Polymer({
* @private
* @return {boolean}
*/
- hasWebRequestInfo_: function() {
- return !!this.data.webRequestInfo && this.data.webRequestInfo != '{}';
+ hasWebRequestInfo_() {
+ return !!this.data.webRequestInfo && this.data.webRequestInfo !== '{}';
},
/**
* @private
* @return {!Array<!StreamArgItem>}
*/
- computeArgsList_: function() {
+ computeArgsList_() {
const parsedArgs = JSON.parse(this.data.args);
if (!Array.isArray(parsedArgs)) {
return [];
@@ -152,7 +152,7 @@ Polymer({
},
/** @private */
- onExpandClick_: function() {
+ onExpandClick_() {
if (this.isExpandable_) {
this.set('data.expanded', !this.data.expanded);
this.fire('resize-stream');
diff --git a/chromium/chrome/browser/resources/extensions/checkup.html b/chromium/chrome/browser/resources/extensions/checkup.html
new file mode 100644
index 00000000000..43fef4133ad
--- /dev/null
+++ b/chromium/chrome/browser/resources/extensions/checkup.html
@@ -0,0 +1,65 @@
+<style include="iron-flex shared-style">
+ :host {
+ --checkup-card-margin: 24px;
+ --banner-img-height: 115px;
+ --banner-img-width: 298px;
+ }
+
+ #card {
+ background-color: var(--cr-card-background-color);
+ border-radius: var(--cr-card-border-radius);
+ box-shadow: var(--cr-card-shadow);
+ overflow: hidden;
+ padding: var(--checkup-card-margin);
+ transition: height var(--drawer-transition);
+ }
+
+ #banner-img {
+ background: url(checkup_image.svg);
+ background-repeat: no-repeat;
+ display: inline-block;
+ float: right;
+ /* Height and width match the dimensions of the banner image. */
+ height: var(--banner-img-height);
+ width: var(--banner-img-width);
+ }
+
+ #banner-description {
+ @apply --cr-secondary-text;
+ flex-basis: var(--extensions-card-width);
+ text-overflow: ellipsis;
+ }
+
+ #banner-title {
+ color: var(--cr-primary-text-color);
+ font-size: 123%;
+ }
+
+ /* 932px is the last screen width in which we can fit a banner that spans two
+ columns and can be calculated by adding 2 card widths of
+ var(--extensions-card-width) and the column gap var(--grid-gutter) and
+ maintain padding of 60px on either side of the content on this page
+ (see content-wrapper in item-list.html).*/
+ @media (max-width: 931px) {
+ #banner-img {
+ display: block;
+ float: initial;
+ margin: 12px auto 0;
+ }
+ }
+
+ @media (prefers-color-scheme: dark) {
+ #banner-img {
+ background: url(checkup_image_dark.svg);
+ }
+ }
+
+</style>
+<div id="card">
+ <div id="banner-title" class="cr-title-text">$i18n{checkupTitle}</div>
+ <div id="banner-img"></div>
+ <div id="banner-description">
+ <p>$i18n{checkupBody1}</p>
+ <p>$i18n{checkupBody2}</p>
+ </div>
+</div>
diff --git a/chromium/chrome/browser/resources/extensions/checkup.js b/chromium/chrome/browser/resources/extensions/checkup.js
new file mode 100644
index 00000000000..cb655c10d73
--- /dev/null
+++ b/chromium/chrome/browser/resources/extensions/checkup.js
@@ -0,0 +1,15 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/cr_components/managed_footnote/managed_footnote.m.js';
+import './shared_style.js';
+
+import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+Polymer({
+ is: 'extensions-checkup',
+
+ _template: html`{__html_template__}`,
+
+});
diff --git a/chromium/chrome/browser/resources/extensions/code_section.js b/chromium/chrome/browser/resources/extensions/code_section.js
index 9a24dd366bb..65c80bd4e0c 100644
--- a/chromium/chrome/browser/resources/extensions/code_section.js
+++ b/chromium/chrome/browser/resources/extensions/code_section.js
@@ -86,7 +86,7 @@ Polymer({
/**
* @private
*/
- onCodeChanged_: function() {
+ onCodeChanged_() {
if (!this.code ||
(!this.code.beforeHighlight && !this.code.highlight &&
!this.code.afterHighlight)) {
@@ -114,7 +114,7 @@ Polymer({
.join('\n');
let visibleAfter = linesAfter.slice(0, visibleLineCountAfter).join('\n');
// If the last character is a \n, force it to be rendered.
- if (visibleAfter.charAt(visibleAfter.length - 1) == '\n') {
+ if (visibleAfter.charAt(visibleAfter.length - 1) === '\n') {
visibleAfter += ' ';
}
@@ -142,7 +142,7 @@ Polymer({
* @private
*/
getLinesNotShownLabel_(lineCount, stringSingular, stringPluralTemplate) {
- return lineCount == 1 ?
+ return lineCount === 1 ?
stringSingular :
loadTimeData.substituteString(stringPluralTemplate, lineCount);
},
@@ -152,7 +152,7 @@ Polymer({
* @param {number} end
* @private
*/
- setLineNumbers_: function(start, end) {
+ setLineNumbers_(start, end) {
let lineNumbers = '';
for (let i = start; i <= end; ++i) {
lineNumbers += i + '\n';
@@ -165,7 +165,7 @@ Polymer({
* @param {number} linesBeforeHighlight
* @private
*/
- scrollToHighlight_: function(linesBeforeHighlight) {
+ scrollToHighlight_(linesBeforeHighlight) {
const CSS_LINE_HEIGHT = 20;
// Count how many pixels is above the highlighted code.
@@ -183,7 +183,7 @@ Polymer({
* @return {string}
* @private
*/
- getAccessibilityHighlightDescription_: function(lineStart, numLines) {
+ getAccessibilityHighlightDescription_(lineStart, numLines) {
if (numLines > 1) {
return this.i18n(
'accessibilityErrorMultiLine', lineStart.toString(),
@@ -197,7 +197,7 @@ Polymer({
* @private
* @return {boolean}
*/
- computeShowNoCode_: function() {
+ computeShowNoCode_() {
return this.isActive && !this.highlighted_;
},
});
diff --git a/chromium/chrome/browser/resources/extensions/detail_view.html b/chromium/chrome/browser/resources/extensions/detail_view.html
index 6f63a2a978f..de97fd2ba01 100644
--- a/chromium/chrome/browser/resources/extensions/detail_view.html
+++ b/chromium/chrome/browser/resources/extensions/detail_view.html
@@ -40,26 +40,22 @@
flex-grow: 1;
}
- .section {
- @apply --cr-section;
- }
-
- .section.block {
+ .cr-section.block {
box-sizing: border-box;
display: block;
padding-bottom: var(--cr-section-vertical-padding);
padding-top: var(--cr-section-vertical-padding);
}
- .section.continuation {
+ .cr-section.continuation {
border-top: none;
}
- .section.control-line {
+ .cr-section.control-line {
justify-content: space-between;
}
- .section:first-child {
+ .cr-section:first-child {
border: none;
}
@@ -110,7 +106,6 @@
}
extensions-toggle-row {
- @apply --cr-section;
box-sizing: border-box;
padding-inline-end: 0;
padding-inline-start: 0;
@@ -132,7 +127,8 @@
}
paper-spinner-lite {
- @apply --cr-icon-height-width;
+ height: var(--cr-icon-size);
+ width: var(--cr-icon-size);
}
</style>
<div class="page-container" id="container">
@@ -150,7 +146,7 @@
[[data.name]]
</span>
</div>
- <div class="section continuation control-line" id="enable-section">
+ <div class="cr-section continuation control-line" id="enable-section">
<span class$="[[computeEnabledStyle_(data.state)]]">
[[computeEnabledText_(data.state, '$i18nPolymer{itemOn}',
'$i18nPolymer{itemOff}')]]
@@ -161,42 +157,42 @@
icon-class="[[getIndicatorIcon_(data.controlledInfo.type)]]"
icon-aria-label="[[data.controlledInfo.type]]">
</cr-tooltip-icon>
- <template is="dom-if" if="[[isTerminated_(data.state)]]">
+ <template is="dom-if" if="[[showReloadButton_(data.state)]]">
<cr-button id="terminated-reload-button" class="action-button"
on-click="onReloadTap_">
$i18n{itemReload}
</cr-button>
</template>
- <cr-toggle id="enable-toggle"
+ <cr-toggle id="enableToggle"
aria-label$="[[appOrExtension(
data.type,
'$i18nPolymer{appEnabled}',
'$i18nPolymer{extensionEnabled}')]]"
aria-describedby="name"
checked="[[isEnabled_(data.state)]]"
- on-change="onEnableChange_"
- disabled="[[!isEnableToggleEnabled_(data.*)]]"
- hidden$="[[isTerminated_(data.state)]]">
+ on-change="onEnableToggleChange_"
+ disabled$="[[!isEnableToggleEnabled_(data.*)]]"
+ hidden$="[[!showEnableToggle_(data.*)]]">
</cr-toggle>
</div>
</div>
<div id="warnings" hidden$="[[!hasWarnings_(data.*)]]">
<div id="runtime-warnings" hidden$="[[!data.runtimeWarnings.length]]"
- class="section continuation warning control-line">
+ class="cr-section continuation warning control-line">
<iron-icon class="warning-icon" icon="cr:error"></iron-icon>
<span>
<template is="dom-repeat" items="[[data.runtimeWarnings]]">
[[item]]
</template>
</span>
- <template is="dom-if" if="[[!isTerminated_(data.state)]]">
+ <template is="dom-if" if="[[!showReloadButton_(data.state)]]">
<cr-button id="warnings-reload-button" class="action-button"
on-click="onReloadTap_">
$i18n{itemReload}
</cr-button>
</template>
</div>
- <div class="section continuation warning" id="suspicious-warning"
+ <div class="cr-section continuation warning" id="suspicious-warning"
hidden$="[[!data.disableReasons.suspiciousInstall]]">
<iron-icon class="warning-icon" icon="cr:warning"></iron-icon>
<span>
@@ -206,9 +202,9 @@
</a>
</span>
</div>
- <div class="section continuation warning control-line"
+ <div class="cr-section continuation warning control-line"
id="corrupted-warning"
- hidden$="[[!data.disableReasons.corruptInstall]]">
+ hidden$="[[!showRepairButton_(data.disableReasons.corruptInstall)]]">
<iron-icon class="warning-icon" icon="cr:warning"></iron-icon>
<span>$i18n{itemCorruptInstall}</span>
<cr-button id="repair-button" class="action-button"
@@ -216,18 +212,18 @@
$i18n{itemRepair}
</cr-button>
</div>
- <div class="section continuation warning" id="blacklisted-warning"
+ <div class="cr-section continuation warning" id="blacklisted-warning"
hidden$="[[!data.blacklistText]]">
<iron-icon class="warning-icon" icon="cr:warning"></iron-icon>
<span>[[data.blacklistText]]</span>
</div>
- <div class="section continuation warning" id="update-required-warning"
+ <div class="cr-section continuation warning" id="update-required-warning"
hidden$="[[!data.disableReasons.updateRequired]]">
<iron-icon class="warning-icon" icon="cr:warning"></iron-icon>
<span>$i18n{updateRequiredByPolicy}</span>
</div>
</div>
- <div class="section continuation block">
+ <div class="cr-section continuation block">
<div class="section-title" role="heading" aria-level="2">
$i18n{itemDescriptionLabel}
</div>
@@ -235,13 +231,13 @@
[[getDescription_(data.description, '$i18nPolymer{noDescription}')]]
</div>
</div>
- <div class="section block">
+ <div class="cr-section block">
<div class="section-title" role="heading" aria-level="2">
$i18n{itemVersion}
</div>
<div class="section-content">[[data.version]]</div>
</div>
- <div class="section block">
+ <div class="cr-section block">
<div class="section-title" role="heading" aria-level="2">
$i18n{itemSize}
</div>
@@ -251,14 +247,14 @@
</paper-spinner-lite>
</div>
</div>
- <div class="section block" id="id-section" hidden$="[[!inDevMode]]">
+ <div class="cr-section block" id="id-section" hidden$="[[!inDevMode]]">
<div class="section-title" role="heading" aria-level="2">
$i18n{itemIdHeading}
</div>
<div class="section-content">[[data.id]]</div>
</div>
<template is="dom-if" if="[[inDevMode]]">
- <div class="section block" id="inspectable-views">
+ <div class="cr-section block" id="inspectable-views">
<div class="section-title" role="heading" aria-level="2">
$i18n{itemInspectViews}
</div>
@@ -279,7 +275,7 @@
</div>
</div>
</template>
- <div class="section block">
+ <div class="cr-section block">
<div class="section-title" role="heading" aria-level="2">
$i18n{itemPermissions}
</div>
@@ -303,7 +299,7 @@
</ul>
</div>
</div>
- <div class="section block">
+ <div class="cr-section block">
<div class="section-title" role="heading" aria-level="2">
$i18n{itemSiteAccess}
</div>
@@ -332,7 +328,7 @@
</div>
<template is="dom-if"
if="[[hasDependentExtensions_(data.dependentExtensions.splices)]]">
- <div class="section block">
+ <div class="cr-section block">
<div class="section-title" role="heading" aria-level="2">
$i18n{itemDependencies}
</div>
@@ -352,6 +348,7 @@
data.incognitoAccess.isEnabled, incognitoAvailable)]]">
<extensions-toggle-row id="allow-incognito"
checked="[[data.incognitoAccess.isActive]]"
+ class="hr"
on-change="onAllowIncognitoChange_">
<div>
<div>$i18n{itemAllowIncognito}</div>
@@ -362,6 +359,7 @@
<template is="dom-if" if="[[data.fileAccess.isEnabled]]">
<extensions-toggle-row id="allow-on-file-urls"
checked="[[data.fileAccess.isActive]]"
+ class="hr"
on-change="onAllowOnFileUrlsChange_">
<span>$i18n{itemAllowOnFileUrls}</span>
</extensions-toggle-row>
@@ -369,6 +367,7 @@
<template is="dom-if" if="[[data.errorCollection.isEnabled]]">
<extensions-toggle-row id="collect-errors"
checked="[[data.errorCollection.isActive]]"
+ class="hr"
on-change="onCollectErrorsChange_">
<span>$i18n{itemCollectErrors}</span>
</extensions-toggle-row>
@@ -390,7 +389,7 @@
<cr-link-row class="hr" hidden="[[!data.webStoreUrl.length]]"
id="viewInStore" label="$i18n{viewInStore}"
on-click="onViewInStoreTap_" external></cr-link-row>
- <div class="section block">
+ <div class="cr-section block">
<div class="section-title" role="heading" aria-level="2">
$i18n{itemSource}
</div>
diff --git a/chromium/chrome/browser/resources/extensions/detail_view.js b/chromium/chrome/browser/resources/extensions/detail_view.js
index 562c6ba0fb4..eb337947210 100644
--- a/chromium/chrome/browser/resources/extensions/detail_view.js
+++ b/chromium/chrome/browser/resources/extensions/detail_view.js
@@ -31,7 +31,7 @@ import {afterNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/po
import {ItemDelegate} from './item.js';
import {ItemBehavior} from './item_behavior.js';
-import {computeInspectableViewLabel, getItemSource, getItemSourceString, isControlled, isEnabled, userCanChangeEnablement} from './item_util.js';
+import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isControlled, isEnabled, userCanChangeEnablement} from './item_util.js';
import {navigation, Page} from './navigation_helper.js';
Polymer({
@@ -82,7 +82,7 @@ Polymer({
* Focuses the extensions options button. This should be used after the
* dialog closes.
*/
- focusOptionsButton: function() {
+ focusOptionsButton() {
this.$$('#extensions-options').focus();
},
@@ -90,7 +90,7 @@ Polymer({
* Focuses the back button when page is loaded.
* @private
*/
- onViewEnterStart_: function() {
+ onViewEnterStart_() {
const elementToFocus = this.fromActivityLog ?
this.$.extensionsActivityLogLink :
this.$.closeButton;
@@ -99,7 +99,7 @@ Polymer({
},
/** @private */
- onItemIdChanged_: function() {
+ onItemIdChanged_() {
// Clear the size, since this view is reused, such that no obsolete size
// is displayed.:
this.size_ = '';
@@ -109,7 +109,7 @@ Polymer({
},
/** @private */
- onActivityLogTap_: function() {
+ onActivityLogTap_() {
navigation.navigateTo({page: Page.ACTIVITY_LOG, extensionId: this.data.id});
},
@@ -119,12 +119,12 @@ Polymer({
* @return {string}
* @private
*/
- getDescription_: function(description, fallback) {
+ getDescription_(description, fallback) {
return description || fallback;
},
/** @private */
- onCloseButtonTap_: function() {
+ onCloseButtonTap_() {
navigation.navigateTo({page: Page.LIST});
},
@@ -132,7 +132,7 @@ Polymer({
* @return {boolean}
* @private
*/
- isControlled_: function() {
+ isControlled_() {
return isControlled(this.data);
},
@@ -140,7 +140,7 @@ Polymer({
* @return {boolean}
* @private
*/
- isEnabled_: function() {
+ isEnabled_() {
return isEnabled(this.data.state);
},
@@ -148,24 +148,15 @@ Polymer({
* @return {boolean}
* @private
*/
- isEnableToggleEnabled_: function() {
+ isEnableToggleEnabled_() {
return userCanChangeEnablement(this.data);
},
/**
- * Returns true if the extension is in the terminated state.
* @return {boolean}
* @private
*/
- isTerminated_: function() {
- return this.data.state == chrome.developerPrivate.ExtensionState.TERMINATED;
- },
-
- /**
- * @return {boolean}
- * @private
- */
- hasDependentExtensions_: function() {
+ hasDependentExtensions_() {
return this.data.dependentExtensions.length > 0;
},
@@ -173,7 +164,7 @@ Polymer({
* @return {boolean}
* @private
*/
- hasWarnings_: function() {
+ hasWarnings_() {
return this.data.disableReasons.corruptInstall ||
this.data.disableReasons.suspiciousInstall ||
this.data.disableReasons.updateRequired || !!this.data.blacklistText ||
@@ -184,7 +175,7 @@ Polymer({
* @return {string}
* @private
*/
- computeEnabledStyle_: function() {
+ computeEnabledStyle_() {
return this.isEnabled_() ? 'enabled-text' : '';
},
@@ -195,7 +186,7 @@ Polymer({
* @return {string}
* @private
*/
- computeEnabledText_: function(state, onText, offText) {
+ computeEnabledText_(state, onText, offText) {
// TODO(devlin): Get the full spectrum of these strings from bettes.
return isEnabled(state) ? onText : offText;
},
@@ -205,7 +196,7 @@ Polymer({
* @return {string}
* @private
*/
- computeInspectLabel_: function(view) {
+ computeInspectLabel_(view) {
return computeInspectableViewLabel(view);
},
@@ -213,7 +204,7 @@ Polymer({
* @return {boolean}
* @private
*/
- shouldShowOptionsLink_: function() {
+ shouldShowOptionsLink_() {
return !!this.data.optionsPage;
},
@@ -221,7 +212,7 @@ Polymer({
* @return {boolean}
* @private
*/
- shouldShowOptionsSection_: function() {
+ shouldShowOptionsSection_() {
return this.data.incognitoAccess.isEnabled ||
this.data.fileAccess.isEnabled || this.data.errorCollection.isEnabled;
},
@@ -230,75 +221,76 @@ Polymer({
* @return {boolean}
* @private
*/
- shouldShowIncognitoOption_: function() {
+ shouldShowIncognitoOption_() {
return this.data.incognitoAccess.isEnabled && this.incognitoAvailable;
},
/** @private */
- onEnableChange_: function() {
- this.delegate.setItemEnabled(this.data.id, this.$['enable-toggle'].checked);
+ onEnableToggleChange_() {
+ this.delegate.setItemEnabled(this.data.id, this.$.enableToggle.checked);
+ this.$.enableToggle.checked = this.isEnabled_();
},
/**
* @param {!{model: !{item: !chrome.developerPrivate.ExtensionView}}} e
* @private
*/
- onInspectTap_: function(e) {
+ onInspectTap_(e) {
this.delegate.inspectItemView(this.data.id, e.model.item);
},
/** @private */
- onExtensionOptionsTap_: function() {
+ onExtensionOptionsTap_() {
this.delegate.showItemOptionsPage(this.data);
},
/** @private */
- onReloadTap_: function() {
+ onReloadTap_() {
this.delegate.reloadItem(this.data.id).catch(loadError => {
this.fire('load-error', loadError);
});
},
/** @private */
- onRemoveTap_: function() {
+ onRemoveTap_() {
this.delegate.deleteItem(this.data.id);
},
/** @private */
- onRepairTap_: function() {
+ onRepairTap_() {
this.delegate.repairItem(this.data.id);
},
/** @private */
- onLoadPathTap_: function() {
+ onLoadPathTap_() {
this.delegate.showInFolder(this.data.id);
},
/** @private */
- onAllowIncognitoChange_: function() {
+ onAllowIncognitoChange_() {
this.delegate.setItemAllowedIncognito(
this.data.id, this.$$('#allow-incognito').checked);
},
/** @private */
- onAllowOnFileUrlsChange_: function() {
+ onAllowOnFileUrlsChange_() {
this.delegate.setItemAllowedOnFileUrls(
this.data.id, this.$$('#allow-on-file-urls').checked);
},
/** @private */
- onCollectErrorsChange_: function() {
+ onCollectErrorsChange_() {
this.delegate.setItemCollectsErrors(
this.data.id, this.$$('#collect-errors').checked);
},
/** @private */
- onExtensionWebSiteTap_: function() {
+ onExtensionWebSiteTap_() {
this.delegate.openUrl(this.data.manifestHomePageUrl);
},
/** @private */
- onViewInStoreTap_: function() {
+ onViewInStoreTap_() {
this.delegate.openUrl(this.data.webStoreUrl);
},
@@ -307,7 +299,7 @@ Polymer({
* @return {string}
* @private
*/
- computeDependentEntry_: function(item) {
+ computeDependentEntry_(item) {
return loadTimeData.getStringF('itemDependentEntry', item.name, item.id);
},
@@ -315,7 +307,7 @@ Polymer({
* @return {string}
* @private
*/
- computeSourceString_: function() {
+ computeSourceString_() {
return this.data.locationText ||
getItemSourceString(getItemSource(this.data));
},
@@ -325,7 +317,7 @@ Polymer({
* @return {string}
* @private
*/
- getIndicatorIcon_: function(type) {
+ getIndicatorIcon_(type) {
switch (type) {
case 'POLICY':
return 'cr20:domain';
@@ -340,7 +332,7 @@ Polymer({
* @return {boolean}
* @private
*/
- hasPermissions_: function() {
+ hasPermissions_() {
return this.data.permissions.simplePermissions.length > 0 ||
this.hasRuntimeHostPermissions_();
},
@@ -349,7 +341,7 @@ Polymer({
* @return {boolean}
* @private
*/
- hasRuntimeHostPermissions_: function() {
+ hasRuntimeHostPermissions_() {
return !!this.data.permissions.runtimeHostPermissions;
},
@@ -357,7 +349,7 @@ Polymer({
* @return {boolean}
* @private
*/
- showSiteAccessContent_: function() {
+ showSiteAccessContent_() {
return this.showFreeformRuntimeHostPermissions_() ||
this.showHostPermissionsToggleList_();
},
@@ -366,7 +358,7 @@ Polymer({
* @return {boolean}
* @private
*/
- showFreeformRuntimeHostPermissions_: function() {
+ showFreeformRuntimeHostPermissions_() {
return this.hasRuntimeHostPermissions_() &&
this.data.permissions.runtimeHostPermissions.hasAllHosts;
},
@@ -375,8 +367,39 @@ Polymer({
* @return {boolean}
* @private
*/
- showHostPermissionsToggleList_: function() {
+ showHostPermissionsToggleList_() {
return this.hasRuntimeHostPermissions_() &&
!this.data.permissions.runtimeHostPermissions.hasAllHosts;
},
+
+ /**
+ * Returns true if the reload button should be shown.
+ * @return {boolean}
+ * @private
+ */
+ showReloadButton_() {
+ return getEnableControl(this.data) === EnableControl.RELOAD;
+ },
+
+ /**
+ * Returns true if the repair button should be shown.
+ * @return {boolean}
+ * @private
+ */
+ showRepairButton_() {
+ return getEnableControl(this.data) === EnableControl.REPAIR;
+ },
+
+ /**
+ * Returns true if the enable toggle should be shown.
+ * @return {boolean}
+ * @private
+ */
+ showEnableToggle_() {
+ const enableControl = getEnableControl(this.data);
+ // We still show the toggle even if we also show the repair button in the
+ // detail view, because the repair button appears just beneath it.
+ return enableControl === EnableControl.ENABLE_TOGGLE ||
+ enableControl === EnableControl.REPAIR;
+ },
});
diff --git a/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js b/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js
index a6bfab31897..43a5771b715 100644
--- a/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js
+++ b/chromium/chrome/browser/resources/extensions/drag_and_drop_handler.js
@@ -54,7 +54,7 @@ export class DragAndDropHandler {
/** @override */
doDrop(e) {
this.fireDragEnded_();
- if (e.dataTransfer.files.length != 1) {
+ if (e.dataTransfer.files.length !== 1) {
return;
}
diff --git a/chromium/chrome/browser/resources/extensions/drop_overlay.js b/chromium/chrome/browser/resources/extensions/drop_overlay.js
index 2a627f85c7a..508280eeca4 100644
--- a/chromium/chrome/browser/resources/extensions/drop_overlay.js
+++ b/chromium/chrome/browser/resources/extensions/drop_overlay.js
@@ -26,7 +26,7 @@ Polymer({
},
/** @override */
- created: function() {
+ created() {
this.hidden = true;
const dragTarget = document.documentElement;
this.dragWrapperHandler_ = new DragAndDropHandler(true, dragTarget);
@@ -49,7 +49,7 @@ Polymer({
* @param {boolean} dragEnabled
* @private
*/
- dragEnabledChanged_: function(dragEnabled) {
+ dragEnabledChanged_(dragEnabled) {
this.dragWrapperHandler_.dragEnabled = dragEnabled;
},
});
diff --git a/chromium/chrome/browser/resources/extensions/error_page.html b/chromium/chrome/browser/resources/extensions/error_page.html
index 5f67a455dd8..e5cb53d1172 100644
--- a/chromium/chrome/browser/resources/extensions/error_page.html
+++ b/chromium/chrome/browser/resources/extensions/error_page.html
@@ -6,8 +6,9 @@
iron-icon {
--iron-icon-fill-color: var(--google-grey-refresh-700);
- @apply --cr-icon-height-width;
flex-shrink: 0;
+ height: var(--cr-icon-size);
+ width: var(--cr-icon-size);
}
iron-icon[icon='cr:warning'] {
diff --git a/chromium/chrome/browser/resources/extensions/error_page.js b/chromium/chrome/browser/resources/extensions/error_page.js
index 1da980e9a85..e922344ae93 100644
--- a/chromium/chrome/browser/resources/extensions/error_page.js
+++ b/chromium/chrome/browser/resources/extensions/error_page.js
@@ -67,7 +67,7 @@ function getRelativeUrl(url, error) {
* @private
*/
function getErrorSeverityText_(item, log, warn, error) {
- if (item.type == chrome.developerPrivate.ErrorType.RUNTIME) {
+ if (item.type === chrome.developerPrivate.ErrorType.RUNTIME) {
switch (item.severity) {
case chrome.developerPrivate.ErrorLevel.LOG:
return log;
@@ -78,7 +78,7 @@ function getErrorSeverityText_(item, log, warn, error) {
}
assertNotReached();
}
- assert(item.type == chrome.developerPrivate.ErrorType.MANIFEST);
+ assert(item.type === chrome.developerPrivate.ErrorType.MANIFEST);
return warn;
}
@@ -121,7 +121,7 @@ Polymer({
/** @private {?chrome.developerPrivate.StackFrame}*/
selectedStackFrame_: {
type: Object,
- value: function() {
+ value() {
return null;
},
},
@@ -136,12 +136,12 @@ Polymer({
},
/** @override */
- ready: function() {
+ ready() {
FocusOutlineManager.forDocument(document);
},
/** @return {!ManifestError|!RuntimeError} */
- getSelectedError: function() {
+ getSelectedError() {
return this.entries_[this.selectedEntry_];
},
@@ -149,7 +149,7 @@ Polymer({
* Focuses the back button when page is loaded.
* @private
*/
- onViewEnterStart_: function() {
+ onViewEnterStart_() {
afterNextRender(this, () => focusWithoutInk(this.$.closeButton));
chrome.metricsPrivate.recordUserAction('Options_ViewExtensionErrors');
},
@@ -160,7 +160,7 @@ Polymer({
* @return {string}
* @private
*/
- getContextUrl_: function(error, unknown) {
+ getContextUrl_(error, unknown) {
return error.contextUrl ? getRelativeUrl(error.contextUrl, error) : unknown;
},
@@ -169,7 +169,7 @@ Polymer({
* file source.
* @private
*/
- observeDataChanges_: function() {
+ observeDataChanges_() {
const errors = this.data.manifestErrors.concat(this.data.runtimeErrors);
this.entries_ = errors;
this.selectedEntry_ = -1; // This also help reset code-section content.
@@ -179,12 +179,12 @@ Polymer({
},
/** @private */
- onCloseButtonTap_: function() {
+ onCloseButtonTap_() {
navigation.navigateTo({page: Page.LIST});
},
/** @private */
- onClearAllTap_: function() {
+ onClearAllTap_() {
const ids = this.entries_.map(entry => entry.id);
this.delegate.deleteErrors(this.data.id, ids);
},
@@ -194,7 +194,7 @@ Polymer({
* @return {string}
* @private
*/
- computeErrorIcon_: function(error) {
+ computeErrorIcon_(error) {
// Do not i18n these strings, they're CSS classes.
return getErrorSeverityText_(error, 'info', 'warning', 'error');
},
@@ -204,7 +204,7 @@ Polymer({
* @return {string}
* @private
*/
- computeErrorTypeLabel_: function(error) {
+ computeErrorTypeLabel_(error) {
return getErrorSeverityText_(
error, loadTimeData.getString('logLevel'),
loadTimeData.getString('warnLevel'),
@@ -215,14 +215,14 @@ Polymer({
* @param {!Event} e
* @private
*/
- onDeleteErrorAction_: function(e) {
+ onDeleteErrorAction_(e) {
this.delegate.deleteErrors(
this.data.id, [(/** @type {!{model:Object}} */ (e)).model.item.id]);
e.stopPropagation();
},
/** private */
- onInDevModeChanged_: function() {
+ onInDevModeChanged_() {
if (!this.inDevMode) {
// Wait until next render cycle in case error page is loading.
this.async(() => {
@@ -235,7 +235,7 @@ Polymer({
* Fetches the source for the selected error and populates the code section.
* @private
*/
- onSelectedErrorChanged_: function() {
+ onSelectedErrorChanged_() {
this.code_ = null;
if (this.selectedEntry_ < 0) {
@@ -271,8 +271,8 @@ Polymer({
* @return {boolean}
* @private
*/
- computeIsRuntimeError_: function(item) {
- return item.type == chrome.developerPrivate.ErrorType.RUNTIME;
+ computeIsRuntimeError_(item) {
+ return item.type === chrome.developerPrivate.ErrorType.RUNTIME;
},
/**
@@ -283,12 +283,12 @@ Polymer({
* @return {string}
* @private
*/
- getStackTraceLabel_: function(frame) {
+ getStackTraceLabel_(frame) {
let description = getRelativeUrl(frame.url, this.getSelectedError()) + ':' +
frame.lineNumber;
if (frame.functionName) {
- const functionName = frame.functionName == '(anonymous function)' ?
+ const functionName = frame.functionName === '(anonymous function)' ?
loadTimeData.getString('anonymousFunction') :
frame.functionName;
description += ' (' + functionName + ')';
@@ -302,8 +302,8 @@ Polymer({
* @return {string}
* @private
*/
- getStackFrameClass_: function(frame) {
- return frame == this.selectedStackFrame_ ? 'selected' : '';
+ getStackFrameClass_(frame) {
+ return frame === this.selectedStackFrame_ ? 'selected' : '';
},
/**
@@ -311,8 +311,8 @@ Polymer({
* @return {number}
* @private
*/
- getStackFrameTabIndex_: function(frame) {
- return frame == this.selectedStackFrame_ ? 0 : -1;
+ getStackFrameTabIndex_(frame) {
+ return frame === this.selectedStackFrame_ ? 0 : -1;
},
/**
@@ -322,7 +322,7 @@ Polymer({
* @return {boolean}
* @private
*/
- shouldDisplayFrame_: function(url) {
+ shouldDisplayFrame_(url) {
// All our internal scripts are in the 'extensions::' namespace.
return !/^extensions::/.test(url);
},
@@ -331,7 +331,7 @@ Polymer({
* @param {!chrome.developerPrivate.StackFrame} frame
* @private
*/
- updateSelected_: function(frame) {
+ updateSelected_(frame) {
this.selectedStackFrame_ = assert(frame);
const selectedError = this.getSelectedError();
@@ -349,7 +349,7 @@ Polymer({
* @param {!Event} e
* @private
*/
- onStackFrameTap_: function(e) {
+ onStackFrameTap_(e) {
const frame = /** @type {!{model:Object}} */ (e).model.item;
this.updateSelected_(frame);
},
@@ -358,12 +358,12 @@ Polymer({
* @param {!Event} e
* @private
*/
- onStackKeydown_: function(e) {
+ onStackKeydown_(e) {
let direction = 0;
- if (e.key == 'ArrowDown') {
+ if (e.key === 'ArrowDown') {
direction = 1;
- } else if (e.key == 'ArrowUp') {
+ } else if (e.key === 'ArrowUp') {
direction = -1;
} else {
return;
@@ -393,14 +393,14 @@ Polymer({
* @return {string}
* @private
*/
- computeErrorClass_: function(index) {
- return index == this.selectedEntry_ ? 'selected' : '';
+ computeErrorClass_(index) {
+ return index === this.selectedEntry_ ? 'selected' : '';
},
/** @private */
- iconName_: function(index) {
- return index == this.selectedEntry_ ? 'icon-expand-less' :
- 'icon-expand-more';
+ iconName_(index) {
+ return index === this.selectedEntry_ ? 'icon-expand-less' :
+ 'icon-expand-more';
},
/**
@@ -409,8 +409,8 @@ Polymer({
* @return {boolean}
* @private
*/
- isOpened_: function(index) {
- return index == this.selectedEntry_;
+ isOpened_(index) {
+ return index === this.selectedEntry_;
},
@@ -419,7 +419,7 @@ Polymer({
* @return {string} The aria-expanded value as a string.
* @private
*/
- isAriaExpanded_: function(index) {
+ isAriaExpanded_(index) {
return this.isOpened_(index).toString();
},
@@ -427,8 +427,8 @@ Polymer({
* @param {!{type: string, code: string, model: !{index: number}}} e
* @private
*/
- onErrorItemAction_: function(e) {
- if (e.type == 'keydown' && !((e.code == 'Space' || e.code == 'Enter'))) {
+ onErrorItemAction_(e) {
+ if (e.type === 'keydown' && !((e.code === 'Space' || e.code === 'Enter'))) {
return;
}
@@ -436,6 +436,6 @@ Polymer({
// is pressed.
e.preventDefault();
this.selectedEntry_ =
- this.selectedEntry_ == e.model.index ? -1 : e.model.index;
+ this.selectedEntry_ === e.model.index ? -1 : e.model.index;
},
});
diff --git a/chromium/chrome/browser/resources/extensions/extensions_resources.grd b/chromium/chrome/browser/resources/extensions/extensions_resources.grd
index a98ad371e92..81d265b85a7 100644
--- a/chromium/chrome/browser/resources/extensions/extensions_resources.grd
+++ b/chromium/chrome/browser/resources/extensions/extensions_resources.grd
@@ -30,6 +30,9 @@
<include name="IDR_EXTENSIONS_ACTIVITY_LOG_ACTIVITY_LOG_STREAM_ITEM_JS"
file="${root_gen_dir}/chrome/browser/resources/extensions/activity_log/activity_log_stream_item.js"
use_base_dir="false" type ="BINDATA" />
+ <include name="IDR_EXTENSIONS_CHECKUP_JS"
+ file="${root_gen_dir}/chrome/browser/resources/extensions/checkup.js"
+ use_base_dir="false" type ="BINDATA" />
<include name="IDR_EXTENSIONS_DETAIL_VIEW_JS"
file="${root_gen_dir}/chrome/browser/resources/extensions/detail_view.js"
use_base_dir="false" type ="BINDATA" />
@@ -38,7 +41,7 @@
use_base_dir="false" type ="BINDATA" />
<include name="IDR_EXTENSIONS_ERROR_PAGE_JS"
file="${root_gen_dir}/chrome/browser/resources/extensions/error_page.js"
- use_base_dir="false" type ="BINDATA" flattenhtml="true" />
+ use_base_dir="false" type ="BINDATA" />
<include name="IDR_EXTENSIONS_KEYBOARD_SHORTCUTS_JS"
file="${root_gen_dir}/chrome/browser/resources/extensions/keyboard_shortcuts.js"
use_base_dir="false" type ="BINDATA" />
@@ -49,7 +52,7 @@
</if>
<include name="IDR_EXTENSIONS_MANAGER_JS"
file="${root_gen_dir}/chrome/browser/resources/extensions/manager.js"
- use_base_dir="false" type ="BINDATA" flattenhtml="true" />
+ preprocess="true" use_base_dir="false" type ="BINDATA" />
<include name="IDR_EXTENSIONS_ICONS_JS"
file="${root_gen_dir}/chrome/browser/resources/extensions/icons.js"
use_base_dir="false" type ="BINDATA" />
@@ -100,12 +103,11 @@
use_base_dir="false" type ="BINDATA" />
<include name="IDR_EXTENSIONS_TOOLBAR_JS"
file="${root_gen_dir}/chrome/browser/resources/extensions/toolbar.js"
- use_base_dir="false" type ="BINDATA" flattenhtml="true" />
- <include name="IDR_WEBUI_IMAGES_CHECKUP_IMAGE"
- file="checkup_image.svg" type="BINDATA" compress="gzip" />
- <include name="IDR_WEBUI_IMAGES_CHECKUP_IMAGE_DARKMODE"
- file="checkup_image_dark.svg" type="BINDATA"
- compress="gzip" />
+ preprocess="true" use_base_dir="false" type ="BINDATA" />
+ <include name="IDR_EXTENSIONS_CHECKUP_IMAGE"
+ file="checkup_image.svg" type="BINDATA" />
+ <include name="IDR_EXTENSIONS_CHECKUP_IMAGE_DARK"
+ file="checkup_image_dark.svg" type="BINDATA" />
</includes>
<structures>
<structure name="IDR_EXTENSIONS_ITEM_BEHAVIOR_JS"
diff --git a/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd b/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd
index d8aec253a44..3ebe27cf553 100644
--- a/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd
+++ b/chromium/chrome/browser/resources/extensions/extensions_resources_vulcanized.grd
@@ -22,6 +22,14 @@
preprocess="true"
type="BINDATA"
compress="gzip" />
+ <include name="IDR_EXTENSIONS_CHECKUP_IMAGE"
+ file="checkup_image.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_EXTENSIONS_CHECKUP_IMAGE_DARK"
+ file="checkup_image_dark.svg"
+ type="BINDATA"
+ compress="gzip" />
</includes>
</release>
</grit>
diff --git a/chromium/chrome/browser/resources/extensions/host_permissions_toggle_list.js b/chromium/chrome/browser/resources/extensions/host_permissions_toggle_list.js
index b8a3e492161..9328014b32f 100644
--- a/chromium/chrome/browser/resources/extensions/host_permissions_toggle_list.js
+++ b/chromium/chrome/browser/resources/extensions/host_permissions_toggle_list.js
@@ -38,8 +38,8 @@ Polymer({
* requested sites.
* @private
*/
- allowedOnAllHosts_: function() {
- return this.permissions.hostAccess ==
+ allowedOnAllHosts_() {
+ return this.permissions.hostAccess ===
chrome.developerPrivate.HostAccess.ON_ALL_SITES;
},
@@ -49,7 +49,7 @@ Polymer({
* @return {!Array<!chrome.developerPrivate.SiteControl>}
* @private
*/
- getSortedHosts_: function() {
+ getSortedHosts_() {
return this.permissions.hosts.sort((a, b) => {
if (a.host < b.host) {
return -1;
@@ -62,7 +62,7 @@ Polymer({
},
/** @private */
- onAllHostsToggleChanged_: function() {
+ onAllHostsToggleChanged_() {
// TODO(devlin): In the case of going from all sites to specific sites,
// we'll withhold all sites (i.e., all specific site toggles will move to
// unchecked, and the user can check them individually). This is slightly
@@ -78,7 +78,7 @@ Polymer({
},
/** @private */
- onHostAccessChanged_: function(e) {
+ onHostAccessChanged_(e) {
const host = e.target.host;
const checked = e.target.checked;
diff --git a/chromium/chrome/browser/resources/extensions/install_warnings_dialog.js b/chromium/chrome/browser/resources/extensions/install_warnings_dialog.js
index b333dca3db5..e599dcfa69c 100644
--- a/chromium/chrome/browser/resources/extensions/install_warnings_dialog.js
+++ b/chromium/chrome/browser/resources/extensions/install_warnings_dialog.js
@@ -21,12 +21,12 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
this.$.dialog.showModal();
},
/** @private */
- onOkTap_: function() {
+ onOkTap_() {
this.$.dialog.close();
},
});
diff --git a/chromium/chrome/browser/resources/extensions/item.html b/chromium/chrome/browser/resources/extensions/item.html
index b70ec925b38..c39e28b1c1c 100644
--- a/chromium/chrome/browser/resources/extensions/item.html
+++ b/chromium/chrome/browser/resources/extensions/item.html
@@ -34,12 +34,12 @@
}
#card {
- @apply --cr-card-elevation;
background-color: var(--cr-card-background-color);
border-radius: var(--cr-card-border-radius);
+ box-shadow: var(--cr-card-shadow);
display: flex;
flex-direction: column;
- height: 160px;
+ height: var(--extensions-card-height);
/* Duration matches --drawer-transition from toolbar.html. */
transition: height 300ms cubic-bezier(.25, .1, .25, 1);
}
@@ -132,7 +132,7 @@
.source-icon-wrapper {
align-items: center;
background: rgb(241, 89, 43); /* Same in light & dark modes. */
- border-radius: 50%; /* 50% border radius == a circle */
+ border-radius: 50%; /* 50% border radius === a circle */
box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.22),
0 2px 2px 0 rgba(0, 0, 0, 0.12);
display: flex;
@@ -299,26 +299,28 @@
aria-label="$i18n{itemReload}" aria-describedby="a11yAssociation"
on-click="onReloadTap_"></cr-icon-button>
</template>
- <template is="dom-if" if="[[data.disableReasons.corruptInstall]]">
+ <template is="dom-if"
+ if="[[showRepairButton_(data.disableReasons.corruptInstall)]]">
<cr-button id="repair-button" class="action-button"
aria-describedby="a11yAssociation" on-click="onRepairTap_">
$i18n{itemRepair}
</cr-button>
</template>
- <template is="dom-if" if="[[isTerminated_(data.state)]]">
+ <template is="dom-if" if="[[showReloadButton_(data.state)]]">
<cr-button id="terminated-reload-button" on-click="onReloadTap_"
aria-describedby="a11yAssociation" class="action-button">
$i18n{itemReload}
</cr-button>
</template>
- <cr-toggle id="enable-toggle"
+ <cr-toggle id="enableToggle"
aria-label$="[[appOrExtension(
data.type,
'$i18nPolymer{appEnabled}',
'$i18nPolymer{extensionEnabled}')]]"
aria-describedby="a11yAssociation"
- checked="[[isEnabled_(data.state)]]" on-change="onEnableChange_"
- disabled="[[!isEnableToggleEnabled_(data.*)]]"
+ checked="[[isEnabled_(data.state)]]"
+ on-change="onEnableToggleChange_"
+ disabled$="[[!isEnableToggleEnabled_(data.*)]]"
hidden$="[[!showEnableToggle_(data.*)]]">
</cr-toggle>
</div>
diff --git a/chromium/chrome/browser/resources/extensions/item.js b/chromium/chrome/browser/resources/extensions/item.js
index 7973811c58e..e82aecbfbe4 100644
--- a/chromium/chrome/browser/resources/extensions/item.js
+++ b/chromium/chrome/browser/resources/extensions/item.js
@@ -26,7 +26,7 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {flush, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {ItemBehavior} from './item_behavior.js';
-import {computeInspectableViewLabel, getItemSource, getItemSourceString, isControlled, isEnabled, SourceType, userCanChangeEnablement} from './item_util.js';
+import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isControlled, isEnabled, SourceType, userCanChangeEnablement} from './item_util.js';
import {navigation, Page} from './navigation_helper.js';
/** @interface */
@@ -153,17 +153,17 @@ Polymer({
],
/** @return {!HTMLElement} The "Details" button. */
- getDetailsButton: function() {
+ getDetailsButton() {
return /** @type {!HTMLElement} */ (this.$.detailsButton);
},
/** @return {?HTMLElement} The "Errors" button, if it exists. */
- getErrorsButton: function() {
+ getErrorsButton() {
return /** @type {?HTMLElement} */ (this.$$('#errors-button'));
},
/** @private string */
- a11yAssociation_: function() {
+ a11yAssociation_() {
// Don't use I18nBehavior.i18n because of additional checks it performs.
// Polymer ensures that this string is not stamped into arbitrary HTML.
// |this.data.name| can contain any data including html tags.
@@ -172,7 +172,7 @@ Polymer({
},
/** @private */
- observeIdVisibility_: function(inDevMode, showingDetails, id) {
+ observeIdVisibility_(inDevMode, showingDetails, id) {
flush();
const idElement = this.$$('#extension-id');
if (idElement) {
@@ -185,7 +185,7 @@ Polymer({
* @return {boolean}
* @private
*/
- shouldShowErrorsButton_: function() {
+ shouldShowErrorsButton_() {
// When the error console is disabled (happens when
// --disable-error-console command line flag is used or when in the
// Stable/Beta channel), |installWarnings| is populated.
@@ -200,17 +200,18 @@ Polymer({
},
/** @private */
- onRemoveTap_: function() {
+ onRemoveTap_() {
this.delegate.deleteItem(this.data.id);
},
/** @private */
- onEnableChange_: function() {
- this.delegate.setItemEnabled(this.data.id, this.$['enable-toggle'].checked);
+ onEnableToggleChange_() {
+ this.delegate.setItemEnabled(this.data.id, this.$.enableToggle.checked);
+ this.$.enableToggle.checked = this.isEnabled_();
},
/** @private */
- onErrorsTap_: function() {
+ onErrorsTap_() {
if (this.data.installWarnings && this.data.installWarnings.length > 0) {
this.fire('show-install-warnings', this.data.installWarnings);
return;
@@ -220,7 +221,7 @@ Polymer({
},
/** @private */
- onDetailsTap_: function() {
+ onDetailsTap_() {
navigation.navigateTo({page: Page.DETAILS, extensionId: this.data.id});
},
@@ -228,17 +229,17 @@ Polymer({
* @param {!{model: !{item: !chrome.developerPrivate.ExtensionView}}} e
* @private
*/
- onInspectTap_: function(e) {
+ onInspectTap_(e) {
this.delegate.inspectItemView(this.data.id, this.data.views[0]);
},
/** @private */
- onExtraInspectTap_: function() {
+ onExtraInspectTap_() {
navigation.navigateTo({page: Page.DETAILS, extensionId: this.data.id});
},
/** @private */
- onReloadTap_: function() {
+ onReloadTap_() {
// Don't reload if in the middle of an update.
if (this.isReloading_) {
return;
@@ -266,7 +267,7 @@ Polymer({
},
/** @private */
- onRepairTap_: function() {
+ onRepairTap_() {
this.delegate.repairItem(this.data.id);
},
@@ -274,7 +275,7 @@ Polymer({
* @return {boolean}
* @private
*/
- isControlled_: function() {
+ isControlled_() {
return isControlled(this.data);
},
@@ -282,7 +283,7 @@ Polymer({
* @return {boolean}
* @private
*/
- isEnabled_: function() {
+ isEnabled_() {
return isEnabled(this.data.state);
},
@@ -290,33 +291,43 @@ Polymer({
* @return {boolean}
* @private
*/
- isEnableToggleEnabled_: function() {
+ isEnableToggleEnabled_() {
return userCanChangeEnablement(this.data);
},
/**
- * Returns true if the enable toggle should be shown.
+ * Returns true if the reload button should be shown.
* @return {boolean}
* @private
*/
- showEnableToggle_: function() {
- return !this.isTerminated_() && !this.data.disableReasons.corruptInstall;
+ showReloadButton_() {
+ return getEnableControl(this.data) === EnableControl.RELOAD;
},
/**
- * Returns true if the extension is in the terminated state.
+ * Returns true if the repair button should be shown.
+ * @return {boolean}
+ * @private
+ */
+ showRepairButton_() {
+ return getEnableControl(this.data) === EnableControl.REPAIR;
+ },
+
+
+ /**
+ * Returns true if the enable toggle should be shown.
* @return {boolean}
* @private
*/
- isTerminated_: function() {
- return this.data.state == chrome.developerPrivate.ExtensionState.TERMINATED;
+ showEnableToggle_() {
+ return getEnableControl(this.data) === EnableControl.ENABLE_TOGGLE;
},
/**
* return {string}
* @private
*/
- computeClasses_: function() {
+ computeClasses_() {
let classes = this.isEnabled_() ? 'enabled' : 'disabled';
if (this.inDevMode) {
classes += ' dev-mode';
@@ -328,7 +339,7 @@ Polymer({
* @return {string}
* @private
*/
- computeSourceIndicatorIcon_: function() {
+ computeSourceIndicatorIcon_() {
switch (getItemSource(this.data)) {
case SourceType.POLICY:
return 'extensions-icons:business';
@@ -349,29 +360,29 @@ Polymer({
* @return {string}
* @private
*/
- computeSourceIndicatorText_: function() {
+ computeSourceIndicatorText_() {
if (this.data.locationText) {
return this.data.locationText;
}
const sourceType = getItemSource(this.data);
- return sourceType == SourceType.WEBSTORE ? '' :
- getItemSourceString(sourceType);
+ return sourceType === SourceType.WEBSTORE ? '' :
+ getItemSourceString(sourceType);
},
/**
* @return {boolean}
* @private
*/
- computeInspectViewsHidden_: function() {
- return !this.data.views || this.data.views.length == 0;
+ computeInspectViewsHidden_() {
+ return !this.data.views || this.data.views.length === 0;
},
/**
* @return {string}
* @private
*/
- computeFirstInspectTitle_: function() {
+ computeFirstInspectTitle_() {
// Note: theoretically, this wouldn't be called without any inspectable
// views (because it's in a dom-if="!computeInspectViewsHidden_()").
// However, due to the recycling behavior of iron list, it seems that
@@ -386,7 +397,7 @@ Polymer({
* @return {string}
* @private
*/
- computeFirstInspectLabel_: function() {
+ computeFirstInspectLabel_() {
const label = this.computeFirstInspectTitle_();
return label && this.data.views.length > 1 ? label + ',' : label;
},
@@ -395,7 +406,7 @@ Polymer({
* @return {boolean}
* @private
*/
- computeExtraViewsHidden_: function() {
+ computeExtraViewsHidden_() {
return this.data.views.length <= 1;
},
@@ -403,13 +414,13 @@ Polymer({
* @return {boolean}
* @private
*/
- computeDevReloadButtonHidden_: function() {
+ computeDevReloadButtonHidden_() {
// Only display the reload spinner if the extension is unpacked and
// enabled. There's no point in reloading a disabled extension, and we'll
// show a crashed reload button if it's terminated.
const showIcon =
- this.data.location == chrome.developerPrivate.Location.UNPACKED &&
- this.data.state == chrome.developerPrivate.ExtensionState.ENABLED;
+ this.data.location === chrome.developerPrivate.Location.UNPACKED &&
+ this.data.state === chrome.developerPrivate.ExtensionState.ENABLED;
return !showIcon;
},
@@ -417,7 +428,7 @@ Polymer({
* @return {string}
* @private
*/
- computeExtraInspectLabel_: function() {
+ computeExtraInspectLabel_() {
return this.i18n(
'itemInspectViewsExtra', (this.data.views.length - 1).toString());
},
@@ -426,7 +437,7 @@ Polymer({
* @return {boolean}
* @private
*/
- hasWarnings_: function() {
+ hasWarnings_() {
return this.data.disableReasons.corruptInstall ||
this.data.disableReasons.suspiciousInstall ||
this.data.runtimeWarnings.length > 0 || !!this.data.blacklistText;
@@ -436,7 +447,7 @@ Polymer({
* @return {string}
* @private
*/
- computeWarningsClasses_: function() {
+ computeWarningsClasses_() {
return this.data.blacklistText ? 'severe' : 'mild';
},
});
diff --git a/chromium/chrome/browser/resources/extensions/item_behavior.js b/chromium/chrome/browser/resources/extensions/item_behavior.js
index c1e368a4368..984ab93ce0f 100644
--- a/chromium/chrome/browser/resources/extensions/item_behavior.js
+++ b/chromium/chrome/browser/resources/extensions/item_behavior.js
@@ -12,7 +12,7 @@ export const ItemBehavior = {
* @param {string} extensionLabel
* @return {string} The app or extension label depending on |type|.
*/
- appOrExtension: function(type, appLabel, extensionLabel) {
+ appOrExtension(type, appLabel, extensionLabel) {
const ExtensionType = chrome.developerPrivate.ExtensionType;
switch (type) {
case ExtensionType.HOSTED_APP:
diff --git a/chromium/chrome/browser/resources/extensions/item_list.html b/chromium/chrome/browser/resources/extensions/item_list.html
index 2ea1c0f87ae..56b2f7b6b8a 100644
--- a/chromium/chrome/browser/resources/extensions/item_list.html
+++ b/chromium/chrome/browser/resources/extensions/item_list.html
@@ -31,7 +31,6 @@
.items-container {
--grid-gutter: 12px;
- --max-columns: 3;
display: grid;
grid-column-gap: var(--grid-gutter);
grid-row-gap: var(--grid-gutter);
@@ -42,6 +41,12 @@
var(--grid-gutter) * var(--max-columns));
}
+ #checkup-container {
+ grid-column: 1 / -1;
+ /* The checkup card should be at least as tall as an extensions item card.*/
+ min-height: var(--extensions-card-height);
+ }
+
extensions-item {
grid-column-start: auto;
grid-row-start: auto;
@@ -74,7 +79,7 @@
</style>
<div id="container">
<managed-footnote hidden="[[filter]]"></managed-footnote>
- <div id="content-wrapper">
+ <div id="content-wrapper" style="--max-columns: [[maxColumns_]];">
<div id="no-items" class="empty-list-message"
hidden$="[[!shouldShowEmptyItemsMessage_(
apps.length, extensions.length)]]">
@@ -88,6 +93,10 @@
<span>$i18n{noSearchResults}</span>
</div>
<div class="items-container" hidden="[[!shownExtensionsCount_]]">
+ <div id="checkup-container" hidden="[[!showCheckup_]]">
+ <extensions-checkup id="checkup" slot="view">
+ </extensions-checkup>
+ </div>
<!-- Render only a few items first, to improve initial render time,
then render the remaining items on a different frame. Value of 3
was chosen by experimentation, and it is a good trade-off between
diff --git a/chromium/chrome/browser/resources/extensions/item_list.js b/chromium/chrome/browser/resources/extensions/item_list.js
index f24ce184d71..82136e86fa8 100644
--- a/chromium/chrome/browser/resources/extensions/item_list.js
+++ b/chromium/chrome/browser/resources/extensions/item_list.js
@@ -4,9 +4,11 @@
import 'chrome://resources/cr_components/managed_footnote/managed_footnote.m.js';
import './shared_style.js';
+import './checkup.js';
import {CrContainerShadowBehavior} from 'chrome://resources/cr_elements/cr_container_shadow_behavior.m.js';
import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -46,9 +48,15 @@ Polymer({
},
/** @private */
- shownExtensionsCount_: {
+ maxColumns_: {
type: Number,
- value: 0,
+ value: () => loadTimeData.getBoolean('showCheckup') ? 2 : 3,
+ },
+
+ /** @private */
+ showCheckup_: {
+ type: Boolean,
+ value: () => loadTimeData.getBoolean('showCheckup'),
},
/** @private */
@@ -56,13 +64,19 @@ Polymer({
type: Number,
value: 0,
},
+
+ /** @private */
+ shownExtensionsCount_: {
+ type: Number,
+ value: 0,
+ },
},
/**
* @param {string} id
* @return {?Element}
*/
- getDetailsButton: function(id) {
+ getDetailsButton(id) {
const item = this.$$(`#${id}`);
return item && item.getDetailsButton();
},
@@ -71,7 +85,7 @@ Polymer({
* @param {string} id
* @return {?Element}
*/
- getErrorsButton: function(id) {
+ getErrorsButton(id) {
const item = this.$$(`#${id}`);
return item && item.getErrorsButton();
},
@@ -83,7 +97,7 @@ Polymer({
* return {?Function}
* @private
*/
- computeFilter_: function() {
+ computeFilter_() {
const formattedFilter = this.filter.trim().toLowerCase();
return formattedFilter ?
i => i.name.toLowerCase().includes(formattedFilter) :
@@ -91,7 +105,7 @@ Polymer({
},
/** @private */
- shouldShowEmptyItemsMessage_: function() {
+ shouldShowEmptyItemsMessage_() {
if (!this.apps || !this.extensions) {
return;
}
@@ -100,20 +114,20 @@ Polymer({
},
/** @private */
- shouldShowEmptySearchMessage_: function() {
+ shouldShowEmptySearchMessage_() {
return !this.shouldShowEmptyItemsMessage_() && this.shownAppsCount_ === 0 &&
this.shownExtensionsCount_ === 0;
},
/** @private */
- onNoExtensionsTap_: function(e) {
- if (e.target.tagName == 'A') {
+ onNoExtensionsTap_(e) {
+ if (e.target.tagName === 'A') {
chrome.metricsPrivate.recordUserAction('Options_GetMoreExtensions');
}
},
/** @private */
- announceSearchResults_: function() {
+ announceSearchResults_() {
if (this.computedFilter_) {
IronA11yAnnouncer.requestAvailability();
this.async(() => { // Async to allow list to update.
@@ -121,7 +135,7 @@ Polymer({
this.fire('iron-announce', {
text: this.shouldShowEmptySearchMessage_() ?
this.i18n('noSearchResults') :
- (total == 1 ?
+ (total === 1 ?
this.i18n('searchResultsSingular', this.filter) :
this.i18n(
'searchResultsPlural', total.toString(), this.filter)),
diff --git a/chromium/chrome/browser/resources/extensions/item_util.js b/chromium/chrome/browser/resources/extensions/item_util.js
index b137f5d8438..a1f91b53f7e 100644
--- a/chromium/chrome/browser/resources/extensions/item_util.js
+++ b/chromium/chrome/browser/resources/extensions/item_util.js
@@ -18,6 +18,13 @@ export const SourceType = {
UNKNOWN: 'unknown',
};
+/** @enum {string} */
+export const EnableControl = {
+ RELOAD: 'RELOAD',
+ REPAIR: 'REPAIR',
+ ENABLE_TOGGLE: 'ENABLE_TOGGLE',
+};
+
/**
* Returns true if the extension is enabled, including terminated
* extensions.
@@ -58,7 +65,8 @@ export function userCanChangeEnablement(item) {
// Item is forcefully disabled.
if (item.disableReasons.corruptInstall ||
item.disableReasons.suspiciousInstall ||
- item.disableReasons.updateRequired) {
+ item.disableReasons.updateRequired ||
+ item.disableReasons.blockedByPolicy) {
return false;
}
// An item with dependent extensions can't be disabled (it would bork the
@@ -67,7 +75,7 @@ export function userCanChangeEnablement(item) {
return false;
}
// Blacklisted can't be enabled, either.
- if (item.state == chrome.developerPrivate.ExtensionState.BLACKLISTED) {
+ if (item.state === chrome.developerPrivate.ExtensionState.BLACKLISTED) {
return false;
}
@@ -80,7 +88,7 @@ export function userCanChangeEnablement(item) {
*/
export function getItemSource(item) {
if (item.controlledInfo &&
- item.controlledInfo.type ==
+ item.controlledInfo.type ===
chrome.developerPrivate.ControllerType.POLICY) {
return SourceType.POLICY;
}
@@ -130,17 +138,17 @@ export function computeInspectableViewLabel(view) {
// Trim the "chrome-extension://<id>/".
const url = new URL(view.url);
let label = view.url;
- if (url.protocol == 'chrome-extension:') {
+ if (url.protocol === 'chrome-extension:') {
label = url.pathname.substring(1);
}
- if (label == '_generated_background_page.html') {
+ if (label === '_generated_background_page.html') {
label = loadTimeData.getString('viewBackgroundPage');
}
// Add any qualifiers.
if (view.incognito) {
label += ' ' + loadTimeData.getString('viewIncognito');
}
- if (view.renderProcessId == -1) {
+ if (view.renderProcessId === -1) {
label += ' ' + loadTimeData.getString('viewInactive');
}
if (view.isIframe) {
@@ -149,3 +157,28 @@ export function computeInspectableViewLabel(view) {
return label;
}
+
+/**
+ * Returns true if the extension is in the terminated state.
+ * @param {!chrome.developerPrivate.ExtensionState} state
+ * @return {boolean}
+ * @private
+ */
+function isTerminated_(state) {
+ return state === chrome.developerPrivate.ExtensionState.TERMINATED;
+}
+
+/**
+ * Determines which enable control to display for a given extension.
+ * @param {!chrome.developerPrivate.ExtensionInfo} data
+ * @return {EnableControl}
+ */
+export function getEnableControl(data) {
+ if (isTerminated_(data.state)) {
+ return EnableControl.RELOAD;
+ }
+ if (data.disableReasons.corruptInstall) {
+ return EnableControl.REPAIR;
+ }
+ return EnableControl.ENABLE_TOGGLE;
+}
diff --git a/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.html b/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.html
index 9c8a8638fb3..832dfb7bd3b 100644
--- a/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.html
+++ b/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.html
@@ -4,9 +4,9 @@
}
.shortcut-card {
- @apply --cr-card-elevation;
background-color: var(--cr-card-background-color);
border-radius: var(--cr-card-border-radius);
+ box-shadow: var(--cr-card-shadow);
color: var(--cr-primary-text-color);
margin: 0 auto 16px auto;
padding-bottom: 8px;
diff --git a/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.js b/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.js
index 92d8663ffee..aa9b03bf06a 100644
--- a/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.js
+++ b/chromium/chrome/browser/resources/extensions/keyboard_shortcuts.js
@@ -44,7 +44,7 @@ Polymer({
},
/** @private */
- onViewEnter_: function() {
+ onViewEnter_() {
chrome.metricsPrivate.recordUserAction('Options_ExtensionCommands');
},
@@ -52,7 +52,7 @@ Polymer({
* @return {!Array<!chrome.developerPrivate.ExtensionInfo>}
* @private
*/
- calculateShownItems_: function() {
+ calculateShownItems_() {
return this.items.filter(function(item) {
return item.commands.length > 0;
});
@@ -66,7 +66,7 @@ Polymer({
* @return {boolean}
* @private
*/
- hasKeybinding_: function(keybinding) {
+ hasKeybinding_(keybinding) {
return !!keybinding;
},
@@ -76,7 +76,7 @@ Polymer({
* @return {boolean}
* @private
*/
- computeScopeDisabled_: function(command) {
+ computeScopeDisabled_(command) {
return command.isExtensionAction || !command.isActive;
},
@@ -86,12 +86,12 @@ Polymer({
* @param {string} scope
* @return {string}
*/
- triggerScopeChange_: function(scope) {
+ triggerScopeChange_(scope) {
return scope;
},
/** @private */
- onCloseButtonClick_: function() {
+ onCloseButtonClick_() {
this.fire('close');
},
@@ -99,7 +99,7 @@ Polymer({
* @param {!{target: HTMLSelectElement, model: Object}} event
* @private
*/
- onScopeChanged_: function(event) {
+ onScopeChanged_(event) {
this.delegate.updateExtensionCommandScope(
event.model.get('item.id'), event.model.get('command.name'),
/** @type {chrome.developerPrivate.CommandScope} */
diff --git a/chromium/chrome/browser/resources/extensions/kiosk_dialog.js b/chromium/chrome/browser/resources/extensions/kiosk_dialog.js
index 04bc4cb1e9b..1ccf476eb04 100644
--- a/chromium/chrome/browser/resources/extensions/kiosk_dialog.js
+++ b/chromium/chrome/browser/resources/extensions/kiosk_dialog.js
@@ -52,12 +52,12 @@ Polymer({
kioskBrowserProxy_: null,
/** @override */
- ready: function() {
+ ready() {
this.kioskBrowserProxy_ = KioskBrowserProxyImpl.getInstance();
},
/** @override */
- attached: function() {
+ attached() {
this.kioskBrowserProxy_.initializeKioskAppSettings()
.then(params => {
this.canEditAutoLaunch_ = params.autoLaunchEnabled;
@@ -77,7 +77,7 @@ Polymer({
* @param {!KioskAppSettings} settings
* @private
*/
- setSettings_: function(settings) {
+ setSettings_(settings) {
this.apps_ = settings.apps;
this.bailoutDisabled_ = settings.disableBailout;
this.canEditBailout_ = settings.hasAutoLaunchApp;
@@ -87,8 +87,8 @@ Polymer({
* @param {!KioskApp} app
* @private
*/
- updateApp_: function(app) {
- const index = this.apps_.findIndex(a => a.id == app.id);
+ updateApp_(app) {
+ const index = this.apps_.findIndex(a => a.id === app.id);
assert(index < this.apps_.length);
this.set('apps_.' + index, app);
},
@@ -97,7 +97,7 @@ Polymer({
* @param {string} appId
* @private
*/
- showError_: function(appId) {
+ showError_(appId) {
this.errorAppId_ = appId;
},
@@ -106,19 +106,19 @@ Polymer({
* @return {string}
* @private
*/
- getErrorMessage_: function(errorMessage) {
+ getErrorMessage_(errorMessage) {
return this.errorAppId_ + ' ' + errorMessage;
},
/** @private */
- onAddAppTap_: function() {
+ onAddAppTap_() {
assert(this.addAppInput_);
this.kioskBrowserProxy_.addKioskApp(this.addAppInput_);
this.addAppInput_ = null;
},
/** @private */
- clearInputInvalid_: function() {
+ clearInputInvalid_() {
this.errorAppId_ = null;
},
@@ -126,7 +126,7 @@ Polymer({
* @param {{model: {item: !KioskApp}}} event
* @private
*/
- onAutoLaunchButtonTap_: function(event) {
+ onAutoLaunchButtonTap_(event) {
const app = event.model.item;
if (app.autoLaunch) { // If the app is originally set to
// auto-launch.
@@ -140,7 +140,7 @@ Polymer({
* @param {!Event} event
* @private
*/
- onBailoutChanged_: function(event) {
+ onBailoutChanged_(event) {
event.preventDefault();
if (this.$.bailout.checked) {
this.$['confirm-dialog'].showModal();
@@ -151,19 +151,19 @@ Polymer({
},
/** @private */
- onBailoutDialogCancelTap_: function() {
+ onBailoutDialogCancelTap_() {
this.$.bailout.checked = false;
this.$['confirm-dialog'].cancel();
},
/** @private */
- onBailoutDialogConfirmTap_: function() {
+ onBailoutDialogConfirmTap_() {
this.kioskBrowserProxy_.setDisableBailoutShortcut(true);
this.$['confirm-dialog'].close();
},
/** @private */
- onDoneTap_: function() {
+ onDoneTap_() {
this.$.dialog.close();
},
@@ -171,7 +171,7 @@ Polymer({
* @param {{model: {item: !KioskApp}}} event
* @private
*/
- onDeleteAppTap_: function(event) {
+ onDeleteAppTap_(event) {
this.kioskBrowserProxy_.removeKioskApp(event.model.item.id);
},
@@ -182,7 +182,7 @@ Polymer({
* @return {string}
* @private
*/
- getAutoLaunchButtonLabel_: function(autoLaunched, disableStr, enableStr) {
+ getAutoLaunchButtonLabel_(autoLaunched, disableStr, enableStr) {
return autoLaunched ? disableStr : enableStr;
},
@@ -190,7 +190,7 @@ Polymer({
* @param {!Event} e
* @private
*/
- stopPropagation_: function(e) {
+ stopPropagation_(e) {
e.stopPropagation();
},
});
diff --git a/chromium/chrome/browser/resources/extensions/load_error.js b/chromium/chrome/browser/resources/extensions/load_error.js
index ff678ac6176..ece39918c1a 100644
--- a/chromium/chrome/browser/resources/extensions/load_error.js
+++ b/chromium/chrome/browser/resources/extensions/load_error.js
@@ -42,16 +42,16 @@ Polymer({
'observeLoadErrorChanges_(loadError)',
],
- show: function() {
+ show() {
/** @type {!CrDialogElement} */ (this.$.dialog).showModal();
},
- close: function() {
+ close() {
/** @type {!CrDialogElement} */ (this.$.dialog).close();
},
/** @private */
- onRetryTap_: function() {
+ onRetryTap_() {
this.retrying_ = true;
this.delegate.retryLoadUnpacked(this.loadError.retryGuid)
.then(
@@ -66,7 +66,7 @@ Polymer({
},
/** @private */
- observeLoadErrorChanges_: function() {
+ observeLoadErrorChanges_() {
assert(this.loadError);
const source = this.loadError.source;
// CodeSection expects a RequestFileSourceResponse, rather than an
diff --git a/chromium/chrome/browser/resources/extensions/manager.html b/chromium/chrome/browser/resources/extensions/manager.html
index 87457fba166..7cbf68e59ba 100644
--- a/chromium/chrome/browser/resources/extensions/manager.html
+++ b/chromium/chrome/browser/resources/extensions/manager.html
@@ -28,6 +28,7 @@
dev-mode-controlled-by-policy="[[devModeControlledByPolicy]]"
delegate="[[delegate]]" on-cr-toolbar-menu-tap="onMenuButtonTap_"
on-search-changed="onFilterChanged_"
+ extensions="[[extensions_]]"
<if expr="chromeos">
on-kiosk-tap="onKioskTap_"
kiosk-enabled="[[kioskEnabled_]]"
diff --git a/chromium/chrome/browser/resources/extensions/manager.js b/chromium/chrome/browser/resources/extensions/manager.js
index b1df5c6fef5..1b80446a0b7 100644
--- a/chromium/chrome/browser/resources/extensions/manager.js
+++ b/chromium/chrome/browser/resources/extensions/manager.js
@@ -46,13 +46,13 @@ const compareExtensions = function(a, b) {
return x < y ? -1 : (x > y ? 1 : 0);
}
function compareLocation(x, y) {
- if (x.location == y.location) {
+ if (x.location === y.location) {
return 0;
}
- if (x.location == chrome.developerPrivate.Location.UNPACKED) {
+ if (x.location === chrome.developerPrivate.Location.UNPACKED) {
return -1;
}
- if (y.location == chrome.developerPrivate.Location.UNPACKED) {
+ if (y.location === chrome.developerPrivate.Location.UNPACKED) {
return 1;
}
return 0;
@@ -76,7 +76,7 @@ Polymer({
/** @type {!Service} */
delegate: {
type: Object,
- value: function() {
+ value() {
return Service.getInstance();
},
},
@@ -211,7 +211,7 @@ Polymer({
navigationListener_: null,
/** @override */
- ready: function() {
+ ready() {
const service = Service.getInstance();
const onProfileStateChanged = profileInfo => {
@@ -242,7 +242,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
document.documentElement.classList.remove('loading');
document.fonts.load('bold 12px Roboto');
@@ -252,7 +252,7 @@ Polymer({
},
/** @override */
- detached: function() {
+ detached() {
assert(navigation.removeListener(
/** @type {number} */ (this.navigationListener_)));
this.navigationListener_ = null;
@@ -263,7 +263,7 @@ Polymer({
* the user visits chrome://extensions/?id=..., we land on the proper page.
* @private
*/
- initPage_: function() {
+ initPage_() {
this.didInitPage_ = true;
this.changePage_(navigation.getCurrentPage());
},
@@ -272,7 +272,7 @@ Polymer({
* @param {!chrome.developerPrivate.EventData} eventData
* @private
*/
- onItemStateChanged_: function(eventData) {
+ onItemStateChanged_(eventData) {
const EventType = chrome.developerPrivate.EventType;
switch (eventData.event_type) {
case EventType.VIEW_REGISTERED:
@@ -301,7 +301,7 @@ Polymer({
const listId = this.getListId_(eventData.extensionInfo);
const currentIndex = this[listId].findIndex(
- item => item.id == eventData.extensionInfo.id);
+ item => item.id === eventData.extensionInfo.id);
if (currentIndex >= 0) {
this.updateItem_(listId, currentIndex, eventData.extensionInfo);
@@ -321,7 +321,7 @@ Polymer({
* @param {!CustomEvent<string>} event
* @private
*/
- onFilterChanged_: function(event) {
+ onFilterChanged_(event) {
if (this.currentPage_.page !== Page.LIST) {
navigation.navigateTo({page: Page.LIST});
}
@@ -329,7 +329,7 @@ Polymer({
},
/** @private */
- onMenuButtonTap_: function() {
+ onMenuButtonTap_() {
this.showDrawer_ = true;
this.async(() => {
this.$$('#drawer').openDrawer();
@@ -341,7 +341,7 @@ Polymer({
* @return {string} The ID of the list that the item belongs in.
* @private
*/
- getListId_: function(item) {
+ getListId_(item) {
const ExtensionType = chrome.developerPrivate.ExtensionType;
switch (item.type) {
case ExtensionType.HOSTED_APP:
@@ -364,9 +364,9 @@ Polymer({
* @return {number} The index of the item in the list, or -1 if not found.
* @private
*/
- getIndexInList_: function(listId, itemId) {
+ getIndexInList_(listId, itemId) {
return this[listId].findIndex(function(item) {
- return item.id == itemId;
+ return item.id === itemId;
});
},
@@ -374,7 +374,7 @@ Polymer({
* @return {?chrome.developerPrivate.ExtensionInfo}
* @private
*/
- getData_: function(id) {
+ getData_(id) {
return this.extensions_[this.getIndexInList_('extensions_', id)] ||
this.apps_[this.getIndexInList_('apps_', id)];
},
@@ -385,7 +385,7 @@ Polymer({
* @param {!Array<!chrome.developerPrivate.ExtensionInfo>} extensionsAndApps
* @private
*/
- initExtensionsAndApps_: function(extensionsAndApps) {
+ initExtensionsAndApps_(extensionsAndApps) {
extensionsAndApps.sort(compareExtensions);
const apps = [];
const extensions = [];
@@ -405,13 +405,13 @@ Polymer({
* the new element is representing.
* @private
*/
- addItem_: function(listId, item) {
+ addItem_(listId, item) {
// We should never try and add an existing item.
- assert(this.getIndexInList_(listId, item.id) == -1);
+ assert(this.getIndexInList_(listId, item.id) === -1);
let insertBeforeChild = this[listId].findIndex(function(listEl) {
return compareExtensions(listEl, item) > 0;
});
- if (insertBeforeChild == -1) {
+ if (insertBeforeChild === -1) {
insertBeforeChild = this[listId].length;
}
this.splice(listId, insertBeforeChild, 0, item);
@@ -422,7 +422,7 @@ Polymer({
* item to update.
* @private
*/
- updateItem_: function(listId, index, item) {
+ updateItem_(listId, index, item) {
// We should never try and update a non-existent item.
assert(index >= 0);
this.set([listId, index], item);
@@ -432,16 +432,16 @@ Polymer({
// set the item correctly before opening the page. It's a little weird
// that the DOM will have stale data, but there's no point in causing the
// extra work.
- if (this.detailViewItem_ && this.detailViewItem_.id == item.id &&
- this.currentPage_.page == Page.DETAILS) {
+ if (this.detailViewItem_ && this.detailViewItem_.id === item.id &&
+ this.currentPage_.page === Page.DETAILS) {
this.detailViewItem_ = item;
} else if (
- this.errorPageItem_ && this.errorPageItem_.id == item.id &&
- this.currentPage_.page == Page.ERRORS) {
+ this.errorPageItem_ && this.errorPageItem_.id === item.id &&
+ this.currentPage_.page === Page.ERRORS) {
this.errorPageItem_ = item;
} else if (
- this.activityLogItem_ && this.activityLogItem_.id == item.id &&
- this.currentPage_.page == Page.ACTIVITY_LOG) {
+ this.activityLogItem_ && this.activityLogItem_.id === item.id &&
+ this.currentPage_.page === Page.ACTIVITY_LOG) {
this.activityLogItem_ = item;
}
},
@@ -450,11 +450,11 @@ Polymer({
* @param {string} itemId The id of item to remove.
* @private
*/
- removeItem_: function(itemId) {
+ removeItem_(itemId) {
// Search for the item to be deleted in |extensions_|.
let listId = 'extensions_';
let index = this.getIndexInList_(listId, itemId);
- if (index == -1) {
+ if (index === -1) {
// If not in |extensions_| it must be in |apps_|.
listId = 'apps_';
index = this.getIndexInList_(listId, itemId);
@@ -463,10 +463,10 @@ Polymer({
// We should never try and remove a non-existent item.
assert(index >= 0);
this.splice(listId, index, 1);
- if ((this.currentPage_.page == Page.ACTIVITY_LOG ||
- this.currentPage_.page == Page.DETAILS ||
- this.currentPage_.page == Page.ERRORS) &&
- this.currentPage_.extensionId == itemId) {
+ if ((this.currentPage_.page === Page.ACTIVITY_LOG ||
+ this.currentPage_.page === Page.DETAILS ||
+ this.currentPage_.page === Page.ERRORS) &&
+ this.currentPage_.extensionId === itemId) {
// Leave the details page (the 'list' page is a fine choice).
navigation.replaceWith({page: Page.LIST});
}
@@ -476,7 +476,7 @@ Polymer({
* @param {!CustomEvent<!chrome.developerPrivate.LoadError>} e
* @private
*/
- onLoadError_: function(e) {
+ onLoadError_(e) {
this.showLoadErrorDialog_ = true;
this.async(() => {
const dialog = this.$$('#load-error');
@@ -490,7 +490,7 @@ Polymer({
* @param {PageState} newPage
* @private
*/
- changePage_: function(newPage) {
+ changePage_(newPage) {
this.onCloseDrawer_();
const optionsDialog = this.$$('#options-dialog');
@@ -509,7 +509,7 @@ Polymer({
// extension ID is not valid. This enables the use case of seeing an
// extension's install-time activities by navigating to an extension's
// activity log page, then installing the extension.
- if (this.showActivityLog && toPage == Page.ACTIVITY_LOG) {
+ if (this.showActivityLog && toPage === Page.ACTIVITY_LOG) {
activityLogPlaceholder = {
id: newPage.extensionId,
isPlaceholder: true,
@@ -522,11 +522,11 @@ Polymer({
}
}
- if (toPage == Page.DETAILS) {
+ if (toPage === Page.DETAILS) {
this.detailViewItem_ = assert(data);
- } else if (toPage == Page.ERRORS) {
+ } else if (toPage === Page.ERRORS) {
this.errorPageItem_ = assert(data);
- } else if (toPage == Page.ACTIVITY_LOG) {
+ } else if (toPage === Page.ACTIVITY_LOG) {
if (!this.showActivityLog) {
// Redirect back to the details page if we try to view the
// activity log of an extension but the flag is not set.
@@ -538,13 +538,13 @@ Polymer({
this.activityLogItem_ = data ? assert(data) : activityLogPlaceholder;
}
- if (fromPage != toPage) {
+ if (fromPage !== toPage) {
/** @type {CrViewManagerElement} */ (this.$.viewManager)
.switchView(/** @type {string} */ (toPage));
}
if (newPage.subpage) {
- assert(newPage.subpage == Dialog.OPTIONS);
+ assert(newPage.subpage === Dialog.OPTIONS);
assert(newPage.extensionId);
this.showOptionsDialog_ = true;
this.async(() => {
@@ -552,7 +552,7 @@ Polymer({
});
}
- document.title = toPage == Page.DETAILS ?
+ document.title = toPage === Page.DETAILS ?
`${loadTimeData.getString('title')} - ${this.detailViewItem_.name}` :
loadTimeData.getString('title');
this.currentPage_ = newPage;
@@ -563,7 +563,7 @@ Polymer({
* triggered by the dialog's 'close' event.
* @private
*/
- onDrawerClose_: function() {
+ onDrawerClose_() {
this.showDrawer_ = false;
},
@@ -571,7 +571,7 @@ Polymer({
* This method animates the closing of the drawer.
* @private
*/
- onCloseDrawer_: function() {
+ onCloseDrawer_() {
const drawer = this.$$('#drawer');
if (drawer && drawer.open) {
drawer.close();
@@ -579,18 +579,18 @@ Polymer({
},
/** @private */
- onLoadErrorDialogClose_: function() {
+ onLoadErrorDialogClose_() {
this.showLoadErrorDialog_ = false;
},
/** @private */
- onOptionsDialogClose_: function() {
+ onOptionsDialogClose_() {
this.showOptionsDialog_ = false;
this.$$('extensions-detail-view').focusOptionsButton();
},
/** @private */
- onViewEnterStart_: function() {
+ onViewEnterStart_() {
this.fromActivityLog_ = false;
},
@@ -598,26 +598,26 @@ Polymer({
* @param {!Event} e
* @private
*/
- onViewExitStart_: function(e) {
+ onViewExitStart_(e) {
const viewType = e.composedPath()[0].tagName;
- this.fromActivityLog_ = viewType == 'EXTENSIONS-ACTIVITY-LOG';
+ this.fromActivityLog_ = viewType === 'EXTENSIONS-ACTIVITY-LOG';
},
/**
* @param {!Event} e
* @private
*/
- onViewExitFinish_: function(e) {
+ onViewExitFinish_(e) {
const viewType = e.composedPath()[0].tagName;
- if (viewType == 'EXTENSIONS-ITEM-LIST' ||
- viewType == 'EXTENSIONS-KEYBOARD-SHORTCUTS' ||
- viewType == 'EXTENSIONS-ACTIVITY-LOG') {
+ if (viewType === 'EXTENSIONS-ITEM-LIST' ||
+ viewType === 'EXTENSIONS-KEYBOARD-SHORTCUTS' ||
+ viewType === 'EXTENSIONS-ACTIVITY-LOG') {
return;
}
const extensionId = e.composedPath()[0].data.id;
const list = this.$$('extensions-item-list');
- const button = viewType == 'EXTENSIONS-DETAIL-VIEW' ?
+ const button = viewType === 'EXTENSIONS-DETAIL-VIEW' ?
list.getDetailsButton(extensionId) :
list.getErrorsButton(extensionId);
@@ -632,7 +632,7 @@ Polymer({
* @param {!CustomEvent<!Array<string>>} e
* @private
*/
- onShowInstallWarnings_: function(e) {
+ onShowInstallWarnings_(e) {
// Leverage Polymer data bindings instead of just assigning the
// installWarnings on the dialog since the dialog hasn't been stamped
// in the DOM yet.
@@ -641,18 +641,18 @@ Polymer({
},
/** @private */
- onInstallWarningsDialogClose_: function() {
+ onInstallWarningsDialogClose_() {
this.installWarnings_ = null;
this.showInstallWarningsDialog_ = false;
},
// <if expr="chromeos">
/** @private */
- onKioskTap_: function() {
+ onKioskTap_() {
this.showKioskDialog_ = true;
},
- onKioskDialogClose_: function() {
+ onKioskDialogClose_() {
this.showKioskDialog_ = false;
},
// </if>
diff --git a/chromium/chrome/browser/resources/extensions/navigation_helper.js b/chromium/chrome/browser/resources/extensions/navigation_helper.js
index b4bc143d1e7..53de02b2a24 100644
--- a/chromium/chrome/browser/resources/extensions/navigation_helper.js
+++ b/chromium/chrome/browser/resources/extensions/navigation_helper.js
@@ -36,8 +36,8 @@ export let PageState;
* @return {boolean} Whether a and b are equal.
*/
function isPageStateEqual(a, b) {
- return a.page == b.page && a.subpage == b.subpage &&
- a.extensionId == b.extensionId;
+ return a.page === b.page && a.subpage === b.subpage &&
+ a.extensionId === b.extensionId;
}
/**
@@ -82,8 +82,8 @@ export class NavigationHelper {
* @private
*/
processRoute_() {
- if (this.currentPath_ == '/configureCommands' ||
- this.currentPath_ == '/shortcuts') {
+ if (this.currentPath_ === '/configureCommands' ||
+ this.currentPath_ === '/shortcuts') {
window.history.replaceState(
undefined /* stateObject */, '', '/shortcuts');
} else if (this.currentPath_ !== '/') {
@@ -114,7 +114,7 @@ export class NavigationHelper {
return {page: Page.ERRORS, extensionId: id};
}
- if (this.currentPath_ == '/shortcuts') {
+ if (this.currentPath_ === '/shortcuts') {
return {page: Page.SHORTCUTS};
}
@@ -195,7 +195,7 @@ export class NavigationHelper {
break;
case Page.DETAILS:
if (entry.subpage) {
- assert(entry.subpage == Dialog.OPTIONS);
+ assert(entry.subpage === Dialog.OPTIONS);
path = '/?options=' + entry.extensionId;
} else {
path = '/?id=' + entry.extensionId;
@@ -211,8 +211,8 @@ export class NavigationHelper {
assert(path);
const state = {url: path};
const currentPage = this.getCurrentPage();
- const isDialogNavigation = currentPage.page == entry.page &&
- currentPage.extensionId == entry.extensionId;
+ const isDialogNavigation = currentPage.page === entry.page &&
+ currentPage.extensionId === entry.extensionId;
// Navigating to a dialog doesn't visually change pages; it just opens
// a dialog. As such, we replace state rather than pushing a new state
// on the stack so that hitting the back button doesn't just toggle the
diff --git a/chromium/chrome/browser/resources/extensions/options_dialog.js b/chromium/chrome/browser/resources/extensions/options_dialog.js
index ce9aa267217..9f6ca1c5517 100644
--- a/chromium/chrome/browser/resources/extensions/options_dialog.js
+++ b/chromium/chrome/browser/resources/extensions/options_dialog.js
@@ -15,13 +15,13 @@ import {navigation, Page} from './navigation_helper.js';
* registered yet.
*/
function whenDocumentReady() {
- if (document.readyState == 'complete') {
+ if (document.readyState === 'complete') {
return Promise.resolve();
}
return new Promise(function(resolve) {
document.addEventListener('readystatechange', function f() {
- if (document.readyState == 'complete') {
+ if (document.readyState === 'complete') {
document.removeEventListener('readystatechange', f);
resolve();
}
@@ -65,7 +65,7 @@ Polymer({
* into account the window width/height.
* @private
*/
- updateDialogSize_: function() {
+ updateDialogSize_() {
const headerHeight = this.$.body.offsetTop;
const maxHeight =
Math.min(0.9 * window.innerHeight, OptionsDialogMaxHeight);
@@ -80,7 +80,7 @@ Polymer({
},
/** @param {chrome.developerPrivate.ExtensionInfo} data */
- show: function(data) {
+ show(data) {
this.data_ = data;
whenDocumentReady().then(() => {
if (!this.extensionOptions_) {
@@ -107,7 +107,7 @@ Polymer({
},
/** @private */
- onClose_: function() {
+ onClose_() {
this.extensionOptions_.onpreferredsizechanged = null;
if (this.boundUpdateDialogSize_) {
@@ -120,7 +120,7 @@ Polymer({
// still on the details page. We could be on a different page if the
// user hit back while the options dialog was visible; in that case, the
// new page is already correct.
- if (currentPage && currentPage.page == Page.DETAILS) {
+ if (currentPage && currentPage.page === Page.DETAILS) {
// This will update the currentPage_ and the NavigationHelper; since
// the active page is already the details page, no main page
// transition occurs.
diff --git a/chromium/chrome/browser/resources/extensions/pack_dialog.js b/chromium/chrome/browser/resources/extensions/pack_dialog.js
index 4791d6ba9eb..1c371fce4b7 100644
--- a/chromium/chrome/browser/resources/extensions/pack_dialog.js
+++ b/chromium/chrome/browser/resources/extensions/pack_dialog.js
@@ -62,12 +62,12 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
this.$.dialog.showModal();
},
/** @private */
- onRootBrowse_: function() {
+ onRootBrowse_() {
this.delegate.choosePackRootDirectory().then(path => {
if (path) {
this.set('packDirectory_', path);
@@ -76,7 +76,7 @@ Polymer({
},
/** @private */
- onKeyBrowse_: function() {
+ onKeyBrowse_() {
this.delegate.choosePrivateKeyPath().then(path => {
if (path) {
this.set('keyFile_', path);
@@ -85,12 +85,12 @@ Polymer({
},
/** @private */
- onCancelTap_: function() {
+ onCancelTap_() {
this.$.dialog.cancel();
},
/** @private */
- onConfirmTap_: function() {
+ onConfirmTap_() {
this.delegate.packExtension(
this.packDirectory_, this.keyFile_, 0, this.onPackResponse_.bind(this));
},
@@ -100,7 +100,7 @@ Polymer({
* response from request to pack an extension.
* @private
*/
- onPackResponse_: function(response) {
+ onPackResponse_(response) {
this.lastResponse_ = response;
},
@@ -112,17 +112,17 @@ Polymer({
* @param {!Event} e
* @private
*/
- onAlertClose_: function(e) {
+ onAlertClose_(e) {
e.stopPropagation();
- if (this.lastResponse_.status ==
+ if (this.lastResponse_.status ===
chrome.developerPrivate.PackStatus.SUCCESS) {
this.$.dialog.close();
return;
}
// This is only possible for a warning dialog.
- if (this.$$('extensions-pack-dialog-alert').returnValue == 'success') {
+ if (this.$$('extensions-pack-dialog-alert').returnValue === 'success') {
this.delegate.packExtension(
this.lastResponse_.item_path, this.lastResponse_.pem_path,
this.lastResponse_.override_flags, this.onPackResponse_.bind(this));
diff --git a/chromium/chrome/browser/resources/extensions/pack_dialog_alert.js b/chromium/chrome/browser/resources/extensions/pack_dialog_alert.js
index a39869e2f70..16e149876e8 100644
--- a/chromium/chrome/browser/resources/extensions/pack_dialog_alert.js
+++ b/chromium/chrome/browser/resources/extensions/pack_dialog_alert.js
@@ -45,7 +45,7 @@ Polymer({
},
/** @override */
- ready: function() {
+ ready() {
// Initialize button label values for initial html binding.
this.cancelLabel_ = null;
this.confirmLabel_ = null;
@@ -71,7 +71,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
this.$.dialog.showModal();
},
@@ -79,17 +79,17 @@ Polymer({
* @return {string}
* @private
*/
- getCancelButtonClass_: function() {
+ getCancelButtonClass_() {
return this.confirmLabel_ ? 'cancel-button' : 'action-button';
},
/** @private */
- onCancelTap_: function() {
+ onCancelTap_() {
this.$.dialog.cancel();
},
/** @private */
- onConfirmTap_: function() {
+ onConfirmTap_() {
// The confirm button should only be available in WARNING state.
assert(this.model.status === chrome.developerPrivate.PackStatus.WARNING);
this.$.dialog.close();
diff --git a/chromium/chrome/browser/resources/extensions/runtime_host_permissions.js b/chromium/chrome/browser/resources/extensions/runtime_host_permissions.js
index 1814e423fe8..a2b743b7de0 100644
--- a/chromium/chrome/browser/resources/extensions/runtime_host_permissions.js
+++ b/chromium/chrome/browser/resources/extensions/runtime_host_permissions.js
@@ -115,12 +115,12 @@ Polymer({
* @param {!Event} event
* @private
*/
- onHostAccessChange_: function(event) {
+ onHostAccessChange_(event) {
const group = /** @type {!HTMLElement} */ (this.$['host-access']);
const access = group.selected;
- if (access == chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES &&
- this.permissions.hostAccess !=
+ if (access === chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES &&
+ this.permissions.hostAccess !==
chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES) {
// If the user is transitioning to the "on specific sites" option, show
// the "add host" dialog. This serves two purposes:
@@ -141,8 +141,8 @@ Polymer({
* @return {boolean}
* @private
*/
- showSpecificSites_: function() {
- return this.permissions.hostAccess ==
+ showSpecificSites_() {
+ return this.permissions.hostAccess ===
chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES;
},
@@ -151,7 +151,7 @@ Polymer({
* @return {!Array<string>}
* @private
*/
- getRuntimeHosts_: function() {
+ getRuntimeHosts_() {
if (!this.permissions.hosts) {
return [];
}
@@ -168,7 +168,7 @@ Polymer({
* @param {Event} e
* @private
*/
- onAddHostClick_: function(e) {
+ onAddHostClick_(e) {
const target = /** @type {!HTMLElement} */ (e.target);
this.doShowHostDialog_(target, null);
},
@@ -180,14 +180,14 @@ Polymer({
* edited, or null if this is to add a new entry.
* @private
*/
- doShowHostDialog_: function(anchorElement, currentSite) {
+ doShowHostDialog_(anchorElement, currentSite) {
this.hostDialogAnchorElement_ = anchorElement;
this.hostDialogModel_ = currentSite;
this.showHostDialog_ = true;
},
/** @private */
- onHostDialogClose_: function() {
+ onHostDialogClose_() {
this.hostDialogModel_ = null;
this.showHostDialog_ = false;
focusWithoutInk(assert(this.hostDialogAnchorElement_, 'Host Anchor'));
@@ -196,11 +196,11 @@ Polymer({
},
/** @private */
- onHostDialogCancel_: function() {
+ onHostDialogCancel_() {
// The user canceled the dialog. Set host-access back to the old value,
// if the dialog was shown when just transitioning to a new state.
if (this.oldHostAccess_) {
- assert(this.permissions.hostAccess == this.oldHostAccess_);
+ assert(this.permissions.hostAccess === this.oldHostAccess_);
this.$['host-access'].selected = this.oldHostAccess_;
this.oldHostAccess_ = null;
}
@@ -210,7 +210,7 @@ Polymer({
* @return {boolean}
* @private
*/
- dialogShouldUpdateHostAccess_: function() {
+ dialogShouldUpdateHostAccess_() {
return !!this.oldHostAccess_;
},
@@ -221,7 +221,7 @@ Polymer({
* }} e
* @private
*/
- onEditHostClick_: function(e) {
+ onEditHostClick_(e) {
this.actionMenuModel_ = e.model.item;
this.actionMenuAnchorElement_ = e.target;
const actionMenu =
@@ -230,7 +230,7 @@ Polymer({
},
/** @private */
- onActionMenuEditClick_: function() {
+ onActionMenuEditClick_() {
// Cache the site before closing the action menu, since it's cleared.
const site = this.actionMenuModel_;
@@ -245,21 +245,21 @@ Polymer({
},
/** @private */
- onActionMenuRemoveClick_: function() {
+ onActionMenuRemoveClick_() {
this.delegate.removeRuntimeHostPermission(
this.itemId, assert(this.actionMenuModel_, 'Action Menu Model'));
this.closeActionMenu_();
},
/** @private */
- closeActionMenu_: function() {
+ closeActionMenu_() {
const menu = this.$.hostActionMenu;
assert(menu.open);
menu.close();
},
/** @private */
- onActionMenuClose_: function() {
+ onActionMenuClose_() {
this.actionMenuModel_ = null;
this.actionMenuAnchorElement_ = null;
},
diff --git a/chromium/chrome/browser/resources/extensions/runtime_hosts_dialog.js b/chromium/chrome/browser/resources/extensions/runtime_hosts_dialog.js
index bbe15acfcda..35fa8ad87e7 100644
--- a/chromium/chrome/browser/resources/extensions/runtime_hosts_dialog.js
+++ b/chromium/chrome/browser/resources/extensions/runtime_hosts_dialog.js
@@ -29,8 +29,8 @@ const patternRegExp = new RegExp(
'((http|https|\\*)://)?' +
// Include subdomains specifier; optional.
'(\\*\\.)?' +
- // Hostname, required.
- '([a-z0-9\\.-]+\\.[a-z0-9]+)' +
+ // Hostname or localhost, required.
+ '([a-z0-9\\.-]+\\.[a-z0-9]+|localhost)' +
// Port, optional.
'(:[0-9]+)?' +
// Path, optional but if present must be '/' or '/*'.
@@ -95,7 +95,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
if (this.currentSite !== null && this.currentSite !== undefined) {
this.site_ = this.currentSite;
this.validate_();
@@ -104,7 +104,7 @@ Polymer({
},
/** @return {boolean} */
- isOpen: function() {
+ isOpen() {
return this.$.dialog.open;
},
@@ -112,10 +112,10 @@ Polymer({
* Validates that the pattern entered is valid.
* @private
*/
- validate_: function() {
+ validate_() {
// If input is empty, disable the action button, but don't show the red
// invalid message.
- if (this.site_.trim().length == 0) {
+ if (this.site_.trim().length === 0) {
this.inputInvalid_ = false;
return;
}
@@ -128,7 +128,7 @@ Polymer({
* @return {string}
* @private
*/
- computeDialogTitle_: function() {
+ computeDialogTitle_() {
const stringId = this.currentSite === null ? 'runtimeHostsDialogTitle' :
'hostPermissionsEdit';
return loadTimeData.getString(stringId);
@@ -138,22 +138,22 @@ Polymer({
* @return {boolean}
* @private
*/
- computeSubmitButtonDisabled_: function() {
+ computeSubmitButtonDisabled_() {
return this.inputInvalid_ || this.site_ === undefined ||
- this.site_.trim().length == 0;
+ this.site_.trim().length === 0;
},
/**
* @return {string}
* @private
*/
- computeSubmitButtonLabel_: function() {
+ computeSubmitButtonLabel_() {
const stringId = this.currentSite === null ? 'add' : 'save';
return loadTimeData.getString(stringId);
},
/** @private */
- onCancelTap_: function() {
+ onCancelTap_() {
this.$.dialog.cancel();
},
@@ -162,7 +162,7 @@ Polymer({
* the dialog).
* @private
*/
- onSubmitTap_: function() {
+ onSubmitTap_() {
if (this.currentSite !== null) {
this.handleEdit_();
} else {
@@ -174,7 +174,7 @@ Polymer({
* Handles adding a new site entry.
* @private
*/
- handleAdd_: function() {
+ handleAdd_() {
assert(!this.currentSite);
if (this.updateHostAccess) {
@@ -189,14 +189,14 @@ Polymer({
* Handles editing an existing site entry.
* @private
*/
- handleEdit_: function() {
+ handleEdit_() {
assert(this.currentSite);
assert(
!this.updateHostAccess,
'Editing host permissions should only be possible if the host ' +
'access is already set to specific sites.');
- if (this.currentSite == this.site_) {
+ if (this.currentSite === this.site_) {
// No change in values, so no need to update anything.
this.$.dialog.close();
return;
@@ -215,7 +215,7 @@ Polymer({
* closes the dialog; otherwise displays the invalid input message.
* @private
*/
- addPermission_: function() {
+ addPermission_() {
const pattern = getPatternFromSite(this.site_);
this.delegate.addRuntimeHostPermission(this.itemId, pattern)
.then(
diff --git a/chromium/chrome/browser/resources/extensions/service.js b/chromium/chrome/browser/resources/extensions/service.js
index 0e1e52cb28d..c49c474af07 100644
--- a/chromium/chrome/browser/resources/extensions/service.js
+++ b/chromium/chrome/browser/resources/extensions/service.js
@@ -117,7 +117,8 @@ export class Service {
return new Promise(function(resolve, reject) {
chrome.developerPrivate.choosePath(selectType, fileType, function(path) {
if (chrome.runtime.lastError &&
- chrome.runtime.lastError != 'File selection was canceled.') {
+ chrome.runtime.lastError.message !==
+ 'File selection was canceled.') {
reject(chrome.runtime.lastError);
} else {
resolve(path || '');
@@ -172,7 +173,7 @@ export class Service {
chrome.developerPrivate.loadUnpacked(options, (loadError) => {
if (chrome.runtime.lastError &&
- chrome.runtime.lastError.message !=
+ chrome.runtime.lastError.message !==
'File selection was canceled.') {
throw new Error(chrome.runtime.lastError.message);
}
@@ -190,6 +191,7 @@ export class Service {
if (this.isDeleting_) {
return;
}
+ chrome.metricsPrivate.recordUserAction('Extensions.RemoveExtensionClick');
this.isDeleting_ = true;
chrome.management.uninstall(id, {showConfirmDialog: true}, () => {
// The "last error" was almost certainly the user canceling the dialog.
@@ -202,6 +204,9 @@ export class Service {
/** @override */
setItemEnabled(id, isEnabled) {
+ chrome.metricsPrivate.recordUserAction(
+ isEnabled ? 'Extensions.ExtensionEnabled' :
+ 'Extensions.ExtensionDisabled');
chrome.management.setEnabled(id, isEnabled);
}
@@ -328,11 +333,34 @@ export class Service {
}
/** @override */
- updateAllExtensions() {
+ updateAllExtensions(extensions) {
+ /**
+ * Attempt to reload local extensions. If an extension fails to load, the
+ * user is prompted to try updating the broken extension using loadUnpacked
+ * and we skip reloading the remaining local extensions.
+ */
return new Promise((resolve) => {
- chrome.developerPrivate.autoUpdate(resolve);
- chrome.metricsPrivate.recordUserAction('Options_UpdateExtensions');
- });
+ chrome.developerPrivate.autoUpdate(resolve);
+ chrome.metricsPrivate.recordUserAction('Options_UpdateExtensions');
+ })
+ .then(() => {
+ return new Promise((resolve, reject) => {
+ const loadLocalExtensions = async () => {
+ for (const extension of extensions) {
+ if (extension.location === 'UNPACKED') {
+ try {
+ await this.reloadItem(extension.id);
+ } catch (loadError) {
+ reject(loadError);
+ break;
+ }
+ }
+ }
+ resolve('Loaded local extensions.');
+ };
+ loadLocalExtensions();
+ });
+ });
}
/** @override */
diff --git a/chromium/chrome/browser/resources/extensions/shared_style.html b/chromium/chrome/browser/resources/extensions/shared_style.html
index 41ca789f85c..56ad91559c5 100644
--- a/chromium/chrome/browser/resources/extensions/shared_style.html
+++ b/chromium/chrome/browser/resources/extensions/shared_style.html
@@ -41,8 +41,8 @@
}
.page-content {
- @apply --cr-card-elevation;
background-color: var(--cr-card-background-color);
+ box-shadow: var(--cr-card-shadow);
box-sizing: border-box;
margin: auto;
min-height: 100%;
diff --git a/chromium/chrome/browser/resources/extensions/shared_vars.html b/chromium/chrome/browser/resources/extensions/shared_vars.html
index b826b8a16d0..8c210336b03 100644
--- a/chromium/chrome/browser/resources/extensions/shared_vars.html
+++ b/chromium/chrome/browser/resources/extensions/shared_vars.html
@@ -4,6 +4,7 @@
/* Note: error-color is used for many warnings. There's also an orange-y
* warning color in 1 place. */
--error-color: var(--google-red-700);
+ --extensions-card-height: 160px;
--separator-gap: 9px;
}
diff --git a/chromium/chrome/browser/resources/extensions/shortcut_input.html b/chromium/chrome/browser/resources/extensions/shortcut_input.html
index f2c4f4247fb..4658ffbc7e0 100644
--- a/chromium/chrome/browser/resources/extensions/shortcut_input.html
+++ b/chromium/chrome/browser/resources/extensions/shortcut_input.html
@@ -14,6 +14,11 @@
left: -2px;
right: inherit;
}
+
+ /* Invisible so the element is still in the tab order. */
+ [invisible] {
+ opacity: 0;
+ }
</style>
<div id="main">
<cr-input id="input" placeholder="$i18n{shortcutTypeAShortcut}"
@@ -25,7 +30,8 @@
value="[[computeText_(capturing_, shortcut, pendingShortcut_)]]">
<cr-icon-button id="clear" aria-label="$i18nPolymer{clear}"
slot="suffix" class="icon-cancel no-overlap"
- hidden$="[[computeClearHidden_(capturing_, shortcut)]]"
+ invisible$="[[computeClearInvisible_(capturing_, shortcut)]]"
+ hidden$="[[computeClearHidden_(shortcut)]]"
on-click="onClearTap_"></cr-icon-button>
</cr-input>
</div>
diff --git a/chromium/chrome/browser/resources/extensions/shortcut_input.js b/chromium/chrome/browser/resources/extensions/shortcut_input.js
index 6f56ac6c1aa..cf3ab1a53a5 100644
--- a/chromium/chrome/browser/resources/extensions/shortcut_input.js
+++ b/chromium/chrome/browser/resources/extensions/shortcut_input.js
@@ -9,6 +9,8 @@ import 'chrome://resources/cr_elements/hidden_style_css.m.js';
import 'chrome://resources/polymer/v3_0/paper-styles/color.js';
import {assert} from 'chrome://resources/js/assert.m.js';
+import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
+import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {KeyboardShortcutDelegate} from './keyboard_shortcut_delegate.js';
@@ -28,6 +30,8 @@ Polymer({
_template: html`{__html_template__}`,
+ behaviors: [I18nBehavior],
+
properties: {
/** @type {!KeyboardShortcutDelegate} */
delegate: Object,
@@ -67,7 +71,7 @@ Polymer({
},
/** @override */
- ready: function() {
+ ready() {
const node = this.$.input;
node.addEventListener('mouseup', this.startCapture_.bind(this));
node.addEventListener('blur', this.endCapture_.bind(this));
@@ -77,7 +81,7 @@ Polymer({
},
/** @private */
- startCapture_: function() {
+ startCapture_() {
if (this.capturing_) {
return;
}
@@ -86,7 +90,7 @@ Polymer({
},
/** @private */
- endCapture_: function() {
+ endCapture_() {
if (!this.capturing_) {
return;
}
@@ -102,12 +106,12 @@ Polymer({
* @param {!Event} e
* @private
*/
- onKeyDown_: function(e) {
- if (e.target == this.$.clear) {
+ onKeyDown_(e) {
+ if (e.target === this.$.clear) {
return;
}
- if (e.keyCode == Key.Escape) {
+ if (e.keyCode === Key.Escape) {
if (!this.capturing_) {
// If we're not currently capturing, allow escape to propagate.
return;
@@ -118,7 +122,7 @@ Polymer({
e.stopPropagation();
return;
}
- if (e.keyCode == Key.Tab) {
+ if (e.keyCode === Key.Tab) {
// Allow tab propagation for keyboard navigation.
return;
}
@@ -134,16 +138,16 @@ Polymer({
* @param {!Event} e
* @private
*/
- onKeyUp_: function(e) {
+ onKeyUp_(e) {
// Ignores pressing 'Space' or 'Enter' on the clear button. In 'Enter's
// case, the clear button disappears before key-up, so 'Enter's key-up
// target becomes the input field, not the clear button, and needs to
// be caught explicitly.
- if (e.target == this.$.clear || e.key == 'Enter') {
+ if (e.target === this.$.clear || e.key === 'Enter') {
return;
}
- if (e.keyCode == Key.Escape || e.keyCode == Key.Tab) {
+ if (e.keyCode === Key.Escape || e.keyCode === Key.Tab) {
return;
}
@@ -158,7 +162,7 @@ Polymer({
* @return {string} UI string.
* @private
*/
- getErrorString_: function(
+ getErrorString_(
error, includeStartModifier, tooManyModifiers, needCharacter) {
switch (this.error_) {
case ShortcutError.INCLUDE_START_MODIFIER:
@@ -168,7 +172,7 @@ Polymer({
case ShortcutError.NEED_CHARACTER:
return needCharacter;
default:
- assert(this.error_ == ShortcutError.NO_ERROR);
+ assert(this.error_ === ShortcutError.NO_ERROR);
return '';
}
},
@@ -177,7 +181,7 @@ Polymer({
* @param {!KeyboardEvent} e
* @private
*/
- handleKey_: function(e) {
+ handleKey_(e) {
// While capturing, we prevent all events from bubbling, to prevent
// shortcuts lacking the right modifier (F3 for example) from activating
// and ending capture prematurely.
@@ -204,12 +208,17 @@ Polymer({
this.error_ = ShortcutError.NO_ERROR;
+ IronA11yAnnouncer.requestAvailability();
+ this.fire('iron-announce', {
+ text: this.i18n('shortcutSet', this.computeText_()),
+ });
+
this.commitPending_();
this.endCapture_();
},
/** @private */
- commitPending_: function() {
+ commitPending_() {
this.shortcut = this.pendingShortcut_;
this.delegate.updateExtensionCommandKeybinding(
this.item, this.commandName, this.shortcut);
@@ -219,32 +228,40 @@ Polymer({
* @return {string} The text to be displayed in the shortcut field.
* @private
*/
- computeText_: function() {
+ computeText_() {
const shortcutString =
this.capturing_ ? this.pendingShortcut_ : this.shortcut;
return shortcutString.split('+').join(' + ');
},
/**
+ * Invisible when capturing AND we have a shortcut.
+ * @return {boolean} Whether the clear button is invisible.
+ * @private
+ */
+ computeClearInvisible_() {
+ return this.capturing_ && !!this.shortcut;
+ },
+
+ /**
+ * Hidden when no shortcut is set.
* @return {boolean} Whether the clear button is hidden.
* @private
*/
- computeClearHidden_: function() {
- // We don't want to show the clear button if the input is currently
- // capturing a new shortcut or if there is no shortcut to clear.
- return this.capturing_ || !this.shortcut;
+ computeClearHidden_() {
+ return !this.shortcut;
},
/**
* @return {boolean}
* @private
*/
- getIsInvalid_: function() {
- return this.error_ != ShortcutError.NO_ERROR;
+ getIsInvalid_() {
+ return this.error_ !== ShortcutError.NO_ERROR;
},
/** @private */
- onClearTap_: function() {
+ onClearTap_() {
assert(this.shortcut);
this.pendingShortcut_ = '';
diff --git a/chromium/chrome/browser/resources/extensions/shortcut_util.js b/chromium/chrome/browser/resources/extensions/shortcut_util.js
index 0f61a402dab..6c20b5bc693 100644
--- a/chromium/chrome/browser/resources/extensions/shortcut_util.js
+++ b/chromium/chrome/browser/resources/extensions/shortcut_util.js
@@ -78,11 +78,11 @@ function hasModifier(e, countShiftAsModifier) {
* @return {boolean} Whether the key is valid.
*/
export function isValidKeyCode(keyCode) {
- if (keyCode == Key.Escape) {
+ if (keyCode === Key.Escape) {
return false;
}
for (const k in Key) {
- if (Key[k] == keyCode) {
+ if (Key[k] === keyCode) {
return true;
}
}
diff --git a/chromium/chrome/browser/resources/extensions/sidebar.js b/chromium/chrome/browser/resources/extensions/sidebar.js
index 5252323fb94..93932a8c7d2 100644
--- a/chromium/chrome/browser/resources/extensions/sidebar.js
+++ b/chromium/chrome/browser/resources/extensions/sidebar.js
@@ -25,23 +25,23 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
this.$.sectionMenu.select(
- navigation.getCurrentPage().page == Page.SHORTCUTS ? 1 : 0);
+ navigation.getCurrentPage().page === Page.SHORTCUTS ? 1 : 0);
},
/**
* @param {!Event} e
* @private
*/
- onLinkTap_: function(e) {
+ onLinkTap_(e) {
e.preventDefault();
navigation.navigateTo({page: e.target.dataset.path});
this.fire('close-drawer');
},
/** @private */
- onMoreExtensionsTap_: function() {
+ onMoreExtensionsTap_() {
assert(!this.isSupervised);
chrome.metricsPrivate.recordUserAction('Options_GetMoreExtensions');
},
diff --git a/chromium/chrome/browser/resources/extensions/toggle_row.html b/chromium/chrome/browser/resources/extensions/toggle_row.html
index 68c0a299250..9752fed0ef8 100644
--- a/chromium/chrome/browser/resources/extensions/toggle_row.html
+++ b/chromium/chrome/browser/resources/extensions/toggle_row.html
@@ -1,6 +1,6 @@
<style>
:host {
- flex-direction: column;
+ display: block;
touch-action: none;
}
diff --git a/chromium/chrome/browser/resources/extensions/toggle_row.js b/chromium/chrome/browser/resources/extensions/toggle_row.js
index 43be17b5f42..8973cbeaf99 100644
--- a/chromium/chrome/browser/resources/extensions/toggle_row.js
+++ b/chromium/chrome/browser/resources/extensions/toggle_row.js
@@ -37,7 +37,7 @@ Polymer({
* @param {!Event} e
* @private
*/
- onNativeClick_: function(e) {
+ onNativeClick_(e) {
// Even though the native checkbox is hidden and can't be actually
// cilcked/tapped by the user, because it resides within the <label> the
// browser emits an extraneous event when the label is clicked. Stop
@@ -51,7 +51,7 @@ Polymer({
* @param {!Event} e
* @private
*/
- onNativeChange_: function(e) {
+ onNativeChange_(e) {
e.stopPropagation();
// Sync value of native checkbox and cr-toggle and |checked|.
@@ -65,7 +65,7 @@ Polymer({
* @param {!CustomEvent<boolean>} e
* @private
*/
- onCrToggleChange_: function(e) {
+ onCrToggleChange_(e) {
e.stopPropagation();
// Sync value of native checkbox and cr-toggle.
diff --git a/chromium/chrome/browser/resources/extensions/toolbar.js b/chromium/chrome/browser/resources/extensions/toolbar.js
index ad6b7eae96c..f67703752bb 100644
--- a/chromium/chrome/browser/resources/extensions/toolbar.js
+++ b/chromium/chrome/browser/resources/extensions/toolbar.js
@@ -33,9 +33,10 @@ export class ToolbarDelegate {
/**
* Updates all extensions.
+ * @param {!Array<!chrome.developerPrivate.ExtensionInfo>} extensions
* @return {!Promise}
*/
- updateAllExtensions() {}
+ updateAllExtensions(extensions) {}
}
Polymer({
@@ -44,6 +45,9 @@ Polymer({
_template: html`{__html_template__}`,
properties: {
+ /** @type {!Array<!chrome.developerPrivate.ExtensionInfo>} */
+ extensions: Array,
+
/** @type {ToolbarDelegate} */
delegate: Object,
@@ -87,7 +91,7 @@ Polymer({
* @return {boolean}
* @private
*/
- shouldDisableDevMode_: function() {
+ shouldDisableDevMode_() {
return this.devModeControlledByPolicy || this.isSupervised;
},
@@ -95,7 +99,7 @@ Polymer({
* @return {string}
* @private
*/
- getTooltipText_: function() {
+ getTooltipText_() {
return this.i18n(
this.isSupervised ? 'controlledSettingChildRestriction' :
'controlledSettingPolicy');
@@ -105,7 +109,7 @@ Polymer({
* @return {string}
* @private
*/
- getIcon_: function() {
+ getIcon_() {
return this.isSupervised ? 'cr20:kite' : 'cr20:domain';
},
@@ -113,7 +117,7 @@ Polymer({
* @param {!CustomEvent<boolean>} e
* @private
*/
- onDevModeToggleChange_: function(e) {
+ onDevModeToggleChange_(e) {
this.delegate.setProfileInDevMode(e.detail);
chrome.metricsPrivate.recordUserAction(
'Options_ToggleDeveloperMode_' + (e.detail ? 'Enabled' : 'Disabled'));
@@ -124,7 +128,7 @@ Polymer({
* @param {boolean} previous
* @private
*/
- onInDevModeChanged_: function(current, previous) {
+ onInDevModeChanged_(current, previous) {
const drawer = this.$.devDrawer;
if (this.inDevMode) {
if (drawer.hidden) {
@@ -134,7 +138,7 @@ Polymer({
/** @suppress {suspiciousCode} */ drawer.offsetTop;
}
} else {
- if (previous == undefined) {
+ if (previous === undefined) {
drawer.hidden = true;
return;
}
@@ -149,7 +153,7 @@ Polymer({
},
/** @private */
- onLoadUnpackedTap_: function() {
+ onLoadUnpackedTap_() {
this.delegate.loadUnpacked().catch(loadError => {
this.fire('load-error', loadError);
});
@@ -157,26 +161,26 @@ Polymer({
},
/** @private */
- onPackTap_: function() {
+ onPackTap_() {
chrome.metricsPrivate.recordUserAction('Options_PackExtension');
this.showPackDialog_ = true;
},
/** @private */
- onPackDialogClose_: function() {
+ onPackDialogClose_() {
this.showPackDialog_ = false;
this.$.packExtensions.focus();
},
// <if expr="chromeos">
/** @private */
- onKioskTap_: function() {
+ onKioskTap_() {
this.fire('kiosk-tap');
},
// </if>
/** @private */
- onUpdateNowTap_: function() {
+ onUpdateNowTap_() {
// If already updating, do not initiate another update.
if (this.isUpdating_) {
return;
@@ -188,16 +192,18 @@ Polymer({
// Keep the toast open indefinitely.
toastManager.duration = 0;
toastManager.show(this.i18n('toolbarUpdatingToast'));
- this.delegate.updateAllExtensions().then(
- () => {
- toastManager.hide();
- toastManager.duration = 3000;
- toastManager.show(this.i18n('toolbarUpdateDone'));
- this.isUpdating_ = false;
- },
- () => {
- toastManager.hide();
- this.isUpdating_ = false;
- });
+ this.delegate.updateAllExtensions(this.extensions)
+ .then(
+ () => {
+ toastManager.hide();
+ toastManager.duration = 3000;
+ toastManager.show(this.i18n('toolbarUpdateDone'));
+ this.isUpdating_ = false;
+ },
+ loadError => {
+ this.fire('load-error', loadError);
+ toastManager.hide();
+ this.isUpdating_ = false;
+ });
},
});
diff --git a/chromium/chrome/browser/resources/feed_internals/BUILD.gn b/chromium/chrome/browser/resources/feed_internals/BUILD.gn
index ff214d984ab..2e98d2be8ba 100644
--- a/chromium/chrome/browser/resources/feed_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/feed_internals/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":feed_internals",
- ]
+ deps = [ ":feed_internals" ]
}
js_library("feed_internals") {
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/BUILD.gn b/chromium/chrome/browser/resources/gaia_auth_host/BUILD.gn
new file mode 100644
index 00000000000..944cf976cfa
--- /dev/null
+++ b/chromium/chrome/browser/resources/gaia_auth_host/BUILD.gn
@@ -0,0 +1,133 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//chrome/test/base/js2gtest.gni")
+import("//chrome/test/include_js_tests.gni")
+import("//third_party/closure_compiler/compile_js.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+
+# Since js2gtest()s don't compile in some scenarios when include_js_tests is
+# false, and since this file may be loaded even when it's false, we need to make
+# sure the js2gtest() target only exists in this file when it works.
+if (is_chromeos && include_js_tests) {
+ js2gtest("login_unitjs_tests") {
+ # These could be unit tests, except they need a browser context in order
+ # to construct a DOMParser object - so they are webui tests.
+ test_type = "webui"
+ sources = [
+ "saml_password_attributes_test.unitjs",
+ "saml_timestamps_test.unitjs",
+ ]
+ gen_include_files = [
+ "saml_password_attributes.js",
+ "saml_timestamps.js",
+ "//ui/webui/resources/js/cr.js",
+ ]
+ defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
+ }
+
+ source_set("browser_tests") {
+ testonly = true
+ deps = [ ":login_unitjs_tests" ]
+ }
+}
+
+js_type_check("closure_compile") {
+ uses_js_modules = true
+ closure_flags =
+ default_closure_args + [
+ "js_module_root=../../chrome/browser/resources/gaia_auth_host/",
+ "js_module_root=./gen/chrome/browser/resources/gaia_auth_host/",
+ ]
+ deps = [
+ ":authenticator.m",
+ ":channel.m",
+ ":post_message_channel.m",
+ ":saml_handler.m",
+ ":saml_password_attributes.m",
+ ":saml_timestamps.m",
+ ":webview_event_manager.m",
+ ]
+}
+
+js_library("channel.m") {
+ sources =
+ [ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/channel.m.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("webview_event_manager.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/webview_event_manager.m.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("post_message_channel.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/post_message_channel.m.js" ]
+ deps = [ ":channel.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("saml_password_attributes.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/saml_password_attributes.m.js" ]
+ deps = [ ":saml_timestamps.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("saml_timestamps.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/saml_timestamps.m.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("saml_handler.m") {
+ sources = [
+ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/saml_handler.m.js",
+ ]
+ deps = [
+ ":channel.m",
+ ":post_message_channel.m",
+ ":saml_password_attributes.m",
+ ":webview_event_manager.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("authenticator.m") {
+ sources = [
+ "$root_gen_dir/chrome/browser/resources/gaia_auth_host/authenticator.m.js",
+ ]
+ deps = [
+ ":saml_handler.m",
+ ":saml_password_attributes.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:util.m",
+ "//ui/webui/resources/js/cr:event_target.m",
+ ]
+ externs_list = [
+ "$externs_path/chrome_extensions.js",
+ "$externs_path/webview_tag.js",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "authenticator.js",
+ "channel.js",
+ "post_message_channel.js",
+ "saml_handler.js",
+ "saml_password_attributes.js",
+ "saml_timestamps.js",
+ "webview_event_manager.js",
+ ]
+ namespace_rewrites = [
+ "DOMWindow|Object",
+ "cr.EventTarget|EventTarget",
+ "cr.login.SamlHandler|SamlHandler",
+ "samlPasswordAttributes.PasswordAttributes|PasswordAttributes",
+ "samlPasswordAttributes.readPasswordAttributes|readPasswordAttributes",
+ "samlTimestamps.decodeTimestamp|decodeTimestamp",
+ "XMLDocument|Object",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js b/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js
index 980e4770262..c219e01b3b0 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/authenticator.js
@@ -5,6 +5,17 @@
// <include src="saml_handler.js">
// Note: webview_event_manager.js is already included by saml_handler.js.
+// clang-format off
+// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// #import {$, appendParam} from 'chrome://resources/js/util.m.js';
+// #import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
+
+// #import {SamlHandler, OnHeadersReceivedDetails} from './saml_handler.m.js';
+// #import {WebviewEventManager} from './webview_event_manager.m.js';
+// #import {PasswordAttributes} from './saml_password_attributes.m.js';
+// clang-format on
+
/**
* @fileoverview An UI component to authenticate to Chrome. The component hosts
* IdP web pages in a webview. A client who is interested in monitoring
@@ -15,7 +26,51 @@
*/
cr.define('cr.login', function() {
- 'use strict';
+ /* #ignore */ 'use strict';
+
+ /**
+ * Credentials passed with 'authCompleted' message.
+ * @typedef {{
+ * email: string,
+ * gaiaId: string,
+ * password: string,
+ * usingSAML: boolean,
+ * publicSAML: boolean,
+ * chooseWhatToSync: boolean,
+ * skipForNow: boolean,
+ * sessionIndex: string,
+ * trusted: boolean,
+ * services: Array,
+ * passwordAttributes: !PasswordAttributes
+ * }}
+ */
+ /* #export */ let AuthCompletedCredentials;
+
+ /**
+ * Parameters for the authorization flow.
+ * @typedef {{
+ * hl: string,
+ * gaiaUrl: string,
+ * authMode: AuthMode,
+ * isLoginPrimaryAccount: boolean,
+ * email: string,
+ * constrained: string,
+ * readOnlyEmail: boolean,
+ * service: string,
+ * dontResizeNonEmbeddedPages: boolean,
+ * clientId: string,
+ * gaiaPath: string,
+ * emailDomain: string,
+ * showTos: string,
+ * extractSamlPasswordAttributes: boolean,
+ * flow: string,
+ * ignoreCrOSIdpSetting: boolean,
+ * enableGaiaActionButtons: boolean,
+ * enterpriseEnrollmentDomain: string,
+ * samlAclUrl: string
+ * }}
+ */
+ /* #export */ let AuthParams;
// TODO(rogerta): should use gaia URL from GaiaUrls::gaia_url() instead
// of hardcoding the prod URL here. As is, this does not work with staging
@@ -32,20 +87,20 @@ cr.define('cr.login', function() {
/**
* The source URL parameter for the constrained signin flow.
*/
- const CONSTRAINED_FLOW_SOURCE = 'chrome';
+ /* #export */ const CONSTRAINED_FLOW_SOURCE = 'chrome';
/**
* Enum for the authorization mode, must match AuthMode defined in
* chrome/browser/ui/webui/inline_login_ui.cc.
* @enum {number}
*/
- const AuthMode = {DEFAULT: 0, OFFLINE: 1, DESKTOP: 2};
+ /* #export */ const AuthMode = {DEFAULT: 0, OFFLINE: 1, DESKTOP: 2};
/**
* Enum for the authorization type.
* @enum {number}
*/
- const AuthFlow = {DEFAULT: 0, SAML: 1};
+ /* #export */ const AuthFlow = {DEFAULT: 0, SAML: 1};
/**
* Supported Authenticator params.
@@ -124,7 +179,7 @@ cr.define('cr.login', function() {
* and the data field of the HTML5 Payload.
*/
const messageHandlers = {
- 'attemptLogin': function(msg) {
+ 'attemptLogin'(msg) {
this.email_ = msg.email;
if (this.authMode == AuthMode.DESKTOP) {
this.password_ = msg.password;
@@ -135,65 +190,65 @@ cr.define('cr.login', function() {
// We need to dispatch only first event, before user enters password.
this.dispatchEvent(new CustomEvent('attemptLogin', {detail: msg.email}));
},
- 'dialogShown': function(msg) {
+ 'dialogShown'(msg) {
this.dispatchEvent(new Event('dialogShown'));
},
- 'dialogHidden': function(msg) {
+ 'dialogHidden'(msg) {
this.dispatchEvent(new Event('dialogHidden'));
},
- 'backButton': function(msg) {
+ 'backButton'(msg) {
this.dispatchEvent(new CustomEvent('backButton', {detail: msg.show}));
},
- 'showView': function(msg) {
+ 'showView'(msg) {
this.dispatchEvent(new Event('showView'));
},
- 'menuItemClicked': function(msg) {
+ 'menuItemClicked'(msg) {
this.dispatchEvent(
new CustomEvent('menuItemClicked', {detail: msg.item}));
},
- 'identifierEntered': function(msg) {
+ 'identifierEntered'(msg) {
this.dispatchEvent(new CustomEvent(
'identifierEntered',
{detail: {accountIdentifier: msg.accountIdentifier}}));
},
- 'userInfo': function(msg) {
+ 'userInfo'(msg) {
this.services_ = msg.services;
if (this.email_ && this.gaiaId_ && this.sessionIndex_) {
this.maybeCompleteAuth_();
}
},
- 'showIncognito': function(msg) {
+ 'showIncognito'(msg) {
this.dispatchEvent(new Event('showIncognito'));
},
- 'setPrimaryActionLabel': function(msg) {
+ 'setPrimaryActionLabel'(msg) {
if (!this.enableGaiaActionButtons_) {
return;
}
this.dispatchEvent(
new CustomEvent('setPrimaryActionLabel', {detail: msg.value}));
},
- 'setPrimaryActionEnabled': function(msg) {
+ 'setPrimaryActionEnabled'(msg) {
if (!this.enableGaiaActionButtons_) {
return;
}
this.dispatchEvent(
new CustomEvent('setPrimaryActionEnabled', {detail: msg.value}));
},
- 'setSecondaryActionLabel': function(msg) {
+ 'setSecondaryActionLabel'(msg) {
if (!this.enableGaiaActionButtons_) {
return;
}
this.dispatchEvent(
new CustomEvent('setSecondaryActionLabel', {detail: msg.value}));
},
- 'setSecondaryActionEnabled': function(msg) {
+ 'setSecondaryActionEnabled'(msg) {
if (!this.enableGaiaActionButtons_) {
return;
}
this.dispatchEvent(
new CustomEvent('setSecondaryActionEnabled', {detail: msg.value}));
},
- 'setAllActionsEnabled': function(msg) {
+ 'setAllActionsEnabled'(msg) {
if (!this.enableGaiaActionButtons_) {
return;
}
@@ -215,7 +270,7 @@ cr.define('cr.login', function() {
/**
* Initializes the authenticator component.
*/
- class Authenticator extends cr.EventTarget {
+ /* #export */ class Authenticator extends cr.EventTarget {
/**
* @param {!WebView|string} webview The webview element or its ID to host
* IdP web pages.
@@ -230,6 +285,10 @@ cr.define('cr.login', function() {
this.chooseWhatToSync_ = false;
this.skipForNow_ = false;
this.authFlow = AuthFlow.DEFAULT;
+ /** @type {AuthMode} */
+ this.authMode = AuthMode.DEFAULT;
+ this.dontResizeNonEmbeddedPages = false;
+
this.authDomain = '';
/**
* @type {!cr.login.SamlHandler|undefined}
@@ -243,7 +302,12 @@ cr.define('cr.login', function() {
this.trusted_ = true;
this.readyFired_ = false;
this.authCompletedFired_ = false;
- this.webview_ = typeof webview == 'string' ? $(webview) : webview;
+ /**
+ * @private {WebView|undefined}
+ */
+ this.webview_ = typeof webview == 'string' ?
+ /** @type {WebView} */ ($(webview)) :
+ webview;
assert(this.webview_);
this.enableGaiaActionButtons_ = false;
this.webviewEventManager_ = WebviewEventManager.create();
@@ -260,7 +324,7 @@ cr.define('cr.login', function() {
* Callback allowing to request whether the specified user which
* authenticates via SAML is a user without a password (neither a manually
* entered one nor one provided via Credentials Passing API).
- * @type {function(string, string, function(boolean))} Arguments are the
+ * @type {?function(string, string, function(boolean))} Arguments are the
* e-mail, the GAIA ID, and the response callback.
*/
this.getIsSamlUserPasswordlessCallback = null;
@@ -273,6 +337,8 @@ cr.define('cr.login', function() {
* @private
*/
this.isSamlUserPasswordless_ = null;
+ /** @private {boolean} */
+ this.isConstrainedWindow_ = false;
this.samlAclUrl_ = null;
window.addEventListener(
@@ -398,7 +464,8 @@ cr.define('cr.login', function() {
/**
* Re-binds to another webview.
- * @param {Object} webview the new webview to be used by this Authenticator.
+ * @param {WebView} webview the new webview to be used by this
+ * Authenticator.
* @private
*/
rebindWebview_(webview) {
@@ -455,14 +522,14 @@ cr.define('cr.login', function() {
webivewParent.replaceChild(newWebview, this.webview_);
- this.rebindWebview_(newWebview);
+ this.rebindWebview_(/** @type {WebView} */ (newWebview));
}
}
/**
* Loads the authenticator component with the given parameters.
* @param {AuthMode} authMode Authorization mode.
- * @param {Object} data Parameters for the authorization flow.
+ * @param {AuthParams} data Parameters for the authorization flow.
*/
load(authMode, data) {
this.authMode = authMode;
@@ -576,7 +643,7 @@ cr.define('cr.login', function() {
}
if (data.isFirstUser) {
- url = appendParam(url, 'is_first_user', true);
+ url = appendParam(url, 'is_first_user', 'true');
if (data.lsbReleaseBoard) {
url = appendParam(url, 'chromeos_board', data.lsbReleaseBoard);
@@ -605,16 +672,17 @@ cr.define('cr.login', function() {
url = appendParam(url, 'flow', data.flow);
}
if (data.emailDomain) {
- url = appendParam(url, 'emaildomain', data.emailDomain);
- // ChromeOS embedded signin page uses 'hd' (hosted domain) as the query
- // argument to show an email domain.
+ // Use 'hd' (hosted domain) as the argument to show an email domain.
url = appendParam(url, 'hd', data.emailDomain);
}
+ if (data.showTos) {
+ url = appendParam(url, 'show_tos', data.showTos);
+ }
if (data.ignoreCrOSIdpSetting === true) {
url = appendParam(url, 'ignoreCrOSIdpSetting', 'true');
}
if (data.enableGaiaActionButtons) {
- url = appendParam(url, 'use_native_navigation', 1);
+ url = appendParam(url, 'use_native_navigation', '1');
}
return url;
}
@@ -683,10 +751,9 @@ cr.define('cr.login', function() {
/**
* Invoked when the sign-in page takes focus.
- * @param {object} e The focus event being triggered.
* @private
*/
- onFocus_(e) {
+ onFocus_() {
if (this.authMode == AuthMode.DESKTOP &&
document.activeElement == document.body) {
this.webview_.focus();
@@ -695,7 +762,7 @@ cr.define('cr.login', function() {
/**
* Invoked when the history state is changed.
- * @param {object} e The popstate event being triggered.
+ * @param {!Event} e The popstate event being triggered.
* @private
*/
onPopState_(e) {
@@ -709,7 +776,7 @@ cr.define('cr.login', function() {
* Invoked when headers are received in the main frame of the webview. It
* 1) reads the authenticated user info from a signin header,
* 2) signals the start of a saml flow upon receiving a saml header.
- * @return {!Object} Modified request headers.
+ * @param {OnHeadersReceivedDetails} details
* @private
*/
onHeadersReceived_(details) {
@@ -744,6 +811,7 @@ cr.define('cr.login', function() {
} else if (headerName == LOCATION_HEADER) {
// If the "choose what to sync" checkbox was clicked, then the
// continue URL will contain a source=3 field.
+ assert(header.value);
const location = decodeURIComponent(header.value);
this.chooseWhatToSync_ = !!location.match(/(\?|&)source=3($|&)/);
}
@@ -752,7 +820,7 @@ cr.define('cr.login', function() {
/**
* Returns true if given HTML5 message is received from the webview element.
- * @param {object} e Payload of the received HTML5 message.
+ * @param {Object} e Payload of the received HTML5 message.
*/
isGaiaMessage(e) {
if (!this.isWebviewEvent_(e)) {
@@ -774,7 +842,7 @@ cr.define('cr.login', function() {
/**
* Invoked when an HTML5 message is received from the webview element.
- * @param {object} e Payload of the received HTML5 message.
+ * @param {Object} e Payload of the received HTML5 message.
* @private
*/
onMessageFromWebview_(e) {
@@ -795,7 +863,7 @@ cr.define('cr.login', function() {
/**
* Invoked to send a HTML5 message to the webview element.
- * @param {object} e Payload of the HTML5 message.
+ * @param {Object} payload Payload of the HTML5 message.
*/
sendMessageToWebview(payload) {
const currentUrl = this.webview_.src;
@@ -1195,6 +1263,7 @@ cr.define('cr.login', function() {
}
}
+ // #cr_define_end
/**
* The current auth flow of the hosted auth page.
* @type {AuthFlow}
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/channel.js b/chromium/chrome/browser/resources/gaia_auth_host/channel.js
index 21ac8715d86..50fc5377b19 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/channel.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/channel.js
@@ -4,8 +4,9 @@
/**
* Channel to the background script.
+ * @constructor
*/
-function Channel() {
+/* #export */ function Channel() {
this.messageCallbacks_ = {};
this.internalRequestCallbacks_ = {};
}
@@ -32,7 +33,7 @@ Channel.prototype = {
/**
* Initialize the channel with given port for the background script.
*/
- init: function(port) {
+ init(port) {
this.port_ = port;
this.port_.onMessage.addListener(this.onMessage_.bind(this));
},
@@ -40,7 +41,7 @@ Channel.prototype = {
/**
* Connects to the background script with the given name.
*/
- connect: function(name) {
+ connect(name) {
this.port_ = chrome.runtime.connect({name: name});
this.port_.onMessage.addListener(this.onMessage_.bind(this));
},
@@ -50,14 +51,14 @@ Channel.prototype = {
* is received, the callback will be invoked with the message as its arg.
* Note only the last registered callback will be invoked.
*/
- registerMessage: function(name, callback) {
+ registerMessage(name, callback) {
this.messageCallbacks_[name] = callback;
},
/**
* Sends a message to the other side of the channel.
*/
- send: function(msg) {
+ send(msg) {
this.port_.postMessage(msg);
},
@@ -65,7 +66,7 @@ Channel.prototype = {
* Sends a message to the other side and invokes the callback with
* the replied object. Useful for message that expects a returned result.
*/
- sendWithCallback: function(msg, callback) {
+ sendWithCallback(msg, callback) {
const requestId = this.nextInternalRequestId_++;
this.internalRequestCallbacks_[requestId] = callback;
this.send({
@@ -79,7 +80,7 @@ Channel.prototype = {
* Invokes message callback using given message.
* @return {*} The return value of the message callback or null.
*/
- invokeMessageCallbacks_: function(msg) {
+ invokeMessageCallbacks_(msg) {
const name = msg.name;
if (this.messageCallbacks_[name]) {
return this.messageCallbacks_[name](msg);
@@ -92,7 +93,7 @@ Channel.prototype = {
/**
* Invoked when a message is received.
*/
- onMessage_: function(msg) {
+ onMessage_(msg) {
const name = msg.name;
if (name == Channel.INTERNAL_REQUEST_MESSAGE) {
const payload = msg.payload;
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd b/chromium/chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd
new file mode 100644
index 00000000000..52a9c5a1e7a
--- /dev/null
+++ b/chromium/chrome/browser/resources/gaia_auth_host/gaia_auth_host_resources.grd
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
+ <outputs>
+ <output filename="grit/gaia_auth_host_resources.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="grit/gaia_auth_host_resources_map.cc"
+ type="resource_file_map_source" />
+ <output filename="grit/gaia_auth_host_resources_map.h"
+ type="resource_map_header" />
+ <output filename="gaia_auth_host_resources.pak" type="data_package" />
+ </outputs>
+ <release seq="1">
+ <includes>
+ <include name="IDR_GAIA_AUTH_AUTHENTICATOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/authenticator.m.js"
+ use_base_dir="false"
+ type ="BINDATA"
+ compress="gzip" />
+ <include name="IDR_GAIA_AUTH_SAML_HANDLER_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/saml_handler.m.js"
+ use_base_dir="false"
+ type ="BINDATA"
+ compress="gzip" />
+ <include name="IDR_GAIA_AUTH_CHANNEL_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/channel.m.js"
+ use_base_dir="false"
+ type ="BINDATA"
+ compress="gzip" />
+ <include name="IDR_GAIA_AUTH_POST_MESSAGE_CHANNEL_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/post_message_channel.m.js"
+ use_base_dir="false"
+ type ="BINDATA"
+ compress="gzip" />
+ <include name="IDR_GAIA_AUTH_WEBVIEW_EVENT_MANAGER_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/webview_event_manager.m.js"
+ use_base_dir="false"
+ type ="BINDATA"
+ compress="gzip" />
+ <include name="IDR_GAIA_AUTH_SAML_PASSWORD_ATTRIBUTES_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/saml_password_attributes.m.js"
+ use_base_dir="false"
+ type ="BINDATA"
+ compress="gzip" />
+ <include name="IDR_GAIA_AUTH_SAML_TIMESTAMPS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/gaia_auth_host/saml_timestamps.m.js"
+ use_base_dir="false"
+ type ="BINDATA"
+ compress="gzip" />
+ </includes>
+ </release>
+</grit>
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js b/chromium/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js
index dbdb4788c1b..00f17b5dab6 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/password_change_authenticator.js
@@ -56,7 +56,8 @@ cr.define('cr.samlPasswordChange', function() {
if (url.host.match(/\.okta\.com$/)) {
return PasswordChangePageProvider.OKTA;
}
- if (url.pathname.match('/password/chg/')) {
+ if (url.pathname.match('/password/chg/') ||
+ url.pathname.match('/pwdchange/')) {
return PasswordChangePageProvider.PING;
}
return PasswordChangePageProvider.UNKNOWN;
@@ -105,8 +106,9 @@ cr.define('cr.samlPasswordChange', function() {
if (pageProvider == PasswordChangePageProvider.PING) {
// The returnurl is always preserved until password change succeeds - then
// it is no longer needed.
- return !!postUrl.searchParams.get('returnurl') &&
- !redirectUrl.searchParams.get('returnurl');
+ return (!!postUrl.searchParams.get('returnurl') &&
+ !redirectUrl.searchParams.get('returnurl')) ||
+ redirectUrl.pathname.endsWith('Success');
}
// We can't currently detect success for Okta just by inspecting the
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/post_message_channel.js b/chromium/chrome/browser/resources/gaia_auth_host/post_message_channel.js
index 8fd7118b449..0fab561d572 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/post_message_channel.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/post_message_channel.js
@@ -11,7 +11,11 @@
// <include src="channel.js">
-const PostMessageChannel = (function() {
+// clang-format off
+// #import {Channel} from './channel.m.js';
+// clang-format on
+
+/* #export */ const PostMessageChannel = (function() {
/**
* Allowed origins of the hosting page.
* @type {Array<string>}
@@ -37,6 +41,7 @@ const PostMessageChannel = (function() {
/**
* A simple event target.
+ * @constructor
*/
function EventTarget() {
this.listeners_ = [];
@@ -46,14 +51,14 @@ const PostMessageChannel = (function() {
/**
* Add an event listener.
*/
- addListener: function(listener) {
+ addListener(listener) {
this.listeners_.push(listener);
},
/**
* Dispatches a given event to all listeners.
*/
- dispatch: function(e) {
+ dispatch(e) {
for (let i = 0; i < this.listeners_.length; ++i) {
this.listeners_[i].call(undefined, e);
}
@@ -110,14 +115,14 @@ const PostMessageChannel = (function() {
* Gets a global unique id to use.
* @return {number}
*/
- createChannelId_: function() {
+ createChannelId_() {
return (new Date()).getTime();
},
/**
* Posts data to upperWindow. Queue it if upperWindow is not available.
*/
- postToUpperWindow: function(data) {
+ postToUpperWindow(data) {
if (this.upperWindow == null) {
this.deferredUpperWindowMessages_.push(data);
return;
@@ -133,11 +138,11 @@ const PostMessageChannel = (function() {
* @param {DOMWindow=} opt_targetWindow
* @param {string=} opt_targetOrigin
*/
- createPort: function(
- channelId, channelName, opt_targetWindow, opt_targetOrigin) {
+ createPort(channelId, channelName, opt_targetWindow, opt_targetOrigin) {
const port = new PostMessagePort(channelId, channelName);
if (opt_targetWindow) {
- port.setTarget(opt_targetWindow, opt_targetOrigin);
+ port.setTarget(
+ opt_targetWindow, /** @type {string} */ (opt_targetOrigin));
}
this.channels_[channelId] = port;
return port;
@@ -147,7 +152,7 @@ const PostMessageChannel = (function() {
* Returns a message forward handler for the given proxy port.
* @private
*/
- getProxyPortForwardHandler_: function(proxyPort) {
+ getProxyPortForwardHandler_(proxyPort) {
return function(msg) {
proxyPort.postMessage(msg);
};
@@ -160,8 +165,7 @@ const PostMessageChannel = (function() {
* @param {!DOMWindow} targetWindow
* @param {!string} targetOrigin
*/
- createProxyPort: function(
- channelId, channelName, targetWindow, targetOrigin) {
+ createProxyPort(channelId, channelName, targetWindow, targetOrigin) {
const port =
this.createPort(channelId, channelName, targetWindow, targetOrigin);
port.onMessage.addListener(this.getProxyPortForwardHandler_(port));
@@ -171,13 +175,13 @@ const PostMessageChannel = (function() {
/**
* Creates a connecting port to the daemon and request connection.
* @param {string} name
- * @return {PostMessagePort}
+ * @return {?PostMessagePort}
*/
- connectToDaemon: function(name) {
+ connectToDaemon(name) {
if (this.isDaemon) {
console.error(
'Error: Connecting from the daemon page is not supported.');
- return;
+ return null;
}
const port = this.createPort(this.createChannelId_(), name);
@@ -199,7 +203,7 @@ const PostMessageChannel = (function() {
* Dispatches a 'message' event to port.
* @private
*/
- dispatchMessageToPort_: function(e) {
+ dispatchMessageToPort_(e) {
const channelId = e.data.channelId;
const port = this.channels_[channelId];
if (!port) {
@@ -213,7 +217,7 @@ const PostMessageChannel = (function() {
/**
* Window 'message' handler.
*/
- onMessage_: function(e) {
+ onMessage_(e) {
if (typeof e.data != 'object' || !e.data.hasOwnProperty('type')) {
return;
}
@@ -272,6 +276,7 @@ const PostMessageChannel = (function() {
/**
* A HTML5 postMessage based port that provides the same port interface
* as the messaging API port.
+ * @constructor
* @param {number} channelId
* @param {string} name
*/
@@ -291,7 +296,7 @@ const PostMessageChannel = (function() {
* @param {DOMWindow} targetWindow
* @param {string} targetOrigin
*/
- setTarget: function(targetWindow, targetOrigin) {
+ setTarget(targetWindow, targetOrigin) {
this.targetWindow = targetWindow;
this.targetOrigin = targetOrigin;
@@ -301,7 +306,7 @@ const PostMessageChannel = (function() {
this.deferredMessages_ = [];
},
- postMessage: function(msg) {
+ postMessage(msg) {
if (!this.targetWindow) {
this.deferredMessages_.push(msg);
return;
@@ -312,7 +317,7 @@ const PostMessageChannel = (function() {
this.targetOrigin);
},
- handleWindowMessage: function(e) {
+ handleWindowMessage(e) {
this.onMessage.dispatch(e.data.payload);
}
};
@@ -330,7 +335,7 @@ const PostMessageChannel = (function() {
__proto__: Channel.prototype,
/** @override */
- connect: function(name) {
+ connect(name) {
this.port_ = channelManager.connectToDaemon(name);
this.port_.onMessage.addListener(this.onMessage_.bind(this));
},
@@ -364,7 +369,6 @@ const PostMessageChannel = (function() {
return PostMessageChannel;
})();
-/** @override */
Channel.create = function() {
return new PostMessageChannel();
};
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js b/chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js
index e8f3aa558ae..6632731b94e 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/saml_handler.js
@@ -4,14 +4,22 @@
// <include src="post_message_channel.js">
// <include src="webview_event_manager.js">
-// <include src="../chromeos/login/saml_password_attributes.js">
+// <include src="saml_password_attributes.js">
+
+// clang-format off
+// #import {Channel} from './channel.m.js';
+// #import {PostMessageChannel} from './post_message_channel.m.js';
+// #import {WebviewEventManager} from './webview_event_manager.m.js';
+// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js'
+// #import {PasswordAttributes, readPasswordAttributes} from './saml_password_attributes.m.js';
+// clang-format on
/**
* @fileoverview Saml support for webview based auth.
*/
cr.define('cr.login', function() {
- 'use strict';
+ /* #ignore */ 'use strict';
/**
* The lowest version of the credentials passing API supported.
@@ -54,6 +62,47 @@ cr.define('cr.login', function() {
`;
/**
+ * @typedef {{
+ * method: string,
+ * requestedVersion: number,
+ * keyType: string,
+ * token: string,
+ * passwordBytes: string
+ * }}
+ */
+ let ApiCallMessageCall;
+
+ /**
+ * @typedef {{
+ * name: string,
+ * call: ApiCallMessageCall
+ * }}
+ */
+ let ApiCallMessage;
+
+ /**
+ * Details about the request.
+ * @typedef {{
+ * method: string,
+ * requestBody: Object,
+ * url: string
+ * }}
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onBeforeRequest#details
+ */
+ /* #export */ let OnBeforeRequestDetails;
+
+ /**
+ * Details of the request.
+ * @typedef {{
+ * responseHeaders: Array<HttpHeader>,
+ * statusCode: number,
+ * url: string,
+ * }}
+ * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onHeadersReceived#details
+ */
+ /* #export */ let OnHeadersReceivedDetails;
+
+ /**
* Creates a new URL by striping all query parameters.
* @param {string} url The original URL.
* @return {string} The new URL with all query parameters stripped.
@@ -77,9 +126,9 @@ cr.define('cr.login', function() {
* A handler to provide saml support for the given webview that hosts the
* auth IdP pages.
*/
- class SamlHandler extends cr.EventTarget {
+ /* #export */ class SamlHandler extends cr.EventTarget {
/**
- * @param {webview} webview
+ * @param {!WebView} webview
* @param {boolean} startsOnSamlPage - whether initial URL is already SAML
* page
* */
@@ -108,25 +157,26 @@ cr.define('cr.login', function() {
/**
* The webview that serves IdP pages.
- * @type {webview}
+ * @private {!WebView}
*/
this.webview_ = webview;
/**
* Whether a Saml page is in the webview from the start.
+ * @private {boolean}
*/
this.startsOnSamlPage_ = startsOnSamlPage;
/**
* Whether a Saml IdP page is display in the webview.
- * @type {boolean}
+ * @private {boolean}
*/
this.isSamlPage_ = this.startsOnSamlPage_;
/**
* Pending Saml IdP page flag that is set when a SAML_HEADER is received
* and is copied to |isSamlPage_| in loadcommit.
- * @type {boolean}
+ * @private {boolean}
*/
this.pendingIsSamlPage_ = this.startsOnSamlPage_;
@@ -134,7 +184,7 @@ cr.define('cr.login', function() {
* The last aborted top level url. It is recorded in loadabort event and
* used to skip injection into Chrome's error page in the following
* loadcommit event.
- * @type {string}
+ * @private {?string}
*/
this.abortedTopLevelUrl_ = null;
@@ -146,34 +196,40 @@ cr.define('cr.login', function() {
/**
* Scraped password stored in an id to password field value map.
- * @type {Object<string, string>}
- * @private
+ * @private {!Object<string, string>}
*/
this.passwordStore_ = {};
/**
* Whether Saml API is initialized.
- * @type {boolean}
+ * @private {boolean}
*/
this.apiInitialized_ = false;
/**
* Saml API version to use.
- * @type {number}
+ * @private {number}
*/
this.apiVersion_ = 0;
/**
- * Saml API token received.
- * @type {string}
+ * Saml API tokens received.
+ * @private {!Object}
*/
- this.apiToken_ = null;
+ this.apiTokenStore_ = {};
/**
- * Saml API password bytes.
- * @type {string}
+ * Saml API confirmation token. Set by last 'confirm' call.
+ * @private {?string}
*/
- this.apiPasswordBytes_ = null;
+ this.confirmToken_ = null;
+
+ /**
+ * Saml API password bytes set by last 'add' call. Needed to not break
+ * existing behavior.
+ * @private {?string}
+ */
+ this.lastApiPasswordBytes_ = null;
/**
* Whether to abort the authentication flow and show an error message
@@ -184,36 +240,33 @@ cr.define('cr.login', function() {
/**
* Whether to attempt to extract password attributes from the SAMLResponse
- * XML. See ../chromeos/login/saml_password_attributes.js
+ * XML. See saml_password_attributes.js
* @type {boolean}
*/
this.extractSamlPasswordAttributes = false;
/**
* Current stage of device attestation flow.
- * @type {DeviceAttestationStage}
- * @private
+ * @private {!SamlHandler.DeviceAttestationStage}
*/
this.deviceAttestationStage_ = SamlHandler.DeviceAttestationStage.NONE;
/**
* Challenge from IdP to perform device attestation.
- * @type {?string}
- * @private
+ * @private {?string}
*/
this.verifiedAccessChallenge_ = null;
/**
* Response for a device attestation challenge.
- * @type {?string}
- * @private
+ * @private {?string}
*/
this.verifiedAccessChallengeResponse_ = null;
/**
* The password-attributes that were extracted from the SAMLResponse, if
* any. (Doesn't contain the password itself).
- * @type {PasswordAttributes}
+ * @private {!PasswordAttributes}
*/
this.passwordAttributes_ =
samlPasswordAttributes.PasswordAttributes.EMPTY;
@@ -278,15 +331,21 @@ cr.define('cr.login', function() {
* @return {boolean}
*/
get samlApiUsed() {
- return !!this.apiPasswordBytes_;
+ return !!this.lastApiPasswordBytes_;
}
/**
* Returns the Saml API password bytes.
- * @return {string}
+ * @return {?string}
*/
get apiPasswordBytes() {
- return this.apiPasswordBytes_;
+ if (this.confirmToken_ != null &&
+ typeof (this.apiTokenStore_[this.confirmToken_]) == 'object' &&
+ typeof (this.apiTokenStore_[this.confirmToken_]['passwordBytes']) ==
+ 'string') {
+ return this.apiTokenStore_[this.confirmToken_]['passwordBytes'];
+ }
+ return this.lastApiPasswordBytes_;
}
/**
@@ -338,7 +397,7 @@ cr.define('cr.login', function() {
/**
* Gets the password attributes extracted from SAML Response.
- * @return {PasswordAttributes}
+ * @return {Object}
*/
get passwordAttributes() {
return this.passwordAttributes_;
@@ -377,8 +436,9 @@ cr.define('cr.login', function() {
this.apiInitialized_ = false;
this.apiVersion_ = 0;
- this.apiToken_ = null;
- this.apiPasswordBytes_ = null;
+ this.apiTokenStore_ = {};
+ this.confirmToken_ = null;
+ this.lastApiPasswordBytes_ = null;
this.passwordAttributes_ =
samlPasswordAttributes.PasswordAttributes.EMPTY;
}
@@ -470,18 +530,24 @@ cr.define('cr.login', function() {
* Handler for webRequest.onBeforeRequest that looks for the Base64
* encoded SAMLResponse in the POST-ed formdata sent from the SAML page.
* Non-blocking.
- * @param {Object} details The web-request details.
+ * @param {OnBeforeRequestDetails} details The web-request details.
*/
onMainFrameWebRequest(details) {
- if (!this.extractSamlPasswordAttributes) return;
- if (!this.isSamlPage_ || details.method != 'POST') return;
+ if (!this.extractSamlPasswordAttributes) {
+ return;
+ }
+ if (!this.isSamlPage_ || details.method != 'POST') {
+ return;
+ }
const formData = details.requestBody.formData;
let samlResponse = (formData && formData.SAMLResponse);
if (!samlResponse) {
samlResponse = new URL(details.url).searchParams.get('SAMLResponse');
}
- if (!samlResponse) return;
+ if (!samlResponse) {
+ return;
+ }
try {
// atob means asciiToBinary, which actually means base64Decode:
@@ -671,6 +737,8 @@ cr.define('cr.login', function() {
'pageLoaded', this.onPageLoaded_.bind(this, channel));
channel.registerMessage(
'getSAMLFlag', this.onGetSAMLFlag_.bind(this, channel));
+ channel.registerMessage(
+ 'scrollInfo', this.onScrollInfo_.bind(this, channel));
}
sendInitializationSuccess_(channel) {
@@ -692,7 +760,7 @@ cr.define('cr.login', function() {
/**
* Handlers for channel messages.
* @param {Channel} channel A channel to send back response.
- * @param {Object} msg Received message.
+ * @param {ApiCallMessage} msg Received message.
* @private
*/
onAPICall_(channel, msg) {
@@ -718,13 +786,15 @@ cr.define('cr.login', function() {
}
// Not setting |email_| and |gaiaId_| because this API call will
// eventually be followed by onCompleteLogin_() which does set it.
- this.apiToken_ = call.token;
- this.apiPasswordBytes_ = call.passwordBytes;
+ this.apiTokenStore_[call.token] = call;
+ this.lastApiPasswordBytes_ = call.passwordBytes;
this.dispatchEvent(new CustomEvent('apiPasswordAdded'));
} else if (call.method == 'confirm') {
- if (call.token != this.apiToken_) {
+ if (!(call.token in this.apiTokenStore_)) {
console.error('SamlHandler.onAPICall_: token mismatch');
+ } else {
+ this.confirmToken_ = call.token;
}
} else {
console.error('SamlHandler.onAPICall_: unknown message');
@@ -748,6 +818,22 @@ cr.define('cr.login', function() {
}));
}
+ onScrollInfo_(channel, msg) {
+ const scrollTop = msg.scrollTop;
+ const scrollHeight = msg.scrollHeight;
+ const clientHeight = this.webview_.clientHeight;
+
+ if (scrollTop === undefined || scrollHeight === undefined) {
+ return;
+ }
+
+ this.webview_.classList.toggle('can-scroll', clientHeight < scrollHeight);
+ this.webview_.classList.toggle('is-scrolled', scrollTop > 0);
+ const scrolledToBottom = (scrollTop > 0) /*is-scrolled*/ &&
+ (Math.ceil(scrollTop + clientHeight) >= scrollHeight);
+ this.webview_.classList.toggle('scrolled-to-bottom', scrolledToBottom);
+ }
+
onPermissionRequest_(permissionEvent) {
if (permissionEvent.permission === 'media') {
// The actual permission check happens in
@@ -762,5 +848,6 @@ cr.define('cr.login', function() {
}
}
+ // #cr_define_end
return {SamlHandler: SamlHandler};
});
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/saml_injected.js b/chromium/chrome/browser/resources/gaia_auth_host/saml_injected.js
index 944f6c9e815..56d99d870b0 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/saml_injected.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/saml_injected.js
@@ -31,7 +31,7 @@ APICallForwarder.prototype = {
* Initialize the API call forwarder.
* @param {!Object} channel Channel to which API calls should be forwarded.
*/
- init: function(channel) {
+ init(channel) {
this.channel_ = channel;
this.channel_.registerMessage(
'apiResponse', this.onAPIResponse_.bind(this));
@@ -39,7 +39,7 @@ APICallForwarder.prototype = {
window.addEventListener('message', this.onMessage_.bind(this));
},
- onMessage_: function(event) {
+ onMessage_(event) {
if (event.source != window || typeof event.data != 'object' ||
!event.data.hasOwnProperty('type') ||
event.data.type != 'gaia_saml_api') {
@@ -49,7 +49,7 @@ APICallForwarder.prototype = {
this.channel_.send({name: 'apiCall', call: event.data.call});
},
- onAPIResponse_: function(msg) {
+ onAPIResponse_(msg) {
// Forward API responses to the SAML page.
window.postMessage(
{type: 'gaia_saml_api_reply', response: msg.response}, '/');
@@ -87,7 +87,7 @@ PasswordInputScraper.prototype = {
* @param {!HTMLElement} docRoot The root element of the DOM tree that
* contains the password fields of interest.
*/
- init: function(channel, pageURL, docRoot) {
+ init(channel, pageURL, docRoot) {
this.pageURL_ = pageURL;
this.channel_ = channel;
@@ -119,7 +119,7 @@ PasswordInputScraper.prototype = {
* Find and track password fields that are descendants of the given element.
* @param {!HTMLElement} element The parent element to search from.
*/
- findAndTrackChildren: function(element) {
+ findAndTrackChildren(element) {
Array.prototype.forEach.call(
element.querySelectorAll('input[type=password]'), function(field) {
this.trackPasswordField(field);
@@ -131,7 +131,7 @@ PasswordInputScraper.prototype = {
* not being tracked yet.
* @param {!HTMLInputElement} passworField The password field to track.
*/
- trackPasswordField: function(passwordField) {
+ trackPasswordField(passwordField) {
const existing = this.passwordFields_.filter(function(element) {
return element === passwordField;
});
@@ -151,7 +151,7 @@ PasswordInputScraper.prototype = {
* Check if the password field at |index| has changed. If so, sends back
* the updated value.
*/
- maybeSendUpdatedPassword: function(index, fieldId) {
+ maybeSendUpdatedPassword(index, fieldId) {
const newValue = this.passwordFields_[index].value;
if (newValue == this.passwordValues_[index]) {
return;
@@ -174,7 +174,7 @@ PasswordInputScraper.prototype = {
* |passwordFields_|.
* @param {string} fieldId The id or name of the password field or blank.
*/
- onPasswordChanged_: function(index, fieldId) {
+ onPasswordChanged_(index, fieldId) {
this.maybeSendUpdatedPassword(index, fieldId);
}
};
@@ -212,4 +212,11 @@ channel.sendWithCallback(
const apiCallForwarder = new APICallForwarder();
apiCallForwarder.init(channel);
+
+// Send scroll information from the topmost frame.
+if (window.top === window.self) {
+ const scrollHelper = WebviewScrollShadowsHelperConstructor();
+ scrollHelper.init(channel);
+}
+
})();
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/saml_password_attributes.js b/chromium/chrome/browser/resources/gaia_auth_host/saml_password_attributes.js
new file mode 100644
index 00000000000..4fecfd13b10
--- /dev/null
+++ b/chromium/chrome/browser/resources/gaia_auth_host/saml_password_attributes.js
@@ -0,0 +1,165 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// <include src="saml_timestamps.js">
+
+// clang-format off;
+// #import {decodeTimestamp} from './saml_timestamps.m.js';
+// clang-format on
+
+/**
+ * @fileoverview A utility for extracting password information from SAML
+ * authorization response. This requires that the SAML IDP administrator
+ * has correctly configured their domain to issue these attributes.
+ */
+
+cr.define('samlPasswordAttributes', function() {
+ /* #ignore */ 'use strict';
+
+ /** @const @private {number} The shortest XML string that could be useful. */
+ const MIN_SANE_XML_LENGTH = 100;
+
+ /** @const @private {number} The max length that we are willing to parse. */
+ const MAX_SANE_XML_LENGTH = 50 * 1024; // 50 KB
+
+ /** @const @private {string} Schema name prefix. */
+ const SCHEMA_NAME_PREFIX = 'http://schemas.google.com/saml/2019/';
+
+ /** @const @private {string} Schema name for password modified timestamp. */
+ const PASSWORD_MODIFIED_TIMESTAMP = 'passwordmodifiedtimestamp';
+
+ /** @const @private {string} Schema name for password expiration timestamp. */
+ const PASSWORD_EXPIRATION_TIMESTAMP = 'passwordexpirationtimestamp';
+
+ /** @const @private {string} Schema name for password-change URL. */
+ const PASSWORD_CHANGE_URL = 'passwordchangeurl';
+
+ /**
+ * Query selector for finding an element with tag AttributeValue that is a
+ * child of an element of tag Attribute with a certain Name attribute.
+ * @const @private {string}
+ */
+ const QUERY_SELECTOR_FORMAT = 'Attribute[Name="{0}"] > AttributeValue';
+
+ /** Turns a schema name into a query selector to find the AttributeValue. */
+ function makeQuerySelector(schemaName) {
+ return QUERY_SELECTOR_FORMAT.replace(
+ '{0}', SCHEMA_NAME_PREFIX + schemaName);
+ }
+
+ /** @const @private {string} Query selector for password modified time. */
+ const PASSWORD_MODIFIED_TIMESTAMP_SELECTOR =
+ makeQuerySelector(PASSWORD_MODIFIED_TIMESTAMP);
+
+ /** @const @private {string} Query selector for password expiration time. */
+ const PASSWORD_EXPIRATION_TIMESTAMP_SELECTOR =
+ makeQuerySelector(PASSWORD_EXPIRATION_TIMESTAMP);
+
+ /** @const @private {string} Query selector for password expiration time. */
+ const PASSWORD_CHANGE_URL_SELECTOR = makeQuerySelector(PASSWORD_CHANGE_URL);
+
+ /**
+ * Extract password information from the Attribute elements in the given SAML
+ * authorization response.
+ * @param {string} xmlStr The SAML response XML, as a string.
+ * @return {!PasswordAttributes} A struct containing all the attributes that
+ * could be extracted, formatted as strings. Some or all of the strings can
+ * be empty if some or all of the attributes could not be extracted.
+ */
+ /* #export */ function readPasswordAttributes(xmlStr) {
+ // Don't throw any exception that could cause login to fail - extracting
+ // these attributes can fail, but login should not be interrupted.
+ try {
+ if (!xmlStr || typeof xmlStr != 'string') {
+ return PasswordAttributes.EMPTY;
+ }
+ if (xmlStr.length < MIN_SANE_XML_LENGTH ||
+ xmlStr.length > MAX_SANE_XML_LENGTH) {
+ return PasswordAttributes.EMPTY;
+ }
+ if (!xmlStr.includes(SCHEMA_NAME_PREFIX)) {
+ // No need to bother parsing the XML if it doesn't contain this string.
+ return PasswordAttributes.EMPTY;
+ }
+
+ const xmlDom = new DOMParser().parseFromString(xmlStr, 'text/xml');
+ if (!xmlDom) {
+ return PasswordAttributes.EMPTY;
+ }
+
+ return new PasswordAttributes(
+ extractTimestampFromXml(xmlDom, PASSWORD_MODIFIED_TIMESTAMP_SELECTOR),
+ extractTimestampFromXml(
+ xmlDom, PASSWORD_EXPIRATION_TIMESTAMP_SELECTOR),
+ extractStringFromXml(xmlDom, PASSWORD_CHANGE_URL_SELECTOR));
+
+ } catch (error) {
+ console.error('Error reading password attributes: ' + error);
+ return PasswordAttributes.EMPTY;
+ }
+ }
+
+ /**
+ * Extracts a string from the given XML DOM, using the given query selector.
+ * @param {!XMLDocument} xmlDom The XML DOM.
+ * @param {string} querySelectorStr The query selector to find the string.
+ * @return {string} The extracted string (empty if failed to extract).
+ */
+ function extractStringFromXml(xmlDom, querySelectorStr) {
+ const element = xmlDom.querySelector(querySelectorStr);
+ return (element && element.textContent) ? element.textContent : '';
+ }
+
+ /**
+ * Extracts a timestamp from the given XML DOM, using the given query selector
+ * to find it and using {@code samlTimestamps.decodeTimestamp} to decode it.
+ * @param {!XMLDocument} xmlDom The XML DOM.
+ * @param {string} querySelectorStr The query selector to find the timestamp.
+ * @return {string} The timestamp as number of ms since 1970, formatted as a
+ * string (or an empty string if the timestamp could not be extracted).
+ */
+ function extractTimestampFromXml(xmlDom, querySelectorStr) {
+ const valueText = extractStringFromXml(xmlDom, querySelectorStr);
+ if (!valueText) {
+ return '';
+ }
+
+ const timestamp = samlTimestamps.decodeTimestamp(valueText);
+ return timestamp ? String(timestamp.valueOf()) : '';
+ }
+
+ /**
+ * Immutable struct to hold password attributes. All three fields are strings
+ * and are always present, but they are empty if that information is missing.
+ * Timestamps are in JS time - the number of ms since 1 January 1970 - but
+ * are also formatted as strings, since this struct is sent from JS into C++,
+ * and strings travel easier than int64s across this boundary.
+ * If this struct is changed, SamlPasswordAttributes::FromJS in
+ * saml_password_attributes.cc must also be changed.
+ * @export @final
+ */
+ /* #export */ class PasswordAttributes {
+ constructor(modifiedTime, expirationTime, passwordChangeUrl) {
+ /** @type {string} Password last-modified timestamp. */
+ this.modifiedTime = modifiedTime;
+
+ /** @type {string} Password expiration timestamp. */
+ this.expirationTime = expirationTime;
+
+ /** @type {string} Password-change URL. */
+ this.passwordChangeUrl = passwordChangeUrl;
+
+ Object.freeze(this); // Make immutable.
+ }
+ }
+
+ /** An immutable and empty PasswordAttributes struct. */
+ PasswordAttributes.EMPTY = new PasswordAttributes('', '', '');
+
+ // #cr_define_end
+ return {
+ readPasswordAttributes: readPasswordAttributes,
+ PasswordAttributes: PasswordAttributes,
+ };
+});
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/saml_password_attributes_test.unitjs b/chromium/chrome/browser/resources/gaia_auth_host/saml_password_attributes_test.unitjs
new file mode 100644
index 00000000000..d44e0ef2072
--- /dev/null
+++ b/chromium/chrome/browser/resources/gaia_auth_host/saml_password_attributes_test.unitjs
@@ -0,0 +1,85 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+GEN_INCLUDE([
+ '//ui/webui/resources/js/cr.js',
+ 'saml_timestamps.js',
+ 'saml_password_attributes.js',
+]);
+
+function SamlPasswordAttributesUnitTest() {}
+
+SamlPasswordAttributesUnitTest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ // WebUI tests run accessibility checks by default, but unit tests don't.
+ // Ideally this would be a unit test, but unit tests can't use the DOMParser.
+ // WebUI tests can, so this is a WebUI test. But, this test has no UI to run
+ // accessibility checks on, so we turn this off manually.
+ runAccessibilityChecks: false,
+
+ /** @override */
+ testGenCppIncludes() {
+ GEN(`#include "chrome/test/base/ui_test_utils.h"`);
+ },
+
+ /** @override */
+ testGenPreamble() {
+ // Generates a preamble that calls InitializeTestData with the contents
+ // of chrome/test/data/chromeos/login/saml_with_password_attributes.xml
+ GEN(`
+ BrowsePreload(GURL("chrome://DummyURL"));
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ std::string xml_test_data;
+ base::FilePath xml_path = ui_test_utils::GetTestFilePath(
+ base::FilePath(FILE_PATH_LITERAL("chromeos/login")),
+ base::FilePath(FILE_PATH_LITERAL("saml_with_password_attributes.xml")));
+ base::ReadFileToString(xml_path, &xml_test_data);
+ RunJavascriptFunction("initializeTestData", base::Value(xml_test_data));
+ `);
+ },
+};
+
+let XML_TEST_DATA;
+let XML_TEST_DATA_WITH_ATTRIBUTES_REMOVED;
+
+const initializeTestData = function(xml_test_data) {
+ XML_TEST_DATA = xml_test_data;
+ // Strips out the timestamps that are in the <AttributeValue> tags.
+ XML_TEST_DATA_WITH_ATTRIBUTES_REMOVED = XML_TEST_DATA.replace(
+ /<AttributeValue>[^<>]+/g,
+ '<AttributeValue>');
+};
+
+TEST_F('SamlPasswordAttributesUnitTest', 'ReadInvalid', function() {
+ // Make sure empty result is returned for empty input:
+ let result = samlPasswordAttributes.readPasswordAttributes('');
+ assertEquals('', result.modifiedTime);
+ assertEquals('', result.expirationTime);
+ assertEquals('', result.passwordChangeUrl);
+
+ // Make sure empty result is returned for random junk:
+ result = samlPasswordAttributes.readPasswordAttributes('<abc></abc>');
+ assertEquals('', result.modifiedTime);
+ assertEquals('', result.expirationTime);
+ assertEquals('', result.passwordChangeUrl);
+
+ // Make sure empty result is returned when the input is almost valid, but not quite:
+ result = samlPasswordAttributes.readPasswordAttributes(
+ XML_TEST_DATA_WITH_ATTRIBUTES_REMOVED);
+ assertEquals('', result.modifiedTime);
+ assertEquals('', result.expirationTime);
+ assertEquals('', result.passwordChangeUrl);
+});
+
+TEST_F('SamlPasswordAttributesUnitTest', 'ReadValid', function() {
+ const result = samlPasswordAttributes.readPasswordAttributes(XML_TEST_DATA);
+
+ assertEquals(String(Date.parse('2019-02-22T11:50:58.421Z')),
+ result.modifiedTime);
+ assertEquals(String(Date.parse('2019-03-06T11:50:58.421Z')),
+ result.expirationTime);
+ assertEquals('https://example.com/adfs/portal/updatepassword/',
+ result.passwordChangeUrl);
+});
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/saml_timestamps.js b/chromium/chrome/browser/resources/gaia_auth_host/saml_timestamps.js
new file mode 100644
index 00000000000..a15a7101719
--- /dev/null
+++ b/chromium/chrome/browser/resources/gaia_auth_host/saml_timestamps.js
@@ -0,0 +1,140 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A utility for decoding timestamps strings into JS Date objects.
+ * This is needed for showing the SAML password expiry notifications.
+ * Timestamps are allowed to be sent to us in a variety of formats, since SAML
+ * administrators may not have the ability to convert between formats at their
+ * end. This class doesn't need to be informed which format the timestamp is in,
+ * since the different allowed formats don't tend to overlap in practice.
+ *
+ * The supported formats are NTFS filetimes, Unix time (in seconds or ms),
+ * and ISO 8601.
+ */
+
+cr.define('samlTimestamps', function() {
+ 'use strict';
+
+ /** @const @private {number} Maximum length of a valid timestamp. */
+ const MAX_SANE_LENGTH = 30;
+
+ /** @const @private {!Date} The earliest date considered sane. */
+ const MIN_SANE_DATE = new Date('1980-01-01 UTC');
+
+ /** @const @private {!Date} The latest date considered sane. */
+ const MAX_SANE_DATE = new Date('10000-01-01 UTC');
+
+ /** @const @private {!Date} Epoch for Windows NTFS FILETIME timestamps. */
+ const NTFS_EPOCH = new Date('1601-01-01 UTC');
+
+ /** @const @private {!RegExp} Pattern to match integers. */
+ const INTEGER_PATTERN = /^-?\d+$/;
+
+ /**
+ * Pattern to match ISO 8601 dates / times. Rejects other text-based timestamp
+ * formats (eg '01-02-03') since they cannot be parsed in a consistent way.
+ * @const @private {!RegExp}
+ */
+ const ISO_8601_PATTERN = /^\d\d\d\d-\d\d-\d\d(T|$)/;
+
+ /**
+ * Decode a timestamp string that is in one of the supported formats.
+ * @param {string} str A timestamp formatted as a string.
+ * @return {?Date} A valid decoded timestamp, or null.
+ */
+ /* #export */ function decodeTimestamp(str) {
+ str = str.trim();
+ if (str.length == 0 || str.length > MAX_SANE_LENGTH) {
+ return null;
+ }
+
+ if (INTEGER_PATTERN.test(str)) {
+ return decodeIntegerTimestamp(parseInt(str, 10));
+ } else if (ISO_8601_PATTERN.test(str)) {
+ return decodeIso8601(str);
+ }
+ return null;
+ }
+
+ /**
+ * Decode a timestamp that is in one of the supported integer formats:
+ * NTFS filetime, Unix time (s), or Unix time (ms).
+ * @param {number} num An integer timestamp.
+ * @return {?Date} A valid decoded timestamp, or null.
+ */
+ function decodeIntegerTimestamp(num) {
+ // We don't ask which format integer timestamps are in, because we can guess
+ // confidently by choosing the decode function that gives a sane result.
+ let result;
+ for (const decodeFunc
+ of [decodeNtfsFiletime, decodeUnixMilliseconds,
+ decodeUnixSeconds]) {
+ result = decodeFunc(num);
+ if (result && result >= MIN_SANE_DATE && result <= MAX_SANE_DATE) {
+ return result;
+ }
+ }
+ // For dates that fall outside the sane range, we cannot guess which format
+ // was used, but at least we can tell if the result should be in the far
+ // past or the far future, and return a result that is roughly equivalent.
+ return result && result < MIN_SANE_DATE ?
+ new Date(MIN_SANE_DATE) // Copy-before-return protects these two
+ :
+ new Date(MAX_SANE_DATE); // constants (since Date is mutable).
+ }
+
+ /**
+ * Decode a NTFS filetime timestamp with an epoch of year 1601.
+ * @param {number} hundredsOfNs Each tick measures 100 nanoseconds.
+ * @return {?Date}
+ */
+ function decodeNtfsFiletime(hundredsOfNs) {
+ return createValidDate(NTFS_EPOCH.valueOf() + (hundredsOfNs / 10000));
+ }
+
+ /**
+ * Decode a Unix timestamp which is counting milliseconds since 1970.
+ * @param {number} milliseconds
+ * @return {?Date}
+ */
+ function decodeUnixMilliseconds(milliseconds) {
+ return createValidDate(milliseconds);
+ }
+
+ /**
+ * Decode a Unix timestamp which is counting seconds since 1970.
+ * @param {number} seconds
+ * @return {?Date}
+ */
+ function decodeUnixSeconds(seconds) {
+ return createValidDate(seconds * 1000);
+ }
+
+ /**
+ * Decodes a timestamp string that is in ISO 8601 format.
+ * @param {string} str
+ * @return {?Date}
+ */
+ function decodeIso8601(str) {
+ // If no timezone is specified, appending 'Z' means we will parse as UTC.
+ // (If a timezone is already specified, appending 'Z' is simply invalid.)
+ // Using UTC as a default is predictable, using local time is unpredictable.
+ return createValidDate(str + 'Z') || createValidDate(str);
+ }
+
+ /**
+ * Constructs a date and returns it if it is valid, otherwise returns null.
+ * @param {*} arg Argument for constructing the date.
+ * @return {?Date} A valid date object, or null.
+ */
+ function createValidDate(arg) {
+ const date = new Date(arg);
+ return isNaN(date) ? null : date;
+ }
+
+ // #cr_define_end
+ // Public functions:
+ return {decodeTimestamp: decodeTimestamp};
+});
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/saml_timestamps_test.unitjs b/chromium/chrome/browser/resources/gaia_auth_host/saml_timestamps_test.unitjs
new file mode 100644
index 00000000000..2069bee233d
--- /dev/null
+++ b/chromium/chrome/browser/resources/gaia_auth_host/saml_timestamps_test.unitjs
@@ -0,0 +1,138 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+GEN_INCLUDE([
+ '//ui/webui/resources/js/cr.js',
+ 'saml_timestamps.js',
+]);
+
+function SamlTimestampsUnitTest() {}
+
+SamlTimestampsUnitTest.prototype = {
+ __proto__: testing.Test.prototype,
+
+ browsePreload: DUMMY_URL,
+
+ // No need to run these checks - see comment in SamlPasswordAttributesTest.
+ runAccessibilityChecks: false,
+};
+
+const ROUNDTRIP_DATA = [
+ '1980-01-01',
+ '1990-02-12',
+ '2000-03-13',
+ '2010-04-14',
+ '2020-05-25',
+ '2050-06-26',
+ '2100-07-27',
+ '3000-08-30',
+ '9999-12-31',
+];
+
+const NTFS_EPOCH = new Date('1601-01-01 UTC');
+
+const assertDecodesAs = function(expectedStr, encodedStr) {
+ const expectedMs = Date.parse(expectedStr);
+ const decodedMs = samlTimestamps.decodeTimestamp(encodedStr).valueOf();
+ assertEquals(expectedMs, decodedMs,
+ 'Expected "' + encodedStr + '" to be decoded as "' + expectedStr + '"');
+}
+
+const assertInvalid = function(encoded) {
+ assertEquals(null, samlTimestamps.decodeTimestamp(encoded),
+ 'Expected that "' + encoded + '" would not decode since it is invalid');
+}
+
+TEST_F('SamlTimestampsUnitTest', 'DecodeValidExamples', function() {
+ assertDecodesAs('2004-09-16T00:00Z', '1095292800'); // Unix time (s)
+ assertDecodesAs('2004-09-16T00:00Z', '1095292800000'); // Unix time (ms)
+
+ assertDecodesAs('2015-08-30T00:00Z', '130853664000000000'); // NTFS filetime
+
+ // ISO 8601
+ assertDecodesAs('2020-06-04T00:00Z', '2020-06-04');
+ assertDecodesAs('2020-06-04T12:00Z', '2020-06-04T12:00');
+ assertDecodesAs('2020-06-04T18:00Z', '2020-06-04T18:00Z');
+});
+
+TEST_F('SamlTimestampsUnitTest', 'RoundtripAsNTFS', function() {
+ for (let data of ROUNDTRIP_DATA) {
+ const ntfsTicks = (Date.parse(data) - NTFS_EPOCH.valueOf()) * 10000;
+ assertDecodesAs(data, ntfsTicks.toString());
+ }
+});
+
+TEST_F('SamlTimestampsUnitTest', 'RoundtripAsUnixSeconds', function() {
+ for (let data of ROUNDTRIP_DATA) {
+ const unixSeconds = Date.parse(data) / 1000;
+ assertDecodesAs(data, unixSeconds.toString());
+ }
+});
+
+TEST_F('SamlTimestampsUnitTest', 'RoundtripAsUnixMilliseconds', function() {
+ for (let data of ROUNDTRIP_DATA) {
+ const unixMilliseconds = Date.parse(data);
+ assertDecodesAs(data, unixMilliseconds.toString());
+ }
+});
+
+TEST_F('SamlTimestampsUnitTest', 'RoundtripAsIso8601', function() {
+ for (let data of ROUNDTRIP_DATA) {
+ assertDecodesAs(data, data);
+ }
+});
+
+TEST_F('SamlTimestampsUnitTest', 'Iso8601Timezones', function() {
+ // No time specified decodes as midnight UTC
+ assertDecodesAs('2020-06-04T00:00Z', '2020-06-04');
+ // No timezone specified decodes as UTC
+ assertDecodesAs('2020-06-04T12:00Z', '2020-06-04T12:00');
+
+ // There are different ways of specifying UTC
+ assertDecodesAs('2020-06-04T18:00Z', '2020-06-04T18:00Z');
+ assertDecodesAs('2020-06-04T18:00Z', '2020-06-04T18:00+0000');
+ assertDecodesAs('2020-06-04T18:00Z', '2020-06-04T18:00+00:00');
+
+ // Other timezones can also be specified
+ assertDecodesAs('2020-06-04T11:00Z', '2020-06-04T12:00+0100');
+ assertDecodesAs('2020-06-04T11:00Z', '2020-06-04T12:00+01:00');
+ assertDecodesAs('2020-06-04T13:00Z', '2020-06-04T12:00-0100');
+ assertDecodesAs('2020-06-04T13:00Z', '2020-06-04T12:00-01:00');
+});
+
+TEST_F('SamlTimestampsUnitTest', 'DecodeSpecialIntegers', function() {
+ // Zero or -1 could mean 1970 or 1601 - we can't guarantee we will decode it
+ // to the exact right value, but we must make sure it means the distant past.
+ assertTrue(samlTimestamps.decodeTimestamp('0') < new Date('2000-01-01'));
+ assertTrue(samlTimestamps.decodeTimestamp('-1') < new Date('2000-01-01'));
+
+ // Max signed int32 (2^31 - 1). Should decode as the year 2038:
+ assertDecodesAs('2038-01-19T03:14:07Z', '2147483647');
+
+ // Max signed int64 (2^63 - 1). Should decode to sometime in the very distant
+ // future, but it doesn't matter exactly when:
+ assertTrue(
+ samlTimestamps.decodeTimestamp('9223372036854775807')
+ > new Date('3000-01-01'));
+});
+
+TEST_F('SamlTimestampsUnitTest', 'DecodeInvalid', function() {
+ // Try some junk:
+ assertInvalid('');
+ assertInvalid('abc');
+ assertInvalid('01-02');
+
+ // These look like dates, but are not ISO 8601 so are rejected.
+ // For dates that are not in ISO 8601, we can't reliably know what was meant.
+ assertInvalid('01-02-03');
+ assertInvalid('99-01-01');
+ assertInvalid('01-02-2003');
+ assertInvalid('2020.01.01');
+ assertInvalid('2020/01/01');
+ assertInvalid('01 January 2020');
+ assertInvalid('2020-31-01'); // Almost, but there's no 31st month.
+ assertInvalid('2020-02-01 02:15'); // Almost, but missing the T separator
+ // Almost, but timezone must be described explicitly as +100:
+ assertInvalid('2020-02-01T02:15 (Central European Time)');
+});
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/scroll_helper_injected.js b/chromium/chrome/browser/resources/gaia_auth_host/scroll_helper_injected.js
new file mode 100644
index 00000000000..c952e2063c7
--- /dev/null
+++ b/chromium/chrome/browser/resources/gaia_auth_host/scroll_helper_injected.js
@@ -0,0 +1,51 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview
+ * -- WebviewScrollShadowsHelper --
+ *
+ * Sends scroll information from within the webview. This information is used
+ * to appropriately add classes to the webview in order to display shadows on
+ * top of it. The shadows show to the user if there is content hidden that
+ * could be seen if the user would scroll up/down.
+ */
+
+/* #export */ const WebviewScrollShadowsHelper = (function() {
+ function WebviewScrollShadowsHelper() {}
+
+ WebviewScrollShadowsHelper.prototype = {
+ init(channel) {
+ this.channel_ = channel;
+
+ window.addEventListener('scroll', this.sendScrollInfo_.bind(this));
+ window.addEventListener('resize', this.sendScrollInfo_.bind(this));
+ this.boundAttachResizeObserver_ = this.attachResizeObserver_.bind(this);
+ window.addEventListener('load', this.boundAttachResizeObserver_);
+ this.resizeObserver = new ResizeObserver(() => {
+ this.sendScrollInfo_();
+ });
+ },
+
+ // Observe when document.body changes in size.
+ attachResizeObserver_(event) {
+ this.resizeObserver.observe(document.body);
+ window.removeEventListener(event.type, this.boundAttachResizeObserver_);
+ },
+
+ sendScrollInfo_(event) {
+ this.channel_.send({
+ name: 'scrollInfo',
+ scrollTop: window.scrollY,
+ scrollHeight: document.body.scrollHeight
+ });
+ },
+ };
+
+ return WebviewScrollShadowsHelper;
+})();
+
+const WebviewScrollShadowsHelperConstructor = function() {
+ return new WebviewScrollShadowsHelper();
+};
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/webview_event_manager.js b/chromium/chrome/browser/resources/gaia_auth_host/webview_event_manager.js
index 1a47d04f5c7..0aa53b3c95b 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/webview_event_manager.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/webview_event_manager.js
@@ -11,8 +11,9 @@
/**
* Creates a new WebviewEventManager.
+ * @constructor
*/
-function WebviewEventManager() {
+/* #export */ function WebviewEventManager() {
this.unbindWebviewCleanupFunctions_ = [];
}
@@ -20,12 +21,11 @@ WebviewEventManager.prototype = {
/**
* Adds a EventListener to |eventTarget| and adds a clean-up function so we
* can remove the listener in unbindFromWebview.
- * @param {Object} webview the object to add the listener to
+ * @param {Object} eventTarget the object to add the listener to
* @param {string} type the event type
* @param {Function} listener the event listener
- * @private
*/
- addEventListener: function(eventTarget, type, listener) {
+ addEventListener(eventTarget, type, listener) {
eventTarget.addEventListener(type, listener);
this.unbindWebviewCleanupFunctions_.push(
eventTarget.removeEventListener.bind(eventTarget, type, listener));
@@ -34,13 +34,14 @@ WebviewEventManager.prototype = {
/**
* Adds a listener to |webRequestEvent| and adds a clean-up function so we can
* remove the listener in unbindFromWebview.
- * @param {Object} webRequestEvent the object to add the listener to
- * @param {string} type the event type
+ * @param {Object} webRequestEvent the object to add the listener to.
* @param {Function} listener the event listener
- * @private
+ * @param {RequestFilter} filter the object describing filters to apply to
+ * webRequest events.
+ * @param {?Object} extraInfoSpec the object to pass additional event-specific
+ * instructions.
*/
- addWebRequestEventListener: function(
- webRequestEvent, listener, filter, extraInfoSpec) {
+ addWebRequestEventListener(webRequestEvent, listener, filter, extraInfoSpec) {
webRequestEvent.addListener(listener, filter, extraInfoSpec);
this.unbindWebviewCleanupFunctions_.push(
webRequestEvent.removeListener.bind(webRequestEvent, listener));
@@ -48,9 +49,8 @@ WebviewEventManager.prototype = {
/**
* Unbinds this Authenticator from the currently bound webview.
- * @private
*/
- removeAllListeners: function() {
+ removeAllListeners() {
for (let i = 0; i < this.unbindWebviewCleanupFunctions_.length; i++) {
this.unbindWebviewCleanupFunctions_[i]();
}
diff --git a/chromium/chrome/browser/resources/gaia_auth_host/webview_saml_injected.js b/chromium/chrome/browser/resources/gaia_auth_host/webview_saml_injected.js
index e148e9135f2..dfa9d50585e 100644
--- a/chromium/chrome/browser/resources/gaia_auth_host/webview_saml_injected.js
+++ b/chromium/chrome/browser/resources/gaia_auth_host/webview_saml_injected.js
@@ -3,4 +3,5 @@
// found in the LICENSE file.
// <include src="post_message_channel.js">
+// <include src="scroll_helper_injected.js">
// <include src="saml_injected.js">
diff --git a/chromium/chrome/browser/resources/history/.eslintrc.js b/chromium/chrome/browser/resources/history/.eslintrc.js
new file mode 100644
index 00000000000..0b691a4dcc5
--- /dev/null
+++ b/chromium/chrome/browser/resources/history/.eslintrc.js
@@ -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.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/history/BUILD.gn b/chromium/chrome/browser/resources/history/BUILD.gn
index fef23d8ad50..a7e687ec7d2 100644
--- a/chromium/chrome/browser/resources/history/BUILD.gn
+++ b/chromium/chrome/browser/resources/history/BUILD.gn
@@ -5,6 +5,7 @@
import("//chrome/common/features.gni")
import("//third_party/closure_compiler/compile_js.gni")
import("//tools/grit/grit_rule.gni")
+import("//tools/polymer/polymer.gni")
import("../optimize_webui.gni")
if (optimize_webui) {
@@ -13,41 +14,40 @@ if (optimize_webui) {
optimize_webui("build") {
host = "history"
- html_in_files = [
- "app.html",
- "lazy_load.html",
- ]
- html_out_files = [
- "app.vulcanized.html",
- "lazy_load.vulcanized.html",
+ js_module_in_files = [
+ "history.js",
+ "lazy_load.js",
]
input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir)
js_out_files = [
- "app.crisper.js",
- "lazy_load.crisper.js",
+ "history.rollup.js",
+ "lazy_load.rollup.js",
+ "shared.rollup.js",
]
deps = [
":unpak",
+ "../../../../ui/webui/resources:modulize",
]
- excludes = [
- "chrome://resources/html/util.html",
- "constants.html",
- ]
+ excludes = [ "chrome://resources/js/cr.m.js" ]
}
unpak("unpak") {
pak_file = history_pak_file
out_folder = unpak_folder
- deps = [
- ":flattened_resources",
- ]
+ deps = [ ":flattened_resources" ]
}
grit("flattened_resources") {
source = "history_resources.grd"
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
+
+ deps = [ ":polymer3_elements" ]
defines = chrome_grit_defines
outputs = [
"grit/history_resources.h",
@@ -60,17 +60,18 @@ if (optimize_webui) {
}
js_type_check("closure_compile") {
+ is_polymer3 = true
deps = [
":app",
":browser_service",
":constants",
":externs",
- ":history",
":history_item",
":history_list",
":history_toolbar",
":query_manager",
":router",
+ ":searched_label",
":side_bar",
":synced_device_card",
":synced_device_manager",
@@ -82,15 +83,13 @@ js_library("constants") {
js_library("browser_service") {
deps = [
+ ":constants",
":externs",
- "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:cr.m",
]
}
js_library("externs") {
- deps = [
- ":constants",
- ]
}
js_library("history_item") {
@@ -98,10 +97,10 @@ js_library("history_item") {
":browser_service",
":constants",
":externs",
- "//ui/webui/resources/js:icon",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:util",
- "//ui/webui/resources/js/cr/ui:focus_row_behavior",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:icon.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
]
}
@@ -111,15 +110,17 @@ js_library("history_list") {
":constants",
":externs",
":history_item",
- "//third_party/polymer/v1_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer-extracted",
- "//third_party/polymer/v1_0/components-chromium/iron-list:iron-list-extracted",
- "//third_party/polymer/v1_0/components-chromium/iron-scroll-threshold:iron-scroll-threshold-extracted",
- "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
- "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:util",
- "//ui/webui/resources/js:web_ui_listener_behavior",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
+ "//third_party/polymer/v3_0/components-chromium/iron-list:iron-list",
+ "//third_party/polymer/v3_0/components-chromium/iron-scroll-threshold:iron-scroll-threshold",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:util.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
]
}
@@ -127,22 +128,12 @@ js_library("history_toolbar") {
deps = [
":constants",
":externs",
- "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar",
- "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar_selection_overlay",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:util",
- ]
-}
-
-js_library("history") {
- deps = [
- ":app",
- ":constants",
- ":externs",
- "//ui/webui/resources/js:icon",
- "//ui/webui/resources/js:load_time_data",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar.m",
+ "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar_selection_overlay.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:util.m",
]
- externs_list = [ "$externs_path/chrome_send.js" ]
}
js_library("app") {
@@ -154,9 +145,11 @@ js_library("app") {
":side_bar",
":synced_device_card",
":synced_device_manager",
- "//ui/webui/resources/cr_elements/cr_drawer:cr_drawer",
- "//ui/webui/resources/js:find_shortcut_behavior",
- "//ui/webui/resources/js:web_ui_listener_behavior",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_drawer:cr_drawer.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:find_shortcut_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
]
}
@@ -165,6 +158,7 @@ js_library("query_manager") {
":browser_service",
":externs",
":router",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
}
@@ -172,16 +166,25 @@ js_library("router") {
deps = [
":constants",
":externs",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
+js_library("searched_label") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:util.m",
]
}
js_library("side_bar") {
deps = [
":browser_service",
- "//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted",
- "//third_party/polymer/v1_0/components-chromium/iron-selector:iron-selector-extracted",
- "//third_party/polymer/v1_0/components-chromium/paper-ripple:paper-ripple-extracted",
- "//ui/webui/resources/js:load_time_data",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior",
+ "//third_party/polymer/v3_0/components-chromium/iron-selector:iron-selector",
+ "//third_party/polymer/v3_0/components-chromium/paper-ripple:paper-ripple",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:load_time_data.m",
]
}
@@ -190,9 +193,10 @@ js_library("synced_device_card") {
":browser_service",
":constants",
":externs",
- "//ui/webui/resources/js:icon",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js/cr/ui:focus_row",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:icon.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_row.m",
]
}
@@ -200,8 +204,86 @@ js_library("synced_device_manager") {
deps = [
":browser_service",
":synced_device_card",
- "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
- "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render",
- "//ui/webui/resources/js/cr/ui:focus_grid",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_grid.m",
+ ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":app_module",
+ ":history_item_module",
+ ":history_list_module",
+ ":history_toolbar_module",
+ ":router_module",
+ ":shared_style_module",
+ ":shared_vars_module",
+ ":side_bar_module",
+ ":synced_device_card_module",
+ ":synced_device_manager_module",
]
}
+
+polymer_modulizer("app") {
+ html_file = "app.html"
+ js_file = "app.js"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("history_item") {
+ html_file = "history_item.html"
+ js_file = "history_item.js"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("history_list") {
+ html_file = "history_list.html"
+ js_file = "history_list.js"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("history_toolbar") {
+ html_file = "history_toolbar.html"
+ js_file = "history_toolbar.js"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("router") {
+ html_file = "router.html"
+ js_file = "router.js"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("shared_style") {
+ html_file = "shared_style.html"
+ js_file = "shared_style.js"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("shared_vars") {
+ html_file = "shared_vars.html"
+ js_file = "shared_vars.js"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("side_bar") {
+ html_file = "side_bar.html"
+ js_file = "side_bar.js"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("synced_device_card") {
+ html_file = "synced_device_card.html"
+ js_file = "synced_device_card.js"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("synced_device_manager") {
+ html_file = "synced_device_manager.html"
+ js_file = "synced_device_manager.js"
+ html_type = "v3-ready"
+}
diff --git a/chromium/chrome/browser/resources/history/OWNERS b/chromium/chrome/browser/resources/history/OWNERS
index 51529300ec1..5e21905007d 100644
--- a/chromium/chrome/browser/resources/history/OWNERS
+++ b/chromium/chrome/browser/resources/history/OWNERS
@@ -1,4 +1,3 @@
calamity@chromium.org
-dbeam@chromium.org
# COMPONENT: UI>Browser>History
diff --git a/chromium/chrome/browser/resources/history/app.html b/chromium/chrome/browser/resources/history/app.html
index e579b8e6f39..0afd8eb4134 100644
--- a/chromium/chrome/browser/resources/history/app.html
+++ b/chromium/chrome/browser/resources/history/app.html
@@ -1,24 +1,3 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/html/find_shortcut_behavior.html">
-<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-media-query/iron-media-query.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-scroll-target-behavior/iron-scroll-target-behavior.html">
-<link rel="import" href="history_list.html">
-<link rel="import" href="history_toolbar.html">
-<link rel="import" href="query_manager.html">
-<link rel="import" href="router.html">
-<link rel="import" href="shared_style.html">
-<link rel="import" href="side_bar.html">
-<link rel="import" href="strings.html">
-
-<!-- Lazy loaded: history-synced-device-manager, cr-drawer. -->
-
-<dom-module id="history-app">
- <template>
<style include="cr-shared-style shared-style">
:host {
color: var(--cr-primary-text-color);
@@ -53,8 +32,9 @@
}
</style>
<history-query-manager query-state="{{queryState_}}"
- query-result="[[queryResult_]]"
- router="[[$$('#router')]]">
+ query-result="{{queryResult_}}"
+ router="[[$$('#router')]]"
+ on-query-finished="onQueryFinished_">
</history-query-manager>
<history-router id="router"
selected-page="{{selectedPage_}}"
@@ -115,6 +95,3 @@
<iron-media-query query="(max-width: 1023px)"
query-matches="{{hasDrawer_}}">
</iron-media-query>
- </template>
- <script src="app.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/app.js b/chromium/chrome/browser/resources/history/app.js
index bc90a5d2e0e..9fd5e282cf4 100644
--- a/chromium/chrome/browser/resources/history/app.js
+++ b/chromium/chrome/browser/resources/history/app.js
@@ -2,21 +2,45 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-/**
- * @typedef {{
- * managed: boolean,
- * otherFormsOfHistory: boolean,
- * }}
- */
-let FooterInfo;
-
-cr.define('history', function() {
+import {Polymer, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import 'chrome://resources/cr_elements/shared_style_css.m.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {FindShortcutBehavior} from 'chrome://resources/js/find_shortcut_behavior.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
+import 'chrome://resources/polymer/v3_0/iron-media-query/iron-media-query.js';
+import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
+import {IronScrollTargetBehavior} from 'chrome://resources/polymer/v3_0/iron-scroll-target-behavior/iron-scroll-target-behavior.js';
+import {BrowserService} from './browser_service.js';
+import {HistoryPageViewHistogram} from './constants.js';
+import {ForeignSession, QueryResult, QueryState} from './externs.js';
+import './history_list.js';
+import './history_toolbar.js';
+import './query_manager.js';
+import './router.js';
+import './shared_style.js';
+import {FooterInfo} from './side_bar.js';
+import './strings.js';
+
let lazyLoadPromise = null;
- function ensureLazyLoaded() {
+ export function ensureLazyLoaded() {
if (!lazyLoadPromise) {
- lazyLoadPromise = new Promise(function(resolve, reject) {
- Polymer.Base.importHref('lazy_load.html', resolve, reject, true);
- });
+ const script = document.createElement('script');
+ script.type = 'module';
+ script.src = './lazy_load.js';
+ document.body.appendChild(script);
+
+ lazyLoadPromise = Promise.all([
+ customElements.whenDefined('history-synced-device-manager'),
+ customElements.whenDefined('cr-action-menu'),
+ customElements.whenDefined('cr-button'),
+ customElements.whenDefined('cr-checkbox'),
+ customElements.whenDefined('cr-dialog'),
+ customElements.whenDefined('cr-drawer'),
+ customElements.whenDefined('cr-icon-button'),
+ customElements.whenDefined('cr-toolbar-selection-overlay'),
+ ]);
}
return lazyLoadPromise;
}
@@ -26,7 +50,7 @@ cr.define('history', function() {
// navigation. Note: This method is *not* re-entrant. Every call to it, will
// re-add listeners on |document|. It's up to callers to ensure this is only
// called once.
- function listenForPrivilegedLinkClicks() {
+ export function listenForPrivilegedLinkClicks() {
['click', 'auxclick'].forEach(function(eventName) {
document.addEventListener(eventName, function(e) {
// Ignore buttons other than left and middle.
@@ -48,9 +72,9 @@ cr.define('history', function() {
// Fallback if Event.path is not available.
let el = e.target;
- if (!anchor && el.nodeType == Node.ELEMENT_NODE &&
+ if (!anchor && el.nodeType === Node.ELEMENT_NODE &&
el.webkitMatchesSelector('A, A *')) {
- while (el.tagName != 'A') {
+ while (el.tagName !== 'A') {
el = el.parentElement;
}
anchor = el;
@@ -61,9 +85,9 @@ cr.define('history', function() {
}
anchor = /** @type {!HTMLAnchorElement} */ (anchor);
- if ((anchor.protocol == 'file:' || anchor.protocol == 'about:') &&
- (e.button == 0 || e.button == 1)) {
- history.BrowserService.getInstance().navigateToUrl(
+ if ((anchor.protocol === 'file:' || anchor.protocol === 'about:') &&
+ (e.button === 0 || e.button === 1)) {
+ BrowserService.getInstance().navigateToUrl(
anchor.href, anchor.target, /** @type {!MouseEvent} */ (e));
e.preventDefault();
}
@@ -71,378 +95,388 @@ cr.define('history', function() {
});
}
- return {
- ensureLazyLoaded: ensureLazyLoaded,
- listenForPrivilegedLinkClicks: listenForPrivilegedLinkClicks,
- };
-});
-
-Polymer({
- is: 'history-app',
-
- behaviors: [
- FindShortcutBehavior,
- Polymer.IronScrollTargetBehavior,
- WebUIListenerBehavior,
- ],
-
- properties: {
- // The id of the currently selected page.
- selectedPage_: {
- type: String,
- observer: 'selectedPageChanged_',
+ Polymer({
+ is: 'history-app',
+
+ _template: html`{__html_template__}`,
+
+ behaviors: [
+ FindShortcutBehavior,
+ IronScrollTargetBehavior,
+ WebUIListenerBehavior,
+ ],
+
+ properties: {
+ // The id of the currently selected page.
+ selectedPage_: {
+ type: String,
+ observer: 'selectedPageChanged_',
+ },
+
+ /** @type {!QueryResult} */
+ queryResult_: {
+ type: Object,
+ value() {
+ return {
+ info: null,
+ results: null,
+ sessionList: null,
+ };
+ }
+ },
+
+ isUserSignedIn_: {
+ type: Boolean,
+ // Updated on synced-device-manager attach by chrome.sending
+ // 'otherDevicesInitialized'.
+ value: loadTimeData.getBoolean('isUserSignedIn'),
+ },
+
+ /** @private */
+ pendingDelete_: Boolean,
+
+ toolbarShadow_: {
+ type: Boolean,
+ reflectToAttribute: true,
+ notify: true,
+ },
+
+ showMenuPromo_: {
+ type: Boolean,
+ value() {
+ return loadTimeData.getBoolean('showMenuPromo');
+ },
+ },
+
+ /** @type {!QueryState} */
+ queryState_: Object,
+
+ // True if the window is narrow enough for the page to have a drawer.
+ hasDrawer_: {
+ type: Boolean,
+ observer: 'hasDrawerChanged_',
+ },
+
+ /** @type {FooterInfo} */
+ footerInfo: {
+ type: Object,
+ value() {
+ return {
+ managed: loadTimeData.getBoolean('isManaged'),
+ otherFormsOfHistory: false,
+ };
+ },
+ },
+ },
+
+ listeners: {
+ 'cr-toolbar-menu-promo-close': 'onCrToolbarMenuPromoClose_',
+ 'cr-toolbar-menu-promo-shown': 'onCrToolbarMenuPromoShown_',
+ 'cr-toolbar-menu-tap': 'onCrToolbarMenuTap_',
+ 'delete-selected': 'deleteSelected',
+ 'history-checkbox-select': 'checkboxSelected',
+ 'history-close-drawer': 'closeDrawer_',
+ 'history-view-changed': 'historyViewChanged_',
+ 'unselect-all': 'unselectAll',
+ },
+
+ /** @private {?function(!Event)} */
+ boundOnKeyDown_: null,
+
+ /** @private {?BrowserService} */
+ browserService_: null,
+
+ /** @override */
+ created() {
+ listenForPrivilegedLinkClicks();
+ },
+
+ /** @override */
+ attached() {
+ this.boundOnKeyDown_ = e => this.onKeyDown_(e);
+ document.addEventListener('keydown', this.boundOnKeyDown_);
+ this.addWebUIListener(
+ 'sign-in-state-changed',
+ signedIn => this.onSignInStateChanged_(signedIn));
+ this.addWebUIListener(
+ 'has-other-forms-changed',
+ hasOtherForms => this.onHasOtherFormsChanged_(hasOtherForms));
+ this.addWebUIListener(
+ 'foreign-sessions-changed',
+ sessionList => this.setForeignSessions_(sessionList));
+ this.browserService_ = BrowserService.getInstance();
+ /** @type {!HistoryQueryManagerElement} */ (
+ this.$$('history-query-manager'))
+ .initialize();
+ this.browserService_.getForeignSessions().then(
+ sessionList => this.setForeignSessions_(sessionList));
+ },
+
+ /** @override */
+ detached() {
+ document.removeEventListener('keydown', this.boundOnKeyDown_);
+ this.boundOnKeyDown_ = null;
+ },
+
+ /** @private */
+ onFirstRender_() {
+ setTimeout(() => {
+ this.browserService_.recordTime(
+ 'History.ResultsRenderedTime', window.performance.now());
+ });
+
+ // Focus the search field on load. Done here to ensure the history page
+ // is rendered before we try to take focus.
+ const searchField =
+ /** @type {HistoryToolbarElement} */ (this.$.toolbar).searchField;
+ if (!searchField.narrow) {
+ searchField.getSearchInput().focus();
+ }
+
+ // Lazily load the remainder of the UI.
+ ensureLazyLoaded().then(function() {
+ window.requestIdleCallback(function() {
+ document.fonts.load('bold 12px Roboto');
+ });
+ });
},
- /** @type {!QueryResult} */
- queryResult_: {
- type: Object,
- value: function() {
- return {
- info: null,
- results: null,
- sessionList: null,
- };
+ /** Overridden from IronScrollTargetBehavior */
+ _scrollHandler() {
+ if (this.scrollTarget) {
+ this.toolbarShadow_ = this.scrollTarget.scrollTop !== 0;
}
},
- isUserSignedIn_: {
- type: Boolean,
- // Updated on synced-device-manager attach by chrome.sending
- // 'otherDevicesInitialized'.
- value: loadTimeData.getBoolean('isUserSignedIn'),
+ /** @private */
+ onCrToolbarMenuPromoClose_() {
+ this.showMenuPromo_ = false;
},
/** @private */
- pendingDelete_: Boolean,
+ onCrToolbarMenuPromoShown_() {
+ this.browserService_.menuPromoShown();
+ },
- toolbarShadow_: {
- type: Boolean,
- reflectToAttribute: true,
- notify: true,
+ /** @private */
+ onCrToolbarMenuTap_() {
+ const drawer = /** @type {!CrDrawerElement} */ (this.$.drawer.get());
+ drawer.toggle();
+ this.showMenuPromo_ = false;
},
- showMenuPromo_: {
- type: Boolean,
- value: function() {
- return loadTimeData.getBoolean('showMenuPromo');
- },
+ /**
+ * Listens for history-item being selected or deselected (through checkbox)
+ * and changes the view of the top toolbar.
+ */
+ checkboxSelected() {
+ const toolbar = /** @type {HistoryToolbarElement} */ (this.$.toolbar);
+ toolbar.count = /** @type {HistoryListElement} */ (this.$.history)
+ .getSelectedItemCount();
},
- /** @type {!QueryState} */
- queryState_: Object,
+ selectOrUnselectAll() {
+ const list = /** @type {HistoryListElement} */ (this.$.history);
+ const toolbar = /** @type {HistoryToolbarElement} */ (this.$.toolbar);
+ list.selectOrUnselectAll();
+ toolbar.count = list.getSelectedItemCount();
+ },
- // True if the window is narrow enough for the page to have a drawer.
- hasDrawer_: {
- type: Boolean,
- observer: 'hasDrawerChanged_',
+ /**
+ * Listens for call to cancel selection and loops through all items to set
+ * checkbox to be unselected.
+ * @private
+ */
+ unselectAll() {
+ const list = /** @type {HistoryListElement} */ (this.$.history);
+ const toolbar = /** @type {HistoryToolbarElement} */ (this.$.toolbar);
+ list.unselectAllItems();
+ toolbar.count = 0;
},
- /** @type {FooterInfo} */
- footerInfo: {
- type: Object,
- value: function() {
- return {
- managed: loadTimeData.getBoolean('isManaged'),
- otherFormsOfHistory: false,
- };
- },
+ deleteSelected() {
+ this.$.history.deleteSelectedWithPrompt();
},
- },
-
- listeners: {
- 'cr-toolbar-menu-promo-close': 'onCrToolbarMenuPromoClose_',
- 'cr-toolbar-menu-promo-shown': 'onCrToolbarMenuPromoShown_',
- 'cr-toolbar-menu-tap': 'onCrToolbarMenuTap_',
- 'delete-selected': 'deleteSelected',
- 'history-checkbox-select': 'checkboxSelected',
- 'history-close-drawer': 'closeDrawer_',
- 'history-view-changed': 'historyViewChanged_',
- 'unselect-all': 'unselectAll',
- },
-
- /** @private {?function(!Event)} */
- boundOnKeyDown_: null,
-
- /** @override */
- created: function() {
- history.listenForPrivilegedLinkClicks();
- },
-
- /** @override */
- attached: function() {
- this.boundOnKeyDown_ = e => this.onKeyDown_(e);
- document.addEventListener('keydown', this.boundOnKeyDown_);
- this.addWebUIListener(
- 'sign-in-state-changed',
- signedIn => this.onSignInStateChanged_(signedIn));
- this.addWebUIListener(
- 'has-other-forms-changed',
- hasOtherForms => this.onHasOtherFormsChanged_(hasOtherForms));
- history.BrowserService.getInstance().historyLoaded();
- },
-
- /** @override */
- detached: function() {
- document.removeEventListener('keydown', this.boundOnKeyDown_);
- this.boundOnKeyDown_ = null;
- },
-
- onFirstRender: function() {
- setTimeout(function() {
- history.BrowserService.getInstance().recordTime(
- 'History.ResultsRenderedTime', window.performance.now());
- });
- // Focus the search field on load. Done here to ensure the history page
- // is rendered before we try to take focus.
- const searchField =
- /** @type {HistoryToolbarElement} */ (this.$.toolbar).searchField;
- if (!searchField.narrow) {
- searchField.getSearchInput().focus();
- }
+ /** @private */
+ onQueryFinished_() {
+ const list = /** @type {HistoryListElement} */ (this.$['history']);
+ list.historyResult(
+ assert(this.queryResult_.info), assert(this.queryResult_.results));
+ if (document.body.classList.contains('loading')) {
+ document.body.classList.remove('loading');
+ this.onFirstRender_();
+ }
+ },
+
+ /**
+ * @param {!KeyboardEvent} e
+ * @private
+ */
+ onKeyDown_(e) {
+ if ((e.key === 'Delete' || e.key === 'Backspace') &&
+ !(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)) {
+ this.onDeleteCommand_();
+ return;
+ }
- // Lazily load the remainder of the UI.
- history.ensureLazyLoaded().then(function() {
- window.requestIdleCallback(function() {
- document.fonts.load('bold 12px Roboto');
+ if (e.key === 'a' && !e.altKey && !e.shiftKey) {
+ let hasTriggerModifier = e.ctrlKey && !e.metaKey;
+ // <if expr="is_macosx">
+ hasTriggerModifier = !e.ctrlKey && e.metaKey;
+ // </if>
+ if (hasTriggerModifier && this.onSelectAllCommand_()) {
+ e.preventDefault();
+ }
+ }
+ },
+
+ /** @private */
+ onDeleteCommand_() {
+ if (this.$.toolbar.count === 0 || this.pendingDelete_) {
+ return;
+ }
+ this.deleteSelected();
+ },
+
+ /**
+ * @return {boolean} Whether the command was actually triggered.
+ * @private
+ */
+ onSelectAllCommand_() {
+ if (this.$.toolbar.searchField.isSearchFocused() ||
+ this.syncedTabsSelected_(this.selectedPage_)) {
+ return false;
+ }
+ this.selectOrUnselectAll();
+ return true;
+ },
+
+ /**
+ * @param {!Array<!ForeignSession>} sessionList Array of objects describing
+ * the sessions from other devices.
+ * @private
+ */
+ setForeignSessions_(sessionList) {
+ this.set('queryResult_.sessionList', sessionList);
+ },
+
+ /**
+ * Update sign in state of synced device manager after user logs in or out.
+ * @param {boolean} isUserSignedIn
+ * @private
+ */
+ onSignInStateChanged_(isUserSignedIn) {
+ this.isUserSignedIn_ = isUserSignedIn;
+ },
+
+ /**
+ * Update sign in state of synced device manager after user logs in or out.
+ * @param {boolean} hasOtherForms
+ * @private
+ */
+ onHasOtherFormsChanged_(hasOtherForms) {
+ this.set('footerInfo.otherFormsOfHistory', hasOtherForms);
+ },
+
+ /**
+ * @param {string} selectedPage
+ * @return {boolean}
+ * @private
+ */
+ syncedTabsSelected_(selectedPage) {
+ return selectedPage === 'syncedTabs';
+ },
+
+ /**
+ * @param {boolean} querying
+ * @param {boolean} incremental
+ * @param {string} searchTerm
+ * @return {boolean} Whether a loading spinner should be shown (implies the
+ * backend is querying a new search term).
+ * @private
+ */
+ shouldShowSpinner_(querying, incremental, searchTerm) {
+ return querying && !incremental && searchTerm !== '';
+ },
+
+ /** @private */
+ selectedPageChanged_() {
+ this.unselectAll();
+ this.historyViewChanged_();
+ },
+
+ /** @private */
+ historyViewChanged_() {
+ // This allows the synced-device-manager to render so that it can be set
+ // as the scroll target.
+ requestAnimationFrame(() => {
+ this._scrollHandler();
});
- });
- },
+ this.recordHistoryPageView_();
+ },
- /** Overridden from IronScrollTargetBehavior */
- _scrollHandler: function() {
- if (this.scrollTarget) {
- this.toolbarShadow_ = this.scrollTarget.scrollTop != 0;
- }
- },
-
- /** @private */
- onCrToolbarMenuPromoClose_: function() {
- this.showMenuPromo_ = false;
- },
-
- /** @private */
- onCrToolbarMenuPromoShown_: function() {
- history.BrowserService.getInstance().menuPromoShown();
- },
-
- /** @private */
- onCrToolbarMenuTap_: function() {
- const drawer = /** @type {!CrDrawerElement} */ (this.$.drawer.get());
- drawer.toggle();
- this.showMenuPromo_ = false;
- },
-
- /**
- * Listens for history-item being selected or deselected (through checkbox)
- * and changes the view of the top toolbar.
- */
- checkboxSelected: function() {
- const toolbar = /** @type {HistoryToolbarElement} */ (this.$.toolbar);
- toolbar.count = /** @type {HistoryListElement} */ (this.$.history)
- .getSelectedItemCount();
- },
-
- selectOrUnselectAll: function() {
- const list = /** @type {HistoryListElement} */ (this.$.history);
- const toolbar = /** @type {HistoryToolbarElement} */ (this.$.toolbar);
- list.selectOrUnselectAll();
- toolbar.count = list.getSelectedItemCount();
- },
-
- /**
- * Listens for call to cancel selection and loops through all items to set
- * checkbox to be unselected.
- * @private
- */
- unselectAll: function() {
- const list = /** @type {HistoryListElement} */ (this.$.history);
- const toolbar = /** @type {HistoryToolbarElement} */ (this.$.toolbar);
- list.unselectAllItems();
- toolbar.count = 0;
- },
-
- deleteSelected: function() {
- this.$.history.deleteSelectedWithPrompt();
- },
-
- /**
- * @param {HistoryQuery} info An object containing information about the
- * query.
- * @param {!Array<HistoryEntry>} results A list of results.
- */
- historyResult: function(info, results) {
- this.set('queryState_.querying', false);
- this.set('queryResult_.info', info);
- this.set('queryResult_.results', results);
- const list = /** @type {HistoryListElement} */ (this.$['history']);
- list.historyResult(info, results);
- },
-
- /**
- * @param {!KeyboardEvent} e
- * @private
- */
- onKeyDown_: function(e) {
- if ((e.key === 'Delete' || e.key === 'Backspace') &&
- !(e.altKey || e.ctrlKey || e.metaKey || e.shiftKey)) {
- this.onDeleteCommand_();
- return;
- }
+ /** @private */
+ hasDrawerChanged_() {
+ const drawer =
+ /** @type {?CrDrawerElement} */ (this.$.drawer.getIfExists());
+ if (!this.hasDrawer_ && drawer && drawer.open) {
+ drawer.cancel();
+ }
+ },
- if (e.key === 'a' && !e.altKey && !e.shiftKey) {
- let hasTriggerModifier = e.ctrlKey && !e.metaKey;
- // <if expr="is_macosx">
- hasTriggerModifier = !e.ctrlKey && e.metaKey;
- // </if>
- if (hasTriggerModifier) {
- this.onSelectAllCommand_();
- e.preventDefault();
+ /**
+ * This computed binding is needed to make the iron-pages selector update
+ * when the synced-device-manager is instantiated for the first time.
+ * Otherwise the fallback selection will continue to be used after the
+ * corresponding item is added as a child of iron-pages.
+ * @param {string} selectedPage
+ * @param {Array} items
+ * @return {string}
+ * @private
+ */
+ getSelectedPage_(selectedPage, items) {
+ return selectedPage;
+ },
+
+ /** @private */
+ closeDrawer_() {
+ const drawer = this.$.drawer.get();
+ if (drawer && drawer.open) {
+ drawer.close();
}
- }
- },
+ },
- /** @private */
- onDeleteCommand_: function() {
- if (this.$.toolbar.count == 0 || this.pendingDelete_) {
- return;
- }
- this.deleteSelected();
- },
-
- /** @private */
- onSelectAllCommand_: function() {
- if (this.$.toolbar.searchField.isSearchFocused() ||
- this.syncedTabsSelected_(this.selectedPage_)) {
- return;
- }
- this.selectOrUnselectAll();
- },
-
- /**
- * @param {!Array<!ForeignSession>} sessionList Array of objects describing
- * the sessions from other devices.
- */
- setForeignSessions: function(sessionList) {
- this.set('queryResult_.sessionList', sessionList);
- },
-
- /**
- * Update sign in state of synced device manager after user logs in or out.
- * @param {boolean} isUserSignedIn
- * @private
- */
- onSignInStateChanged_: function(isUserSignedIn) {
- this.isUserSignedIn_ = isUserSignedIn;
- },
-
- /**
- * Update sign in state of synced device manager after user logs in or out.
- * @param {boolean} hasOtherForms
- * @private
- */
- onHasOtherFormsChanged_: function(hasOtherForms) {
- this.set('footerInfo.otherFormsOfHistory', hasOtherForms);
- },
-
- /**
- * @param {string} selectedPage
- * @return {boolean}
- * @private
- */
- syncedTabsSelected_: function(selectedPage) {
- return selectedPage == 'syncedTabs';
- },
-
- /**
- * @param {boolean} querying
- * @param {boolean} incremental
- * @param {string} searchTerm
- * @return {boolean} Whether a loading spinner should be shown (implies the
- * backend is querying a new search term).
- * @private
- */
- shouldShowSpinner_: function(querying, incremental, searchTerm) {
- return querying && !incremental && searchTerm != '';
- },
-
- /** @private */
- selectedPageChanged_: function() {
- this.unselectAll();
- this.historyViewChanged_();
- },
-
- /** @private */
- historyViewChanged_: function() {
- // This allows the synced-device-manager to render so that it can be set as
- // the scroll target.
- requestAnimationFrame(() => {
- this._scrollHandler();
- });
- this.recordHistoryPageView_();
- },
-
- /** @private */
- hasDrawerChanged_: function() {
- const drawer =
- /** @type {?CrDrawerElement} */ (this.$.drawer.getIfExists());
- if (!this.hasDrawer_ && drawer && drawer.open) {
- drawer.cancel();
- }
- },
-
- /**
- * This computed binding is needed to make the iron-pages selector update when
- * the synced-device-manager is instantiated for the first time. Otherwise the
- * fallback selection will continue to be used after the corresponding item is
- * added as a child of iron-pages.
- * @param {string} selectedPage
- * @param {Array} items
- * @return {string}
- * @private
- */
- getSelectedPage_: function(selectedPage, items) {
- return selectedPage;
- },
-
- /** @private */
- closeDrawer_: function() {
- const drawer = this.$.drawer.get();
- if (drawer && drawer.open) {
- drawer.close();
- }
- },
-
- /** @private */
- recordHistoryPageView_: function() {
- let histogramValue = HistoryPageViewHistogram.END;
- switch (this.selectedPage_) {
- case 'syncedTabs':
- histogramValue = this.isUserSignedIn_ ?
- HistoryPageViewHistogram.SYNCED_TABS :
- HistoryPageViewHistogram.SIGNIN_PROMO;
- break;
- default:
- histogramValue = HistoryPageViewHistogram.HISTORY;
- break;
- }
+ /** @private */
+ recordHistoryPageView_() {
+ let histogramValue = HistoryPageViewHistogram.END;
+ switch (this.selectedPage_) {
+ case 'syncedTabs':
+ histogramValue = this.isUserSignedIn_ ?
+ HistoryPageViewHistogram.SYNCED_TABS :
+ HistoryPageViewHistogram.SIGNIN_PROMO;
+ break;
+ default:
+ histogramValue = HistoryPageViewHistogram.HISTORY;
+ break;
+ }
- history.BrowserService.getInstance().recordHistogram(
- 'History.HistoryPageView', histogramValue,
- HistoryPageViewHistogram.END);
- },
+ this.browserService_.recordHistogram(
+ 'History.HistoryPageView', histogramValue,
+ HistoryPageViewHistogram.END);
+ },
- // Override FindShortcutBehavior methods.
- handleFindShortcut: function(modalContextOpen) {
- if (modalContextOpen) {
- return false;
- }
- this.$.toolbar.searchField.showAndFocus();
- return true;
- },
-
- // Override FindShortcutBehavior methods.
- searchInputHasFocus: function() {
- return this.$.toolbar.searchField.isSearchFocused();
- },
-});
+ // Override FindShortcutBehavior methods.
+ handleFindShortcut(modalContextOpen) {
+ if (modalContextOpen) {
+ return false;
+ }
+ this.$.toolbar.searchField.showAndFocus();
+ return true;
+ },
+
+ // Override FindShortcutBehavior methods.
+ searchInputHasFocus() {
+ return this.$.toolbar.searchField.isSearchFocused();
+ },
+ });
diff --git a/chromium/chrome/browser/resources/history/browser_service.html b/chromium/chrome/browser/resources/history/browser_service.html
deleted file mode 100644
index 6b330c1b8c7..00000000000
--- a/chromium/chrome/browser/resources/history/browser_service.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<link rel="import" href="chrome://resources/html/cr.html">
-<link rel="import" href="chrome://resources/html/promise_resolver.html">
-<link rel="import" href="constants.html">
-<script src="browser_service.js"></script>
diff --git a/chromium/chrome/browser/resources/history/browser_service.js b/chromium/chrome/browser/resources/history/browser_service.js
index 4874cd0bb58..f02be099457 100644
--- a/chromium/chrome/browser/resources/history/browser_service.js
+++ b/chromium/chrome/browser/resources/history/browser_service.js
@@ -2,20 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
+import {RESULTS_PER_PAGE} from './constants.js';
+import {ForeignSession, HistoryEntry, HistoryQuery} from './externs.js';
+
/**
* @fileoverview Defines a singleton object, history.BrowserService, which
* provides access to chrome.send APIs.
*/
-cr.define('history', function() {
- class BrowserService {
- historyLoaded() {
- chrome.send('historyLoaded');
+ export class BrowserService {
+ /** @return {!Promise<!Array<!ForeignSession>>} */
+ getForeignSessions() {
+ return sendWithPromise('getForeignSessions');
}
- /**
- * @param {!string} url
- */
+ /** @param {!string} url */
removeBookmark(url) {
chrome.send('removeBookmark', [url]);
}
@@ -26,12 +28,10 @@ cr.define('history', function() {
* successfully or rejected when deletion fails.
*/
removeVisits(removalList) {
- return cr.sendWithPromise('removeVisits', removalList);
+ return sendWithPromise('removeVisits', removalList);
}
- /**
- * @param {string} sessionTag
- */
+ /** @param {string} sessionTag */
openForeignSessionAllTabs(sessionTag) {
chrome.send('openForeignSession', [sessionTag]);
}
@@ -49,9 +49,7 @@ cr.define('history', function() {
]);
}
- /**
- * @param {string} sessionTag
- */
+ /** @param {string} sessionTag */
deleteForeignSession(sessionTag) {
chrome.send('deleteForeignSession', [sessionTag]);
}
@@ -74,7 +72,7 @@ cr.define('history', function() {
* @param {string} action The name of the action to be logged.
*/
recordAction(action) {
- if (action.indexOf('_') == -1) {
+ if (action.indexOf('_') === -1) {
action = `HistoryPage_${action}`;
}
chrome.send('metricsHandler:recordAction', [action]);
@@ -107,13 +105,19 @@ cr.define('history', function() {
chrome.send('otherDevicesInitialized');
}
+ /**
+ * @return {!Promise<{info: !HistoryQuery, value: !Array<!HistoryEntry>}>}
+ */
queryHistoryContinuation() {
- chrome.send('queryHistoryContinuation');
+ return sendWithPromise('queryHistoryContinuation');
}
- /** @param {string} searchTerm */
+ /**
+ * @param {string} searchTerm
+ * @return {!Promise<{info: !HistoryQuery, value: !Array<!HistoryEntry>}>}
+ */
queryHistory(searchTerm) {
- chrome.send('queryHistory', [searchTerm, RESULTS_PER_PAGE]);
+ return sendWithPromise('queryHistory', searchTerm, RESULTS_PER_PAGE);
}
startSignInFlow() {
@@ -121,7 +125,5 @@ cr.define('history', function() {
}
}
- cr.addSingletonGetter(BrowserService);
+ addSingletonGetter(BrowserService);
- return {BrowserService: BrowserService};
-});
diff --git a/chromium/chrome/browser/resources/history/constants.html b/chromium/chrome/browser/resources/history/constants.html
deleted file mode 100644
index 2b6bc6b93e9..00000000000
--- a/chromium/chrome/browser/resources/history/constants.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src="constants.js"></script>
diff --git a/chromium/chrome/browser/resources/history/constants.js b/chromium/chrome/browser/resources/history/constants.js
index 970d4001f0e..98da52083a9 100644
--- a/chromium/chrome/browser/resources/history/constants.js
+++ b/chromium/chrome/browser/resources/history/constants.js
@@ -2,15 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Globals:
-/** @type {number} */ const RESULTS_PER_PAGE = 150;
+/** @type {number} */ export const RESULTS_PER_PAGE = 150;
/**
* Amount of time between pageviews that we consider a 'break' in browsing,
* measured in milliseconds.
* @type {number}
*/
-const BROWSING_GAP_TIME = 15 * 60 * 1000;
+export const BROWSING_GAP_TIME = 15 * 60 * 1000;
/**
* The largest bucket value for UMA histogram, based on entry ID. All entries
@@ -19,7 +18,7 @@ const BROWSING_GAP_TIME = 15 * 60 * 1000;
* (see HistoryManager.java).
* @type {number}
*/
-const UMA_MAX_BUCKET_VALUE = 1000;
+export const UMA_MAX_BUCKET_VALUE = 1000;
/**
* The largest bucket value for a UMA histogram that is a subset of above.
@@ -27,7 +26,7 @@ const UMA_MAX_BUCKET_VALUE = 1000;
* (see HistoryManager.java).
* @type {number}
*/
-const UMA_MAX_SUBSET_BUCKET_VALUE = 100;
+export const UMA_MAX_SUBSET_BUCKET_VALUE = 100;
/**
* Histogram buckets for UMA tracking of which view is being shown to the user.
@@ -35,7 +34,7 @@ const UMA_MAX_SUBSET_BUCKET_VALUE = 100;
* This enum is append-only.
* @enum {number}
*/
-const HistoryPageViewHistogram = {
+export const HistoryPageViewHistogram = {
HISTORY: 0,
DEPRECATED_GROUPED_WEEK: 1,
DEPRECATED_GROUPED_MONTH: 2,
@@ -45,7 +44,7 @@ const HistoryPageViewHistogram = {
};
/** @type {string} */
-const SYNCED_TABS_HISTOGRAM_NAME = 'HistoryPage.OtherDevicesMenu';
+export const SYNCED_TABS_HISTOGRAM_NAME = 'HistoryPage.OtherDevicesMenu';
/**
* Histogram buckets for UMA tracking of synced tabs. Keep in sync with
@@ -54,7 +53,7 @@ const SYNCED_TABS_HISTOGRAM_NAME = 'HistoryPage.OtherDevicesMenu';
* reused.
* @enum {number}
*/
-const SyncedTabsHistogram = {
+export const SyncedTabsHistogram = {
INITIALIZED: 0,
SHOW_MENU_DEPRECATED: 1,
LINK_CLICKED: 2,
diff --git a/chromium/chrome/browser/resources/history/externs.js b/chromium/chrome/browser/resources/history/externs.js
index 553d51d971e..e990c15cad7 100644
--- a/chromium/chrome/browser/resources/history/externs.js
+++ b/chromium/chrome/browser/resources/history/externs.js
@@ -4,7 +4,6 @@
/**
* @fileoverview Externs for objects sent from C++ to chrome://history.
- * @externs
*/
/**
@@ -29,7 +28,7 @@
* title: string,
* url: string}}
*/
-let HistoryEntry;
+export let HistoryEntry;
/**
* The type of the history results info object. The definition is based on
@@ -38,7 +37,7 @@ let HistoryEntry;
* @typedef {{finished: boolean,
* term: string}}
*/
-let HistoryQuery;
+export let HistoryQuery;
/**
* The type of the foreign session tab object. This definition is based on
@@ -51,7 +50,7 @@ let HistoryQuery;
* type: string,
* url: string}}
*/
-let ForeignSessionTab;
+export let ForeignSessionTab;
/**
* The type of the foreign session tab object. This definition is based on
@@ -60,7 +59,7 @@ let ForeignSessionTab;
* sessionId: number,
* tabs: Array<ForeignSessionTab>}}
*/
-let ForeignSessionWindow;
+export let ForeignSessionWindow;
/**
* The type of the foreign session info object. This definition is based on
@@ -73,27 +72,18 @@ let ForeignSessionWindow;
* timestamp: number,
* windows: Array<ForeignSessionWindow>}}
*/
-let ForeignSession;
+export let ForeignSession;
/**
* @typedef {{incremental: boolean,
* querying: boolean,
* searchTerm: string}}
*/
-let QueryState;
+export let QueryState;
/**
* @typedef {{info: ?HistoryQuery,
* results: ?Array<!HistoryEntry>,
* sessionList: ?Array<!ForeignSession>}}
*/
-let QueryResult;
-
-/**
- * @constructor
- * @extends {MouseEvent}
- */
-const DomRepeatClickEvent = function() {};
-
-/** @type {Object} */
-DomRepeatClickEvent.prototype.model;
+export let QueryResult;
diff --git a/chromium/chrome/browser/resources/history/history.html b/chromium/chrome/browser/resources/history/history.html
index 2d3f0939cdd..506a68f4ff3 100644
--- a/chromium/chrome/browser/resources/history/history.html
+++ b/chromium/chrome/browser/resources/history/history.html
@@ -1,6 +1,7 @@
<!doctype html>
<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{a11yenhanced}>
<head>
+ <base href="chrome://history">
<meta charset="utf8">
<title>$i18n{title}</title>
@@ -88,11 +89,8 @@
</div>
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
- <link rel="import" href="chrome://resources/html/util.html">
- <link rel="import" href="constants.html">
- <script src="history.js"></script>
- <link rel="import" href="app.html" async id="bundle">
+ <script type="module" src="history.js"></script>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/history/history.js b/chromium/chrome/browser/resources/history/history.js
index 56bcddaa3c7..26c7f036391 100644
--- a/chromium/chrome/browser/resources/history/history.js
+++ b/chromium/chrome/browser/resources/history/history.js
@@ -1,63 +1,9 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
+// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Send the history query immediately. This allows the query to process during
-// the initial page startup.
-chrome.send('queryHistory', ['', RESULTS_PER_PAGE]);
-chrome.send('getForeignSessions');
+import './app.js';
-/** @type {Promise} */
-let upgradePromise = null;
-
-/**
- * Adding this on |window| since it is accessed by tests.
- * @type {boolean}
- */
-window.resultsRendered = false;
-
-/**
- * @return {!Promise} Resolves once the history-app has been fully upgraded.
- */
-function waitForAppUpgrade() {
- if (!upgradePromise) {
- upgradePromise = new Promise(function(resolve, reject) {
- $('bundle').addEventListener('load', resolve);
- });
- }
- return upgradePromise;
-}
-
-// Chrome Callbacks-------------------------------------------------------------
-
-/**
- * Our history system calls this function with results from searches.
- * @param {HistoryQuery} info An object containing information about the query.
- * @param {!Array<HistoryEntry>} results A list of results.
- */
-function historyResult(info, results) {
- waitForAppUpgrade().then(function() {
- const app = /** @type {HistoryAppElement} */ ($('history-app'));
- app.historyResult(info, results);
- document.body.classList.remove('loading');
-
- if (!window.resultsRendered) {
- window.resultsRendered = true;
- app.onFirstRender();
- }
- });
-}
-
-/**
- * Receives the synced history data. An empty list means that either there are
- * no foreign sessions, or tab sync is disabled for this profile.
- *
- * @param {!Array<!ForeignSession>} sessionList Array of objects describing the
- * sessions from other devices.
- */
-function setForeignSessions(sessionList) {
- waitForAppUpgrade().then(function() {
- /** @type {HistoryAppElement} */ ($('history-app'))
- .setForeignSessions(sessionList);
- });
-}
+export {ensureLazyLoaded, listenForPrivilegedLinkClicks} from './app.js';
+export {BrowserService} from './browser_service.js';
+export {HistoryPageViewHistogram, SyncedTabsHistogram, SYNCED_TABS_HISTOGRAM_NAME} from './constants.js';
diff --git a/chromium/chrome/browser/resources/history/history_item.html b/chromium/chrome/browser/resources/history/history_item.html
index 8c6543d238b..d83a9315518 100644
--- a/chromium/chrome/browser/resources/history/history_item.html
+++ b/chromium/chrome/browser/resources/history/history_item.html
@@ -1,23 +1,3 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="browser_service.html">
-<link rel="import" href="constants.html">
-<link rel="import" href="searched_label.html">
-<link rel="import" href="shared_style.html">
-<link rel="import" href="strings.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/html/cr/ui/focus_row_behavior.html">
-<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
-<link rel="import" href="chrome://resources/html/icon.html">
-<link rel="import" href="chrome://resources/html/util.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-
-<!-- Lazy loaded: cr-icon-button. -->
-
-<dom-module id="history-item">
- <template>
<style include="shared-style cr-icons">
:host {
display: block;
@@ -144,9 +124,9 @@
}
#background {
- @apply --cr-card-elevation;
background-color: var(--cr-card-background-color);
bottom: 0;
+ box-shadow: var(--cr-card-shadow);
left: 0;
position: absolute;
right: 0;
@@ -225,6 +205,3 @@
</div>
<div id="time-gap-separator" hidden="[[!hasTimeGap]]"></div>
</div>
- </template>
- <script src="history_item.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/history_item.js b/chromium/chrome/browser/resources/history/history_item.js
index 272ac057190..e47037acb37 100644
--- a/chromium/chrome/browser/resources/history/history_item.js
+++ b/chromium/chrome/browser/resources/history/history_item.js
@@ -2,328 +2,340 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-cr.define('history', function() {
- const HistoryItem = Polymer({
- is: 'history-item',
-
- behaviors: [cr.ui.FocusRowBehavior],
-
- properties: {
- // Underlying HistoryEntry data for this item. Contains read-only fields
- // from the history backend, as well as fields computed by history-list.
- item: {
- type: Object,
- observer: 'itemChanged_',
- },
-
- selected: {
- type: Boolean,
- reflectToAttribute: true,
- },
-
- isCardStart: {
- type: Boolean,
- reflectToAttribute: true,
- },
-
- isCardEnd: {
- type: Boolean,
- reflectToAttribute: true,
- },
-
- /** @type {Element} */
- lastFocused: {
- type: Object,
- notify: true,
- },
-
- listBlurred: {
- type: Boolean,
- notify: true,
- },
-
- ironListTabIndex: {
- type: Number,
- observer: 'ironListTabIndexChanged_',
- },
-
- selectionNotAllowed_: {
- type: Boolean,
- value: !loadTimeData.getBoolean('allowDeletingHistory'),
- },
-
- hasTimeGap: Boolean,
-
- index: Number,
-
- numberOfItems: Number,
-
- // Search term used to obtain this history-item.
- searchTerm: String,
-
- overrideCustomEquivalent: {
- type: Boolean,
- value: true,
- },
+import {Polymer, html, afterNextRender} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {BrowserService} from './browser_service.js';
+import {UMA_MAX_BUCKET_VALUE, UMA_MAX_SUBSET_BUCKET_VALUE} from './constants.js';
+import './searched_label.js';
+import './shared_style.js';
+import './strings.js';
+import 'chrome://resources/cr_elements/cr_icons_css.m.js';
+import {getFaviconForPageURL} from 'chrome://resources/js/icon.m.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import {FocusRowBehavior} from 'chrome://resources/js/cr/ui/focus_row_behavior.m.js';
+import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
+import 'chrome://resources/js/icon.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
+
+Polymer({
+ is: 'history-item',
+
+ _template: html`{__html_template__}`,
+
+ behaviors: [FocusRowBehavior],
+
+ properties: {
+ // Underlying HistoryEntry data for this item. Contains read-only fields
+ // from the history backend, as well as fields computed by history-list.
+ item: {
+ type: Object,
+ observer: 'itemChanged_',
},
- hostAttributes: {'role': 'row'},
+ selected: {
+ type: Boolean,
+ reflectToAttribute: true,
+ },
- /** @private {boolean} */
- mouseDown_: false,
+ isCardStart: {
+ type: Boolean,
+ reflectToAttribute: true,
+ },
- /** @private {boolean} */
- isShiftKeyDown_: false,
+ isCardEnd: {
+ type: Boolean,
+ reflectToAttribute: true,
+ },
- /** @override */
- attached: function() {
- Polymer.RenderStatus.afterNextRender(this, function() {
- // Adding listeners asynchronously to reduce blocking time, since these
- // history items are items in a potentially long list.
- this.listen(this.$.checkbox, 'keydown', 'onCheckboxKeydown_');
- });
+ /** @type {Element} */
+ lastFocused: {
+ type: Object,
+ notify: true,
},
- /** @override */
- detached: function() {
- this.unlisten(this.$.checkbox, 'keydown', 'onCheckboxKeydown_');
+ listBlurred: {
+ type: Boolean,
+ notify: true,
},
- focusOnMenuButton: function() {
- cr.ui.focusWithoutInk(this.$['menu-button']);
+ ironListTabIndex: {
+ type: Number,
+ observer: 'ironListTabIndexChanged_',
},
- /** @param {!KeyboardEvent} e */
- onCheckboxKeydown_: function(e) {
- if (e.shiftKey && e.key === 'Tab') {
- this.focus();
- }
+ selectionNotAllowed_: {
+ type: Boolean,
+ value: !loadTimeData.getBoolean('allowDeletingHistory'),
},
- /**
- * Toggle item selection whenever the checkbox or any non-interactive part
- * of the item is clicked.
- * @param {MouseEvent} e
- * @private
- */
- onItemClick_: function(e) {
- for (let i = 0; i < e.path.length; i++) {
- const elem = e.path[i];
- if (elem.id != 'checkbox' &&
- (elem.nodeName == 'A' || elem.nodeName == 'CR-ICON-BUTTON')) {
- return;
- }
- }
+ hasTimeGap: Boolean,
- if (this.selectionNotAllowed_) {
- return;
- }
+ index: Number,
- this.$.checkbox.focus();
- this.fire('history-checkbox-select', {
- index: this.index,
- shiftKey: e.shiftKey,
- });
- },
+ numberOfItems: Number,
- /**
- * This is bound to mouse/keydown instead of click/press because this
- * has to fire before onCheckboxChange_. If we bind it to click/press,
- * it might trigger out of disired order.
- *
- * @param {!Event} e
- * @private
- */
- onCheckboxClick_: function(e) {
- this.isShiftKeyDown_ = e.shiftKey;
- },
+ // Search term used to obtain this history-item.
+ searchTerm: String,
- /**
- * @param {!Event} e
- * @private
- */
- onCheckboxChange_: function(e) {
- this.fire('history-checkbox-select', {
- index: this.index,
- // If the user clicks or press enter/space key, oncheckboxClick_ will
- // trigger before this function, so a shift-key might be recorded.
- shiftKey: this.isShiftKeyDown_,
- });
-
- this.isShiftKeyDown_ = false;
+ overrideCustomEquivalent: {
+ type: Boolean,
+ value: true,
},
+ },
- /**
- * @param {MouseEvent} e
- * @private
- */
- onItemMousedown_: function(e) {
- // Prevent shift clicking a checkbox from selecting text.
- if (e.shiftKey) {
- e.preventDefault();
- }
- },
+ hostAttributes: {'role': 'row'},
- /**
- * @private
- * @return {string}
- */
- getEntrySummary_: function() {
- const item = this.item;
- return loadTimeData.getStringF(
- 'entrySummary', item.dateTimeOfDay,
- item.starred ? loadTimeData.getString('bookmarked') : '', item.title,
- item.domain);
- },
+ /** @private {boolean} */
+ mouseDown_: false,
- /**
- * @param {boolean} selected
- * @return {string}
- * @private
- */
- getAriaChecked_: function(selected) {
- return selected ? 'true' : 'false';
- },
+ /** @private {boolean} */
+ isShiftKeyDown_: false,
+
+ /** @override */
+ attached() {
+ afterNextRender(this, function() {
+ // Adding listeners asynchronously to reduce blocking time, since these
+ // history items are items in a potentially long list.
+ this.listen(this.$.checkbox, 'keydown', 'onCheckboxKeydown_');
+ });
+ },
+
+ /** @override */
+ detached() {
+ this.unlisten(this.$.checkbox, 'keydown', 'onCheckboxKeydown_');
+ },
+
+ focusOnMenuButton() {
+ focusWithoutInk(this.$['menu-button']);
+ },
+
+ /** @param {!KeyboardEvent} e */
+ onCheckboxKeydown_(e) {
+ if (e.shiftKey && e.key === 'Tab') {
+ this.focus();
+ }
+ },
- /**
- * Remove bookmark of current item when bookmark-star is clicked.
- * @private
- */
- onRemoveBookmarkTap_: function() {
- if (!this.item.starred) {
+ /**
+ * Toggle item selection whenever the checkbox or any non-interactive part
+ * of the item is clicked.
+ * @param {MouseEvent} e
+ * @private
+ */
+ onItemClick_(e) {
+ for (let i = 0; i < e.path.length; i++) {
+ const elem = e.path[i];
+ if (elem.id !== 'checkbox' &&
+ (elem.nodeName === 'A' || elem.nodeName === 'CR-ICON-BUTTON')) {
return;
}
+ }
- if (this.$$('#bookmark-star') == this.root.activeElement) {
- cr.ui.focusWithoutInk(this.$['menu-button']);
- }
+ if (this.selectionNotAllowed_) {
+ return;
+ }
- const browserService = history.BrowserService.getInstance();
- browserService.removeBookmark(this.item.url);
- browserService.recordAction('BookmarkStarClicked');
+ this.$.checkbox.focus();
+ this.fire('history-checkbox-select', {
+ index: this.index,
+ shiftKey: e.shiftKey,
+ });
+ },
- this.fire('remove-bookmark-stars', this.item.url);
- },
+ /**
+ * This is bound to mouse/keydown instead of click/press because this
+ * has to fire before onCheckboxChange_. If we bind it to click/press,
+ * it might trigger out of desired order.
+ *
+ * @param {!Event} e
+ * @private
+ */
+ onCheckboxClick_(e) {
+ this.isShiftKeyDown_ = e.shiftKey;
+ },
- /**
- * Fires a custom event when the menu button is clicked. Sends the details
- * of the history item and where the menu should appear.
- */
- onMenuButtonTap_: function(e) {
- this.fire('open-menu', {
- target: e.target,
- index: this.index,
- item: this.item,
- });
-
- // Stops the 'click' event from closing the menu when it opens.
- e.stopPropagation();
- },
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onCheckboxChange_(e) {
+ this.fire('history-checkbox-select', {
+ index: this.index,
+ // If the user clicks or press enter/space key, oncheckboxClick_ will
+ // trigger before this function, so a shift-key might be recorded.
+ shiftKey: this.isShiftKeyDown_,
+ });
- /**
- * Record metrics when a result is clicked.
- * @private
- */
- onLinkClick_: function() {
- const browserService = history.BrowserService.getInstance();
- browserService.recordAction('EntryLinkClick');
+ this.isShiftKeyDown_ = false;
+ },
- if (this.searchTerm) {
- browserService.recordAction('SearchResultClick');
- }
+ /**
+ * @param {MouseEvent} e
+ * @private
+ */
+ onItemMousedown_(e) {
+ // Prevent shift clicking a checkbox from selecting text.
+ if (e.shiftKey) {
+ e.preventDefault();
+ }
+ },
- if (this.index == undefined) {
- return;
- }
+ /**
+ * @private
+ * @return {string}
+ */
+ getEntrySummary_() {
+ const item = this.item;
+ return loadTimeData.getStringF(
+ 'entrySummary', item.dateTimeOfDay,
+ item.starred ? loadTimeData.getString('bookmarked') : '', item.title,
+ item.domain);
+ },
- const ageInDays = Math.ceil(
- (new Date() - new Date(this.item.time)) / 1000 /* s/ms */ /
- 60 /* m/s */ / 60 /* h/m */ / 24 /* d/h */);
+ /**
+ * @param {boolean} selected
+ * @return {string}
+ * @private
+ */
+ getAriaChecked_(selected) {
+ return selected ? 'true' : 'false';
+ },
- browserService.recordHistogram(
- 'HistoryPage.ClickPosition',
- Math.min(this.index, UMA_MAX_BUCKET_VALUE), UMA_MAX_BUCKET_VALUE);
+ /**
+ * Remove bookmark of current item when bookmark-star is clicked.
+ * @private
+ */
+ onRemoveBookmarkTap_() {
+ if (!this.item.starred) {
+ return;
+ }
- browserService.recordHistogram(
- 'HistoryPage.ClickAgeInDays',
- Math.min(ageInDays, UMA_MAX_BUCKET_VALUE), UMA_MAX_BUCKET_VALUE);
+ if (this.$$('#bookmark-star') === this.root.activeElement) {
+ focusWithoutInk(this.$['menu-button']);
+ }
- if (this.index <= UMA_MAX_SUBSET_BUCKET_VALUE) {
- browserService.recordHistogram(
- 'HistoryPage.ClickPositionSubset', this.index,
- UMA_MAX_SUBSET_BUCKET_VALUE);
- }
+ const browserService = BrowserService.getInstance();
+ browserService.removeBookmark(this.item.url);
+ browserService.recordAction('BookmarkStarClicked');
- if (ageInDays <= UMA_MAX_SUBSET_BUCKET_VALUE) {
- browserService.recordHistogram(
- 'HistoryPage.ClickAgeInDaysSubset', ageInDays,
- UMA_MAX_SUBSET_BUCKET_VALUE);
- }
- },
+ this.fire('remove-bookmark-stars', this.item.url);
+ },
- onLinkRightClick_: function() {
- history.BrowserService.getInstance().recordAction('EntryLinkRightClick');
- },
+ /**
+ * Fires a custom event when the menu button is clicked. Sends the details
+ * of the history item and where the menu should appear.
+ */
+ onMenuButtonTap_(e) {
+ this.fire('open-menu', {
+ target: e.target,
+ index: this.index,
+ item: this.item,
+ });
- /**
- * Set the favicon image, based on the URL of the history item.
- * @private
- */
- itemChanged_: function() {
- this.$.icon.style.backgroundImage = cr.icon.getFaviconForPageURL(
- this.item.url, this.item.isUrlInRemoteUserData,
- this.item.remoteIconUrlForUma);
- this.listen(this.$['time-accessed'], 'mouseover', 'addTimeTitle_');
- },
+ // Stops the 'click' event from closing the menu when it opens.
+ e.stopPropagation();
+ },
- /**
- * @param {number} numberOfItems The number of items in the card.
- * @param {string} historyDate Date of the current result.
- * @param {string} search The search term associated with these results.
- * @return {string} The title for this history card.
- * @private
- */
- cardTitle_: function(numberOfItems, historyDate, search) {
- if (this.item === undefined) {
- return '';
- }
+ /**
+ * Record metrics when a result is clicked.
+ * @private
+ */
+ onLinkClick_() {
+ const browserService = BrowserService.getInstance();
+ browserService.recordAction('EntryLinkClick');
- if (!search) {
- return this.item.dateRelativeDay;
- }
- return HistoryItem.searchResultsTitle(numberOfItems, search);
- },
+ if (this.searchTerm) {
+ browserService.recordAction('SearchResultClick');
+ }
- /** @private */
- addTimeTitle_: function() {
- const el = this.$['time-accessed'];
- el.setAttribute('title', new Date(this.item.time).toString());
- this.unlisten(el, 'mouseover', 'addTimeTitle_');
- },
+ if (this.index === undefined) {
+ return;
+ }
- /**
- * @param {!Element} sampleElement An element to find an equivalent for.
- * @return {?Element} An equivalent element to focus, or null to use the
- * default element.
- */
- getCustomEquivalent(sampleElement) {
- return sampleElement.getAttribute('focus-type') === 'star' ?
- this.$.link :
- null;
- },
- });
+ const ageInDays = Math.ceil(
+ (new Date() - new Date(this.item.time)) / 1000 /* s/ms */ /
+ 60 /* m/s */ / 60 /* h/m */ / 24 /* d/h */);
+
+ browserService.recordHistogram(
+ 'HistoryPage.ClickPosition', Math.min(this.index, UMA_MAX_BUCKET_VALUE),
+ UMA_MAX_BUCKET_VALUE);
+
+ browserService.recordHistogram(
+ 'HistoryPage.ClickAgeInDays', Math.min(ageInDays, UMA_MAX_BUCKET_VALUE),
+ UMA_MAX_BUCKET_VALUE);
+
+ if (this.index <= UMA_MAX_SUBSET_BUCKET_VALUE) {
+ browserService.recordHistogram(
+ 'HistoryPage.ClickPositionSubset', this.index,
+ UMA_MAX_SUBSET_BUCKET_VALUE);
+ }
+
+ if (ageInDays <= UMA_MAX_SUBSET_BUCKET_VALUE) {
+ browserService.recordHistogram(
+ 'HistoryPage.ClickAgeInDaysSubset', ageInDays,
+ UMA_MAX_SUBSET_BUCKET_VALUE);
+ }
+ },
+
+ onLinkRightClick_() {
+ BrowserService.getInstance().recordAction('EntryLinkRightClick');
+ },
/**
- * @param {number} numberOfResults
- * @param {string} searchTerm
- * @return {string} The title for a page of search results.
+ * Set the favicon image, based on the URL of the history item.
+ * @private
*/
- HistoryItem.searchResultsTitle = function(numberOfResults, searchTerm) {
- const resultId = numberOfResults == 1 ? 'searchResult' : 'searchResults';
- return loadTimeData.getStringF(
- 'foundSearchResults', numberOfResults, loadTimeData.getString(resultId),
- searchTerm);
- };
+ itemChanged_() {
+ this.$.icon.style.backgroundImage = getFaviconForPageURL(
+ this.item.url, this.item.isUrlInRemoteUserData,
+ this.item.remoteIconUrlForUma);
+ this.listen(this.$['time-accessed'], 'mouseover', 'addTimeTitle_');
+ },
+
+ /**
+ * @param {number} numberOfItems The number of items in the card.
+ * @param {string} historyDate Date of the current result.
+ * @param {string} search The search term associated with these results.
+ * @return {string} The title for this history card.
+ * @private
+ */
+ cardTitle_(numberOfItems, historyDate, search) {
+ if (this.item === undefined) {
+ return '';
+ }
+
+ if (!search) {
+ return this.item.dateRelativeDay;
+ }
+ return searchResultsTitle(numberOfItems, search);
+ },
+
+ /** @private */
+ addTimeTitle_() {
+ const el = this.$['time-accessed'];
+ el.setAttribute('title', new Date(this.item.time).toString());
+ this.unlisten(el, 'mouseover', 'addTimeTitle_');
+ },
- return {HistoryItem: HistoryItem};
+ /**
+ * @param {!Element} sampleElement An element to find an equivalent for.
+ * @return {?Element} An equivalent element to focus, or null to use the
+ * default element.
+ */
+ getCustomEquivalent(sampleElement) {
+ return sampleElement.getAttribute('focus-type') === 'star' ? this.$.link :
+ null;
+ },
});
+
+/**
+ * @param {number} numberOfResults
+ * @param {string} searchTerm
+ * @return {string} The title for a page of search results.
+ */
+export function searchResultsTitle(numberOfResults, searchTerm) {
+ const resultId = numberOfResults === 1 ? 'searchResult' : 'searchResults';
+ return loadTimeData.getStringF(
+ 'foundSearchResults', numberOfResults, loadTimeData.getString(resultId),
+ searchTerm);
+}
diff --git a/chromium/chrome/browser/resources/history/history_list.html b/chromium/chrome/browser/resources/history/history_list.html
index 1da7f4a93e7..1ee41a6085c 100644
--- a/chromium/chrome/browser/resources/history/history_list.html
+++ b/chromium/chrome/browser/resources/history/history_list.html
@@ -1,21 +1,3 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
-<link rel="import" href="chrome://resources/html/i18n_behavior.html">
-<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-announcer/iron-a11y-announcer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-scroll-threshold/iron-scroll-threshold.html">
-<link rel="import" href="browser_service.html">
-<link rel="import" href="constants.html">
-<link rel="import" href="history_item.html">
-<link rel="import" href="shared_style.html">
-
-<!-- Lazy loaded: cr-dialog, cr-action-menu, cr-button. -->
-
-<dom-module id="history-list">
- <template>
<style include="shared-style cr-shared-style">
:host {
box-sizing: border-box;
@@ -96,6 +78,3 @@
</cr-action-menu>
</template>
</cr-lazy-render>
- </template>
- <script src="history_list.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/history_list.js b/chromium/chrome/browser/resources/history/history_list.js
index 805bfd2e0c0..73be8345615 100644
--- a/chromium/chrome/browser/resources/history/history_list.js
+++ b/chromium/chrome/browser/resources/history/history_list.js
@@ -2,9 +2,28 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {Polymer, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
+import 'chrome://resources/cr_elements/shared_style_css.m.js';
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
+import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
+import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
+import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
+import 'chrome://resources/polymer/v3_0/iron-scroll-threshold/iron-scroll-threshold.js';
+import {BrowserService} from './browser_service.js';
+import {HistoryEntry, HistoryQuery, QueryState} from './externs.js';
+import {BROWSING_GAP_TIME, UMA_MAX_BUCKET_VALUE, UMA_MAX_SUBSET_BUCKET_VALUE} from './constants.js';
+import {searchResultsTitle} from './history_item.js';
+import './shared_style.js';
+
Polymer({
is: 'history-list',
+ _template: html`{__html_template__}`,
+
behaviors: [I18nBehavior, WebUIListenerBehavior],
properties: {
@@ -79,7 +98,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
// It is possible (eg, when middle clicking the reload button) for all other
// resize events to fire before the list is attached and can be measured.
// Adding another resize here ensures it will get sized correctly.
@@ -99,14 +118,14 @@ Polymer({
* query.
* @param {!Array<!HistoryEntry>} results A list of results.
*/
- historyResult: function(info, results) {
+ historyResult(info, results) {
this.initializeResults_(info, results);
this.closeMenu_();
if (info.term && !this.queryState.incremental) {
- Polymer.IronA11yAnnouncer.requestAvailability();
+ IronA11yAnnouncer.requestAvailability();
this.fire('iron-announce', {
- text: history.HistoryItem.searchResultsTitle(results.length, info.term)
+ text: searchResultsTitle(results.length, info.term)
});
}
@@ -122,7 +141,7 @@ Polymer({
* @param {boolean} finished True if there are no more results available and
* result loading should be disabled.
*/
- addNewResults: function(historyResults, incremental, finished) {
+ addNewResults(historyResults, incremental, finished) {
const results = historyResults.slice();
/** @type {IronScrollThresholdElement} */ (this.$['scroll-threshold'])
.clearTriggers();
@@ -151,7 +170,7 @@ Polymer({
},
/** @private */
- onHistoryDeleted_: function() {
+ onHistoryDeleted_() {
// Do not reload the list when there are items checked.
if (this.getSelectedItemCount() > 0) {
return;
@@ -161,8 +180,8 @@ Polymer({
this.fire('query-history', false);
},
- selectOrUnselectAll: function() {
- if (this.historyData_.length == this.getSelectedItemCount()) {
+ selectOrUnselectAll() {
+ if (this.historyData_.length === this.getSelectedItemCount()) {
this.unselectAllItems();
} else {
this.selectAllItems();
@@ -172,8 +191,8 @@ Polymer({
/**
* Select each item in |historyData|.
*/
- selectAllItems: function() {
- if (this.historyData_.length == this.getSelectedItemCount()) {
+ selectAllItems() {
+ if (this.historyData_.length === this.getSelectedItemCount()) {
return;
}
@@ -185,16 +204,16 @@ Polymer({
/**
* Deselect each item in |selectedItems|.
*/
- unselectAllItems: function() {
+ unselectAllItems() {
this.selectedItems.forEach((index) => {
this.changeSelection_(index, false);
});
- assert(this.selectedItems.size == 0);
+ assert(this.selectedItems.size === 0);
},
/** @return {number} */
- getSelectedItemCount: function() {
+ getSelectedItemCount() {
return this.selectedItems.size;
},
@@ -202,14 +221,14 @@ Polymer({
* Delete all the currently selected history items. Will prompt the user with
* a dialog to confirm that the deletion should be performed.
*/
- deleteSelectedWithPrompt: function() {
+ deleteSelectedWithPrompt() {
if (!this.canDeleteHistory_) {
return;
}
- const browserService = history.BrowserService.getInstance();
+ const browserService = BrowserService.getInstance();
browserService.recordAction('RemoveSelected');
- if (this.queryState.searchTerm != '') {
+ if (this.queryState.searchTerm !== '') {
browserService.recordAction('SearchResultRemove');
}
this.$.dialog.get().showModal();
@@ -227,7 +246,7 @@ Polymer({
* @param {boolean} selected
* @private
*/
- changeSelection_: function(index, selected) {
+ changeSelection_(index, selected) {
this.set(`historyData_.${index}.selected`, selected);
if (selected) {
this.selectedItems.add(index);
@@ -243,7 +262,7 @@ Polymer({
* does prompt.
* @private
*/
- deleteSelected_: function() {
+ deleteSelected_() {
assert(!this.pendingDelete);
const toBeRemoved = Array.from(this.selectedItems.values())
@@ -253,7 +272,7 @@ Polymer({
this.pendingDelete = false;
this.removeItemsByIndex_(Array.from(this.selectedItems));
this.fire('unselect-all');
- if (this.historyData_.length == 0) {
+ if (this.historyData_.length === 0) {
// Try reloading if nothing is rendered.
this.fire('query-history', false);
}
@@ -267,7 +286,7 @@ Polymer({
* @param {!Array<number>} indices
* @private
*/
- removeItemsByIndex_: function(indices) {
+ removeItemsByIndex_(indices) {
const splices = [];
indices.sort(function(a, b) {
// Sort in reverse numerical order.
@@ -290,7 +309,7 @@ Polymer({
* Closes the overflow menu.
* @private
*/
- closeMenu_: function() {
+ closeMenu_() {
const menu = this.$.sharedMenu.getIfExists();
if (menu && menu.open) {
this.actionMenuModel_ = null;
@@ -302,8 +321,8 @@ Polymer({
// Event listeners:
/** @private */
- onDialogConfirmTap_: function() {
- history.BrowserService.getInstance().recordAction('ConfirmRemoveSelected');
+ onDialogConfirmTap_() {
+ BrowserService.getInstance().recordAction('ConfirmRemoveSelected');
this.deleteSelected_();
const dialog = assert(this.$.dialog.getIfExists());
@@ -311,8 +330,8 @@ Polymer({
},
/** @private */
- onDialogCancelTap_: function() {
- history.BrowserService.getInstance().recordAction('CancelRemoveSelected');
+ onDialogCancelTap_() {
+ BrowserService.getInstance().recordAction('CancelRemoveSelected');
const dialog = assert(this.$.dialog.getIfExists());
dialog.close();
@@ -323,7 +342,7 @@ Polymer({
* @param {!CustomEvent<string>} e
* @private
*/
- onRemoveBookmarkStars_: function(e) {
+ onRemoveBookmarkStars_(e) {
const url = e.detail;
if (this.historyData_ === undefined) {
@@ -331,7 +350,7 @@ Polymer({
}
for (let i = 0; i < this.historyData_.length; i++) {
- if (this.historyData_[i].url == url) {
+ if (this.historyData_[i].url === url) {
this.set(`historyData_.${i}.starred`, false);
}
}
@@ -341,7 +360,7 @@ Polymer({
* Called when the page is scrolled to near the bottom of the list.
* @private
*/
- onScrollToBottom_: function() {
+ onScrollToBottom_() {
if (this.resultLoadingDisabled_ || this.queryState.querying) {
return;
}
@@ -359,7 +378,7 @@ Polymer({
* }>} e
* @private
*/
- onOpenMenu_: function(e) {
+ onOpenMenu_(e) {
const index = e.detail.index;
const list = /** @type {IronListElement} */ (this.$['infinite-list']);
if (index < list.firstVisibleIndex || index > list.lastVisibleIndex) {
@@ -373,9 +392,8 @@ Polymer({
},
/** @private */
- onMoreFromSiteTap_: function() {
- history.BrowserService.getInstance().recordAction(
- 'EntryMenuShowMoreFromSite');
+ onMoreFromSiteTap_() {
+ BrowserService.getInstance().recordAction('EntryMenuShowMoreFromSite');
const menu = assert(this.$.sharedMenu.getIfExists());
this.fire('change-query', {search: this.actionMenuModel_.item.domain});
@@ -388,19 +406,19 @@ Polymer({
* @return {!Promise}
* @private
*/
- deleteItems_: function(items) {
+ deleteItems_(items) {
const removalList = items.map(item => ({
url: item.url,
timestamps: item.allTimestamps,
}));
this.pendingDelete = true;
- return history.BrowserService.getInstance().removeVisits(removalList);
+ return BrowserService.getInstance().removeVisits(removalList);
},
/** @private */
- onRemoveFromHistoryTap_: function() {
- const browserService = history.BrowserService.getInstance();
+ onRemoveFromHistoryTap_() {
+ const browserService = BrowserService.getInstance();
browserService.recordAction('EntryMenuRemoveFromHistory');
assert(!this.pendingDelete);
@@ -418,18 +436,22 @@ Polymer({
this.removeItemsByIndex_([itemData.index]);
const index = itemData.index;
- if (index == undefined) {
+ if (index === undefined) {
return;
}
- setTimeout(() => {
- this.$['infinite-list'].focusItem(index);
- const item = getDeepActiveElement();
- if (item) {
- item.focusOnMenuButton();
- }
- }, 1);
-
- const browserService = history.BrowserService.getInstance();
+
+ if (this.historyData_.length > 0) {
+ setTimeout(() => {
+ this.$['infinite-list'].focusItem(
+ Math.min(this.historyData_.length - 1, index));
+ const item = getDeepActiveElement();
+ if (item && item.focusOnMenuButton) {
+ item.focusOnMenuButton();
+ }
+ }, 1);
+ }
+
+ const browserService = BrowserService.getInstance();
browserService.recordHistogram(
'HistoryPage.RemoveEntryPosition',
Math.min(index, UMA_MAX_BUCKET_VALUE), UMA_MAX_BUCKET_VALUE);
@@ -446,20 +468,20 @@ Polymer({
* @param {Event} e
* @private
*/
- onItemSelected_: function(e) {
+ onItemSelected_(e) {
const index = e.detail.index;
const indices = [];
// Handle shift selection. Change the selection state of all items between
// |path| and |lastSelected| to the selection state of |item|.
- if (e.detail.shiftKey && this.lastSelectedIndex != undefined) {
+ if (e.detail.shiftKey && this.lastSelectedIndex !== undefined) {
for (let i = Math.min(index, this.lastSelectedIndex);
i <= Math.max(index, this.lastSelectedIndex); i++) {
indices.push(i);
}
}
- if (indices.length == 0) {
+ if (indices.length === 0) {
indices.push(index);
}
@@ -483,9 +505,9 @@ Polymer({
* @return {boolean} Whether or not time gap separator is required.
* @private
*/
- needsTimeGap_: function(item, index) {
+ needsTimeGap_(item, index) {
const length = this.historyData_.length;
- if (index === undefined || index >= length - 1 || length == 0) {
+ if (index === undefined || index >= length - 1 || length === 0) {
return false;
}
@@ -493,11 +515,11 @@ Polymer({
const nextItem = this.historyData_[index + 1];
if (this.searchedTerm) {
- return currentItem.dateShort != nextItem.dateShort;
+ return currentItem.dateShort !== nextItem.dateShort;
}
return currentItem.time - nextItem.time > BROWSING_GAP_TIME &&
- currentItem.dateRelativeDay == nextItem.dateRelativeDay;
+ currentItem.dateRelativeDay === nextItem.dateRelativeDay;
},
/**
@@ -507,13 +529,13 @@ Polymer({
* @return {boolean}
* @private
*/
- isCardStart_: function(item, i) {
+ isCardStart_(item, i) {
const length = this.historyData_.length;
- if (i === undefined || length == 0 || i > length - 1) {
+ if (i === undefined || length === 0 || i > length - 1) {
return false;
}
- return i == 0 ||
- this.historyData_[i].dateRelativeDay !=
+ return i === 0 ||
+ this.historyData_[i].dateRelativeDay !==
this.historyData_[i - 1].dateRelativeDay;
},
@@ -524,13 +546,13 @@ Polymer({
* @return {boolean}
* @private
*/
- isCardEnd_: function(item, i) {
+ isCardEnd_(item, i) {
const length = this.historyData_.length;
- if (i === undefined || length == 0 || i > length - 1) {
+ if (i === undefined || length === 0 || i > length - 1) {
return false;
}
- return i == length - 1 ||
- this.historyData_[i].dateRelativeDay !=
+ return i === length - 1 ||
+ this.historyData_[i].dateRelativeDay !==
this.historyData_[i + 1].dateRelativeDay;
},
@@ -538,7 +560,7 @@ Polymer({
* @return {boolean}
* @private
*/
- hasResults_: function() {
+ hasResults_() {
return this.historyData_.length > 0;
},
@@ -547,7 +569,7 @@ Polymer({
* @return {string}
* @private
*/
- noResultsMessage_: function(searchedTerm) {
+ noResultsMessage_(searchedTerm) {
const messageId = searchedTerm !== '' ? 'noSearchResults' : 'noResults';
return loadTimeData.getString(messageId);
},
@@ -558,7 +580,7 @@ Polymer({
* @return {boolean}
* @private
*/
- canSearchMoreFromSite_: function(searchedTerm, domain) {
+ canSearchMoreFromSite_(searchedTerm, domain) {
return searchedTerm === '' || searchedTerm !== domain;
},
@@ -567,8 +589,8 @@ Polymer({
* @param {!Array<HistoryEntry>} results
* @private
*/
- initializeResults_: function(info, results) {
- if (results.length == 0) {
+ initializeResults_(info, results) {
+ if (results.length === 0) {
return;
}
@@ -578,9 +600,9 @@ Polymer({
// Sets the default values for these fields to prevent undefined types.
results[i].selected = false;
results[i].readableTimestamp =
- info.term == '' ? results[i].dateTimeOfDay : results[i].dateShort;
+ info.term === '' ? results[i].dateTimeOfDay : results[i].dateShort;
- if (results[i].dateRelativeDay != currentDate) {
+ if (results[i].dateRelativeDay !== currentDate) {
currentDate = results[i].dateRelativeDay;
}
}
@@ -592,7 +614,7 @@ Polymer({
* This has yet to be reproduced in manual testing.
* @private
*/
- onHistoryDataChanged_: function() {
+ onHistoryDataChanged_() {
this.$['infinite-list'].fire('iron-resize');
},
});
diff --git a/chromium/chrome/browser/resources/history/history_resources.grd b/chromium/chrome/browser/resources/history/history_resources.grd
index 1d74a2ac3ef..3268ac6eb86 100644
--- a/chromium/chrome/browser/resources/history/history_resources.grd
+++ b/chromium/chrome/browser/resources/history/history_resources.grd
@@ -12,12 +12,44 @@
</outputs>
<release seq="1">
<includes>
- <include name="IDR_HISTORY_CONSTANTS_HTML"
- file="constants.html"
- type="BINDATA" />
+ <!-- Generated Polymer 3 elements -->
+ <include name="IDR_HISTORY_APP_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/app.js"
+ use_base_dir="false" type="BINDATA" preprocess="true" />
+ <include name="IDR_HISTORY_HISTORY_ITEM_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/history_item.js"
+ use_base_dir="false" type="BINDATA" />
+ <include name="IDR_HISTORY_HISTORY_LIST_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/history_list.js"
+ use_base_dir="false" type="BINDATA" />
+ <include name="IDR_HISTORY_HISTORY_TOOLBAR_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/history_toolbar.js"
+ use_base_dir="false" type="BINDATA" />
+ <include name="IDR_HISTORY_ROUTER_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/router.js"
+ use_base_dir="false" type="BINDATA" />
+ <include name="IDR_HISTORY_SHARED_STYLE_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/shared_style.js"
+ use_base_dir="false" type="BINDATA" />
+ <include name="IDR_HISTORY_SHARED_VARS_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/shared_vars.js"
+ use_base_dir="false" type="BINDATA" />
+ <include name="IDR_HISTORY_SIDE_BAR_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/side_bar.js"
+ use_base_dir="false" type="BINDATA" />
+ <include name="IDR_HISTORY_SYNCED_DEVICE_CARD_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/synced_device_card.js"
+ use_base_dir="false" type="BINDATA" />
+ <include name="IDR_HISTORY_SYNCED_DEVICE_MANAGER_JS"
+ file="${root_gen_dir}/chrome/browser/resources/history/synced_device_manager.js"
+ use_base_dir="false" type="BINDATA" />
+
<include name="IDR_HISTORY_CONSTANTS_JS"
file="constants.js"
type="BINDATA" />
+ <include name="IDR_HISTORY_EXTERNS_JS"
+ file="externs.js"
+ type="BINDATA" />
<include name="IDR_HISTORY_HISTORY_HTML"
file="history.html"
preprocess="true"
@@ -31,85 +63,18 @@
<include name="IDR_HISTORY_IMAGES_SIGN_IN_PROMO_SVG"
file="images\sign_in_promo.svg"
type="BINDATA" />
- <include name="IDR_HISTORY_STRINGS_HTML"
- file="strings.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_APP_HTML"
- file="app.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_APP_JS"
- file="app.js"
- preprocess="true"
- type="BINDATA" />
- <include name="IDR_HISTORY_BROWSER_SERVICE_HTML"
- file="browser_service.html"
- type="BINDATA" />
<include name="IDR_HISTORY_BROWSER_SERVICE_JS"
file="browser_service.js"
type="BINDATA" />
- <include name="IDR_HISTORY_HISTORY_ITEM_HTML"
- file="history_item.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_HISTORY_ITEM_JS"
- file="history_item.js"
- type="BINDATA" />
- <include name="IDR_HISTORY_HISTORY_LIST_HTML"
- file="history_list.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_HISTORY_LIST_JS"
- file="history_list.js"
- type="BINDATA" />
- <include name="IDR_HISTORY_HISTORY_TOOLBAR_HTML"
- file="history_toolbar.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_HISTORY_TOOLBAR_JS"
- file="history_toolbar.js"
- type="BINDATA" />
- <include name="IDR_HISTORY_LAZY_LOAD_HTML"
- file="lazy_load.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_QUERY_MANAGER_HTML"
- file="query_manager.html"
+ <include name="IDR_HISTORY_LAZY_LOAD_JS"
+ file="lazy_load.js"
type="BINDATA" />
<include name="IDR_HISTORY_QUERY_MANAGER_JS"
file="query_manager.js"
type="BINDATA" />
- <include name="IDR_HISTORY_ROUTER_HTML"
- file="router.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_ROUTER_JS"
- file="router.js"
- type="BINDATA" />
- <include name="IDR_HISTORY_SEARCHED_LABEL_HTML"
- file="searched_label.html"
- type="BINDATA" />
<include name="IDR_HISTORY_SEARCHED_LABEL_JS"
file="searched_label.js"
type="BINDATA" />
- <include name="IDR_HISTORY_SHARED_STYLE_HTML"
- file="shared_style.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_SHARED_VARS_HTML"
- file="shared_vars.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_SIDE_BAR_HTML"
- file="side_bar.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_SIDE_BAR_JS"
- file="side_bar.js"
- type="BINDATA" />
- <include name="IDR_HISTORY_SYNCED_DEVICE_CARD_HTML"
- file="synced_device_card.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_SYNCED_DEVICE_CARD_JS"
- file="synced_device_card.js"
- type="BINDATA" />
- <include name="IDR_HISTORY_SYNCED_DEVICE_MANAGER_HTML"
- file="synced_device_manager.html"
- type="BINDATA" />
- <include name="IDR_HISTORY_SYNCED_DEVICE_MANAGER_JS"
- file="synced_device_manager.js"
- type="BINDATA" />
</includes>
</release>
</grit>
diff --git a/chromium/chrome/browser/resources/history/history_resources_vulcanized.grd b/chromium/chrome/browser/resources/history/history_resources_vulcanized.grd
index 3806a16e117..c602d28c9c9 100644
--- a/chromium/chrome/browser/resources/history/history_resources_vulcanized.grd
+++ b/chromium/chrome/browser/resources/history/history_resources_vulcanized.grd
@@ -12,23 +12,11 @@
</outputs>
<release seq="1">
<includes>
- <include name="IDR_HISTORY_CONSTANTS_HTML"
- file="constants.html"
- compress="gzip"
- type="BINDATA" />
- <include name="IDR_HISTORY_CONSTANTS_JS"
- file="constants.js"
- compress="gzip"
- type="BINDATA" />
<include name="IDR_HISTORY_HISTORY_HTML"
file="history.html"
preprocess="true"
type="BINDATA"
compress="gzip" />
- <include name="IDR_HISTORY_HISTORY_JS"
- file="history.js"
- compress="gzip"
- type="BINDATA" />
<include name="IDR_HISTORY_IMAGES_SIGN_IN_PROMO_DARK_SVG"
file="images\sign_in_promo_dark.svg"
compress="gzip"
@@ -37,30 +25,20 @@
file="images\sign_in_promo.svg"
compress="gzip"
type="BINDATA" />
- <include name="IDR_HISTORY_STRINGS_HTML"
- file="strings.html"
- compress="gzip"
- type="BINDATA" />
- <include name="IDR_HISTORY_APP_VULCANIZED_HTML"
- file="${root_gen_dir}\chrome\browser\resources\history\app.vulcanized.html"
- preprocess="true"
- type="BINDATA"
- compress="gzip"
- use_base_dir="false" />
- <include name="IDR_HISTORY_APP_CRISPER_JS"
- file="${root_gen_dir}\chrome\browser\resources\history\app.crisper.js"
+ <include name="IDR_HISTORY_HISTORY_ROLLUP_JS"
+ file="${root_gen_dir}\chrome\browser\resources\history\history.rollup.js"
preprocess="true"
type="BINDATA"
compress="gzip"
use_base_dir="false" />
- <include name="IDR_HISTORY_LAZY_LOAD_VULCANIZED_HTML"
- file="${root_gen_dir}\chrome\browser\resources\history\lazy_load.vulcanized.html"
+ <include name="IDR_HISTORY_LAZY_LOAD_ROLLUP_JS"
+ file="${root_gen_dir}\chrome\browser\resources\history\lazy_load.rollup.js"
preprocess="true"
type="BINDATA"
compress="gzip"
use_base_dir="false" />
- <include name="IDR_HISTORY_LAZY_LOAD_CRISPER_JS"
- file="${root_gen_dir}\chrome\browser\resources\history\lazy_load.crisper.js"
+ <include name="IDR_HISTORY_SHARED_ROLLUP_JS"
+ file="${root_gen_dir}\chrome\browser\resources\history\shared.rollup.js"
preprocess="true"
type="BINDATA"
compress="gzip"
diff --git a/chromium/chrome/browser/resources/history/history_toolbar.html b/chromium/chrome/browser/resources/history/history_toolbar.html
index 68cf4bc6690..f195233e447 100644
--- a/chromium/chrome/browser/resources/history/history_toolbar.html
+++ b/chromium/chrome/browser/resources/history/history_toolbar.html
@@ -1,14 +1,3 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar.html">
-<link rel="import" href="browser_service.html">
-<link rel="import" href="shared_style.html">
-<link rel="import" href="strings.html">
-
-<!-- Lazy loaded: cr-toolbar-selection-overlay. -->
-
-<dom-module id="history-toolbar">
- <template>
<style include="shared-style">
:host {
display: flex;
@@ -59,6 +48,3 @@
on-clear-selected-items="clearSelectedItems"
on-delete-selected-items="deleteSelectedItems">
</cr-toolbar-selection-overlay>
- </template>
- <script src="history_toolbar.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/history_toolbar.js b/chromium/chrome/browser/resources/history/history_toolbar.js
index e869dff0d23..07fb6424108 100644
--- a/chromium/chrome/browser/resources/history/history_toolbar.js
+++ b/chromium/chrome/browser/resources/history/history_toolbar.js
@@ -2,8 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {Polymer, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
+import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import './shared_style.js';
+import './strings.js';
+
Polymer({
is: 'history-toolbar',
+
+ _template: html`{__html_template__}`,
+
properties: {
// Number of history items currently selected.
// TODO(calamity): bind this to
@@ -59,11 +69,11 @@ Polymer({
.getSearchField();
},
- deleteSelectedItems: function() {
+ deleteSelectedItems() {
this.fire('delete-selected');
},
- clearSelectedItems: function() {
+ clearSelectedItems() {
this.fire('unselect-all');
},
@@ -72,7 +82,7 @@ Polymer({
* are currently selected.
* @private
*/
- changeToolbarView_: function() {
+ changeToolbarView_() {
this.itemsSelected_ = this.count > 0;
},
@@ -81,8 +91,8 @@ Polymer({
* reflect the new search term.
* @private
*/
- searchTermChanged_: function() {
- if (this.searchField.getValue() != this.searchTerm) {
+ searchTermChanged_() {
+ if (this.searchField.getValue() !== this.searchTerm) {
this.searchField.showAndFocus();
this.searchField.setValue(this.searchTerm);
}
@@ -93,7 +103,7 @@ Polymer({
* @return {boolean}
* @private
*/
- canShowMenuPromo_: function(showMenuPromo) {
+ canShowMenuPromo_(showMenuPromo) {
return this.showMenuPromo && !loadTimeData.getBoolean('isGuestSession');
},
@@ -101,12 +111,12 @@ Polymer({
* @param {!CustomEvent<string>} event
* @private
*/
- onSearchChanged_: function(event) {
+ onSearchChanged_(event) {
this.fire('change-query', {search: event.detail});
},
/** @private */
- numberOfItemsSelected_: function(count) {
+ numberOfItemsSelected_(count) {
return count > 0 ? loadTimeData.getStringF('itemsSelected', count) : '';
},
});
diff --git a/chromium/chrome/browser/resources/history/lazy_load.html b/chromium/chrome/browser/resources/history/lazy_load.html
deleted file mode 100644
index 567691b16bb..00000000000
--- a/chromium/chrome/browser/resources/history/lazy_load.html
+++ /dev/null
@@ -1,13 +0,0 @@
-<html>
-<head></head>
-<body>
- <link rel="import" href="synced_device_manager.html">
- <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
- <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
- <link rel="import" href="chrome://resources/cr_elements/cr_checkbox/cr_checkbox.html">
- <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
- <link rel="import" href="chrome://resources/cr_elements/cr_drawer/cr_drawer.html">
- <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
- <link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.html">
-</body>
-</html>
diff --git a/chromium/chrome/browser/resources/history/lazy_load.js b/chromium/chrome/browser/resources/history/lazy_load.js
new file mode 100644
index 00000000000..3b412fcba78
--- /dev/null
+++ b/chromium/chrome/browser/resources/history/lazy_load.js
@@ -0,0 +1,12 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import './synced_device_manager.js';
+import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.m.js';
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
+import 'chrome://resources/cr_elements/cr_drawer/cr_drawer.m.js';
+import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
+import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.m.js';
diff --git a/chromium/chrome/browser/resources/history/query_manager.html b/chromium/chrome/browser/resources/history/query_manager.html
deleted file mode 100644
index 7afc93f756e..00000000000
--- a/chromium/chrome/browser/resources/history/query_manager.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-<script src="query_manager.js"></script>
diff --git a/chromium/chrome/browser/resources/history/query_manager.js b/chromium/chrome/browser/resources/history/query_manager.js
index 3d801026eab..432ed83034b 100644
--- a/chromium/chrome/browser/resources/history/query_manager.js
+++ b/chromium/chrome/browser/resources/history/query_manager.js
@@ -2,6 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {BrowserService} from './browser_service.js';
+import {HistoryQuery, HistoryEntry, QueryResult} from './externs.js';
+import {QueryState} from './externs.js';
+
Polymer({
is: 'history-query-manager',
@@ -10,20 +15,22 @@ Polymer({
queryState: {
type: Object,
notify: true,
- value: function() {
+ value() {
return {
// Whether the most recent query was incremental.
incremental: false,
// A query is initiated by page load.
querying: true,
- queryingDisabled: false,
searchTerm: '',
};
},
},
/** @type {QueryResult} */
- queryResult: Object,
+ queryResult: {
+ type: Object,
+ notify: true,
+ },
/** @type {?HistoryRouterElement} */
router: Object,
@@ -37,7 +44,7 @@ Polymer({
documentListeners_: {},
/** @override */
- attached: function() {
+ attached() {
this.documentListeners_['change-query'] = this.onChangeQuery_.bind(this);
this.documentListeners_['query-history'] = this.onQueryHistory_.bind(this);
@@ -47,43 +54,42 @@ Polymer({
},
/** @override */
- detached: function() {
+ detached() {
for (const e in this.documentListeners_) {
document.removeEventListener(e, this.documentListeners_[e]);
}
},
+ initialize() {
+ this.queryHistory_(false /* incremental */);
+ },
+
/**
* @param {boolean} incremental
* @private
*/
- queryHistory_: function(incremental) {
- const queryState = this.queryState;
-
- if (queryState.queryingDisabled) {
- return;
- }
-
+ queryHistory_(incremental) {
this.set('queryState.querying', true);
this.set('queryState.incremental', incremental);
- if (incremental) {
- history.BrowserService.getInstance().queryHistoryContinuation();
- } else {
- history.BrowserService.getInstance().queryHistory(queryState.searchTerm);
- }
+ const browserService = BrowserService.getInstance();
+ const promise = incremental ?
+ browserService.queryHistoryContinuation() :
+ browserService.queryHistory(this.queryState.searchTerm);
+ // Ignore rejected (cancelled) queries.
+ promise.then(result => this.onQueryResult_(result), () => {});
},
/**
* @param {!Event} e
* @private
*/
- onChangeQuery_: function(e) {
+ onChangeQuery_(e) {
const changes = /** @type {{search: ?string}} */ (e.detail);
let needsUpdate = false;
- if (changes.search != null &&
- changes.search != this.queryState.searchTerm) {
+ if (changes.search !== null &&
+ changes.search !== this.queryState.searchTerm) {
this.set('queryState.searchTerm', changes.search);
needsUpdate = true;
}
@@ -100,16 +106,29 @@ Polymer({
* @param {!Event} e
* @private
*/
- onQueryHistory_: function(e) {
+ onQueryHistory_(e) {
this.queryHistory_(/** @type {boolean} */ (e.detail));
return false;
},
+ /**
+ * @param {{info: !HistoryQuery,
+ * value: !Array<!HistoryEntry>}} results List of results with
+ * information about the query.
+ * @private
+ */
+ onQueryResult_(results) {
+ this.set('queryState.querying', false);
+ this.set('queryResult.info', results.info);
+ this.set('queryResult.results', results.value);
+ this.fire('query-finished');
+ },
+
/** @private */
- searchTermChanged_: function() {
+ searchTermChanged_() {
// TODO(tsergeant): Ignore incremental searches in this metric.
if (this.queryState.searchTerm) {
- history.BrowserService.getInstance().recordAction('Search');
+ BrowserService.getInstance().recordAction('Search');
}
},
});
diff --git a/chromium/chrome/browser/resources/history/router.html b/chromium/chrome/browser/resources/history/router.html
index d53cc985e9a..b6c9f9a615f 100644
--- a/chromium/chrome/browser/resources/history/router.html
+++ b/chromium/chrome/browser/resources/history/router.html
@@ -1,12 +1,3 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-location/iron-location.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-location/iron-query-params.html">
-
-<dom-module id="history-router">
- <template>
<iron-location query="{{urlQuery_}}" path="{{path_}}"></iron-location>
<iron-query-params params-string="{{query_}}"
params-object="{{queryParams_}}"></iron-query-params>
- </template>
- <script src="router.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/router.js b/chromium/chrome/browser/resources/history/router.js
index 1f1327c316f..2c43ccac767 100644
--- a/chromium/chrome/browser/resources/history/router.js
+++ b/chromium/chrome/browser/resources/history/router.js
@@ -2,9 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {Polymer, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import 'chrome://resources/polymer/v3_0/iron-location/iron-location.js';
+import 'chrome://resources/polymer/v3_0/iron-location/iron-query-params.js';
+import {QueryState} from './externs.js';
+
Polymer({
is: 'history-router',
+ _template: html`{__html_template__}`,
+
properties: {
selectedPage: {
type: String,
@@ -40,7 +47,7 @@ Polymer({
],
/** @override */
- attached: function() {
+ attached() {
// Redirect legacy search URLs to URLs compatible with History.
if (window.location.hash) {
window.location.href = window.location.href.split('#')[0] + '?' +
@@ -53,24 +60,24 @@ Polymer({
* @param {?string} previous Previous value of the query.
* @private
*/
- onQueryChanged_: function(current, previous) {
+ onQueryChanged_(current, previous) {
if (previous !== undefined) {
this.urlQuery_ = this.query_;
}
},
/** @private */
- onUrlQueryChanged_: function() {
+ onUrlQueryChanged_() {
this.query_ = this.urlQuery_;
},
/**
* Write all relevant page state to the URL.
*/
- serializeUrl: function() {
+ serializeUrl() {
let path = this.selectedPage;
- if (path == 'history') {
+ if (path === 'history') {
path = '';
}
@@ -81,7 +88,7 @@ Polymer({
},
/** @private */
- selectedPageChanged_: function() {
+ selectedPageChanged_() {
// Update the URL if the page was changed externally, but ignore the update
// if it came from parseUrl_().
if (!this.parsing_) {
@@ -90,7 +97,7 @@ Polymer({
},
/** @private */
- parseUrl_: function() {
+ parseUrl_() {
this.parsing_ = true;
const changes = {};
const sections = this.path_.substr(1).split('/');
@@ -108,7 +115,7 @@ Polymer({
},
/** @private */
- onUrlChanged_: function() {
+ onUrlChanged_() {
// Changing the url and query parameters at the same time will cause two
// calls to onUrlChanged_. Debounce the actual work so that these two
// changes get processed together.
diff --git a/chromium/chrome/browser/resources/history/searched_label.html b/chromium/chrome/browser/resources/history/searched_label.html
deleted file mode 100644
index a91da5c5f9c..00000000000
--- a/chromium/chrome/browser/resources/history/searched_label.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/html/util.html">
-
-<dom-module id="history-searched-label">
- <script src="searched_label.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/searched_label.js b/chromium/chrome/browser/resources/history/searched_label.js
index 573c703a77c..dfa9837fe30 100644
--- a/chromium/chrome/browser/resources/history/searched_label.js
+++ b/chromium/chrome/browser/resources/history/searched_label.js
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {quoteString} from 'chrome://resources/js/util.m.js';
+
Polymer({
is: 'history-searched-label',
@@ -20,14 +23,15 @@ Polymer({
* occurrences of the search term in bold.
* @private
*/
- setSearchedTextToBold_: function() {
+ setSearchedTextToBold_() {
if (this.title === undefined) {
return;
}
const titleText = this.title;
- if (this.searchTerm == '' || this.searchTerm == null) {
+ if (this.searchTerm === '' || this.searchTerm === null ||
+ this.searchTerm === undefined) {
this.textContent = titleText;
return;
}
diff --git a/chromium/chrome/browser/resources/history/shared_style.html b/chromium/chrome/browser/resources/history/shared_style.html
index c915d823deb..fb85d9ee6a1 100644
--- a/chromium/chrome/browser/resources/history/shared_style.html
+++ b/chromium/chrome/browser/resources/history/shared_style.html
@@ -1,8 +1,3 @@
-<link rel="import" href="shared_vars.html">
-<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-
-<dom-module id="shared-style">
<template>
<style include="cr-hidden-style">
a {
@@ -59,4 +54,3 @@
}
</style>
</template>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/shared_style.js b/chromium/chrome/browser/resources/history/shared_style.js
new file mode 100644
index 00000000000..94a61b7934c
--- /dev/null
+++ b/chromium/chrome/browser/resources/history/shared_style.js
@@ -0,0 +1,13 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import './shared_vars.js';
+import 'chrome://resources/cr_elements/hidden_style_css.m.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+
+const template = document.createElement('template');
+template.innerHTML = `
+<dom-module id="shared-style">{__html_template__}</dom-module>
+`;
+document.body.appendChild(template.content.cloneNode(true));
diff --git a/chromium/chrome/browser/resources/history/shared_vars.html b/chromium/chrome/browser/resources/history/shared_vars.html
index ade6397b74d..0a91d29e929 100644
--- a/chromium/chrome/browser/resources/history/shared_vars.html
+++ b/chromium/chrome/browser/resources/history/shared_vars.html
@@ -1,7 +1,3 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
<custom-style>
<style>
diff --git a/chromium/chrome/browser/resources/history/shared_vars.js b/chromium/chrome/browser/resources/history/shared_vars.js
new file mode 100644
index 00000000000..22d1ad54a34
--- /dev/null
+++ b/chromium/chrome/browser/resources/history/shared_vars.js
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {Polymer, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import 'chrome://resources/polymer/v3_0/paper-styles/color.js';
+
+const $_documentContainer = document.createElement('template');
+$_documentContainer.innerHTML = `{__html_template__}`;
+document.head.appendChild($_documentContainer.content);
diff --git a/chromium/chrome/browser/resources/history/side_bar.html b/chromium/chrome/browser/resources/history/side_bar.html
index 73fa9dec87d..372d46cf8ef 100644
--- a/chromium/chrome/browser/resources/history/side_bar.html
+++ b/chromium/chrome/browser/resources/history/side_bar.html
@@ -1,21 +1,3 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="chrome://resources/cr_components/managed_footnote/managed_footnote.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-selector/iron-selector.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/typography.html">
-<link rel="import" href="browser_service.html">
-<link rel="import" href="shared_style.html">
-<link rel="import" href="strings.html">
-
-<dom-module id="history-side-bar">
- <template>
<style include="shared-style cr-icons">
:host {
display: flex;
@@ -145,6 +127,3 @@
</div>
</div>
</iron-selector>
- </template>
- <script src="side_bar.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/side_bar.js b/chromium/chrome/browser/resources/history/side_bar.js
index 5d325d21c0f..018d05c01df 100644
--- a/chromium/chrome/browser/resources/history/side_bar.js
+++ b/chromium/chrome/browser/resources/history/side_bar.js
@@ -2,10 +2,36 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {Polymer, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import 'chrome://resources/cr_components/managed_footnote/managed_footnote.m.js';
+import 'chrome://resources/cr_elements/cr_icons_css.m.js';
+import 'chrome://resources/cr_elements/icons.m.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {IronA11yKeysBehavior} from 'chrome://resources/polymer/v3_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
+import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
+import 'chrome://resources/polymer/v3_0/paper-ripple/paper-ripple.js';
+import 'chrome://resources/polymer/v3_0/paper-styles/color.js';
+import 'chrome://resources/polymer/v3_0/paper-styles/typography.js';
+import {BrowserService} from './browser_service.js';
+import './shared_style.js';
+import './strings.js';
+
+/**
+ * @typedef {{
+ * managed: boolean,
+ * otherFormsOfHistory: boolean,
+ * }}
+ */
+export let FooterInfo;
+
Polymer({
is: 'history-side-bar',
- behaviors: [Polymer.IronA11yKeysBehavior],
+ _template: html`{__html_template__}`,
+
+ behaviors: [IronA11yKeysBehavior],
properties: {
selectedPage: {
@@ -41,14 +67,14 @@ Polymer({
* @param {!CustomEvent<{keyboardEvent: !KeyboardEvent}>} e
* @private
*/
- onSpacePressed_: function(e) {
+ onSpacePressed_(e) {
e.detail.keyboardEvent.path[0].click();
},
/**
* @private
*/
- onSelectorActivate_: function() {
+ onSelectorActivate_() {
this.fire('history-close-drawer');
},
@@ -57,8 +83,8 @@ Polymer({
* @param {Event} e
* @private
*/
- onClearBrowsingDataTap_: function(e) {
- const browserService = history.BrowserService.getInstance();
+ onClearBrowsingDataTap_(e) {
+ const browserService = BrowserService.getInstance();
browserService.recordAction('InitClearBrowsingData');
browserService.openClearBrowsingData();
/** @type {PaperRippleElement} */ (this.$['cbd-ripple']).upAction();
@@ -69,7 +95,7 @@ Polymer({
* @return {string}
* @private
*/
- computeClearBrowsingDataTabIndex_: function() {
+ computeClearBrowsingDataTabIndex_() {
return this.guestSession_ ? '-1' : '';
},
@@ -78,7 +104,7 @@ Polymer({
* accessibility purposes, taps are handled separately by <iron-selector>.
* @private
*/
- onItemClick_: function(e) {
+ onItemClick_(e) {
e.preventDefault();
},
@@ -86,7 +112,7 @@ Polymer({
* @return {boolean}
* @private
*/
- computeShowFooter_: function(includeOtherFormsOfBrowsingHistory, managed) {
+ computeShowFooter_(includeOtherFormsOfBrowsingHistory, managed) {
return includeOtherFormsOfBrowsingHistory || managed;
},
});
diff --git a/chromium/chrome/browser/resources/history/strings.html b/chromium/chrome/browser/resources/history/strings.html
deleted file mode 100644
index 6565a6f748d..00000000000
--- a/chromium/chrome/browser/resources/history/strings.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<link rel="import" href="chrome://resources/html/load_time_data.html">
-
-<script src="chrome://history/strings.js"></script>
diff --git a/chromium/chrome/browser/resources/history/synced_device_card.html b/chromium/chrome/browser/resources/history/synced_device_card.html
index a8a9f1d5370..7f7b760db02 100644
--- a/chromium/chrome/browser/resources/history/synced_device_card.html
+++ b/chromium/chrome/browser/resources/history/synced_device_card.html
@@ -1,20 +1,3 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html">
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="chrome://resources/html/cr/ui/focus_row.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
-<link rel="import" href="chrome://resources/html/icon.html">
-<link rel="import" href="browser_service.html">
-<link rel="import" href="constants.html">
-<link rel="import" href="searched_label.html">
-<link rel="import" href="shared_style.html">
-<link rel="import" href="strings.html">
-
-<dom-module id="history-synced-device-card">
- <template>
<style include="shared-style">
:host {
@apply --card-sizing;
@@ -58,9 +41,9 @@
}
#history-item-container {
- @apply --cr-card-elevation;
background-color: var(--cr-card-background-color);
border-radius: var(--cr-card-border-radius);
+ box-shadow: var(--cr-card-shadow);
}
.item-container {
@@ -115,6 +98,3 @@
</div>
</iron-collapse>
</div>
- </template>
- <script src="synced_device_card.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/synced_device_card.js b/chromium/chrome/browser/resources/history/synced_device_card.js
index dbcb3ced83e..4e4c888e62a 100644
--- a/chromium/chrome/browser/resources/history/synced_device_card.js
+++ b/chromium/chrome/browser/resources/history/synced_device_card.js
@@ -2,9 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {Polymer, dom, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
+import 'chrome://resources/cr_elements/icons.m.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import {FocusRow} from 'chrome://resources/js/cr/ui/focus_row.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
+import {getFaviconForPageURL} from 'chrome://resources/js/icon.m.js';
+import {BrowserService} from './browser_service.js';
+import {SyncedTabsHistogram, SYNCED_TABS_HISTOGRAM_NAME} from './constants.js';
+import {ForeignSessionTab} from './externs.js';
+import './searched_label.js';
+import './shared_style.js';
+import './strings.js';
+
Polymer({
is: 'history-synced-device-card',
+ _template: html`{__html_template__}`,
+
properties: {
/**
* The list of tabs open for this device.
@@ -12,7 +30,7 @@ Polymer({
*/
tabs: {
type: Array,
- value: function() {
+ value() {
return [];
},
observer: 'updateIcons_'
@@ -48,16 +66,16 @@ Polymer({
/**
* Create FocusRows for this card. One is always made for the card heading and
* one for each result if the card is open.
- * @return {!Array<!cr.ui.FocusRow>}
+ * @return {!Array<!FocusRow>}
*/
- createFocusRows: function() {
- const titleRow = new cr.ui.FocusRow(this.$['card-heading'], null);
+ createFocusRows() {
+ const titleRow = new FocusRow(this.$['card-heading'], null);
titleRow.addItem('menu', '#menu-button');
titleRow.addItem('collapse', '#collapse-button');
const rows = [titleRow];
if (this.opened) {
this.shadowRoot.querySelectorAll('.item-container').forEach(function(el) {
- const row = new cr.ui.FocusRow(el, null);
+ const row = new FocusRow(el, null);
row.addItem('link', '.website-link');
rows.push(row);
});
@@ -67,12 +85,13 @@ Polymer({
/**
* Open a single synced tab.
- * @param {DomRepeatClickEvent} e
+ * @param {MouseEvent} e
* @private
*/
- openTab_: function(e) {
- const tab = /** @type {ForeignSessionTab} */ (e.model.tab);
- const browserService = history.BrowserService.getInstance();
+ openTab_(e) {
+ const model = /** @type {{model: Object}} */ (e).model;
+ const tab = /** @type {ForeignSessionTab} */ (model.tab);
+ const browserService = BrowserService.getInstance();
browserService.recordHistogram(
SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.LINK_CLICKED,
SyncedTabsHistogram.LIMIT);
@@ -84,12 +103,12 @@ Polymer({
/**
* Toggles the dropdown display of synced tabs for each device card.
*/
- toggleTabCard: function() {
+ toggleTabCard() {
const histogramValue = this.$.collapse.opened ?
SyncedTabsHistogram.COLLAPSE_SESSION :
SyncedTabsHistogram.EXPAND_SESSION;
- history.BrowserService.getInstance().recordHistogram(
+ BrowserService.getInstance().recordHistogram(
SYNCED_TABS_HISTOGRAM_NAME, histogramValue, SyncedTabsHistogram.LIMIT);
this.$.collapse.toggle();
@@ -98,7 +117,7 @@ Polymer({
},
/** @private */
- notifyFocusUpdate_: function() {
+ notifyFocusUpdate_() {
// Refresh focus after all rows are rendered.
this.fire('update-focus-grid');
},
@@ -108,22 +127,22 @@ Polymer({
* website is also set.
* @private
*/
- updateIcons_: function() {
+ updateIcons_() {
this.async(function() {
const icons = this.shadowRoot.querySelectorAll('.website-icon');
for (let i = 0; i < this.tabs.length; i++) {
// Entries on this UI are coming strictly from sync, so we can set
// |isSyncedUrlForHistoryUi| to true on the getFavicon call below.
- icons[i].style.backgroundImage = cr.icon.getFaviconForPageURL(
+ icons[i].style.backgroundImage = getFaviconForPageURL(
this.tabs[i].url, true, this.tabs[i].remoteIconUrlForUma);
}
});
},
/** @private */
- isWindowSeparatorIndex_: function(index, separatorIndexes) {
- return this.separatorIndexes.indexOf(index) != -1;
+ isWindowSeparatorIndex_(index, separatorIndexes) {
+ return this.separatorIndexes.indexOf(index) !== -1;
},
/**
@@ -131,7 +150,7 @@ Polymer({
* @return {string}
* @private
*/
- getCollapseIcon_: function(opened) {
+ getCollapseIcon_(opened) {
return opened ? 'cr:expand-less' : 'cr:expand-more';
},
@@ -140,7 +159,7 @@ Polymer({
* @return {string}
* @private
*/
- getCollapseTitle_: function(opened) {
+ getCollapseTitle_(opened) {
return opened ? loadTimeData.getString('collapseSessionButton') :
loadTimeData.getString('expandSessionButton');
},
@@ -149,16 +168,16 @@ Polymer({
* @param {!Event} e
* @private
*/
- onMenuButtonTap_: function(e) {
+ onMenuButtonTap_(e) {
this.fire('open-menu', {
- target: Polymer.dom(e).localTarget,
+ target: dom(e).localTarget,
tag: this.sessionTag,
});
e.stopPropagation(); // Prevent iron-collapse.
},
- onLinkRightClick_: function() {
- history.BrowserService.getInstance().recordHistogram(
+ onLinkRightClick_() {
+ BrowserService.getInstance().recordHistogram(
SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.LINK_RIGHT_CLICKED,
SyncedTabsHistogram.LIMIT);
},
diff --git a/chromium/chrome/browser/resources/history/synced_device_manager.html b/chromium/chrome/browser/resources/history/synced_device_manager.html
index 7e714788853..61f2d58223c 100644
--- a/chromium/chrome/browser/resources/history/synced_device_manager.html
+++ b/chromium/chrome/browser/resources/history/synced_device_manager.html
@@ -1,18 +1,3 @@
-<link rel="import" href="chrome://resources/html/polymer.html">
-
-<link rel="import" href="chrome://resources/html/cr/ui/focus_grid.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
-<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<link rel="import" href="shared_style.html">
-<link rel="import" href="synced_device_card.html">
-<link rel="import" href="strings.html">
-
-<dom-module id="history-synced-device-manager">
- <template>
<style include="shared-style cr-shared-style">
:host {
display: block;
@@ -107,6 +92,3 @@
</cr-action-menu>
</template>
</cr-lazy-render>
- </template>
- <script src="synced_device_manager.js"></script>
-</dom-module>
diff --git a/chromium/chrome/browser/resources/history/synced_device_manager.js b/chromium/chrome/browser/resources/history/synced_device_manager.js
index c760a5bf5db..c030526bdae 100644
--- a/chromium/chrome/browser/resources/history/synced_device_manager.js
+++ b/chromium/chrome/browser/resources/history/synced_device_manager.js
@@ -2,6 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {Polymer, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {FocusGrid} from 'chrome://resources/js/cr/ui/focus_grid.m.js';
+import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js';
+import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.m.js';
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js';
+import 'chrome://resources/cr_elements/shared_style_css.m.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import './shared_style.js';
+import './synced_device_card.js';
+import './strings.js';
+import {BrowserService} from './browser_service.js';
+import {ForeignSession, ForeignSessionTab} from './externs.js';
+import {SyncedTabsHistogram, SYNCED_TABS_HISTOGRAM_NAME} from './constants.js';
+
/**
* @typedef {{device: string,
* lastUpdateTime: string,
@@ -16,6 +33,8 @@ let ForeignDeviceInternal;
Polymer({
is: 'history-synced-device-manager',
+ _template: html`{__html_template__}`,
+
properties: {
/**
* @type {?Array<!ForeignSession>}
@@ -36,7 +55,7 @@ Polymer({
*/
syncedDevices_: {
type: Array,
- value: function() {
+ value() {
return [];
},
},
@@ -74,27 +93,27 @@ Polymer({
'update-focus-grid': 'updateFocusGrid_',
},
- /** @type {?cr.ui.FocusGrid} */
+ /** @type {?FocusGrid} */
focusGrid_: null,
/** @override */
- attached: function() {
- this.focusGrid_ = new cr.ui.FocusGrid();
+ attached() {
+ this.focusGrid_ = new FocusGrid();
// Update the sign in state.
- history.BrowserService.getInstance().otherDevicesInitialized();
- history.BrowserService.getInstance().recordHistogram(
+ BrowserService.getInstance().otherDevicesInitialized();
+ BrowserService.getInstance().recordHistogram(
SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.INITIALIZED,
SyncedTabsHistogram.LIMIT);
},
/** @override */
- detached: function() {
+ detached() {
this.focusGrid_.destroy();
},
/** @return {HTMLElement} */
- getContentScrollTarget: function() {
+ getContentScrollTarget() {
return this;
},
@@ -103,13 +122,13 @@ Polymer({
* @return {!ForeignDeviceInternal}
* @private
*/
- createInternalDevice_: function(session) {
+ createInternalDevice_(session) {
let tabs = [];
const separatorIndexes = [];
for (let i = 0; i < session.windows.length; i++) {
const windowId = session.windows[i].sessionId;
const newTabs = session.windows[i].tabs;
- if (newTabs.length == 0) {
+ if (newTabs.length === 0) {
continue;
}
@@ -126,13 +145,13 @@ Polymer({
const searchText = this.searchTerm.toLowerCase();
for (let j = 0; j < newTabs.length; j++) {
const tab = newTabs[j];
- if (tab.title.toLowerCase().indexOf(searchText) != -1) {
+ if (tab.title.toLowerCase().indexOf(searchText) !== -1) {
tabs.push(tab);
windowAdded = true;
}
}
}
- if (windowAdded && i != session.windows.length - 1) {
+ if (windowAdded && i !== session.windows.length - 1) {
separatorIndexes.push(tabs.length - 1);
}
}
@@ -148,24 +167,24 @@ Polymer({
},
/** @private */
- onSignInTap_: function() {
- history.BrowserService.getInstance().startSignInFlow();
+ onSignInTap_() {
+ BrowserService.getInstance().startSignInFlow();
},
/** @private */
- onOpenMenu_: function(e) {
+ onOpenMenu_(e) {
const menu = /** @type {CrActionMenuElement} */ (this.$.menu.get());
this.actionMenuModel_ = e.detail.tag;
menu.showAt(e.detail.target);
- history.BrowserService.getInstance().recordHistogram(
+ BrowserService.getInstance().recordHistogram(
SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.SHOW_SESSION_MENU,
SyncedTabsHistogram.LIMIT);
},
/** @private */
- onOpenAllTap_: function() {
+ onOpenAllTap_() {
const menu = assert(this.$.menu.getIfExists());
- const browserService = history.BrowserService.getInstance();
+ const browserService = BrowserService.getInstance();
browserService.recordHistogram(
SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.OPEN_ALL,
SyncedTabsHistogram.LIMIT);
@@ -175,7 +194,7 @@ Polymer({
},
/** @private */
- updateFocusGrid_: function() {
+ updateFocusGrid_() {
if (!this.focusGrid_) {
return;
}
@@ -193,9 +212,9 @@ Polymer({
},
/** @private */
- onDeleteSessionTap_: function() {
+ onDeleteSessionTap_() {
const menu = assert(this.$.menu.getIfExists());
- const browserService = history.BrowserService.getInstance();
+ const browserService = BrowserService.getInstance();
browserService.recordHistogram(
SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.HIDE_FOR_NOW,
SyncedTabsHistogram.LIMIT);
@@ -205,7 +224,7 @@ Polymer({
},
/** @private */
- clearDisplayedSyncedDevices_: function() {
+ clearDisplayedSyncedDevices_() {
this.syncedDevices_ = [];
},
@@ -216,13 +235,13 @@ Polymer({
* @param {boolean} guestSession
* @return {boolean}
*/
- showNoSyncedMessage: function(
+ showNoSyncedMessage(
signInState, syncedDevicesLength, guestSession) {
if (guestSession) {
return true;
}
- return signInState && syncedDevicesLength == 0;
+ return signInState && syncedDevicesLength === 0;
},
/**
@@ -232,10 +251,10 @@ Polymer({
* @param {boolean} guestSession
* @return {boolean}
*/
- showSignInGuide: function(signInState, guestSession) {
+ showSignInGuide(signInState, guestSession) {
const show = !signInState && !guestSession;
if (show) {
- history.BrowserService.getInstance().recordAction(
+ BrowserService.getInstance().recordAction(
'Signin_Impression_FromRecentTabs');
}
@@ -247,7 +266,7 @@ Polymer({
* are no synced tabs.
* @return {string}
*/
- noSyncedTabsMessage: function() {
+ noSyncedTabsMessage() {
let stringName = this.fetchingSyncedTabs_ ? 'loading' : 'noSyncedResults';
if (this.searchTerm !== '') {
stringName = 'noSearchResults';
@@ -263,7 +282,7 @@ Polymer({
* this approach seems to have acceptable performance.
* @param {?Array<!ForeignSession>} sessionList
*/
- updateSyncedDevices: function(sessionList) {
+ updateSyncedDevices(sessionList) {
this.fetchingSyncedTabs_ = false;
if (!sessionList) {
@@ -272,7 +291,7 @@ Polymer({
if (sessionList.length > 0 && !this.hasSeenForeignData_) {
this.hasSeenForeignData_ = true;
- history.BrowserService.getInstance().recordHistogram(
+ BrowserService.getInstance().recordHistogram(
SYNCED_TABS_HISTOGRAM_NAME, SyncedTabsHistogram.HAS_FOREIGN_DATA,
SyncedTabsHistogram.LIMIT);
}
@@ -280,7 +299,7 @@ Polymer({
const devices = [];
sessionList.forEach((session) => {
const device = this.createInternalDevice_(session);
- if (device.tabs.length != 0) {
+ if (device.tabs.length !== 0) {
devices.push(device);
}
});
@@ -295,7 +314,7 @@ Polymer({
* @param {?boolean} current
* @param {?boolean} previous
*/
- signInStateChanged_: function(current, previous) {
+ signInStateChanged_(current, previous) {
if (previous === undefined) {
return;
}
@@ -312,7 +331,7 @@ Polymer({
this.fetchingSyncedTabs_ = true;
},
- searchTermChanged: function(searchTerm) {
+ searchTermChanged(searchTerm) {
this.clearDisplayedSyncedDevices_();
this.updateSyncedDevices(this.sessionList);
}
diff --git a/chromium/chrome/browser/resources/identity_internals/identity_internals.js b/chromium/chrome/browser/resources/identity_internals/identity_internals.js
index 76de89b9d71..5e3fd4fb82d 100644
--- a/chromium/chrome/browser/resources/identity_internals/identity_internals.js
+++ b/chromium/chrome/browser/resources/identity_internals/identity_internals.js
@@ -22,7 +22,7 @@ cr.define('identity_internals', function() {
__proto__: HTMLDivElement.prototype,
/** @override */
- decorate: function() {
+ decorate() {
this.textContent = '';
this.id = this.data_.accessToken;
@@ -53,7 +53,7 @@ cr.define('identity_internals', function() {
* @param {string} accessor Additional class to tag the field for testing.
* @return {HTMLElement} An HTML element with the property name and value.
*/
- createEntry_: function(label, value, accessor) {
+ createEntry_(label, value, accessor) {
const row = this.ownerDocument.createElement('tr');
const labelField = this.ownerDocument.createElement('td');
labelField.classList.add('label');
@@ -71,7 +71,7 @@ cr.define('identity_internals', function() {
* Creates an entry for a list of token scopes.
* @return {!HTMLElement} An HTML element with scopes.
*/
- createEntryForScopes_: function() {
+ createEntryForScopes_() {
const row = this.ownerDocument.createElement('tr');
const labelField = this.ownerDocument.createElement('td');
labelField.classList.add('label');
@@ -93,7 +93,7 @@ cr.define('identity_internals', function() {
* @return {HTMLElement} An HTML element with actionable buttons for the
* token.
*/
- createButtons_: function() {
+ createButtons_() {
const row = this.ownerDocument.createElement('tr');
const buttonHolder = this.ownerDocument.createElement('td');
buttonHolder.colSpan = 2;
@@ -109,7 +109,7 @@ cr.define('identity_internals', function() {
* @return {!HTMLButtonElement} The created revoke button.
* @private
*/
- createRevokeButton_: function() {
+ createRevokeButton_() {
const revokeButton = this.ownerDocument.createElement('button');
revokeButton.classList.add('revoke-button');
revokeButton.addEventListener('click', function() {
@@ -134,7 +134,7 @@ cr.define('identity_internals', function() {
__proto__: HTMLDivElement.prototype,
/** @override */
- decorate: function() {
+ decorate() {
this.textContent = '';
this.showTokenNodes_();
},
@@ -142,7 +142,7 @@ cr.define('identity_internals', function() {
/**
* Populates the list of tokens.
*/
- showTokenNodes_: function() {
+ showTokenNodes_() {
this.data_.forEach(function(tokenInfo) {
this.appendChild(new TokenListItem(tokenInfo));
}, this);
@@ -154,7 +154,7 @@ cr.define('identity_internals', function() {
* @param {string} accessToken The id of the token to remove.
* @private
*/
- removeTokenNode_: function(accessToken) {
+ removeTokenNode_(accessToken) {
let tokenIndex;
for (let index = 0; index < this.data_.length; index++) {
if (this.data_[index].accessToken == accessToken) {
diff --git a/chromium/chrome/browser/resources/identity_scope_approval_dialog/inject.js b/chromium/chrome/browser/resources/identity_scope_approval_dialog/inject.js
new file mode 100644
index 00000000000..74c5ab702c9
--- /dev/null
+++ b/chromium/chrome/browser/resources/identity_scope_approval_dialog/inject.js
@@ -0,0 +1,18 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+const injectCode =
+ `const identityAppExtensionId = 'ahjaciijnoiaklcomgnblndopackapon';
+if (!window.OAuthConsent) {
+ window.OAuthConsent = {};
+}
+if (!window.OAuthConsent.setConsentResult) {
+ window.OAuthConsent.setConsentResult = function(result) {
+ chrome.runtime.sendMessage(identityAppExtensionId, {consentResult: result});
+ };
+}`;
+
+const script = document.createElement('script');
+script.innerText = injectCode;
+document.documentElement.prepend(script);
diff --git a/chromium/chrome/browser/resources/identity_scope_approval_dialog/manifest.json b/chromium/chrome/browser/resources/identity_scope_approval_dialog/manifest.json
index 4b2469536a9..89cb20dd27d 100644
--- a/chromium/chrome/browser/resources/identity_scope_approval_dialog/manifest.json
+++ b/chromium/chrome/browser/resources/identity_scope_approval_dialog/manifest.json
@@ -22,5 +22,8 @@
"content_security_policy": "default-src 'none'; script-src 'self' blob: filesystem:; style-src 'self' blob: filesystem:; img-src chrome://theme; object-src 'self' blob: filesystem:"
},
"display_in_launcher": false,
- "display_in_new_tab_page": false
+ "display_in_new_tab_page": false,
+ "externally_connectable": {
+ "matches" : ["https://accounts.google.com/*"]
+ }
}
diff --git a/chromium/chrome/browser/resources/identity_scope_approval_dialog/scope_approval_dialog.js b/chromium/chrome/browser/resources/identity_scope_approval_dialog/scope_approval_dialog.js
index 64f7edb8920..32abed9db34 100644
--- a/chromium/chrome/browser/resources/identity_scope_approval_dialog/scope_approval_dialog.js
+++ b/chromium/chrome/browser/resources/identity_scope_approval_dialog/scope_approval_dialog.js
@@ -3,6 +3,7 @@
// found in the LICENSE file.
let webview;
+let windowId;
/**
* Points the webview to the starting URL of a scope authorization
@@ -19,6 +20,13 @@ function loadAuthUrlAndShowWindow(url, win) {
window.open(e.targetUrl);
});
+ webview.addContentScripts([{
+ name: 'injectRule',
+ matches: ['https://accounts.google.com/*'],
+ js: {files: ['inject.js']},
+ run_at: 'document_start'
+ }]);
+
// Request a customized view from GAIA.
webview.request.onBeforeSendHeaders.addListener(
function(details) {
@@ -36,13 +44,19 @@ function loadAuthUrlAndShowWindow(url, win) {
}
webview.src = url;
- if (win) {
- webview.addEventListener('loadstop', function() {
+ webview.addEventListener('loadstop', function() {
+ if (win) {
win.show();
- });
- }
+ windowId = win.id;
+ }
+ });
}
+chrome.runtime.onMessageExternal.addListener(function(
+ message, sender, sendResponse) {
+ chrome.identityPrivate.setConsentResult(message.consentResult, windowId);
+});
+
document.addEventListener('DOMContentLoaded', function() {
webview = document.querySelector('webview');
diff --git a/chromium/chrome/browser/resources/inline_login/inline_login.js b/chromium/chrome/browser/resources/inline_login/inline_login.js
index 98b6518a718..44635972745 100644
--- a/chromium/chrome/browser/resources/inline_login/inline_login.js
+++ b/chromium/chrome/browser/resources/inline_login/inline_login.js
@@ -66,8 +66,11 @@ cr.define('inline.login', function() {
*/
function initialize() {
$('navigation-button').addEventListener('click', navigationButtonClicked);
- cr.addWebUIListener('showBackButton', showBackButton);
- cr.addWebUIListener('navigateBackInWebview', navigateBackInWebview);
+ cr.addWebUIListener('show-back-button', showBackButton);
+ cr.addWebUIListener('navigate-back-in-webview', navigateBackInWebview);
+ cr.addWebUIListener('load-auth-extension', loadAuthExtension);
+ cr.addWebUIListener('close-dialog', closeDialog);
+
authExtHost = new cr.login.Authenticator('signin-frame');
authExtHost.addEventListener('dropLink', onDropLink);
authExtHost.addEventListener('ready', onAuthReady);
diff --git a/chromium/chrome/browser/resources/inspect/inspect.css b/chromium/chrome/browser/resources/inspect/inspect.css
index 64084cd0f18..e13ea7a561a 100644
--- a/chromium/chrome/browser/resources/inspect/inspect.css
+++ b/chromium/chrome/browser/resources/inspect/inspect.css
@@ -257,6 +257,10 @@ img {
margin-top: 5px;
}
+.actions {
+ user-select: none;
+}
+
.action {
color: rgb(17, 85, 204);
cursor: pointer;
@@ -322,7 +326,7 @@ dialog.config::backdrop {
dialog.config {
background: white;
- border: 0;
+ border: 1px solid transparent;
border-radius: 3px;
box-shadow: 0 4px 23px 5px rgba(0, 0, 0, 0.2), 0 2px 6px rgba(0,0,0,0.15);
color: #333;
@@ -440,3 +444,48 @@ dialog.target-discovery .port-forwarding {
.config-buttons > label {
flex-grow: 1
}
+
+@media (forced-colors: active) {
+ .content-header {
+ background: Canvas;
+ border-bottom-color: transparent;
+ forced-color-adjust: none;
+ }
+ .tab-header {
+ forced-color-adjust: none;
+ }
+ .tab-header.selected {
+ background-color: Highlight;
+ border-inline-start-color: Highlight;
+ }
+ .tab-header > button {
+ background-color: ButtonFace;
+ }
+ .tab-header:not(.selected) > button {
+ color: ButtonText;
+ }
+ .tab-header.selected > button {
+ background-color: Highlight;
+ color: HighlightText;
+ }
+ .tab-header > button:focus {
+ background-color: Highlight;
+ color: HighlightText;
+ outline: none;
+ }
+ dialog.config {
+ background: Canvas;
+ border-color: CanvasText;
+ color: CanvasText;
+ forced-color-adjust: none;
+ }
+ .config-list-row.selected,
+ .config-list-row.selected:hover,
+ .config-list-row:hover {
+ background-color: Highlight;
+ }
+ .config-list-row input {
+ border-color: ButtonText;
+ outline: none;
+ }
+}
diff --git a/chromium/chrome/browser/resources/inspect/inspect.js b/chromium/chrome/browser/resources/inspect/inspect.js
index c0e873b4a7e..74065a6b484 100644
--- a/chromium/chrome/browser/resources/inspect/inspect.js
+++ b/chromium/chrome/browser/resources/inspect/inspect.js
@@ -573,6 +573,9 @@ function addWebViewDescription(row, webview) {
} else {
viewStatus.visibility = 'empty';
}
+ if (webview.never_attached) {
+ viewStatus.visibility += ' never-attached';
+ }
if (webview.attached) {
viewStatus.position =
'at (' + webview.screenX + ', ' + webview.screenY + ')';
diff --git a/chromium/chrome/browser/resources/interventions_internals/BUILD.gn b/chromium/chrome/browser/resources/interventions_internals/BUILD.gn
index e6c48042880..0b1deb57020 100644
--- a/chromium/chrome/browser/resources/interventions_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/interventions_internals/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":index",
- ]
+ deps = [ ":index" ]
}
js_library("index") {
diff --git a/chromium/chrome/browser/resources/interventions_internals/index.js b/chromium/chrome/browser/resources/interventions_internals/index.js
index c417033d8c4..3e58e98b90f 100644
--- a/chromium/chrome/browser/resources/interventions_internals/index.js
+++ b/chromium/chrome/browser/resources/interventions_internals/index.js
@@ -465,7 +465,7 @@ InterventionsInternalPageImpl.prototype = {
* @param {!mojom.MessageLog} log The new log message recorded by
* PreviewsLogger.
*/
- logNewMessage: function(log) {
+ logNewMessage(log) {
insertMessageRowToMessageLogTable(
log.time, log.type, log.description, log.url.url, log.pageId);
},
@@ -478,7 +478,7 @@ InterventionsInternalPageImpl.prototype = {
* @param {number} time The time when the host was blacklisted in milliseconds
* since Unix epoch.
*/
- onBlacklistedHost: function(host, time) {
+ onBlacklistedHost(host, time) {
const row = document.createElement('tr');
row.setAttribute('class', 'blacklisted-host-row');
@@ -503,7 +503,7 @@ InterventionsInternalPageImpl.prototype = {
* @param {boolean} blacklisted The time of the event in milliseconds since
* Unix epoch.
*/
- onUserBlacklistedStatusChange: function(blacklisted) {
+ onUserBlacklistedStatusChange(blacklisted) {
const userBlacklistedStatus = $('user-blacklisted-status-value');
userBlacklistedStatus.textContent =
(blacklisted ? 'Blacklisted' : 'Not blacklisted');
@@ -516,7 +516,7 @@ InterventionsInternalPageImpl.prototype = {
* @param {number} time The time of the event in milliseconds since Unix
* epoch.
*/
- onBlacklistCleared: function(time) {
+ onBlacklistCleared(time) {
const blacklistClearedStatus = $('blacklist-last-cleared-time');
blacklistClearedStatus.textContent = getTimeFormat(time);
@@ -541,7 +541,7 @@ InterventionsInternalPageImpl.prototype = {
* @param {boolean} ignored The new status of whether the previews blacklist
* decisions is blacklisted or not.
*/
- onIgnoreBlacklistDecisionStatusChanged: function(ignored) {
+ onIgnoreBlacklistDecisionStatusChanged(ignored) {
const ignoreButton = $('ignore-blacklist-button');
ignoreButton.textContent =
ignored ? ENABLE_BLACKLIST_BUTTON : IGNORE_BLACKLIST_BUTTON;
@@ -560,7 +560,7 @@ InterventionsInternalPageImpl.prototype = {
* @param {string} maxInterventionType The string representation of the
* session's maximum ECT threshold for interventions.
*/
- updateEffectiveConnectionType: function(type, maxInterventionType) {
+ updateEffectiveConnectionType(type, maxInterventionType) {
// Change the current ECT.
const ectType = $('nqe-type');
ectType.textContent = type;
@@ -589,7 +589,7 @@ InterventionsInternalPageImpl.prototype = {
/**
* Returns a remote interface to the receiver.
*/
- bindNewPipeAndPassRemote: function() {
+ bindNewPipeAndPassRemote() {
const helper = this.receiver_.$;
return helper.bindNewPipeAndPassRemote();
},
diff --git a/chromium/chrome/browser/resources/local_discovery/local_discovery.js b/chromium/chrome/browser/resources/local_discovery/local_discovery.js
index 1d2a54502cf..7ba7f554515 100644
--- a/chromium/chrome/browser/resources/local_discovery/local_discovery.js
+++ b/chromium/chrome/browser/resources/local_discovery/local_discovery.js
@@ -28,10 +28,11 @@ cr.define('local_discovery', function() {
let isUserLoggedIn = true;
/**
- * Whether or not the user is supervised or off the record.
+ * Whether or not the user's profile is restricted because of being
+ * supervised, off the record, or limited by an enterprise policy.
* @type bool
*/
- let isUserSupervisedOrOffTheRecord = false;
+ let isUserProfileRestricted = false;
/**
* Whether or not the path-based dialog has been shown.
@@ -61,7 +62,7 @@ cr.define('local_discovery', function() {
* Update the device.
* @param {Object} info New information about the device.
*/
- updateDevice: function(info) {
+ updateDevice(info) {
this.info = info;
this.renderDevice();
},
@@ -69,14 +70,14 @@ cr.define('local_discovery', function() {
/**
* Delete the device.
*/
- removeDevice: function() {
+ removeDevice() {
this.deviceContainer().removeChild(this.domElement);
},
/**
* Render the device to the device list.
*/
- renderDevice: function() {
+ renderDevice() {
if (this.domElement) {
clearElement(this.domElement);
} else {
@@ -95,21 +96,21 @@ cr.define('local_discovery', function() {
/**
* Return the correct container for the device.
*/
- deviceContainer: function() {
+ deviceContainer() {
return $('register-device-list');
},
/**
* Register the device.
*/
- register: function() {
+ register() {
chrome.send('registerDevice', [this.info.service_name]);
setRegisterPage('register-printer-page-adding1');
},
/**
* Show registrtation UI for device.
*/
- showRegister: function() {
+ showRegister() {
$('register-continue').onclick = this.register.bind(this);
showRegisterOverlay();
@@ -117,7 +118,7 @@ cr.define('local_discovery', function() {
/**
* Set registration button enabled/disabled
*/
- setRegisterEnabled: function(isEnabled) {
+ setRegisterEnabled(isEnabled) {
this.registerEnabled = isEnabled;
if (this.registerButton) {
this.registerButton.disabled = !isEnabled;
@@ -138,7 +139,7 @@ cr.define('local_discovery', function() {
LocalDiscoveryFocusManager.prototype = {
__proto__: cr.ui.FocusManager.prototype,
/** @override */
- getFocusParent: function() {
+ getFocusParent() {
return document.querySelector('#overlay .showing') || $('main-page');
}
};
@@ -357,7 +358,7 @@ cr.define('local_discovery', function() {
} else {
$('no-printers-message').hidden = true;
$('register-login-promo').hidden =
- isUserLoggedIn || isUserSupervisedOrOffTheRecord;
+ isUserLoggedIn || isUserProfileRestricted;
}
if (!($('register-login-promo').hidden) ||
!($('cloud-devices-login-promo').hidden) ||
@@ -433,26 +434,31 @@ cr.define('local_discovery', function() {
}
/**
- * User is not logged in.
+ * Registers whether the user is logged in. Modifies the UI to display the
+ * appropriate content based on user log-in status and profile restrictions.
+ * @param {boolean} userLoggedIn Whether the user is logged in.
+ * @param {boolean} userProfileRestricted Whether the user profile's access to
+ * the local discovery page is restricted because of being supervised, off
+ * the record, or disallowed by policy.
*/
- function setUserLoggedIn(userLoggedIn, userSupervisedOrOffTheRecord) {
+ function setUserLoggedIn(userLoggedIn, userProfileRestricted) {
isUserLoggedIn = userLoggedIn;
- isUserSupervisedOrOffTheRecord = userSupervisedOrOffTheRecord;
+ isUserProfileRestricted = userProfileRestricted;
$('cloud-devices-login-promo').hidden =
- isUserLoggedIn || isUserSupervisedOrOffTheRecord;
+ isUserLoggedIn || isUserProfileRestricted;
$('register-overlay-login-promo').hidden =
- isUserLoggedIn || isUserSupervisedOrOffTheRecord;
+ isUserLoggedIn || isUserProfileRestricted;
$('register-continue').disabled =
- !isUserLoggedIn || isUserSupervisedOrOffTheRecord;
+ !isUserLoggedIn || isUserProfileRestricted;
- $('my-devices-container').hidden = userSupervisedOrOffTheRecord;
+ $('my-devices-container').hidden = isUserProfileRestricted;
- if (isUserSupervisedOrOffTheRecord) {
+ if (isUserProfileRestricted) {
$('cloud-print-connector-section').hidden = true;
}
- if (isUserLoggedIn && !isUserSupervisedOrOffTheRecord) {
+ if (isUserLoggedIn && !isUserProfileRestricted) {
requestDeviceList();
$('register-login-promo').hidden = true;
} else {
diff --git a/chromium/chrome/browser/resources/local_ntp/BUILD.gn b/chromium/chrome/browser/resources/local_ntp/BUILD.gn
index 15edd04f0af..77846905f27 100644
--- a/chromium/chrome/browser/resources/local_ntp/BUILD.gn
+++ b/chromium/chrome/browser/resources/local_ntp/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":local_ntp",
- ]
+ deps = [ ":local_ntp" ]
}
js_library("local_ntp") {
@@ -23,8 +21,6 @@ js_library("local_ntp") {
"utils.js",
"voice.js",
]
- deps = [
- "//ui/webui/resources/js:assert",
- ]
+ deps = [ "//ui/webui/resources/js:assert" ]
externs_list = [ "externs.js" ]
}
diff --git a/chromium/chrome/browser/resources/local_ntp/customize.js b/chromium/chrome/browser/resources/local_ntp/customize.js
index 7119d708109..b5d694d61cd 100644
--- a/chromium/chrome/browser/resources/local_ntp/customize.js
+++ b/chromium/chrome/browser/resources/local_ntp/customize.js
@@ -329,10 +329,6 @@ customize.setMenuVisibility = function() {
$(customize.IDS.UPLOAD_IMAGE).hidden = false;
$(customize.IDS.RESTORE_DEFAULT).hidden = false;
$(customize.IDS.EDIT_BG_DIVIDER).hidden = false;
- $(customize.IDS.COLORS_BUTTON).hidden = !configData.chromeColors;
- $(customize.IDS.COLOR_PICKER_CONTAINER)
- .classList.toggle(
- customize.CLASSES.VISIBLE, configData.chromeColorsCustomColorPicker);
};
/**
@@ -2282,12 +2278,6 @@ customize.loadColorsMenu = function() {
customize.loadColorMenuTiles = function() {
const colorsColl = ntpApiHandle.getColorsInfo();
for (let i = 0; i < colorsColl.length; ++i) {
- // After 4 color tiles create an empty tile to take the place of the color
- // picker. This is done so that the rest of the colors don't move if color
- // picker is not present.
- if (!configData.chromeColorsCustomColorPicker && i == 4) {
- $(customize.IDS.COLORS_MENU).appendChild(document.createElement('div'));
- }
const id = 'color_' + i;
const imageUrl = colorsColl[i].icon;
const dataset = {'color': colorsColl[i].color, 'id': colorsColl[i].id};
@@ -2311,26 +2301,19 @@ customize.loadColorMenuTiles = function() {
$(customize.IDS.COLORS_MENU).onkeydown = function(event) {
if (document.activeElement === $(customize.IDS.COLORS_MENU) &&
customize.arrowKeys.includes(event.keyCode)) {
- if (configData.chromeColorsCustomColorPicker) {
- $(customize.IDS.COLOR_PICKER_TILE).focus();
- } else {
- $(customize.IDS.COLORS_DEFAULT_ICON).focus();
- }
+ $(customize.IDS.COLOR_PICKER_TILE).focus();
event.preventDefault();
}
};
// Configure custom color picker.
- if (configData.chromeColorsCustomColorPicker) {
- $(customize.IDS.COLOR_PICKER_TILE).onclick = function(event) {
- $(customize.IDS.COLOR_PICKER).value = customize.customColorPicked;
- $(customize.IDS.COLOR_PICKER).click();
- };
- $(customize.IDS.COLOR_PICKER_TILE).onkeydown =
- customize.tileOnKeyDownInteraction;
- $(customize.IDS.COLOR_PICKER).onchange =
- customize.colorPickerTileInteraction;
- }
+ $(customize.IDS.COLOR_PICKER_TILE).onclick = function(event) {
+ $(customize.IDS.COLOR_PICKER).value = customize.customColorPicked;
+ $(customize.IDS.COLOR_PICKER).click();
+ };
+ $(customize.IDS.COLOR_PICKER_TILE).onkeydown =
+ customize.tileOnKeyDownInteraction;
+ $(customize.IDS.COLOR_PICKER).onchange = customize.colorPickerTileInteraction;
};
/**
@@ -2386,8 +2369,7 @@ customize.colorsMenuPreselectTile = function() {
}
}
} else if (
- configData.chromeColorsCustomColorPicker && ntpTheme.colorDark &&
- ntpTheme.colorLight && ntpTheme.colorPicked) {
+ ntpTheme.colorDark && ntpTheme.colorLight && ntpTheme.colorPicked) {
// Custom color is selected.
tile = $(customize.IDS.COLOR_PICKER_TILE);
diff --git a/chromium/chrome/browser/resources/local_ntp/externs.js b/chromium/chrome/browser/resources/local_ntp/externs.js
index b3cd6ddd552..62e31b4748f 100644
--- a/chromium/chrome/browser/resources/local_ntp/externs.js
+++ b/chromium/chrome/browser/resources/local_ntp/externs.js
@@ -111,7 +111,8 @@ let og;
* ConvertPromoDataToDict()
* @typedef {{promoHtml: (string|undefined),
* promoLogUrl: (string|undefined),
- * promoId: (string|undefined)}}
+ * promoId: (string|undefined),
+ * canOpenExtensionsPage: boolean}}
*/
let promo;
@@ -329,13 +330,17 @@ window.chrome.embeddedSearch.newTabPage.setBackgroundInfo;
* searchBox: (!{
* bg: !Array<number>,
* icon: !Array<number>,
+ * iconSelected: !Array<number>,
* placeholder: !Array<number>,
* resultsBg: !Array<number>,
* resultsBgHovered: !Array<number>,
* resultsBgSelected: !Array<number>,
* resultsDim: !Array<number>,
+ * resultsDimSelected: !Array<number>,
* resultsText: !Array<number>,
+ * resultsTextSelected: !Array<number>,
* resultsUrl: !Array<number>,
+ * resultsUrlSelected: !Array<number>,
* text: !Array<number>,
* }|undefined),
* textColorLightRgba: !Array<number>,
@@ -392,6 +397,15 @@ window.chrome.embeddedSearch.newTabPage.updateCustomLink;
window.chrome.embeddedSearch.newTabPage.blocklistPromo;
/**
+ * @param {number} button
+ * @param {boolean} altKey
+ * @param {boolean} ctrlKey
+ * @param {boolean} metaKey
+ * @param {boolean} shiftKey
+ */
+window.chrome.embeddedSearch.newTabPage.openExtensionsPage;
+
+/**
* Embedded Search API methods defined in
* chrome/renderer/searchbox/searchbox_extension.cc:
* SearchBoxBindings::GetObjectTemplateBuilder()
@@ -400,6 +414,8 @@ window.chrome.embeddedSearch.searchBox;
/** @param {number} line */
window.chrome.embeddedSearch.searchBox.deleteAutocompleteMatch;
window.chrome.embeddedSearch.searchBox.isKeyCaptureEnabled;
+/** @param {number} latencyMs */
+window.chrome.embeddedSearch.searchBox.logCharTypedToRepaintLatency;
window.chrome.embeddedSearch.searchBox.paste;
window.chrome.embeddedSearch.searchBox.rtl;
window.chrome.embeddedSearch.searchBox.startCapturingKeyStrokes;
@@ -423,9 +439,12 @@ let ACMatchClassification;
* description: string,
* descriptionClass: !Array<!ACMatchClassification>,
* destinationUrl: string,
+ * fillIntoEdit: string,
+ * iconUrl: string,
+ * imageDominantColor: string,
+ * imageUrl: string,
* inlineAutocompletion: string,
* isSearchType: boolean,
- * fillIntoEdit: string,
* supportsDeletion: boolean,
* swapContentsAndDescription: boolean,
* type: string,
@@ -444,6 +463,9 @@ let AutocompleteResult;
/** @type {function(!AutocompleteResult):void} */
window.chrome.embeddedSearch.searchBox.autocompleteresultchanged;
+/** @type {function(number, string, string):void} */
+window.chrome.embeddedSearch.searchBox.autocompletematchimageavailable;
+
/**
* @param {number} line
* @param {string} url
@@ -527,4 +549,5 @@ configData.translatedStrings.undoThumbnailRemove;
configData.translatedStrings.uploadImage;
configData.translatedStrings.urlField;
configData.translatedStrings.voiceCloseTooltip;
+configData.translatedStrings.voiceSearchClosed;
configData.translatedStrings.waiting;
diff --git a/chromium/chrome/browser/resources/local_ntp/icons.grdp b/chromium/chrome/browser/resources/local_ntp/icons.grdp
new file mode 100644
index 00000000000..23d21d00472
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons.grdp
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <include name="IDR_LOCAL_NTP_ICONS_BOOKMARK"
+ file="resources/local_ntp/icons/bookmark.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_CALCULATOR"
+ file="resources/local_ntp/icons/calculator.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_CLOCK"
+ file="resources/local_ntp/icons/clock.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_DRIVE_DOCS"
+ file="resources/local_ntp/icons/drive_docs.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_DRIVE_FOLDER"
+ file="resources/local_ntp/icons/drive_folder.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_DRIVE_FORM"
+ file="resources/local_ntp/icons/drive_form.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_DRIVE_IMAGE"
+ file="resources/local_ntp/icons/drive_image.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_DRIVE_LOGO"
+ file="resources/local_ntp/icons/drive_logo.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_DRIVE_PDF"
+ file="resources/local_ntp/icons/drive_pdf.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_DRIVE_SHEETS"
+ file="resources/local_ntp/icons/drive_sheets.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_DRIVE_SLIDES"
+ file="resources/local_ntp/icons/drive_slides.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_DRIVE_VIDEO"
+ file="resources/local_ntp/icons/drive_video.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_EXTENSION_APP"
+ file="resources/local_ntp/icons/extension_app.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_LOCAL_NTP_ICONS_PAGE"
+ file="resources/local_ntp/icons/page.svg" type="BINDATA" compress="gzip" />
+</grit-part>
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/bookmark.svg b/chromium/chrome/browser/resources/local_ntp/icons/bookmark.svg
new file mode 100644
index 00000000000..87ecd1b0776
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/bookmark.svg
@@ -0,0 +1 @@
+<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path id="a" d="M16 23.027L24.24 28l-2.187-9.373 7.28-6.307-9.586-.813L16 2.667l-3.747 8.84-9.586.813 7.28 6.307L7.76 28z"/></defs><use xlink:href="#a"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/calculator.svg b/chromium/chrome/browser/resources/local_ntp/icons/calculator.svg
new file mode 100644
index 00000000000..4fb2f8b6bce
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/calculator.svg
@@ -0,0 +1 @@
+<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M8 12h16v3H8v-3zm0 5h16v3H8v-3z" id="a"/></defs><use xlink:href="#a"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/clock.svg b/chromium/chrome/browser/resources/local_ntp/icons/clock.svg
index d4420ae7d7a..ad93660e2d1 100644
--- a/chromium/chrome/browser/resources/local_ntp/icons/clock.svg
+++ b/chromium/chrome/browser/resources/local_ntp/icons/clock.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M11.99 2C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/><path d="M0 0h24v24H0z" fill="none"/><path d="M12.5 7H11v6l5.25 3.15.75-1.23-4.5-2.67z"/></svg> \ No newline at end of file
+<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M15.993 2.667C8.627 2.667 2.667 8.633 2.667 16s5.96 13.333 13.326 13.333c7.367 0 13.34-5.966 13.34-13.333S23.36 2.667 15.993 2.667zM16 5.333c5.893 0 10.667 4.774 10.667 10.667S21.893 26.667 16 26.667 5.333 21.893 5.333 16 10.107 5.333 16 5.333zm.667 4h-2v8l6.993 4.2 1.007-1.64-6-3.56v-7z" id="a"/></defs><use xlink:href="#a"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/drive_docs.svg b/chromium/chrome/browser/resources/local_ntp/icons/drive_docs.svg
new file mode 100644
index 00000000000..563cdebf621
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/drive_docs.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.222 0H1.778C.8 0 0 .8 0 1.778v12.444C0 15.2.8 16 1.778 16h12.444C15.2 16 16 15.2 16 14.222V1.778C16 .8 15.2 0 14.222 0zm-1.769 5.333H3.556V3.556h8.897v1.777zm0 3.556H3.556V7.11h8.897v1.78zm-2.666 3.555H3.556v-1.777h6.23v1.777z" fill="#4285F4"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/drive_folder.svg b/chromium/chrome/browser/resources/local_ntp/icons/drive_folder.svg
new file mode 100644
index 00000000000..d7d3519effb
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/drive_folder.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.4 3.6H8L6.4 2H1.6C.72 2 .008 2.72.008 3.6L0 13.2c0 .88.72 1.6 1.6 1.6h12.8c.88 0 1.6-.72 1.6-1.6v-8c0-.88-.72-1.6-1.6-1.6zm0 9.6H1.6v-8h12.8v8z" fill="#5F6368"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/drive_form.svg b/chromium/chrome/browser/resources/local_ntp/icons/drive_form.svg
new file mode 100644
index 00000000000..7702b0a6566
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/drive_form.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.222 0H1.778C.8 0 0 .8 0 1.778v12.444C0 15.2.8 16 1.778 16h12.444C15.2 16 16 15.2 16 14.222V1.778C16 .8 15.2 0 14.222 0zM5.333 12.444H3.556v-1.777h1.777v1.777zm0-3.555H3.556V7.11h1.777v1.78zm0-3.556H3.556V3.556h1.777v1.777zm7.111 7.111H6.222v-1.777h6.222v1.777zm0-3.555H6.222V7.11h6.222v1.78zm0-3.556H6.222V3.556h6.222v1.777z" fill="#673AB7"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/drive_image.svg b/chromium/chrome/browser/resources/local_ntp/icons/drive_image.svg
new file mode 100644
index 00000000000..3e150ebf545
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/drive_image.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M16 14.222V1.778C16 .8 15.2 0 14.222 0H1.778C.8 0 0 .8 0 1.778v12.444C0 15.2.8 16 1.778 16h12.444C15.2 16 16 15.2 16 14.222zM4.889 9.333L7.11 12.01 10.222 8l4 5.333H1.778l3.11-4z" fill="#E94335"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/drive_logo.svg b/chromium/chrome/browser/resources/local_ntp/icons/drive_logo.svg
new file mode 100644
index 00000000000..87f673712dd
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/drive_logo.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path fill="#4285F4" d="M16 10.391l-2.548 4.522H2.548l2.62-4.522z"/><path fill="#FFCD40" d="M10.61 1H5.39l5.442 9.391H16z"/><path fill="#0F9D58" d="M5.39 1L8 5.504l-5.452 9.409L0 10.391z"/></g></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/drive_pdf.svg b/chromium/chrome/browser/resources/local_ntp/icons/drive_pdf.svg
new file mode 100644
index 00000000000..494b7137f6b
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/drive_pdf.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M3.556 7.556h.888v-.89h-.888v.89zM14.222 0H1.778C.8 0 0 .8 0 1.778v12.444C0 15.2.8 16 1.778 16h12.444C15.2 16 16 15.2 16 14.222V1.778C16 .8 15.2 0 14.222 0zM5.778 7.556c0 .737-.596 1.333-1.334 1.333h-.888v1.778H2.222V5.333h2.222c.738 0 1.334.596 1.334 1.334v.889zm8.889-.89h-2.223v.89h1.334v1.333h-1.334v1.778h-1.333V5.333h3.556v1.334zm-4.445 2.667c0 .738-.595 1.334-1.333 1.334H6.667V5.333h2.222c.738 0 1.333.596 1.333 1.334v2.666zM8 9.333h.889V6.667H8v2.666z" fill="#DB4537"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/drive_sheets.svg b/chromium/chrome/browser/resources/local_ntp/icons/drive_sheets.svg
new file mode 100644
index 00000000000..d45b86587c8
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/drive_sheets.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.222 0H1.778C.8 0 .008.8.008 1.778L0 4.444v9.778C0 15.2.8 16 1.778 16h12.444C15.2 16 16 15.2 16 14.222V1.778C16 .8 15.2 0 14.222 0zm0 7.111h-7.11v7.111h-1.78v-7.11H1.778v-1.78h3.555V1.778h1.778v3.555h7.111v1.778z" fill="#0E9D58"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/drive_slides.svg b/chromium/chrome/browser/resources/local_ntp/icons/drive_slides.svg
new file mode 100644
index 00000000000..d3c1148e982
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/drive_slides.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.221 0H1.77C.792 0 0 .8 0 1.778v12.444C0 15.2.792 16 1.77 16h12.45c.98 0 1.78-.8 1.78-1.778V1.778C16 .8 15.2 0 14.221 0zM14 12H2V4h12v8z" fill="#FDB700"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/drive_video.svg b/chromium/chrome/browser/resources/local_ntp/icons/drive_video.svg
new file mode 100644
index 00000000000..28309f1f8ec
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/drive_video.svg
@@ -0,0 +1 @@
+<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M12.8 2l1.6 3.2H12L10.4 2H8.8l1.6 3.2H8L6.4 2H4.8l1.6 3.2H4L2.4 2h-.8C.72 2 .008 2.72.008 3.6L0 13.2c0 .88.72 1.6 1.6 1.6h12.8c.88 0 1.6-.72 1.6-1.6V2h-3.2z" fill="#EA4335"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/extension_app.svg b/chromium/chrome/browser/resources/local_ntp/icons/extension_app.svg
new file mode 100644
index 00000000000..f730feb1fa7
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/extension_app.svg
@@ -0,0 +1 @@
+<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M24.5 15H23v-4c0-1.1-.9-2-2-2h-4V7.5a2.5 2.5 0 0 0-5 0V9H8c-1.1 0-1.99.9-1.99 2v3.8H7.5c1.49 0 2.7 1.21 2.7 2.7 0 1.49-1.21 2.7-2.7 2.7H6V24c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7 1.49 0 2.7 1.21 2.7 2.7V26H21c1.1 0 2-.9 2-2v-4h1.5a2.5 2.5 0 0 0 0-5z" id="a"/></defs><use xlink:href="#a" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/icons/page.svg b/chromium/chrome/browser/resources/local_ntp/icons/page.svg
new file mode 100644
index 00000000000..0de98847e26
--- /dev/null
+++ b/chromium/chrome/browser/resources/local_ntp/icons/page.svg
@@ -0,0 +1 @@
+<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M16 2c7.728 0 14 6.272 14 14s-6.272 14-14 14S2 23.728 2 16 8.272 2 16 2zm0 3.333c-5.887 0-10.667 4.78-10.667 10.667H11.2c4.543.029 6.562 2.308 6.058 6.836H12.65v3.293c1.054.349 2.18.538 3.35.538 5.887 0 10.667-4.78 10.667-10.667 0-.217-.007-.433-.02-.647-.876 1.32-2.203 1.98-3.98 1.98-2.85 0-4.275-1.222-4.275-3.665h-4.998c-.365-3.638.91-5.457 3.827-5.457 0-1.3.436-2.13 1.082-2.628A10.69 10.69 0 0 0 16 5.333z" id="a"/></defs><use xlink:href="#a"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/local_ntp/local_ntp.css b/chromium/chrome/browser/resources/local_ntp/local_ntp.css
index ef088a6c3e2..e563fe18ff8 100644
--- a/chromium/chrome/browser/resources/local_ntp/local_ntp.css
+++ b/chromium/chrome/browser/resources/local_ntp/local_ntp.css
@@ -116,7 +116,8 @@ body.hide-fakebox #fakebox {
visibility: hidden;
}
-#fakebox-container {
+#fakebox-container,
+#realbox-container {
margin: 0 auto 0 auto;
/* Increase min-width again to account for the search icon: 390px new
* min-width + additional 20px */
@@ -152,24 +153,6 @@ body.hide-fakebox #fakebox {
max-width: 584px;
}
-.google-g-icon {
- background-image:
- url(../../../../ui/webui/resources/images/200-logo_googleg.png);
- background-position: center;
- background-repeat: no-repeat;
- background-size: 14px;
- bottom: 0;
- left: 16px;
- position: absolute;
- top: 0;
- width: 24px;
-}
-
-[dir=rtl] .google-g-icon {
- left: auto;
- right: 16px;
-}
-
#fakebox {
background: white;
cursor: text;
@@ -218,15 +201,41 @@ body.hide-fakebox #fakebox {
display: none;
}
-/* The realbox is a "loupe" (.search-icon) by default, but when the selection
- * ends up on match with a different icon, the realbox also gets that icon.
- * Example: typing the start of a URL with a favicon or the user pressing
- * up/down to select matches sets a background-image here and disables the
- * -webkit-mask applied by .search-icon. */
-#realbox-icon {
+/* The realbox has a "loupe" or "search" icon by default. When a match with a
+ * different icon ("clock" for historical searches or "page" for URLs) or a
+ * favicon is selected, the realbox also gets that icon/favicon. For both the
+ * realbox as well as the dropdown, icons are rendered via webkit-mask-image and
+ * background-color and favicons are rendered via background-
+ image set on the
+ * element's style property in JS. */
+#realbox-icon,
+.match-icon {
+ -webkit-mask-position: center;
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 16px;
+ background-color: var(--search-box-icon, rgb(117, 117, 117));
background-position: center center;
background-repeat: no-repeat;
- background-size: 24px;
+ background-size: 16px;
+ bottom: 0;
+ left: 16px;
+ margin: auto;
+ position: absolute;
+ top: 0;
+ width: 24px;
+}
+
+[dir=rtl] :-webkit-any(#realbox-icon, .match-icon) {
+ left: auto;
+ right: 16px;
+}
+
+#realbox-icon[data-icon='google_g'] {
+ background-size: 12px;
+}
+
+#realbox-icon[data-icon='search'] {
+ -webkit-mask-size: 20px; /* Loupe in realbox is bigger than in matches. */
}
#realbox-matches {
@@ -254,16 +263,13 @@ body.hide-fakebox #fakebox {
}
#realbox-matches a {
- background-position: 16px center;
- background-repeat: no-repeat;
- background-size: 24px;
font-size: 16px;
line-height: 1;
outline: none;
overflow: hidden;
padding-bottom: 8px;
padding-inline-end: 16px;
- padding-inline-start: 48px;
+ padding-inline-start: 52px;
padding-top: 8px;
position: relative;
text-decoration: none;
@@ -275,6 +281,24 @@ body.hide-fakebox #fakebox {
background-position-x: calc(100% - 16px);
}
+#realbox-matches a.has-image {
+ display: flex;
+ flex-direction: column;
+ height: 32px;
+ justify-content: center;
+ padding-bottom: 6px;
+ padding-top: 6px;
+}
+
+#realbox-matches a.has-image > span {
+ margin-bottom: 2px;
+ margin-top: 2px;
+}
+
+#realbox-matches a.has-image .description {
+ font-size: 14px;
+}
+
#realbox-matches.removable a {
padding-inline-end: 48px;
}
@@ -283,42 +307,42 @@ body.hide-fakebox #fakebox {
margin-bottom: 8px; /* Last result is tight with border-radius. */
}
-.clock-icon,
-.search-icon {
- -webkit-mask-position: center;
- -webkit-mask-repeat: no-repeat;
- -webkit-mask-size: 16px;
- background-color: var(--search-box-icon, rgb(117, 117, 117));
+#realbox-matches a:-webkit-any(:focus-within, .selected) .match-icon {
+ background-color: var(--search-box-icon-selected, rgb(117, 117, 117));
+}
+
+.image-container {
+ align-items: center;
+ border-radius: 8px;
bottom: 0;
- left: 16px;
+ display: flex;
+ height: 32px;
+ justify-content: center;
+ left: 12px;
+ margin: auto;
position: absolute;
top: 0;
- width: 24px;
-}
-
-.clock-icon {
- -webkit-mask-image: url(icons/clock.svg);
-}
-
-.search-icon {
- -webkit-mask-image:
- url(../../../../ui/webui/resources/images/icon_search.svg);
+ width: 32px;
}
-#realbox-input-wrapper > .search-icon {
- -webkit-mask-size: 20px; /* Loupe in realbox is bigger than in matches. */
+html[dir=rtl] .image-container {
+ left: auto;
+ right: 12px;
}
-html[dir=rtl] :-webkit-any(.clock-icon, .search-icon) {
- right: 16px;
+.match-image {
+ border-radius: 8px;
+ max-height: 32px;
+ max-width: 32px;
}
-#realbox-matches a:-webkit-any(:hover, .selected) {
+#realbox-matches a:hover {
background-color: var(--search-box-results-bg-hovered, rgb(232, 232, 233));
}
-#realbox-matches a:focus-within {
+#realbox-matches a:-webkit-any(:focus-within, .selected) {
background-color: var(--search-box-results-bg-selected, rgb(219, 219, 220));
+ color: var(--search-box-results-text-selected, rgb(var(--GG900-rgb)));
}
#realbox-matches .match {
@@ -329,10 +353,18 @@ html[dir=rtl] :-webkit-any(.clock-icon, .search-icon) {
color: var(--search-box-results-dim, rgb(var(--GG600-rgb)));
}
+#realbox-matches a:-webkit-any(:focus-within, .selected) .dim {
+ color: var(--search-box-results-dim-selected, rgb(var(--GG600-rgb)));
+}
+
#realbox-matches .url {
color: var(--search-box-results-url, rgb(var(--GB600-rgb)));
}
+#realbox-matches a:-webkit-any(:focus-within, .selected) .url {
+ color: var(--search-box-results-url-selected, rgb(var(--GB600-rgb)));
+}
+
#realbox-matches .remove-match {
border-radius: 50%;
height: 24px;
@@ -348,11 +380,17 @@ html[dir=rtl] :-webkit-any(.clock-icon, .search-icon) {
}
#realbox-matches .remove-match:hover {
- background-color: var(--remove-match-hovered, rgba(var(--GG900-rgb), .08));
+ background-color: var(--remove-match-hovered, rgba(var(--GG900-rgb), .16));
}
-#realbox-matches .remove-match:focus-within {
- background-color: var(--remove-match-focused, rgba(var(--GG900-rgb), .16));
+#realbox-matches a:-webkit-any(:focus-within, .selected) .remove-match:hover {
+ background-color:
+ var(--remove-match-selected-hovered, rgba(var(--GG900-rgb), .16));
+}
+
+#realbox-matches a:-webkit-any(:focus-within, .selected)
+ .remove-match:focus-within {
+ background-color: var(--remove-match-focused, rgba(var(--GG900-rgb), .32));
}
#realbox-matches .remove-icon {
@@ -360,14 +398,21 @@ html[dir=rtl] :-webkit-any(.clock-icon, .search-icon) {
width: 100%;
}
-#realbox-matches a:-webkit-any(:hover, :focus-within, .selected) .remove-icon {
+#realbox-matches .remove-icon {
-webkit-mask-image: url(../../../../ui/webui/resources/images/icon_clear.svg);
-webkit-mask-position: center;
-webkit-mask-repeat: no-repeat;
-webkit-mask-size: 16px;
+}
+
+#realbox-matches a:-webkit-any(:hover) .remove-icon {
background-color: var(--search-box-icon, rgb(var(--GG900-rgb)));
}
+#realbox-matches a:-webkit-any(:focus-within, .selected) .remove-icon {
+ background-color: var(--search-box-icon-selected, rgb(var(--GG900-rgb)));
+}
+
#fakebox > input {
bottom: 0;
box-sizing: border-box;
@@ -385,7 +430,22 @@ html[dir=rtl] #fakebox > input {
}
#fakebox .search-icon {
+ -webkit-mask-image: url(../../../../ui/webui/resources/images/icon_search.svg);
+ -webkit-mask-position: center;
+ -webkit-mask-repeat: no-repeat;
-webkit-mask-size: 20px;
+ background-color: rgb(117, 117, 117);
+ bottom: 0;
+ left: 16px;
+ margin: auto;
+ position: absolute;
+ top: 0;
+ width: 24px;
+}
+
+html[dir=rtl] #fakebox .search-icon {
+ left: auto;
+ right: 16px;
}
#fakebox-text {
@@ -415,7 +475,7 @@ html[dir=rtl] #fakebox-text {
#fakebox-text,
#realbox {
- padding-inline-start: 48px;
+ padding-inline-start: 52px;
}
#fakebox-cursor {
@@ -453,8 +513,7 @@ html[dir=rtl] .microphone-icon {
right: auto;
}
-#realbox-input-wrapper > :-webkit-any(.google-g-icon, .microphone-icon,
- .search-icon) {
+#realbox-input-wrapper > :-webkit-any(#realbox-icon, .microphone-icon) {
z-index: 3;
}
@@ -2004,12 +2063,7 @@ html[dir=rtl] #colors-menu .bg-sel-tile .selected-check {
margin-inline-end: 16px;
}
-#color-picker-container.visible {
- display: inline-block;
-}
-
#color-picker-container {
- display: none;
vertical-align: top;
}
diff --git a/chromium/chrome/browser/resources/local_ntp/local_ntp.html b/chromium/chrome/browser/resources/local_ntp/local_ntp.html
index 7f2cf920294..ccefbd553b0 100644
--- a/chromium/chrome/browser/resources/local_ntp/local_ntp.html
+++ b/chromium/chrome/browser/resources/local_ntp/local_ntp.html
@@ -78,7 +78,8 @@
<div id="realbox-container" $i18n{hiddenIfRealboxDisabled}>
<div id="realbox-input-wrapper">
- <div id="realbox-icon" class="$i18n{realboxIconClass}"></div>
+ <div id="realbox-icon" data-default-icon="$i18n{realboxDefaultIcon}">
+ </div>
<input id="realbox" type="search" autocomplete="off" spellcheck="false"
aria-live="polite" autofocus>
<button id="realbox-microphone" class="microphone-icon" hidden></button>
@@ -400,6 +401,7 @@
</div>
</div>
</dialog>
+ <div id="screen-reader-announcer" role="status" aria-live="polite"></div>
<div id="one-google-end-of-body"></div>
diff --git a/chromium/chrome/browser/resources/local_ntp/local_ntp.js b/chromium/chrome/browser/resources/local_ntp/local_ntp.js
index 213a2982d5f..9ab299da153 100644
--- a/chromium/chrome/browser/resources/local_ntp/local_ntp.js
+++ b/chromium/chrome/browser/resources/local_ntp/local_ntp.js
@@ -1,3 +1,4 @@
+
// 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.
@@ -62,11 +63,11 @@ let RealboxOutputUpdate;
*/
const CLASSES = {
ALTERNATE_LOGO: 'alternate-logo', // Shows white logo if required by theme
- // Shows a clock next to historical realbox results.
- CLOCK_ICON: 'clock-icon',
// Applies styles to dialogs used in customization.
CUSTOMIZE_DIALOG: 'customize-dialog',
DELAYED_HIDE_NOTIFICATION: 'mv-notice-delayed-hide',
+ DESCRIPTION: 'description',
+ DIM: 'dim',
DISMISSABLE: 'dismissable',
DISMISS_ICON: 'dismiss-icon',
DISMISS_PROMO: 'dismiss-promo',
@@ -78,18 +79,25 @@ const CLASSES = {
FLOAT_UP: 'float-up',
// Applies drag focus style to the fakebox
FAKEBOX_DRAG_FOCUS: 'fakebox-drag-focused',
+ HAS_IMAGE: 'has-image', // A realbox match with an image.
// Applies a different style to the error notification if a link is present.
HAS_LINK: 'has-link',
HIDE_FAKEBOX: 'hide-fakebox',
HIDE_NOTIFICATION: 'notice-hide',
+ // Contains the image next to a realbox match. Displays a placeholder color
+ // while the realbox match image is loading.
+ IMAGE_CONTAINER: 'image-container',
INITED: 'inited', // Reveals the <body> once init() is done.
LEFT_ALIGN_ATTRIBUTION: 'left-align-attribution',
+ // The icon next to a realbox match.
+ MATCH_ICON: 'match-icon',
+ // The image next to a realbox match.
+ MATCH_IMAGE: 'match-image',
// Vertically centers the most visited section for a non-Google provided page.
NON_GOOGLE_PAGE: 'non-google-page',
REMOVABLE: 'removable',
REMOVE_ICON: 'remove-icon',
REMOVE_MATCH: 'remove-match',
- SEARCH_ICON: 'search-icon', // Magnifying glass/search icon.
SELECTED: 'selected', // A selected (via up/down arrow key) realbox match.
SHOW_ELEMENT: 'show-element',
// When the realbox has matches to show.
@@ -98,10 +106,7 @@ const CLASSES = {
USE_NOTIFIER: 'use-notifier',
};
-const SEARCH_HISTORY_MATCH_TYPES = [
- 'search-history',
- 'search-suggest-personalized',
-];
+const DOCUMENT_MATCH_TYPE = 'document';
/**
* The period of time (ms) before transitions can be applied to a toast
@@ -262,6 +267,21 @@ let delayedHideNotification = null;
let enterWasPressed = false;
/**
+ * A cache from image URL to image content in the form of data URL in order to
+ * reuse match image data that have been loaded before and to avoid flickering.
+ * @type {!Object<string>}
+ */
+const faviconOrImageUrlToDataUrlCache = {};
+
+/**
+ * The time of the first character insert operation that has not yet been
+ * painted in floating point milliseconds. Used to measure the realbox
+ * responsiveness with a histogram.
+ * @type {number}
+ */
+let charTypedTime = 0;
+
+/**
* True if dark mode is enabled.
* @type {boolean}
*/
@@ -330,6 +350,7 @@ function autocompleteResultChanged(result) {
}
renderAutocompleteMatches(result.matches);
+
autocompleteResult = result;
$(IDS.REALBOX).focus();
@@ -354,6 +375,54 @@ function autocompleteResultChanged(result) {
}
/**
+ * @param {number} matchIndex
+ * @param {string} url AutocompleteMatch's imageUrl or destinationUrl.
+ * @param {string} dataUrl
+ */
+function autocompleteMatchImageAvailable(matchIndex, url, dataUrl) {
+ if (!autocompleteResult || !autocompleteResult.matches[matchIndex]) {
+ return;
+ }
+
+ const match = autocompleteResult.matches[matchIndex];
+ if (match.imageUrl !== url && match.destinationUrl !== url) {
+ return;
+ }
+
+ // Return if the image has been rendered. Re-rendering it will cause flicker.
+ if (faviconOrImageUrlToDataUrlCache[url]) {
+ return;
+ }
+ faviconOrImageUrlToDataUrlCache[url] = dataUrl;
+
+ const matchEls = Array.from($(IDS.REALBOX_MATCHES).children);
+ assert(autocompleteResult.matches.length === matchEls.length);
+
+ // Update the match image/favicon.
+ if (match.imageUrl === url) {
+ const imageContainerEl = assert(matchEls[matchIndex].getElementsByClassName(
+ CLASSES.IMAGE_CONTAINER)[0]);
+ const imageEl = document.createElement('img');
+ imageEl.classList.add(CLASSES.MATCH_IMAGE);
+ imageEl.src = dataUrl;
+ imageContainerEl.appendChild(imageEl);
+ imageContainerEl.style.backgroundColor = 'transparent';
+ } else {
+ const iconEl = assert(
+ matchEls[matchIndex].getElementsByClassName(CLASSES.MATCH_ICON)[0]);
+ setBackgroundImageByUrl(iconEl, dataUrl);
+ }
+
+ // If the match is selected, also update the realbox favicon.
+ const selectedMatchIndex = matchEls.findIndex(matchEl => {
+ return matchEl.classList.contains(CLASSES.SELECTED);
+ });
+ if (selectedMatchIndex === matchIndex) {
+ setRealboxIcon(match);
+ }
+}
+
+/**
* @param {number} style
* @return {!Array<string>}
*/
@@ -392,6 +461,15 @@ function convertToRGBAColor(color) {
}
/**
+ * Converts an Array of color components into 8-digit Hex format "#RRGGBBAA".
+ * @param {Array<number>} color Array of rgba color components.
+ * @return {string} CSS color in 8-digit Hex format.
+ */
+function convertToHexColor(color) {
+ return '#' + assert(color).map(c => c.toString(16).padStart(2, '0')).join('');
+}
+
+/**
* Returns a timeout that can be executed early. Calls back true if this was
* an early execution, false otherwise.
* @param {!Function} timeout The timeout function. Requires a boolean param.
@@ -653,19 +731,6 @@ function floatUpNotification(notification, notificationContainer) {
}
/**
- * @param {string} url
- * @return {string} The chrome-search://ntpicon/ corresponding to |url|.
- */
-function getIconUrl(url) {
- // TODO(crbug.com/997229): use chrome://favicon/<url> when perms allow.
- const iconUrl = new URL('chrome-search://ntpicon/');
- iconUrl.searchParams.set('show_fallback_monogram', 'false');
- iconUrl.searchParams.set('size', '24@' + window.devicePixelRatio + 'x');
- iconUrl.searchParams.set('url', url);
- return iconUrl.toString();
-}
-
-/**
* Returns theme background info, first checking for history.state.notheme. If
* the page has notheme set, returns a fallback light-colored theme (or dark-
* colored theme if dark mode is enabled). This is used when the doodle is
@@ -847,18 +912,27 @@ function init() {
customize.init(showErrorNotification, hideNotification);
if (configData.realboxEnabled) {
+ setRealboxIcon(undefined);
+
const realboxEl = $(IDS.REALBOX);
realboxEl.placeholder = configData.translatedStrings.searchboxPlaceholder;
+ // Using .onmousedown instead of addEventListener('mousedown') to support
+ // tests.
+ realboxEl.onmousedown = onRealboxMouseDown;
realboxEl.addEventListener('copy', onRealboxCutCopy);
realboxEl.addEventListener('cut', onRealboxCutCopy);
+ realboxEl.addEventListener('focus', onRealboxFocus);
realboxEl.addEventListener('input', onRealboxInput);
+ realboxEl.addEventListener('keyup', onRealboxKeyup);
realboxEl.addEventListener('paste', onRealboxPaste);
const realboxWrapper = $(IDS.REALBOX_INPUT_WRAPPER);
- realboxWrapper.addEventListener('focusin', onRealboxWrapperFocusIn);
- setRealboxWrapperListenForFocusOut(true);
+ realboxWrapper.addEventListener('focusout', onRealboxWrapperFocusOut);
+ realboxWrapper.addEventListener('keydown', onRealboxWrapperKeydown);
searchboxApiHandle.autocompleteresultchanged = autocompleteResultChanged;
+ searchboxApiHandle.autocompletematchimageavailable =
+ autocompleteMatchImageAvailable;
if (!iframesAndVoiceSearchDisabledForTesting) {
speech.init(
@@ -1013,7 +1087,13 @@ function injectPromo(promo) {
const link = promoContainer.querySelector('a');
if (link) {
- link.onclick = function() {
+ link.onclick = e => {
+ const url = new URL(link.href);
+ if (promo.canOpenExtensionsPage && url.origin == 'chrome://extensions') {
+ ntpApiHandle.openExtensionsPage(
+ e.button, e.altKey, e.ctrlKey, e.metaKey, e.shiftKey);
+ e.preventDefault();
+ }
ntpApiHandle.logEvent(LOG_TYPE.NTP_MIDDLE_SLOT_PROMO_LINK_CLICKED);
};
}
@@ -1224,6 +1304,18 @@ function onMostVisitedChange() {
reloadTiles();
}
+/** @param {Event} e */
+function onRealboxMouseDown(e) {
+ if (!e.isTrusted || e.button !== 0) {
+ // Only handle main (generally left) button presses generated by a user
+ // action.
+ return;
+ }
+ if (!$(IDS.REALBOX).value) {
+ queryAutocomplete('');
+ }
+}
+
/** @param {!Event} e */
function onRealboxCutCopy(e) {
const realboxEl = $(IDS.REALBOX);
@@ -1249,46 +1341,55 @@ function onRealboxCutCopy(e) {
}
}
+function onRealboxFocus() {
+ lastRealboxFocusTime = Date.now();
+}
+
function onRealboxInput() {
const realboxValue = $(IDS.REALBOX).value;
updateRealboxOutput({inline: '', text: realboxValue});
+ const charTyped = !isDeletingInput && !!realboxValue.trim();
+ // If a character has been typed, update |charTypedTime|. Otherwise reset it.
+ // If |charTypedTime| is not 0, there's a pending typed character for which
+ // the results have not been painted yet. In that case, keep the earlier time.
+ charTypedTime = charTyped ? charTypedTime || window.performance.now() : 0;
+
if (realboxValue.trim()) {
queryAutocomplete(realboxValue);
} else {
setRealboxMatchesVisible(false);
- setRealboxWrapperListenForKeydown(false);
clearAutocompleteMatches();
}
pastedInRealbox = false;
}
+/** @param {!Event} e */
+function onRealboxKeyup(e) {
+ if (e.key === 'Tab' && !$(IDS.REALBOX).value) {
+ queryAutocomplete('');
+ }
+}
+
function onRealboxPaste() {
pastedInRealbox = true;
}
-/** @param {Event} e */
-function onRealboxWrapperFocusIn(e) {
- if (e.target.matches(`#${IDS.REALBOX}`)) {
- if (!$(IDS.REALBOX).value) {
- queryAutocomplete('');
- }
- lastRealboxFocusTime = Date.now();
- } else if (e.target.matches(`#${IDS.REALBOX_MATCHES} *`)) {
- const target = /** @type {Element} */ (e.target);
- const link = findAncestor(target, el => el.nodeName === 'A');
- if (!link) {
- return;
- }
- const selectedIndex = selectMatchEl(link);
- // It doesn't really make sense to use fillFromMatch() here as the focus
- // change drops the selection (and is probably just noisy to
- // screenreaders).
- const newFill = autocompleteResult.matches[selectedIndex].fillIntoEdit;
- updateRealboxOutput({moveCursorToEnd: true, inline: '', text: newFill});
+/** @param {!Event} e */
+function onRealboxMatchesFocusIn(e) {
+ const target = /** @type {Element} */ (e.target);
+ const link = findAncestor(target, el => el.nodeName === 'A');
+ if (!link) {
+ return;
}
+ const selectedIndex = selectMatchEl(link);
+ // It doesn't really make sense to use fillFromMatch() here as the focus
+ // change drops the selection (and is probably just noisy to
+ // screenreaders).
+ const newFill = autocompleteResult.matches[selectedIndex].fillIntoEdit;
+ updateRealboxOutput({moveCursorToEnd: true, inline: '', text: newFill});
}
/** @param {Event} e */
@@ -1301,6 +1402,7 @@ function onRealboxWrapperFocusOut(e) {
// Clear the input if it was empty when displaying the matches.
if (lastQueriedInput === '') {
updateRealboxOutput({inline: '', text: ''});
+ setRealboxIcon(undefined);
}
setRealboxMatchesVisible(false);
@@ -1308,9 +1410,7 @@ function onRealboxWrapperFocusOut(e) {
// listening for key presses. These stale results should never be shown, but
// correspond to the potentially stale suggestion left in the realbox when
// blurred. That stale result may be navigated to by focusing and pressing
- // Enter, and that match may be privileged, so we need to keep the data
- // around in order to ascertain this. If matches are reshown, fresh
- // autocomplete data will be fetched.
+ // Enter.
window.chrome.embeddedSearch.searchBox.stopAutocomplete(
/*clearResult=*/ false);
}
@@ -1336,6 +1436,12 @@ function onRealboxWrapperKeydown(e) {
inline: lastOutput.inline.substr(1),
text: assert(lastOutput.text + key),
});
+
+ // If |charTypedTime| is not 0, there's a pending typed character for
+ // which the results have not been painted yet. In that case, keep the
+ // earlier time.
+ charTypedTime = charTypedTime || window.performance.now();
+
queryAutocomplete(lastOutput.text);
e.preventDefault();
return;
@@ -1346,6 +1452,21 @@ function onRealboxWrapperKeydown(e) {
return;
}
+ if (!areRealboxMatchesVisible()) {
+ if (key === 'ArrowUp' || key === 'ArrowDown') {
+ const realboxValue = $(IDS.REALBOX).value;
+ if (realboxValue.trim() || !realboxValue) {
+ queryAutocomplete(realboxValue);
+ }
+ e.preventDefault();
+ return;
+ }
+ }
+
+ if (!autocompleteResult || autocompleteResult.matches.length === 0) {
+ return;
+ }
+
const realboxMatchesEl = $(IDS.REALBOX_MATCHES);
const matchEls = Array.from(realboxMatchesEl.children);
assert(matchEls.length > 0);
@@ -1373,17 +1494,6 @@ function onRealboxWrapperKeydown(e) {
return;
}
- if (!areRealboxMatchesVisible()) {
- if (key === 'ArrowUp' || key === 'ArrowDown') {
- const realboxValue = $(IDS.REALBOX).value;
- if (realboxValue.trim()) {
- queryAutocomplete(realboxValue);
- }
- e.preventDefault();
- }
- return;
- }
-
if (key === 'Delete') {
if (e.shiftKey && !e.altKey && !e.ctrlKey && !e.metaKey) {
const selectedMatch = autocompleteResult.matches[selected];
@@ -1403,7 +1513,6 @@ function onRealboxWrapperKeydown(e) {
if (key === 'Escape' && selected === 0) {
updateRealboxOutput({inline: '', text: ''});
setRealboxMatchesVisible(false);
- setRealboxWrapperListenForKeydown(false);
clearAutocompleteMatches();
e.preventDefault();
return;
@@ -1589,28 +1698,56 @@ function renderAutocompleteMatches(matches) {
}
};
- if (match.isSearchType) {
- const icon = document.createElement('div');
- const isSearchHistory = SEARCH_HISTORY_MATCH_TYPES.includes(match.type);
- icon.classList.add(
- isSearchHistory ? CLASSES.CLOCK_ICON : CLASSES.SEARCH_ICON);
- matchEl.appendChild(icon);
+ const hasImage = !!match.imageUrl;
+ if (hasImage) {
+ matchEl.classList.add(CLASSES.HAS_IMAGE);
+ }
+
+ if (hasImage) {
+ const imageContainer = document.createElement('div');
+ imageContainer.classList.add(CLASSES.IMAGE_CONTAINER);
+
+ if (faviconOrImageUrlToDataUrlCache[match.imageUrl]) {
+ const imageEl = document.createElement('img');
+ imageEl.classList.add(CLASSES.MATCH_IMAGE);
+ imageEl.src = faviconOrImageUrlToDataUrlCache[match.imageUrl];
+ imageContainer.appendChild(imageEl);
+ } else if (match.imageDominantColor) {
+ // .25 Opacity matching c/b/u/views/omnibox/omnibox_match_cell_view.cc
+ imageContainer.style.backgroundColor = match.imageDominantColor + '40';
+ }
+ matchEl.appendChild(imageContainer);
} else {
- const iconUrl = getIconUrl(match.destinationUrl);
- matchEl.style.backgroundImage = `url(${iconUrl})`;
+ const iconEl = document.createElement('div');
+ iconEl.classList.add(CLASSES.MATCH_ICON);
+ if (faviconOrImageUrlToDataUrlCache[match.destinationUrl]) {
+ setBackgroundImageByUrl(
+ iconEl, faviconOrImageUrlToDataUrlCache[match.destinationUrl]);
+ } else if (match.type == DOCUMENT_MATCH_TYPE) {
+ // Document matches use colored SVG icons.
+ setBackgroundImageByUrl(iconEl, match.iconUrl);
+ } else {
+ setWebkitMaskImageByUrl(iconEl, match.iconUrl);
+ }
+ matchEl.appendChild(iconEl);
}
- const contentsEls =
+ const contentsEl =
renderMatchClassifications(match.contents, match.contentsClass);
- const descriptionEls = [];
- const separatorEls = [];
+ let descriptionEl;
+ let separatorEl;
let separatorText = '';
if (match.description) {
- descriptionEls.push(...renderMatchClassifications(
- match.description, match.descriptionClass));
- separatorText = configData.translatedStrings.realboxSeparator;
- separatorEls.push(document.createTextNode(separatorText));
+ descriptionEl =
+ renderMatchClassifications(match.description, match.descriptionClass);
+ descriptionEl.classList.add(CLASSES.DESCRIPTION);
+ if (hasImage) {
+ descriptionEl.classList.add(CLASSES.DIM);
+ } else {
+ separatorText = configData.translatedStrings.realboxSeparator;
+ separatorEl = document.createTextNode(separatorText);
+ }
}
const ariaLabel = match.swapContentsAndDescription ?
@@ -1619,11 +1756,13 @@ function renderAutocompleteMatches(matches) {
matchEl.setAttribute('aria-label', ariaLabel);
const layout = match.swapContentsAndDescription ?
- [descriptionEls, separatorEls, contentsEls] :
- [contentsEls, separatorEls, descriptionEls];
+ [descriptionEl, separatorEl, contentsEl] :
+ [contentsEl, separatorEl, descriptionEl];
- for (const col of layout) {
- col.forEach(colEl => matchEl.appendChild(colEl));
+ for (const colEl of layout) {
+ if (colEl) {
+ matchEl.appendChild(colEl);
+ }
}
if (match.supportsDeletion && configData.suggestionTransparencyEnabled) {
@@ -1655,37 +1794,50 @@ function renderAutocompleteMatches(matches) {
realboxMatchesEl.append(matchEl);
}
+ if (charTypedTime) {
+ window.chrome.embeddedSearch.searchBox.logCharTypedToRepaintLatency(
+ Math.floor(window.performance.now() - charTypedTime));
+ charTypedTime = 0;
+ }
+
// When the matches are replaced, the focus gets dropped temporariliy as the
// focused element is being deleted from the DOM. Stop listening to 'focusout'
- // event and retore it immediately after since we don't want to stop
+ // event and restore it immediately after since we don't want to stop
// autocomplete in those cases.
- setRealboxWrapperListenForFocusOut(false);
+ const realboxWrapper = $(IDS.REALBOX_INPUT_WRAPPER);
+ realboxWrapper.removeEventListener('focusout', onRealboxWrapperFocusOut);
$(IDS.REALBOX_MATCHES).remove();
realboxMatchesEl.id = IDS.REALBOX_MATCHES;
+ realboxMatchesEl.addEventListener('focusin', onRealboxMatchesFocusIn);
- $(IDS.REALBOX_INPUT_WRAPPER).appendChild(realboxMatchesEl);
+ realboxWrapper.appendChild(realboxMatchesEl);
- setRealboxWrapperListenForFocusOut(true);
+ realboxWrapper.addEventListener('focusout', onRealboxWrapperFocusOut);
const hasMatches = matches.length > 0;
setRealboxMatchesVisible(hasMatches);
- setRealboxWrapperListenForKeydown(hasMatches);
}
/**
* @param {string} text
* @param {!Array<!ACMatchClassification>} classifications
- * @return {!Array<!Element>}
+ * @return {!Element}
*/
function renderMatchClassifications(text, classifications) {
- return classifications.map((classification, i) => {
- const classes = classificationStyleToClasses(classification.style);
- const next = classifications[i + 1] || {offset: text.length};
- const classifiedText = text.substring(classification.offset, next.offset);
- return classes.length ? spanWithClasses(classifiedText, classes) :
- document.createTextNode(classifiedText);
- });
+ return classifications
+ .map((classification, i) => {
+ const classes = classificationStyleToClasses(classification.style);
+ const next = classifications[i + 1] || {offset: text.length};
+ const classifiedText =
+ text.substring(classification.offset, next.offset);
+ return classes.length ? spanWithClasses(classifiedText, classes) :
+ document.createTextNode(classifiedText);
+ })
+ .reduce((container, currentElement) => {
+ container.appendChild(currentElement);
+ return container;
+ }, document.createElement('span'));
}
/**
@@ -1734,7 +1886,8 @@ function renderTheme() {
// includes non-white backgrounds, excluding dark mode gray if dark mode is
// enabled.
const isDefaultBackground = theme.usingDefaultTheme && !theme.imageUrl;
- document.body.classList.toggle(CLASSES.USE_NOTIFIER, !isDefaultBackground);
+ const useNotifier = configData.doodleNotifierEnabled && !isDefaultBackground;
+ document.body.classList.toggle(CLASSES.USE_NOTIFIER, useNotifier);
// If a custom background has been selected the image will be applied to the
// custom-background element instead of the body.
@@ -1800,10 +1953,14 @@ function renderTheme() {
if (configData.realboxMatchOmniboxTheme) {
// TODO(dbeam): actually get these from theme service.
const removeMatchHovered = assert(theme.searchBox.icon).slice();
- removeMatchHovered[3] = .08 * 255;
+ removeMatchHovered[3] = .16 * 255;
+
+ const removeMatchSelectedHovered =
+ assert(theme.searchBox.iconSelected).slice();
+ removeMatchSelectedHovered[3] = .16 * 255;
- const removeMatchFocused = theme.searchBox.icon.slice();
- removeMatchFocused[3] = .16 * 255;
+ const removeMatchFocused = theme.searchBox.iconSelected.slice();
+ removeMatchFocused[3] = .32 * 255;
/**
* @param {string} varName
@@ -1816,6 +1973,7 @@ function renderTheme() {
setCssVar('search-box-bg', theme.searchBox.bg);
setCssVar('search-box-icon', theme.searchBox.icon);
+ setCssVar('search-box-icon-selected', theme.searchBox.iconSelected);
setCssVar('search-box-placeholder', theme.searchBox.placeholder);
setCssVar('search-box-results-bg', theme.searchBox.resultsBg);
setCssVar(
@@ -1823,10 +1981,18 @@ function renderTheme() {
setCssVar(
'search-box-results-bg-selected', theme.searchBox.resultsBgSelected);
setCssVar('search-box-results-dim', theme.searchBox.resultsDim);
+ setCssVar(
+ 'search-box-results-dim-selected', theme.searchBox.resultsDimSelected);
setCssVar('search-box-results-text', theme.searchBox.resultsText);
+ setCssVar(
+ 'search-box-results-text-selected',
+ theme.searchBox.resultsTextSelected);
setCssVar('search-box-results-url', theme.searchBox.resultsUrl);
+ setCssVar(
+ 'search-box-results-url-selected', theme.searchBox.resultsUrlSelected);
setCssVar('search-box-text', theme.searchBox.text);
setCssVar('remove-match-hovered', removeMatchHovered);
+ setCssVar('remove-match-selected-hovered', removeMatchSelectedHovered);
setCssVar('remove-match-focused', removeMatchFocused);
}
}
@@ -1966,40 +2132,63 @@ function setFakeboxVisibility(show) {
document.body.classList.toggle(CLASSES.HIDE_FAKEBOX, !show);
}
-/** @param {!AutocompleteMatch|undefined} match */
-function setRealboxIcon(match) {
- const showIcon = match && !match.isSearchType;
-
- const realboxIcon = $(IDS.REALBOX_ICON);
- realboxIcon.style.webkitMask = showIcon ? 'none' : '';
- realboxIcon.style.backgroundColor = showIcon ? 'transparent' : '';
- realboxIcon.style.backgroundImage =
- showIcon ? `url(${getIconUrl(match.destinationUrl)})` : '';
+/**
+ * @param {!Element} element
+ * @param {string} url
+ */
+function setBackgroundImageByUrl(element, url) {
+ element.style.webkitMaskImage = '';
+ element.style.backgroundImage = `url(${url})`;
+ element.style.backgroundColor = 'transparent';
}
-/** @param {boolean} visible */
-function setRealboxMatchesVisible(visible) {
- $(IDS.REALBOX_INPUT_WRAPPER).classList.toggle(CLASSES.SHOW_MATCHES, visible);
+/**
+ * @param {!Element} element
+ * @param {string} url
+ */
+function setWebkitMaskImageByUrl(element, url) {
+ element.style.webkitMaskImage = `url(${url})`;
+ element.style.backgroundImage = '';
+ element.style.backgroundColor = '';
}
-/** @param {boolean} listen */
-function setRealboxWrapperListenForFocusOut(listen) {
- const realboxWrapper = $(IDS.REALBOX_INPUT_WRAPPER);
- if (listen) {
- realboxWrapper.addEventListener('focusout', onRealboxWrapperFocusOut);
+/** @param {!AutocompleteMatch|undefined} match */
+function setRealboxIcon(match) {
+ const realboxIcon = $(IDS.REALBOX_ICON);
+ if (match && !match.isSearchType) {
+ // if the selected match is a navigation match and has a favicon loaded,
+ // display the favicon. Otherwise display the match icon.
+ if (faviconOrImageUrlToDataUrlCache[match.destinationUrl]) {
+ realboxIcon.dataset.icon = '';
+ setBackgroundImageByUrl(
+ realboxIcon, faviconOrImageUrlToDataUrlCache[match.destinationUrl]);
+ } else if (match.type == DOCUMENT_MATCH_TYPE) {
+ realboxIcon.dataset.icon = match.iconUrl;
+ // Document matches use colored SVG icons.
+ setBackgroundImageByUrl(realboxIcon, realboxIcon.dataset.icon);
+ } else {
+ realboxIcon.dataset.icon = match.iconUrl;
+ setWebkitMaskImageByUrl(realboxIcon, realboxIcon.dataset.icon);
+ }
+ } else if (configData.useGoogleGIcon) {
+ // if google_g icon should be used (as the default icon and search matches),
+ // display the default icon which is set to the google_g icon.
+ /** @suppress {missingProperties} */
+ realboxIcon.dataset.icon = realboxIcon.dataset.defaultIcon;
+ setBackgroundImageByUrl(realboxIcon, realboxIcon.dataset.icon);
} else {
- realboxWrapper.removeEventListener('focusout', onRealboxWrapperFocusOut);
+ // if no match is selected, display the default icon. Otherwise display the
+ // match icon.
+ /** @suppress {missingProperties} */
+ realboxIcon.dataset.icon =
+ match ? match.iconUrl : realboxIcon.dataset.defaultIcon;
+ setWebkitMaskImageByUrl(realboxIcon, realboxIcon.dataset.icon);
}
}
-/** @param {boolean} listen */
-function setRealboxWrapperListenForKeydown(listen) {
- const realboxWrapper = $(IDS.REALBOX_INPUT_WRAPPER);
- if (listen) {
- realboxWrapper.addEventListener('keydown', onRealboxWrapperKeydown);
- } else {
- realboxWrapper.removeEventListener('keydown', onRealboxWrapperKeydown);
- }
+/** @param {boolean} visible */
+function setRealboxMatchesVisible(visible) {
+ $(IDS.REALBOX_INPUT_WRAPPER).classList.toggle(CLASSES.SHOW_MATCHES, visible);
}
/**
diff --git a/chromium/chrome/browser/resources/local_ntp/most_visited_single.css b/chromium/chrome/browser/resources/local_ntp/most_visited_single.css
index d1ed09f7a96..7c3d32a4688 100644
--- a/chromium/chrome/browser/resources/local_ntp/most_visited_single.css
+++ b/chromium/chrome/browser/resources/local_ntp/most_visited_single.css
@@ -253,11 +253,13 @@ body:not(.reordering) .md-menu:focus:not(.mouse-navigation) {
/* We use ::after without content to provide the masked X element. */
.md-menu::after {
- --mask-width: calc(var(--md-menu-size) - 2);
+ --mask-gap: 1px;
+ --mask-width: calc(var(--md-menu-size) - 2 * var(--mask-gap));
/* TODO(crbug.com/1012065): Use SVG for the "X" icon. */
-webkit-mask-image: -webkit-image-set(
url(chrome-search://most-visited/dont_show.png) 1x,
url(chrome-search://most-visited/dont_show_2x.png) 2x);
+ -webkit-mask-position: var(--mask-gap);
-webkit-mask-repeat: no-repeat;
-webkit-mask-size: var(--mask-width);
background-color: rgb(var(--GG600-rgb));
diff --git a/chromium/chrome/browser/resources/local_ntp/voice.css b/chromium/chrome/browser/resources/local_ntp/voice.css
index a3118e7f2cf..01a8b4be263 100644
--- a/chromium/chrome/browser/resources/local_ntp/voice.css
+++ b/chromium/chrome/browser/resources/local_ntp/voice.css
@@ -588,3 +588,9 @@ html[dir=rtl] .overlay .voice-text {
border-color: rgb(var(--GG200-rgb));
}
}
+
+#screen-reader-announcer {
+ clip: rect(0, 0, 0, 0);
+ display: inline-block;
+ position: fixed;
+}
diff --git a/chromium/chrome/browser/resources/local_ntp/voice.js b/chromium/chrome/browser/resources/local_ntp/voice.js
index 46497631c86..bb8ce4fa6b6 100644
--- a/chromium/chrome/browser/resources/local_ntp/voice.js
+++ b/chromium/chrome/browser/resources/local_ntp/voice.js
@@ -96,6 +96,8 @@ const RecognitionError = {
*/
const speech = {};
+speech.SCREEN_READER_ANNOUNCER_ = 'screen-reader-announcer';
+
/**
* Localized translations for messages used in the Speech UI.
* @type {{
@@ -321,6 +323,13 @@ speech.init = function(
throw new Error('OnFocusChange handler already set on searchbox.');
}
searchboxApiHandle.onfocuschange = speech.onOmniboxFocused;
+ const dialog = $(view.DIALOG_ID_);
+ if (dialog) {
+ dialog.addEventListener('close', () => {
+ speech.screenReaderAnnounce_(translatedStrings.voiceSearchClosed);
+ fakeboxMicrophoneElem.focus();
+ });
+ }
// Initialize speech internal state.
speech.googleBaseUrl_ = googleBaseUrl;
@@ -919,6 +928,18 @@ speech.onClick_ = function(shouldSubmit, shouldRetry, navigatingAway) {
}
};
+/**
+ * @param {string} message
+ * @private
+ */
+speech.screenReaderAnnounce_ = function(message) {
+ const annoucer = $(speech.SCREEN_READER_ANNOUNCER_);
+ annoucer.innerText = '';
+ setTimeout(() => {
+ annoucer.innerText = message;
+ }, 100);
+};
+
/* TEXT VIEW */
/**
diff --git a/chromium/chrome/browser/resources/local_state/BUILD.gn b/chromium/chrome/browser/resources/local_state/BUILD.gn
index 7b50454e2c3..47ea708cfeb 100644
--- a/chromium/chrome/browser/resources/local_state/BUILD.gn
+++ b/chromium/chrome/browser/resources/local_state/BUILD.gn
@@ -6,9 +6,7 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
uses_js_modules = true
- deps = [
- ":local_state",
- ]
+ deps = [ ":local_state" ]
}
js_library("local_state") {
diff --git a/chromium/chrome/browser/resources/management/BUILD.gn b/chromium/chrome/browser/resources/management/BUILD.gn
index 4e27e412b9f..8681246c50a 100644
--- a/chromium/chrome/browser/resources/management/BUILD.gn
+++ b/chromium/chrome/browser/resources/management/BUILD.gn
@@ -23,9 +23,7 @@ js_library("management_ui") {
}
js_library("management_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
}
polymer_modulizer("management_ui") {
@@ -41,7 +39,7 @@ polymer_modulizer("icons") {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":icons_module",
":management_ui_module",
]
diff --git a/chromium/chrome/browser/resources/management/icons.html b/chromium/chrome/browser/resources/management/icons.html
index e6a075711d8..61de7530161 100644
--- a/chromium/chrome/browser/resources/management/icons.html
+++ b/chromium/chrome/browser/resources/management/icons.html
@@ -8,6 +8,8 @@
<g id="supervised-user"><path d="M11.99 2c-5.52 0-10 4.48-10 10s4.48 10 10 10 10-4.48 10-10-4.48-10-10-10zm3.61 6.34c1.07 0 1.93.86 1.93 1.93 0 1.07-.86 1.93-1.93 1.93-1.07 0-1.93-.86-1.93-1.93-.01-1.07.86-1.93 1.93-1.93zm-6-1.58c1.3 0 2.36 1.06 2.36 2.36 0 1.3-1.06 2.36-2.36 2.36s-2.36-1.06-2.36-2.36c0-1.31 1.05-2.36 2.36-2.36zm0 9.13v3.75c-2.4-.75-4.3-2.6-5.14-4.96 1.05-1.12 3.67-1.69 5.14-1.69.53 0 1.2.08 1.9.22-1.64.87-1.9 2.02-1.9 2.68zM11.99 20c-.27 0-.53-.01-.79-.04v-4.07c0-1.42 2.94-2.13 4.4-2.13 1.07 0 2.92.39 3.84 1.15-1.17 2.97-4.06 5.09-7.45 5.09z"></path></g>
<g id="timelapse"><path d="M16.24 7.76C15.07 6.59 13.54 6 12 6v6l-4.24 4.24c2.34 2.34 6.14 2.34 8.49 0 2.34-2.34 2.34-6.14-.01-8.48zM12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"></path></g>
<g id="linux"><path d="M 6.9375 22.042969 C 3.867188 20.457031 1.886719 17.347656 1.824219 13.234375 C 1.527344 13.378906 1.1875 13.402344 0.800781 13.265625 C -0.3125 12.875 -0.0625 11.578125 0.34375 10.421875 C 0.683594 9.460938 1.835938 8.761719 2.402344 8.613281 C 3.71875 3.78125 6.804688 0 12 0 C 17.257812 0 20.367188 3.625 21.644531 8.628906 C 22.222656 8.796875 23.324219 9.484375 23.65625 10.421875 C 24.0625 11.578125 24.3125 12.875 23.199219 13.265625 C 22.8125 13.402344 22.472656 13.378906 22.175781 13.234375 C 22.117188 17.375 20.140625 20.472656 17.070312 22.046875 C 17.257812 22.191406 17.363281 22.375 17.363281 22.613281 C 17.363281 23.378906 17.75 24 14.898438 24 C 12.8125 24 12.457031 23.578125 12.417969 23.117188 C 12.28125 23.035156 12.140625 22.910156 12 22.910156 C 11.859375 22.910156 11.71875 23.042969 11.582031 23.128906 C 11.535156 23.582031 11.171875 24 9.101562 24 C 6.25 24 6.636719 23.378906 6.636719 22.613281 C 6.636719 22.371094 6.746094 22.183594 6.9375 22.042969 Z M 12 21.222656 C 17.929688 21.222656 20.070312 17.1875 20.070312 11.820312 C 20.070312 7.371094 18.125 3.28125 14.898438 2.597656 C 13.863281 2.378906 13.136719 4.761719 12 4.761719 C 10.863281 4.761719 10.035156 2.378906 9.101562 2.597656 C 5.863281 3.359375 3.929688 7.605469 3.929688 11.820312 C 3.929688 16.882812 6.070312 21.222656 12 21.222656 Z M 8.277344 9.324219 C 7.589844 9.324219 7.035156 8.789062 7.035156 8.132812 C 7.035156 7.476562 7.589844 6.941406 8.277344 6.941406 C 8.960938 6.941406 9.515625 7.476562 9.515625 8.132812 C 9.515625 8.789062 8.960938 9.324219 8.277344 9.324219 Z M 15.722656 9.324219 C 15.039062 9.324219 14.484375 8.789062 14.484375 8.132812 C 14.484375 7.476562 15.039062 6.941406 15.722656 6.941406 C 16.410156 6.941406 16.964844 7.476562 16.964844 8.132812 C 16.964844 8.789062 16.410156 9.324219 15.722656 9.324219 Z M 12.226562 9.964844 L 13.929688 10.683594 C 14.222656 10.804688 14.355469 11.132812 14.226562 11.414062 C 14.199219 11.46875 14.164062 11.519531 14.121094 11.5625 L 12.425781 13.308594 C 12.210938 13.535156 11.839844 13.546875 11.601562 13.339844 C 11.589844 13.332031 11.578125 13.320312 11.566406 13.308594 L 9.878906 11.558594 C 9.660156 11.332031 9.675781 10.980469 9.914062 10.773438 C 9.960938 10.734375 10.011719 10.703125 10.070312 10.679688 L 11.75 9.964844 C 11.898438 9.902344 12.074219 9.902344 12.226562 9.964844 Z M 12.226562 9.964844"></path></g>
+ <g id="play-store"><path d="M20.18 10.88l-3.06-1.74L14.26 12l2.86 2.86 3.06-1.74c.55-.31.82-.71.82-1.12 0-.41-.27-.81-.82-1.12zM4.71 2.45l8.42 8.42 2.55-2.55-10.7-6.06c-.07-.04-.14-.07-.21-.1-.17-.07-.3.05-.15.21.03.02.06.05.09.08zm0 19.1l-.08.08c-.15.15-.02.28.15.21.07-.03.14-.06.21-.1l10.69-6.06-2.55-2.55s-7.2 7.21-8.42 8.42zM12 12L3.38 3.38c-.19-.19-.38-.07-.38.19v16.86c0 .26.19.38.38.19L12 12z"></path></g>
+ <g id="crash"><path d="M23 12l-2.44-2.78.34-3.68-3.61-.82-1.89-3.18L12 3 8.6 1.54 6.71 4.72l-3.61.81.34 3.68L1 12l2.44 2.78-.34 3.69 3.61.82 1.89 3.18L12 21l3.4 1.46 1.89-3.18 3.61-.82-.34-3.68L23 12zm-4.51 2.11l.26 2.79-2.74.62-1.43 2.41L12 18.82l-2.58 1.11-1.43-2.41-2.74-.62.26-2.8L3.66 12l1.85-2.12-.26-2.78 2.74-.61 1.43-2.41L12 5.18l2.58-1.11 1.43 2.41 2.74.62-.26 2.79L20.34 12l-1.85 2.11zM11 15h2v2h-2zm0-8h2v6h-2z"></path></g>
</if>
<g id="account-circle"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-1.28-6-3.22.03-1.99 4-3.08 6-3.08 1.99 0 5.97 1.09 6 3.08-1.29 1.94-3.5 3.22-6 3.22z"></path><path d="M0 0h24v24H0z" fill="none"></path></g>
<g id="public"><path d="M0 0h24v24H0z" fill="none"></path><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"></path></g>
diff --git a/chromium/chrome/browser/resources/management/management_browser_proxy.js b/chromium/chrome/browser/resources/management/management_browser_proxy.js
index 9c5614071dd..9846ddc10c7 100644
--- a/chromium/chrome/browser/resources/management/management_browser_proxy.js
+++ b/chromium/chrome/browser/resources/management/management_browser_proxy.js
@@ -68,9 +68,13 @@ export const DeviceReportingType = {
DEVICE_ACTIVITY: 'device activity',
STATISTIC: 'device statistics',
DEVICE: 'device',
+ CRASH_REPORT: 'crash report',
LOGS: 'logs',
PRINT: 'print',
- CROSTINI: 'crostini'
+ CROSTINI: 'crostini',
+ USERNAME: 'username',
+ EXTENSION: 'extension',
+ ANDROID_APPLICATION: 'android application'
};
diff --git a/chromium/chrome/browser/resources/management/management_ui.html b/chromium/chrome/browser/resources/management/management_ui.html
index 93ecc899507..57fdf8e732d 100644
--- a/chromium/chrome/browser/resources/management/management_ui.html
+++ b/chromium/chrome/browser/resources/management/management_ui.html
@@ -28,8 +28,8 @@
}
.card {
- @apply --cr-card-elevation;
background-color: var(--cr-card-background-color);
+ box-shadow: var(--cr-card-shadow);
margin: 0 3px;
min-height: 100%;
}
@@ -83,13 +83,12 @@
}
section {
- @apply --cr-section;
align-items: flex-start;
- border-top: none;
+ display: flex;
flex-direction: column;
justify-content: center;
- padding-bottom: 12px;
- padding-top: 12px;
+ min-height: var(--cr-section-min-height);
+ padding: 12px var(--cr-section-padding);
}
section:not(.page-subtitle) h2 {
diff --git a/chromium/chrome/browser/resources/management/management_ui.js b/chromium/chrome/browser/resources/management/management_ui.js
index 4968ac9d058..914d6adf30e 100644
--- a/chromium/chrome/browser/resources/management/management_ui.js
+++ b/chromium/chrome/browser/resources/management/management_ui.js
@@ -219,12 +219,20 @@ Polymer({
return 'management:bar-chart';
case DeviceReportingType.DEVICE:
return 'cr:computer';
+ case DeviceReportingType.CRASH_REPORT:
+ return 'management:crash';
case DeviceReportingType.LOGS:
return 'management:report';
case DeviceReportingType.PRINT:
return 'cr:print';
case DeviceReportingType.CROSTINI:
return 'management:linux';
+ case DeviceReportingType.USERNAME:
+ return 'management:account-circle';
+ case DeviceReportingType.EXTENSION:
+ return 'cr:extension';
+ case DeviceReportingType.ANDROID_APPLICATION:
+ return 'management:play-store';
default:
return 'cr:computer';
}
@@ -277,7 +285,7 @@ Polymer({
* @param {!CustomEvent<string>} e
* @private
*/
- onSearchChanged_: function(e) {
+ onSearchChanged_(e) {
const query = e.detail;
window.location.href =
`chrome://settings?search=${encodeURIComponent(query)}`;
diff --git a/chromium/chrome/browser/resources/media/BUILD.gn b/chromium/chrome/browser/resources/media/BUILD.gn
index b0ce7fbd7dc..2fef84adc3e 100644
--- a/chromium/chrome/browser/resources/media/BUILD.gn
+++ b/chromium/chrome/browser/resources/media/BUILD.gn
@@ -2,22 +2,55 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//third_party/closure_compiler/compile_js.gni")
import("//tools/grit/grit_rule.gni")
grit("webrtc_logs_resources") {
source = "webrtc_logs_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
use_brotli = true
outputs = [
"grit/webrtc_logs_resources.h",
"webrtc_logs_resources.pak",
]
output_dir = "$root_gen_dir/chrome"
- depfile_dir = target_gen_dir
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
}
+
+js_type_check("closure_compile") {
+ deps = [
+ ":media_data_table",
+ ":media_feeds",
+ ":media_history",
+ ]
+}
+
+js_library("media_history") {
+ deps = [
+ ":media_data_table",
+ "//chrome/browser/media:mojo_bindings_js_library_for_compile",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:util",
+ "//ui/webui/resources/js/cr/ui:tabs",
+ ]
+}
+
+js_library("media_feeds") {
+ deps = [
+ ":media_data_table",
+ "//chrome/browser/media/feeds:mojo_bindings_js_library_for_compile",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:util",
+ ]
+}
+
+js_library("media_data_table") {
+ deps = [
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:util",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/media/media_data_table.js b/chromium/chrome/browser/resources/media/media_data_table.js
new file mode 100644
index 00000000000..758ace61120
--- /dev/null
+++ b/chromium/chrome/browser/resources/media/media_data_table.js
@@ -0,0 +1,124 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+cr.define('cr.ui', function() {
+ /**
+ * TODO(beccahughes): Description
+ */
+ /* #export */ class MediaDataTable {
+ /**
+ * @param {HTMLElement} table
+ * @param {!cr.ui.MediaDataTableDelegate} delegate
+ */
+ constructor(table, delegate) {
+ /** @private {HTMLElement} */
+ this.table_ = table;
+
+ /** @private {Array<Object>} */
+ this.data_ = [];
+
+ /** @private {cr.ui.MediaDataTableDelegate} */
+ this.delegate_ = delegate;
+
+ // Set table header sort handlers.
+ const headers = this.table_.querySelectorAll('th[sort-key]');
+ headers.forEach(header => {
+ header.addEventListener('click', this.handleSortClick_.bind(this));
+ });
+ }
+
+ handleSortClick_(e) {
+ if (e.target.classList.contains('sort-column')) {
+ e.target.toggleAttribute('sort-reverse');
+ } else {
+ document.querySelector('.sort-column').classList.remove('sort-column');
+ e.target.classList.add('sort-column');
+ }
+
+ this.render();
+ }
+
+ render() {
+ // Find the body of the table and clear it.
+ const body = this.table_.querySelectorAll('tbody')[0];
+ body.innerHTML = '';
+
+ // Get the sort key from the columns to determine which data should be in
+ // which column.
+ const headerCells = Array.from(this.table_.querySelectorAll('thead th'));
+ const dataAndSortKeys = headerCells.map((e) => {
+ return e.getAttribute('sort-key') ? e.getAttribute('sort-key') :
+ e.getAttribute('data-key');
+ });
+
+ const currentSortCol = this.table_.querySelectorAll('.sort-column')[0];
+ const currentSortKey = currentSortCol.getAttribute('sort-key');
+ const currentSortReverse = currentSortCol.hasAttribute('sort-reverse');
+
+ // Sort the data based on the current sort key.
+ this.data_.sort((a, b) => {
+ return (currentSortReverse ? -1 : 1) *
+ this.delegate_.compareTableItem(currentSortKey, a, b);
+ });
+
+ // Generate the table rows.
+ this.data_.forEach((dataRow) => {
+ const tr = document.createElement('tr');
+ body.appendChild(tr);
+
+ dataAndSortKeys.forEach((key) => {
+ const td = document.createElement('td');
+
+ // Keys with a period denote nested objects.
+ let data = dataRow;
+ const expandedKey = key.split('.');
+ expandedKey.forEach((k) => {
+ data = data[k];
+ key = k;
+ });
+
+ this.delegate_.insertDataField(td, data, key, dataRow);
+ tr.appendChild(td);
+ });
+ });
+ }
+
+ /**
+ * @param {Array} data The data to update
+ */
+ setData(data) {
+ this.data_ = data;
+ this.render();
+ }
+ }
+
+ /** @interface */
+ /* #export */ class MediaDataTableDelegate {
+ /**
+ * Formats a field to be displayed in the data table and inserts it into the
+ * element.
+ * @param {Element} td
+ * @param {?Object} data
+ * @param {string} key
+ * @param {Object} dataRow This is the row itself in case we need extra
+ * data to render the field.
+ */
+ insertDataField(td, data, key, dataRow) {}
+
+ /**
+ * Compares two objects based on |sortKey|.
+ * @param {string} sortKey The name of the property to sort by.
+ * @param {?Object} a The first object to compare.
+ * @param {?Object} b The second object to compare.
+ * @return {number} A negative number if |a| should be ordered
+ * before |b|, a positive number otherwise.
+ */
+ compareTableItem(sortKey, a, b) {}
+ }
+
+ // #cr_define_end
+ return {MediaDataTable, MediaDataTableDelegate};
+});
diff --git a/chromium/chrome/browser/resources/media/media_feeds.html b/chromium/chrome/browser/resources/media/media_feeds.html
new file mode 100644
index 00000000000..b7e3edf4a5f
--- /dev/null
+++ b/chromium/chrome/browser/resources/media/media_feeds.html
@@ -0,0 +1,206 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <title>Media Feeds</title>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+ <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js"></script>
+ <script src="chrome://resources/js/promise_resolver.js"></script>
+ <script src="chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js"></script>
+ <script src="chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js"></script>
+ <script src="chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js"></script>
+ <script src="chrome://resources/mojo/url/mojom/url.mojom-lite.js"></script>
+ <script src="ui/gfx/geometry/mojom/geometry.mojom-lite.js"></script>
+ <script src="services/media_session/public/mojom/media_session.mojom-lite.js"></script>
+ <script src="chrome://resources/js/util.js"></script>
+
+ <script src="chrome/browser/media/feeds/media_feeds_store.mojom-lite.js">
+ </script>
+
+ <script src="chrome://resources/js/cr.js"></script>
+ <script src="chrome://resources/js/cr/ui.js"></script>
+
+ <script src="chrome://media-feeds/media-data-table.js"></script>
+ <script src="chrome://media-feeds/media-feeds.js"></script>
+ <style>
+ body {
+ font-family: 'Roboto', 'Noto', sans-serif;
+ font-size: 14px;
+ }
+
+ button {
+ margin-bottom: 20px;
+ }
+
+ table {
+ border-collapse: collapse;
+ margin-bottom: 20px;
+ }
+
+ table td,
+ table th {
+ border: 1px solid #777;
+ padding-inline-end: 4px;
+ padding-inline-start: 4px;
+ }
+
+ table th {
+ background: rgb(224, 236, 255);
+ cursor: pointer;
+ padding-bottom: 4px;
+ padding-inline-end: 4px;
+ padding-top: 4px;
+ white-space: nowrap;
+ }
+
+ .url-cell {
+ background-color: rgba(230, 230, 230, 0.5);
+ }
+
+ .name-cell {
+ background-color: rgba(230, 230, 230, 0.5);
+ }
+
+ table tr:hover {
+ background: rgb(255, 255, 187);
+ }
+
+ th.sort-column {
+ padding-inline-end: 16px;
+ }
+
+ th.sort-column::after {
+ content: '▲';
+ position: absolute;
+ }
+
+ th[sort-reverse].sort-column::after {
+ content: '▼';
+ position: absolute;
+ }
+ </style>
+</head>
+<body>
+ <h1>Media Feeds</h1>
+ <button id="copy-all-to-clipboard">Copy all to clipboard</button>
+ <table id="feeds-table">
+ <thead>
+ <tr id="feed-table-header">
+ <th sort-key="id" class="sort-column" sort-reverse>
+ ID
+ </th>
+ <th sort-key="url">
+ Url
+ </th>
+ <th sort-key="displayName">
+ Display Name
+ </th>
+ <th sort-key="lastDiscoveryTime">
+ Last Discovery Time
+ </th>
+ <th sort-key="lastFetchTime">
+ Last Fetch Time
+ </th>
+ <th sort-key="userStatus">
+ User Status
+ </th>
+ <th sort-key="lastFetchResult">
+ Last Fetch Result
+ </th>
+ <th sort-key="fetchFailedCount">
+ Fetch Failed Count
+ </th>
+ <th sort-key="cacheExpiryTime">
+ Cache Expiry Time
+ </th>
+ <th sort-key="lastFetchItemCount">
+ Last Fetch Item Count
+ </th>
+ <th sort-key="lastFetchPlayNextCount">
+ Last Fetch Play Next Count
+ </th>
+ <th sort-key="lastFetchContentTypes">
+ Last Fetch Content Types
+ </th>
+ <th data-key="logos">
+ Logos
+ <th data-key="actions">
+ Actions
+ </th>
+ </tr>
+ </thead>
+ <tbody id="feed-table-body">
+ </tbody>
+ </table>
+
+ <div id="feed-content" style="display:none;">
+ <hr>
+ <h2>Feed Contents: <span id="current-feed"></span></h2>
+ <table id="feed-items-table">
+ <thead>
+ <tr>
+ <th sort-key="type" class="sort-column" sort-reverse>
+ Type
+ </th>
+ <th sort-key="name">
+ Name
+ </th>
+ <th sort-key="author">
+ Author
+ </th>
+ <th sort-key="datePublished">
+ Date Published
+ </th>
+ <th sort-key="isFamilyFriendly">
+ Family Friendly
+ </th>
+ <th sort-key="actionStatus">
+ Action Status
+ </th>
+ <th sort-key="action.url">
+ Action URL
+ </th>
+ <th sort-key="action.startTime">
+ Action Start Time (secs)
+ </th>
+ <th sort-key="interactionCounters">
+ Interaction Counters
+ </th>
+ <th sort-key="contentRatings">
+ Content Ratings
+ </th>
+ <th sort-key="genre">
+ Genre
+ </th>
+ <th sort-key="live">
+ Live Details
+ </th>
+ <th sort-key="tvEpisode">
+ TV Episode
+ </th>
+ <th sort-key="playNextCandidate">
+ Play Next Candidate
+ </th>
+ <th sort-key="identifiers">
+ Identifiers
+ </th>
+ <th sort-key="shownCount">
+ Shown Count
+ </th>
+ <th sort-key="clicked">
+ Clicked
+ </th>
+ <th sort-key="images">
+ Images
+ </th>
+ <th sort-key="safeSearchResult">
+ Safe Search Result
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ </tbody>
+ </table>
+ </div>
+</body>
+</html>
diff --git a/chromium/chrome/browser/resources/media/media_feeds.js b/chromium/chrome/browser/resources/media/media_feeds.js
new file mode 100644
index 00000000000..9f0e1732a63
--- /dev/null
+++ b/chromium/chrome/browser/resources/media/media_feeds.js
@@ -0,0 +1,396 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+// Allow a function to be provided by tests, which will be called when
+// the page has been populated with media feeds details.
+const mediaFeedsPageIsPopulatedResolver = new PromiseResolver();
+function whenPageIsPopulatedForTest() {
+ return mediaFeedsPageIsPopulatedResolver.promise;
+}
+
+const mediaFeedItemsPageIsPopulatedResolver = new PromiseResolver();
+function whenFeedTableIsPopulatedForTest() {
+ return mediaFeedItemsPageIsPopulatedResolver.promise;
+}
+
+(function() {
+
+let delegate = null;
+let feedsTable = null;
+let feedItemsTable = null;
+let store = null;
+
+/** @implements {cr.ui.MediaDataTableDelegate} */
+class MediaFeedsTableDelegate {
+ /**
+ * Formats a field to be displayed in the data table and inserts it into the
+ * element.
+ * @param {Element} td
+ * @param {?Object} data
+ * @param {string} key
+ * @param {Object} dataRow
+ */
+ insertDataField(td, data, key, dataRow) {
+ if (key == 'actions') {
+ const a = document.createElement('a');
+ a.href = '#feed-content';
+ a.textContent = 'Show Contents';
+ td.appendChild(a);
+
+ a.addEventListener('click', () => {
+ store.getItemsForMediaFeed(dataRow.id).then(response => {
+ feedItemsTable.setData(response.items);
+
+ // Show the feed items section.
+ $('current-feed').textContent = dataRow.url.url;
+ $('feed-content').style.display = 'block';
+
+ mediaFeedItemsPageIsPopulatedResolver.resolve();
+ });
+ });
+ }
+
+ if (data === undefined || data === null) {
+ return;
+ }
+
+ if (key === 'url') {
+ // Format a mojo GURL.
+ td.textContent = data.url;
+ } else if (
+ key === 'lastDiscoveryTime' || key === 'lastFetchTime' ||
+ key === 'cacheExpiryTime' || key === 'datePublished') {
+ // Format a mojo time.
+ td.textContent =
+ convertMojoTimeToJS(/** @type {mojoBase.mojom.Time} */ (data))
+ .toLocaleString();
+ } else if (key === 'userStatus') {
+ // Format a FeedUserStatus.
+ if (data == mediaFeeds.mojom.FeedUserStatus.kAuto) {
+ td.textContent = 'Auto';
+ } else if (data == mediaFeeds.mojom.FeedUserStatus.kDisabled) {
+ td.textContent = 'Disabled';
+ }
+ } else if (key === 'lastFetchResult') {
+ // Format a FetchResult.
+ if (data == mediaFeeds.mojom.FetchResult.kNone) {
+ td.textContent = 'None';
+ } else if (data == mediaFeeds.mojom.FetchResult.kSuccess) {
+ td.textContent = 'Success';
+ } else if (data == mediaFeeds.mojom.FetchResult.kFailedBackendError) {
+ td.textContent = 'Failed (Backend Error)';
+ } else if (data == mediaFeeds.mojom.FetchResult.kFailedNetworkError) {
+ td.textContent = 'Failed (Network Error)';
+ }
+ } else if (key === 'lastFetchContentTypes') {
+ // Format a MediaFeedItemType.
+ const contentTypes = [];
+ const itemType = parseInt(data, 10);
+
+ if (itemType & mediaFeeds.mojom.MediaFeedItemType.kVideo) {
+ contentTypes.push('Video');
+ } else if (itemType & mediaFeeds.mojom.MediaFeedItemType.kTVSeries) {
+ contentTypes.push('TV Series');
+ } else if (itemType & mediaFeeds.mojom.MediaFeedItemType.kMovie) {
+ contentTypes.push('Movie');
+ }
+
+ td.textContent =
+ contentTypes.length === 0 ? 'None' : contentTypes.join(',');
+ } else if (key === 'logos' || key === 'images') {
+ // Format an array of mojo media images.
+ data.forEach((image) => {
+ const a = document.createElement('a');
+ a.href = image.src.url;
+ a.textContent = image.src.url;
+ a.target = '_blank';
+ td.appendChild(a);
+ td.appendChild(document.createElement('br'));
+ });
+ } else if (key == 'type') {
+ // Format a MediaFeedItemType.
+ switch (parseInt(data, 10)) {
+ case mediaFeeds.mojom.MediaFeedItemType.kVideo:
+ td.textContent = 'Video';
+ break;
+ case mediaFeeds.mojom.MediaFeedItemType.kTVSeries:
+ td.textContent = 'TV Series';
+ break;
+ case mediaFeeds.mojom.MediaFeedItemType.kMovie:
+ td.textContent = 'Movie';
+ break;
+ }
+ } else if (key == 'isFamilyFriendly' || key == 'clicked') {
+ // Format a boolean.
+ td.textContent = data ? 'Yes' : 'No';
+ } else if (key == 'actionStatus') {
+ // Format a MediaFeedItemActionStatus.
+ switch (parseInt(data, 10)) {
+ case mediaFeeds.mojom.MediaFeedItemActionStatus.kUnknown:
+ td.textContent = 'Unknown';
+ break;
+ case mediaFeeds.mojom.MediaFeedItemActionStatus.kActive:
+ td.textContent = 'Active';
+ break;
+ case mediaFeeds.mojom.MediaFeedItemActionStatus.kPotential:
+ td.textContent = 'Potential';
+ break;
+ case mediaFeeds.mojom.MediaFeedItemActionStatus.kCompleted:
+ td.textContent = 'Completed';
+ break;
+ }
+ } else if (key == 'safeSearchResult') {
+ // Format a SafeSearchResult.
+ switch (parseInt(data, 10)) {
+ case mediaFeeds.mojom.SafeSearchResult.kUnknown:
+ td.textContent = 'Unknown';
+ break;
+ case mediaFeeds.mojom.SafeSearchResult.kSafe:
+ td.textContent = 'Safe';
+ break;
+ case mediaFeeds.mojom.SafeSearchResult.kUnsafe:
+ td.textContent = 'Unsafe';
+ break;
+ }
+ } else if (key == 'startTime') {
+ // Format a start time.
+ td.textContent =
+ timeDeltaToSeconds(/** @type {mojoBase.mojom.TimeDelta} */ (data));
+ } else if (key == 'interactionCounters') {
+ // Format interaction counters.
+ const counters = [];
+
+ Object.keys(data).forEach((key) => {
+ let keyString = '';
+
+ switch (parseInt(key, 10)) {
+ case mediaFeeds.mojom.InteractionCounterType.kWatch:
+ keyString = 'Watch';
+ break;
+ case mediaFeeds.mojom.InteractionCounterType.kLike:
+ keyString = 'Like';
+ break;
+ case mediaFeeds.mojom.InteractionCounterType.kDislike:
+ keyString = 'Dislike';
+ break;
+ }
+
+ counters.push(keyString + '=' + data[key]);
+ });
+
+ td.textContent = counters.join(' ');
+ } else if (key == 'contentRatings') {
+ // Format content ratings.
+ const ratings = [];
+
+ data.forEach((rating) => {
+ ratings.push(rating.agency + ' ' + rating.value);
+ });
+
+ td.textContent = ratings.join(', ');
+ } else if (key == 'author') {
+ // Format a mojom author.
+ const a = document.createElement('a');
+ a.href = data.url;
+ a.textContent = data.name;
+ a.target = '_blank';
+ td.appendChild(a);
+ } else if (key == 'name') {
+ // Format a mojo string16.
+ td.textContent =
+ decodeString16(/** @type {mojoBase.mojom.String16} */ (data));
+ } else if (key == 'genre') {
+ // Format an array of strings.
+ td.textContent = data.join(', ');
+ } else if (key == 'live') {
+ // Format LiveDetails.
+ td.textContent = 'Live';
+
+ if (data.startTime) {
+ td.textContent += ' ' +
+ 'StartTime=' +
+ convertMojoTimeToJS(
+ /** @type {mojoBase.mojom.Time} */ (data.startTime))
+ .toLocaleString();
+ }
+
+ if (data.endTime) {
+ td.textContent += ' ' +
+ 'EndTime=' +
+ convertMojoTimeToJS(
+ /** @type {mojoBase.mojom.Time} */ (data.endTime))
+ .toLocaleString();
+ }
+ } else if (key == 'tvEpisode') {
+ // Format a TV Episode.
+ td.textContent = data.name + ' EpisodeNumber=' + data.episodeNumber +
+ ' SeasonNumber=' + data.seasonNumber + ' ' +
+ formatIdentifiers(/** @type {Array<mediaFeeds.mojom.Identifier>} */ (
+ data.identifiers));
+ } else if (key == 'playNextCandidate') {
+ // Format a Play Next Candidate.
+ td.textContent = data.name + ' EpisodeNumber=' + data.episodeNumber +
+ ' SeasonNumber=' + data.seasonNumber + ' ' +
+ formatIdentifiers(
+ /** @type {Array<mediaFeeds.mojom.Identifier>} */ (
+ data.identifiers)) +
+ ' ActionURL=' + data.action.url.url;
+
+ if (data.action.startTime) {
+ td.textContent +=
+ ' ActionStartTimeSecs=' + timeDeltaToSeconds(data.action.startTime);
+ }
+
+ td.textContent += ' DurationSecs=' + timeDeltaToSeconds(data.duration);
+ } else if (key == 'identifiers') {
+ // Format identifiers.
+ td.textContent = formatIdentifiers(
+ /** @type {Array<mediaFeeds.mojom.Identifier>} */ (data));
+ } else {
+ td.textContent = data;
+ }
+ }
+
+ /**
+ * Compares two objects based on |sortKey|.
+ * @param {string} sortKey The name of the property to sort by.
+ * @param {?Object} a The first object to compare.
+ * @param {?Object} b The second object to compare.
+ * @return {number} A negative number if |a| should be ordered
+ * before |b|, a positive number otherwise.
+ */
+ compareTableItem(sortKey, a, b) {
+ const val1 = a[sortKey];
+ const val2 = b[sortKey];
+
+ if (sortKey === 'url') {
+ return val1.url > val2.url ? 1 : -1;
+ } else if (
+ sortKey === 'id' || sortKey === 'displayName' ||
+ sortKey === 'userStatus' || sortKey === 'lastFetchResult' ||
+ sortKey === 'fetchFailedCount' || sortKey === 'lastFetchItemCount' ||
+ sortKey === 'lastFetchPlayNextCount' ||
+ sortKey === 'lastFetchContentTypes' || sortKey === 'safeSearchResult') {
+ return val1 > val2 ? 1 : -1;
+ } else if (
+ sortKey === 'lastDiscoveryTime' || sortKey === 'lastFetchTime' ||
+ sortKey === 'cacheExpiryTime') {
+ return val1.internalValue > val2.internalValue ? 1 : -1;
+ }
+
+ assertNotReached('Unsupported sort key: ' + sortKey);
+ return 0;
+ }
+}
+
+/**
+ * Convert a time delta to seconds.
+ * @param {mojoBase.mojom.TimeDelta} timeDelta
+ * @returns {number}
+ */
+function timeDeltaToSeconds(timeDelta) {
+ return timeDelta.microseconds / 1000 / 1000;
+}
+
+/**
+ * Formats an array of identifiers for display.
+ * @param {Array<mediaFeeds.mojom.Identifier>} mojoIdentifiers
+ * @returns {string}
+ */
+function formatIdentifiers(mojoIdentifiers) {
+ const identifiers = [];
+
+ mojoIdentifiers.forEach((identifier) => {
+ let keyString = '';
+
+ switch (identifier.type) {
+ case mediaFeeds.mojom.Identifier_Type.kTMSRootId:
+ keyString = 'TMSRootId';
+ break;
+ case mediaFeeds.mojom.Identifier_Type.kTMSId:
+ keyString = 'TMSId';
+ break;
+ case mediaFeeds.mojom.Identifier_Type.kPartnerId:
+ keyString = 'PartnerId';
+ break;
+ }
+
+ identifiers.push(keyString + '=' + identifier.value);
+ });
+
+ return identifiers.join(' ');
+}
+
+/**
+ * Parses utf16 coded string.
+ * @param {?mojoBase.mojom.String16} arr
+ * @return {string}
+ */
+function decodeString16(arr) {
+ if (arr == null) {
+ return '';
+ }
+
+ return arr.data.map(ch => String.fromCodePoint(ch)).join('');
+}
+
+/**
+ * Converts a mojo time to a JS time.
+ * @param {mojoBase.mojom.Time} mojoTime
+ * @return {Date}
+ */
+function convertMojoTimeToJS(mojoTime) {
+ if (mojoTime === null) {
+ return new Date();
+ }
+
+ // The new Date().getTime() returns the number of milliseconds since the
+ // UNIX epoch (1970-01-01 00::00:00 UTC), while |internalValue| of the
+ // device.mojom.Geoposition represents the value of microseconds since the
+ // Windows FILETIME epoch (1601-01-01 00:00:00 UTC). So add the delta when
+ // sets the |internalValue|. See more info in //base/time/time.h.
+ const windowsEpoch = Date.UTC(1601, 0, 1, 0, 0, 0, 0);
+ const unixEpoch = Date.UTC(1970, 0, 1, 0, 0, 0, 0);
+ // |epochDeltaInMs| equals to base::Time::kTimeTToMicrosecondsOffset.
+ const epochDeltaInMs = unixEpoch - windowsEpoch;
+ const timeInMs = Number(mojoTime.internalValue) / 1000;
+
+ return new Date(timeInMs - epochDeltaInMs);
+}
+
+/**
+ * Retrieve feed info and render the feed table.
+ */
+function updateFeedsTable() {
+ store.getMediaFeeds().then(response => {
+ feedsTable.setData(response.feeds);
+ mediaFeedsPageIsPopulatedResolver.resolve();
+ });
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ store = mediaFeeds.mojom.MediaFeedsStore.getRemote();
+
+ delegate = new MediaFeedsTableDelegate();
+ feedsTable = new cr.ui.MediaDataTable($('feeds-table'), delegate);
+ feedItemsTable = new cr.ui.MediaDataTable($('feed-items-table'), delegate);
+
+ updateFeedsTable();
+
+ // Add handler to 'copy all to clipboard' button
+ const copyAllToClipboardButton = $('copy-all-to-clipboard');
+ copyAllToClipboardButton.addEventListener('click', (e) => {
+ // Make sure nothing is selected
+ window.getSelection().removeAllRanges();
+
+ document.execCommand('selectAll');
+ document.execCommand('copy');
+
+ // And deselect everything at the end.
+ window.getSelection().removeAllRanges();
+ });
+});
+})();
diff --git a/chromium/chrome/browser/resources/media/media_history.html b/chromium/chrome/browser/resources/media/media_history.html
new file mode 100644
index 00000000000..894eb8aa5d9
--- /dev/null
+++ b/chromium/chrome/browser/resources/media/media_history.html
@@ -0,0 +1,249 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <title>Media History</title>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+ <link rel="stylesheet" href="chrome://resources/css/tabs.css">
+
+ <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js"></script>
+ <script src="chrome://resources/js/promise_resolver.js"></script>
+ <script src="chrome://resources/js/util.js"></script>
+ <script src="chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-lite.js"></script>
+ <script src="chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-lite.js"></script>
+ <script src="chrome://resources/mojo/mojo/public/mojom/base/unguessable_token.mojom-lite.js"></script>
+ <script src="chrome://resources/mojo/mojo/public/mojom/base/time.mojom-lite.js"></script>
+ <script src="chrome://resources/mojo/url/mojom/url.mojom-lite.js"></script>
+ <script src="chrome://resources/mojo/url/mojom/origin.mojom-lite.js"></script>
+ <script src="ui/gfx/geometry/mojom/geometry.mojom-lite.js"></script>
+ <script src="services/media_session/public/mojom/media_session.mojom-lite.js"></script>
+ <script src="chrome/browser/media/history/media_history_store.mojom-lite.js"></script>
+
+ <script src="chrome://resources/js/cr.js"></script>
+ <script src="chrome://resources/js/cr/ui.js"></script>
+ <script src="chrome://resources/js/cr/ui/focus_outline_manager.js"></script>
+ <script src="chrome://resources/js/cr/ui/tabs.js"></script>
+
+ <script src="chrome://media-history/media-data-table.js"></script>
+ <script src="chrome://media-history/media-history.js"></script>
+ <style>
+ html,
+ body {
+ font-family: 'Roboto', 'Noto', sans-serif;
+ font-size: 14px;
+ height: 100%;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ }
+
+ tabbox {
+ padding-top: 10px;
+ }
+
+ tab {
+ -webkit-user-select: none;
+ }
+
+ body tabpanels {
+ box-shadow: none;
+ }
+
+ tabpanel {
+ padding: 10px;
+ }
+
+ h1 {
+ margin-top: 10px;
+ }
+
+ button {
+ margin-bottom: 20px;
+ }
+
+ table {
+ border-collapse: collapse;
+ margin-bottom: 20px;
+ }
+
+ table td,
+ table th {
+ border: 1px solid #777;
+ padding-inline-end: 4px;
+ padding-inline-start: 4px;
+ }
+
+ table th {
+ background: rgb(224, 236, 255);
+ cursor: pointer;
+ padding-bottom: 4px;
+ padding-inline-end: 4px;
+ padding-top: 4px;
+ white-space: nowrap;
+ }
+
+ .name-cell {
+ background-color: rgba(230, 230, 230, 0.5);
+ }
+
+ th.sort-column {
+ padding-inline-end: 16px;
+ }
+
+ th.sort-column::after {
+ content: '▲';
+ position: absolute;
+ }
+
+ th[sort-reverse].sort-column::after {
+ content: '▼';
+ position: absolute;
+ }
+ </style>
+</head>
+<body>
+ <tabbox id="tabbox">
+ <tabs>
+ <tab id="stats">Stats</tab>
+ <tab id="origins">Origins</tab>
+ <tab id="playbacks">Playbacks</tab>
+ <tab id="sessions">Sessions</tab>
+ </tabs>
+ <tabpanels>
+ <tabpanel>
+ <h1>Media History</h1>
+ <button class="copy-all-to-clipboard">Copy all to clipboard</button>
+ <table>
+ <thead>
+ <tr id="stats-table-header">
+ <th>
+ Table Name
+ </th>
+ <th>
+ Row Count
+ </th>
+ </tr>
+ </thead>
+ <tbody id="stats-table-body">
+ </tbody>
+ </table>
+ </tabpanel>
+ <tabpanel>
+ <h1>Origins</h1>
+ <button class="copy-all-to-clipboard">Copy all to clipboard</button>
+ <table id="origins-table">
+ <thead>
+ <tr>
+ <th sort-key="origin">
+ Origin
+ </th>
+ <th sort-key="lastUpdatedTime">
+ Last Updated
+ </th>
+ <th sort-key="cachedAudioVideoWatchtime" class="sort-column" sort-reverse>
+ Audio + Video Watchtime (secs, cached)
+ </th>
+ <th sort-key="actualAudioVideoWatchtime">
+ Audio + Video Watchtime (secs, actual)
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ </tbody>
+ </table>
+ </tabpanel>
+ <tabpanel>
+ <h1>Playbacks</h1>
+ <p>
+ The playbacks table stores playbacks that happened on a page. These
+ can be of any type and there is one playback stored for each player
+ per page.
+ </p>
+ <button class="copy-all-to-clipboard">Copy all to clipboard</button>
+ <table id="playbacks-table">
+ <thead>
+ <tr>
+ <th sort-key="url">
+ URL
+ </th>
+ <th sort-key="lastUpdatedTime" class="sort-column" sort-reverse>
+ Last Updated
+ </th>
+ <th sort-key="hasAudio">
+ Has Audio
+ </th>
+ <th sort-key="hasVideo">
+ Has Video
+ </th>
+ <th sort-key="watchtime">
+ Watchtime (secs)
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ </tbody>
+ </table>
+ </tabpanel>
+ <tabpanel>
+ <h1>Sessions</h1>
+ <p>
+ The sessions table stores media sessions that had media playback that
+ had both an audio and video track. There is only one session recorded
+ for the lifetime of the page.
+ </p>
+ <button class="copy-all-to-clipboard">Copy all to clipboard</button>
+ <table id="sessions-table">
+ <thead>
+ <tr>
+ <th sort-key="url">
+ URL
+ </th>
+ <th sort-key="lastUpdatedTime" class="sort-column" sort-reverse>
+ Last Updated
+ </th>
+ <th sort-key="position">
+ Position (secs)
+ </th>
+ <th sort-key="duration">
+ Duration (secs)
+ </th>
+ <th sort-key="metadata.title">
+ Title
+ </th>
+ <th sort-key="metadata.artist">
+ Artist
+ </th>
+ <th sort-key="metadata.album">
+ Album
+ </th>
+ <th sort-key="metadata.sourceTitle">
+ Source Title
+ </th>
+ <th data-key="artwork">
+ Artwork
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ </tbody>
+ </table>
+ </tabpanel>
+ </tabpanels>
+ </tabbox>
+
+ <template id="data-row">
+ <tr>
+ <td class="origin-cell"></td>
+ <td class="last-updated-cell"></td>
+ <td class="cached-watchtime-cell"></td>
+ <td class="actual-watchtime-cell"></td>
+ </tr>
+ </template>
+ <template id="stats-row">
+ <tr>
+ <td class="name-cell"></td>
+ <td></td>
+ </tr>
+ </template>
+</body>
+</html>
diff --git a/chromium/chrome/browser/resources/media/media_history.js b/chromium/chrome/browser/resources/media/media_history.js
new file mode 100644
index 00000000000..30c66de2df0
--- /dev/null
+++ b/chromium/chrome/browser/resources/media/media_history.js
@@ -0,0 +1,250 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+// Allow a function to be provided by tests, which will be called when
+// the page has been populated.
+const mediaHistoryPageIsPopulatedResolver = new PromiseResolver();
+function whenPageIsPopulatedForTest() {
+ return mediaHistoryPageIsPopulatedResolver.promise;
+}
+
+(function() {
+
+let store = null;
+let statsTableBody = null;
+let originsTable = null;
+let playbacksTable = null;
+let sessionsTable = null;
+let delegate = null;
+
+/**
+ * Creates a single row in the stats table.
+ * @param {string} name The name of the table.
+ * @param {number} count The row count of the table.
+ * @return {!Node}
+ */
+function createStatsRow(name, count) {
+ const template = $('stats-row');
+ const td = template.content.querySelectorAll('td');
+ td[0].textContent = name;
+ td[1].textContent = count;
+ return document.importNode(template.content, true);
+}
+
+/** @implements {cr.ui.MediaDataTableDelegate} */
+class MediaHistoryTableDelegate {
+ /**
+ * Formats a field to be displayed in the data table and inserts it into the
+ * element.
+ * @param {Element} td
+ * @param {?Object} data
+ * @param {string} key
+ */
+ insertDataField(td, data, key) {
+ if (data === undefined || data === null) {
+ return;
+ }
+
+ if (key === 'origin') {
+ // Format a mojo origin.
+ const {scheme, host, port} = data;
+ td.textContent = new URL(`${scheme}://${host}:${port}`).origin;
+ } else if (key === 'lastUpdatedTime') {
+ // Format a JS timestamp.
+ td.textContent = data ? new Date(data).toISOString() : '';
+ } else if (
+ key === 'cachedAudioVideoWatchtime' ||
+ key === 'actualAudioVideoWatchtime' || key === 'watchtime' ||
+ key === 'duration' || key === 'position') {
+ // Format a mojo timedelta.
+ const secs = (data.microseconds / 1000000);
+ td.textContent =
+ secs.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
+ } else if (key === 'url') {
+ // Format a mojo GURL.
+ td.textContent = data.url;
+ } else if (key === 'hasAudio' || key === 'hasVideo') {
+ // Format a boolean.
+ td.textContent = data ? 'Yes' : 'No';
+ } else if (
+ key === 'title' || key === 'artist' || key === 'album' ||
+ key === 'sourceTitle') {
+ // Format a mojo string16.
+ td.textContent = decodeString16(
+ /** @type {mojoBase.mojom.String16} */ (data));
+ } else if (key === 'artwork') {
+ // Format an array of mojo media images.
+ data.forEach((image) => {
+ const a = document.createElement('a');
+ a.href = image.src.url;
+ a.textContent = image.src.url;
+ a.target = '_blank';
+ td.appendChild(a);
+ td.appendChild(document.createElement('br'));
+ });
+ } else {
+ td.textContent = data;
+ }
+ }
+
+ /**
+ * Compares two objects based on |sortKey|.
+ * @param {string} sortKey The name of the property to sort by.
+ * @param {?Object} a The first object to compare.
+ * @param {?Object} b The second object to compare.
+ * @return {number} A negative number if |a| should be ordered
+ * before |b|, a positive number otherwise.
+ */
+ compareTableItem(sortKey, a, b) {
+ const val1 = a[sortKey];
+ const val2 = b[sortKey];
+
+ // Compare the hosts of the origin ignoring schemes.
+ if (sortKey === 'origin') {
+ return val1.host > val2.host ? 1 : -1;
+ }
+
+ // Compare the url property.
+ if (sortKey === 'url') {
+ return val1.url > val2.url ? 1 : -1;
+ }
+
+ // Compare mojo_base.mojom.TimeDelta microseconds value.
+ if (sortKey === 'cachedAudioVideoWatchtime' ||
+ sortKey === 'actualAudioVideoWatchtime' || sortKey === 'watchtime' ||
+ sortKey === 'duration' || sortKey === 'position') {
+ return val1.microseconds - val2.microseconds;
+ }
+
+ if (sortKey.startsWith('metadata.')) {
+ // Keys with a period denote nested objects.
+ let nestedA = a;
+ let nestedB = b;
+ const expandedKey = sortKey.split('.');
+ expandedKey.forEach((k) => {
+ nestedA = nestedA[k];
+ nestedB = nestedB[k];
+ });
+
+ return nestedA > nestedB ? 1 : -1;
+ }
+
+ if (sortKey === 'lastUpdatedTime') {
+ return val1 - val2;
+ }
+
+ assertNotReached('Unsupported sort key: ' + sortKey);
+ return 0;
+ }
+}
+
+/**
+ * Parses utf16 coded string.
+ * @param {mojoBase.mojom.String16} arr
+ * @return {string}
+ */
+function decodeString16(arr) {
+ if (!arr) {
+ return '';
+ }
+
+ return arr.data.map(ch => String.fromCodePoint(ch)).join('');
+}
+
+/**
+ * Regenerates the stats table.
+ * @param {!mediaHistory.mojom.MediaHistoryStats} stats The stats for the Media
+ * History store.
+ */
+function renderStatsTable(stats) {
+ statsTableBody.innerHTML = '';
+
+ Object.keys(stats.tableRowCounts).forEach((key) => {
+ statsTableBody.appendChild(createStatsRow(key, stats.tableRowCounts[key]));
+ });
+}
+
+/**
+ * @param {!string} name The name of the tab to show.
+ * @return {Promise}
+ */
+function showTab(name) {
+ switch (name) {
+ case 'stats':
+ return store.getMediaHistoryStats().then(response => {
+ renderStatsTable(response.stats);
+ });
+ case 'origins':
+ return store.getMediaHistoryOriginRows().then(response => {
+ originsTable.setData(response.rows);
+ });
+ case 'playbacks':
+ return store.getMediaHistoryPlaybackRows().then(response => {
+ playbacksTable.setData(response.rows);
+ });
+ case 'sessions':
+ return store.getMediaHistoryPlaybackSessionRows().then(response => {
+ sessionsTable.setData(response.rows);
+ });
+ }
+
+ // Return an empty promise if there is no tab.
+ return new Promise(() => {});
+}
+
+document.addEventListener('DOMContentLoaded', function() {
+ store = mediaHistory.mojom.MediaHistoryStore.getRemote();
+
+ statsTableBody = $('stats-table-body');
+
+ delegate = new MediaHistoryTableDelegate();
+
+ originsTable = new cr.ui.MediaDataTable($('origins-table'), delegate);
+ playbacksTable = new cr.ui.MediaDataTable($('playbacks-table'), delegate);
+ sessionsTable = new cr.ui.MediaDataTable($('sessions-table'), delegate);
+
+ cr.ui.decorate('tabbox', cr.ui.TabBox);
+
+ // Allow tabs to be navigated to by fragment. The fragment with be of the
+ // format "#tab-<tab id>".
+ window.onhashchange = function() {
+ showTab(window.location.hash.substr(5));
+ };
+
+ // Default to the stats tab.
+ if (!window.location.hash.substr(5)) {
+ window.location.hash = 'tab-stats';
+ } else {
+ showTab(window.location.hash.substr(5))
+ .then(mediaHistoryPageIsPopulatedResolver.resolve);
+ }
+
+ // When the tab updates, update the anchor.
+ $('tabbox').addEventListener('selectedChange', function() {
+ const tabbox = $('tabbox');
+ const tabs = tabbox.querySelector('tabs').children;
+ const selectedTab = tabs[tabbox.selectedIndex];
+ window.location.hash = 'tab-' + selectedTab.id;
+ }, true);
+
+ // Add handler to 'copy all to clipboard' button.
+ const copyAllToClipboardButtons =
+ document.querySelectorAll('.copy-all-to-clipboard');
+
+ copyAllToClipboardButtons.forEach((button) => {
+ button.addEventListener('click', (e) => {
+ // Make sure nothing is selected.
+ window.getSelection().removeAllRanges();
+
+ document.execCommand('selectAll');
+ document.execCommand('copy');
+
+ // And deselect everything at the end.
+ window.getSelection().removeAllRanges();
+ });
+ });
+});
+})();
diff --git a/chromium/chrome/browser/resources/media/mei_preload/BUILD.gn b/chromium/chrome/browser/resources/media/mei_preload/BUILD.gn
index 3a7260963da..46e59a5d18c 100644
--- a/chromium/chrome/browser/resources/media/mei_preload/BUILD.gn
+++ b/chromium/chrome/browser/resources/media/mei_preload/BUILD.gn
@@ -12,17 +12,13 @@ mei_preload_out_dir = "MEIPreload"
copy("component") {
sources = mei_preload_sources
- outputs = [
- "$root_out_dir/$mei_preload_out_dir/{{source_file_part}}",
- ]
+ outputs = [ "$root_out_dir/$mei_preload_out_dir/{{source_file_part}}" ]
}
if (is_mac) {
bundle_data("component_bundle") {
sources = mei_preload_sources
- outputs = [
- "{{bundle_contents_dir}}/Libraries/$mei_preload_out_dir/{{source_file_part}}",
- ]
+ outputs = [ "{{bundle_contents_dir}}/Libraries/$mei_preload_out_dir/{{source_file_part}}" ]
}
}
diff --git a/chromium/chrome/browser/resources/media_router/BUILD.gn b/chromium/chrome/browser/resources/media_router/BUILD.gn
index 22e52f0ca33..6b913e1aee3 100644
--- a/chromium/chrome/browser/resources/media_router/BUILD.gn
+++ b/chromium/chrome/browser/resources/media_router/BUILD.gn
@@ -6,9 +6,7 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
uses_js_modules = true
- deps = [
- ":media_router_internals",
- ]
+ deps = [ ":media_router_internals" ]
}
js_library("media_router_internals") {
diff --git a/chromium/chrome/browser/resources/media_router/extension/BUILD.gn b/chromium/chrome/browser/resources/media_router/extension/BUILD.gn
index a1b45248410..bf47062f87d 100644
--- a/chromium/chrome/browser/resources/media_router/extension/BUILD.gn
+++ b/chromium/chrome/browser/resources/media_router/extension/BUILD.gn
@@ -14,9 +14,7 @@ if (enable_media_router_jscompile) {
"src/externs.js",
"src/mojo_externs.js",
]
- outputs = [
- target_gen_dir + "/$target_name.stamp",
- ]
+ outputs = [ target_gen_dir + "/$target_name.stamp" ]
args = [
"--out_file",
rebase_path(outputs[0], root_build_dir),
@@ -47,12 +45,8 @@ action("media_router_modules") {
}
copy("copy_prelude") {
- sources = [
- "prelude.js",
- ]
- outputs = [
- "${target_gen_dir}/prelude.js",
- ]
+ sources = [ "prelude.js" ]
+ outputs = [ "${target_gen_dir}/prelude.js" ]
}
# Produce the Media Router extension. At present, the extension isn't
@@ -60,12 +54,8 @@ copy("copy_prelude") {
# Chromium for testing.
action("media_router") {
script = "generate_manifest.py"
- inputs = [
- "manifest.yaml",
- ]
- outputs = [
- "$target_gen_dir/manifest.json",
- ]
+ inputs = [ "manifest.yaml" ]
+ outputs = [ "$target_gen_dir/manifest.json" ]
data_deps = [
":copy_prelude",
":media_router_modules",
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/external_message_listener.js b/chromium/chrome/browser/resources/media_router/extension/src/external_message_listener.js
index 3f4e0800dfa..e98418993dd 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/external_message_listener.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/external_message_listener.js
@@ -29,11 +29,12 @@ mr.ExternalMessageListener = class extends mr.EventListener {
* @override
*/
validateEvent(message, sender, sendResponse) {
- // Make sure all messages have a sender |id| and that the ID is whitelisted.
- // If messages have a |tab| they are from a web page (most likely the Cast
- // setup page).
- if (!sender.id ||
- mr.ExternalMessageListener.WHITELIST_.indexOf(sender.id) == -1) {
+ // Make sure all messages have a sender |origin| and that the origin is
+ // whitelisted.
+ const prefix = 'chrome-extension://';
+ if (!sender.origin || !sender.origin.startsWith(prefix) ||
+ !mr.ExternalMessageListener.WHITELIST_.includes(
+ sender.origin.substring(prefix.length))) {
return false;
}
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/external_message_listener_test.js b/chromium/chrome/browser/resources/media_router/extension/src/external_message_listener_test.js
index e1f5480a27a..0adde359238 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/external_message_listener_test.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/external_message_listener_test.js
@@ -21,7 +21,7 @@ describe('Tests mr.ExternalMessageListener', () => {
});
it('rejects sender not in whitelist', () => {
- const sender = {'id': 'invalid'};
+ const sender = {'origin': 'invalid'};
const callback = response => {
fail('should not have called back');
};
@@ -30,7 +30,9 @@ describe('Tests mr.ExternalMessageListener', () => {
});
it('invalid type returns empty and closes channel', () => {
- const sender = {'id': 'njjegkblellcjnakomndbaloifhcoccg'};
+ const sender = {
+ 'origin': 'chrome-extension://njjegkblellcjnakomndbaloifhcoccg'
+ };
const callback = response => {
fail('should not have called back');
};
@@ -39,7 +41,9 @@ describe('Tests mr.ExternalMessageListener', () => {
});
it('valid start message', () => {
- const sender = {'id': 'njjegkblellcjnakomndbaloifhcoccg'};
+ const sender = {
+ 'origin': 'chrome-extension://njjegkblellcjnakomndbaloifhcoccg'
+ };
const callback = response => {
fail('should not have called back');
};
@@ -48,7 +52,9 @@ describe('Tests mr.ExternalMessageListener', () => {
});
it('valid stop message', () => {
- const sender = {'id': 'njjegkblellcjnakomndbaloifhcoccg'};
+ const sender = {
+ 'origin': 'chrome-extension://njjegkblellcjnakomndbaloifhcoccg'
+ };
const callback = response => {
fail('should not have called back');
};
@@ -57,7 +63,9 @@ describe('Tests mr.ExternalMessageListener', () => {
});
it('valid log subscription message', () => {
- const sender = {'id': 'njjegkblellcjnakomndbaloifhcoccg'};
+ const sender = {
+ 'origin': 'chrome-extension://njjegkblellcjnakomndbaloifhcoccg'
+ };
const callback = response => {
fail('should not have called back');
};
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/externs.js b/chromium/chrome/browser/resources/media_router/extension/src/externs.js
index 4e9ded5910e..8764f3c25da 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/externs.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/externs.js
@@ -291,10 +291,6 @@ chrome.cast.channel.onError.addListener = function(listener) {};
chrome.cast.channel.onError.removeListener = function(listener) {};
-/** @const */
-chrome.cast.media = {};
-
-
/**
* @param {function(ChromeWindow)} callback
*/
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/files.gni b/chromium/chrome/browser/resources/media_router/extension/src/files.gni
index d4733ef85fc..dbbc3db2eda 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/files.gni
+++ b/chromium/chrome/browser/resources/media_router/extension/src/files.gni
@@ -7,7 +7,7 @@ mr_module_names = [
]
mr_module_specs = [
"module=common:8",
- "module=mirroring_common:73:common",
+ "module=mirroring_common:60:common",
"module=background_script:4:mirroring_common",
]
mr_module_files = [
@@ -48,8 +48,6 @@ mr_module_files = [
"utils/sha1.js",
"utils/string_utils.js",
"providers/common/sink_utils.js",
- "providers/dial/sink_app_status.js",
- "providers/dial/dial_sink.js",
"utils/device_counts.js",
"utils/device_counts_provider.js",
"providers/common/id_generator.js",
@@ -64,23 +62,10 @@ mr_module_files = [
"interface_data/sink_list.js",
"manager/presentation_enums.js",
"manager/sink_availability.js",
- "utils/event_target.js",
- "manager/provider_manager_callbacks.js",
- "providers/common/net_utils.js",
- "providers/common/xhr_utils.js",
- "providers/dial/dial_client.js",
- "providers/dial/dial_activity.js",
- "providers/dial/dial_provider_callbacks.js",
- "providers/dial/dial_activity_records.js",
- "providers/dial/dial_analytics.js",
- "providers/dial/dial_sink_discovery_service.js",
- "utils/promise_utils.js",
- "providers/dial/dial_app_discovery_service.js",
- "providers/dial/presentation_url.js",
- "providers/dial/dial_provider.js",
"interface_data/sink_search_criteria.js",
"utils/fixed_size_queue.js",
"log_manager.js",
+ "utils/promise_utils.js",
"utils/object_utils.js",
"presentation_services/presentation_session.js",
"presentation_services/cloud_webrtc/webrtc_presentation_session.js",
@@ -92,6 +77,8 @@ mr_module_files = [
"manager/mr_event_senders/throttling_sender.js",
"manager/mr_event_senders/route_message_sender.js",
"manager/provider_events.js",
+ "utils/event_target.js",
+ "manager/provider_manager_callbacks.js",
"manager/route_message_port_impl.js",
"utils/throttle.js",
"manager/provider_manager.js",
@@ -122,14 +109,6 @@ mr_test_files = [
"providers/common/id_generator_test.js",
"providers/common/net_utils_test.js",
"providers/common/retry_test.js",
- "providers/dial/dial_activity_records_test.js",
- "providers/dial/dial_analytics_test.js",
- "providers/dial/dial_app_discovery_service_test.js",
- "providers/dial/dial_client_test.js",
- "providers/dial/dial_provider_test.js",
- "providers/dial/dial_sink_discovery_service_test.js",
- "providers/dial/dial_sink_test.js",
- "providers/dial/presentation_url_test.js",
"providers/test/test_provider_test.js",
"utils/analytics_test.js",
"utils/base64_test.js",
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/init.js b/chromium/chrome/browser/resources/media_router/extension/src/init.js
index 1e511bc8297..fdb16a71626 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/init.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/init.js
@@ -38,11 +38,13 @@ mr.Init.providerManager_;
/**
* @param {!mr.ProviderManager} providerManager
+ * @param {boolean} enableExtensionCastProvider
* @return {!Array.<!mr.Provider>}
* @private
*/
-mr.Init.getProviders_ = function(providerManager) {
- const providers = mr.InitHelper.getProviders(providerManager);
+mr.Init.getProviders_ = function(providerManager, enableExtensionCastProvider) {
+ const providers =
+ mr.InitHelper.getProviders(providerManager, enableExtensionCastProvider);
if (!mr.Config.isPublicChannel) {
providers.push(new mr.TestProvider(providerManager));
}
@@ -66,7 +68,7 @@ mr.Init.initProviderManager_ = function() {
throw Error('Failed to get MR instance ID.');
}
mr.Init.logger_.info('MR instance ID: ' + mrInstanceId);
- mr.Init.logDialogType_(result['mrConfig'].use_views_dialog);
+ mr.Init.logFeatureStatuses_(result['mrConfig']);
const mediaRouterService =
/** @type {!mr.MediaRouterService} */ (result['mrService']);
if (!mr.Init.providerManager_) {
@@ -86,7 +88,8 @@ mr.Init.initProviderManager_ = function() {
mr.LogManager.getInstance().registerDataManager();
- const providers = mr.Init.getProviders_(providerManager);
+ const providers = mr.Init.getProviders_(
+ providerManager, !!result['mrConfig'].enable_cast_sink_query);
if (!mr.Config.isDebugChannel) {
// Log unhandled promise rejections for external channels,
// but leave them as thrown exceptions for internal.
@@ -143,13 +146,23 @@ mr.Init.addEventListeners_ = function() {
/**
- * @param {boolean|undefined} useViewsDialog
+ * @param {!mojo.MediaRouteProviderConfig} config
* @private
*/
-mr.Init.logDialogType_ = function(useViewsDialog) {
- if (useViewsDialog === undefined) return;
- const dialogType = useViewsDialog ? 'Views (Harmony)' : 'WebUI';
- mr.Init.logger_.info(`Using the ${dialogType} dialog.`);
+mr.Init.logFeatureStatuses_ = function(config) {
+ if (config.use_views_dialog !== undefined) {
+ mr.Init.logger_.info(`Using the ${
+ config.use_views_dialog ? 'Views (Harmony)' : 'WebUI'} dialog.`);
+ }
+ if (config.enable_cast_sink_query !== undefined) {
+ // Native Cast MRP usage is the opposite of |enable_cast_sink_query|.
+ mr.Init.logger_.info(`Native Cast MRP is ${
+ config.enable_cast_sink_query ? 'disabled' : 'enabled'}.`);
+ }
+ if (config.use_mirroring_service !== undefined) {
+ mr.Init.logger_.info(`Native Mirroring Service is ${
+ config.use_mirroring_service ? 'enabled' : 'disabled'}.`);
+ }
};
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/init_helper.js b/chromium/chrome/browser/resources/media_router/extension/src/init_helper.js
index 320629a8547..3322f28f71d 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/init_helper.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/init_helper.js
@@ -7,7 +7,6 @@
goog.module('mr.InitHelper');
goog.module.declareLegacyNamespace();
-const DialProvider = goog.require('mr.DialProvider');
const EventListener = goog.require('mr.EventListener');
const Provider = goog.require('mr.Provider');
const ProviderManager = goog.forwardDeclare('mr.ProviderManager');
@@ -18,7 +17,7 @@ const ProviderManager = goog.forwardDeclare('mr.ProviderManager');
* @return {!Array<!Provider>}
*/
function getProviders(providerManager) {
- return [new DialProvider(providerManager)];
+ return [];
}
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/init_test.js b/chromium/chrome/browser/resources/media_router/extension/src/init_test.js
index bf60f2fa6c8..28c7c9e5166 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/init_test.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/init_test.js
@@ -32,7 +32,6 @@ describe('Tests init', function() {
'mrInstanceId': 'mrInstanceId',
'mrConfig': {
'enable_dial_discovery': true,
- 'enable_dial_sink_query': true,
'enable_cast_discovery': true,
'enable_cast_sink_query': true,
'use_views_dialog': true
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener.js b/chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener.js
index c55869c2b4a..cd87d34c082 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener.js
@@ -14,6 +14,7 @@ goog.require('mr.EventAnalytics');
goog.require('mr.EventListener');
goog.require('mr.InternalMessage');
goog.require('mr.InternalMessageType');
+goog.require('mr.ModuleId');
/**
@@ -30,10 +31,10 @@ mr.InternalMessageListener = class extends mr.EventListener {
* @override
*/
validateEvent(message, sender, sendResponse) {
- const internalMessage = /** @type {mr.InternalMessage} */ (message);
+ const internalMessage = /** @type {!mr.InternalMessage} */ (message);
return internalMessage.type == mr.InternalMessageType.RETRIEVE_LOG_DATA &&
- sender.id == chrome.runtime.id &&
- sender.url == `chrome-extension://${sender.id}/feedback.html`;
+ sender.origin == `chrome-extension://${chrome.runtime.id}` &&
+ sender.url == `${sender.origin}/feedback.html`;
}
/**
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener_test.js b/chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener_test.js
index f9e64ae45cb..e1767332706 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener_test.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/internal_message_listener_test.js
@@ -5,6 +5,7 @@
goog.setTestOnly('internal_message_listener_test');
goog.require('mr.InternalMessageListener');
+goog.require('mr.InternalMessageType');
describe('Tests mr.InternalMessageListener', () => {
let listener;
@@ -14,7 +15,7 @@ describe('Tests mr.InternalMessageListener', () => {
};
const validEvent = {'type': mr.InternalMessageType.RETRIEVE_LOG_DATA};
const validSender = {
- 'id': 'foo',
+ 'origin': 'chrome-extension://foo',
'url': 'chrome-extension://foo/feedback.html'
};
beforeEach(() => {
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/log_manager.js b/chromium/chrome/browser/resources/media_router/extension/src/log_manager.js
index c6424fc8cab..0bdb3e109b6 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/log_manager.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/log_manager.js
@@ -49,17 +49,41 @@ class LogManager {
const browserLogger = Logger.getInstance('browser');
const oldErrorHandler = window.onerror;
/**
+ * We set |window.onerror| instead of calling window.addEventListener()
+ * because we need to ensure that this handler is called before any others.
+ *
* @param {string} message
* @param {string} url
* @param {number} line
* @param {number=} col
* @param {*=} error
+ * @return {*}
*/
window.onerror = (message, url, line, col, error) => {
+
+ //
+ // This is necessary because even if we handle the error reported by GAPI
+ // at the call site (in WeaveDevicesService), the GAPI client still raises
+ // a separate exception we apparently can't handle until it gets here.
+ // The code below attempts to see if the error looks like the one the GAPI
+ // client throws and ignores it if so.
+ try {
+ const gapiError = error.result.error.errors[0];
+ if (gapiError.domain == 'usageLimits' &&
+ gapiError.reason == 'accessNotConfigured') {
+ // Suppress default error handling.
+ return true;
+ }
+ } catch (err) {
+ // Ignore; this is not the error we're interested in.
+ }
+
if (oldErrorHandler) {
oldErrorHandler(message, url, line, col, error);
}
browserLogger.error(`Error: ${message} (${url} @ Line: ${line})`, error);
+
+
};
Logger.addHandler(this.onNewLog_.bind(this));
@@ -95,7 +119,7 @@ class LogManager {
/**
* Saves logs in the internal buffer.
*
- * @param {Logger.Record} logRecord The log entry.
+ * @param {!Logger.Record} logRecord The log entry.
* @private
*/
onNewLog_(logRecord) {
@@ -107,7 +131,7 @@ class LogManager {
}
/**
- * @param {Logger.Record} logRecord The log entry.
+ * @param {!Logger.Record} logRecord The log entry.
* @private
*/
logToConsole_(logRecord) {
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/manager/provider.js b/chromium/chrome/browser/resources/media_router/extension/src/manager/provider.js
index fe0217eff71..7ae1c737a97 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/manager/provider.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/manager/provider.js
@@ -18,7 +18,6 @@ goog.require('mr.CancellablePromise');
*/
mr.ProviderName = {
CAST: 'cast',
- DIAL: 'dial',
CLOUD: 'cloud',
TEST: 'test'
};
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager.js b/chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager.js
index eb619dd8d93..5c3047a558b 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager.js
@@ -51,6 +51,11 @@ mr.ProviderManager = class extends mr.Module {
super();
/**
+ * @type {?mojo.MediaRouteProviderConfig}
+ */
+ this.config = null;
+
+ /**
* @private {mr.Logger}
*/
this.logger_ = mr.Logger.getInstance('mr.ProviderManager');
@@ -154,19 +159,6 @@ mr.ProviderManager = class extends mr.Module {
this.externalMessageHandler_ =
mr.InitHelper.getExternalMessageHandler(this);
- /**
- * The type of the Cast dialog used (WebUI or Views). This value is
- * submitted with feedback reports.
- * @type {string}
- */
- this.dialogType = '';
-
- /**
- * Indicates whether to use mirroring service for cast mirroring.
- * @private {boolean}
- */
- this.useMirroringService_ = false;
-
mr.ProviderManager.exportProperties_(this);
}
@@ -193,7 +185,8 @@ mr.ProviderManager = class extends mr.Module {
const moduleId = this.mirrorServiceModules_.get(serviceName);
return mr.Module.load(moduleId).then(module => {
let service = /** @type {!mr.mirror.Service} */ (module);
- service.initialize(this, this.useMirroringService_);
+ service.initialize(
+ this, !!this.config && this.config.use_mirroring_service);
return service;
});
}
@@ -202,9 +195,9 @@ mr.ProviderManager = class extends mr.Module {
* Registers and initalizes providers.
*
* @param {!Array<!mr.Provider>} providers
- * @param {!mojo.MediaRouteProviderConfig=} config
+ * @param {!mojo.MediaRouteProviderConfig} config
*/
- registerAllProviders(providers, config = undefined) {
+ registerAllProviders(providers, config) {
providers.forEach(provider => {
this.registerProvider_(provider, config);
});
@@ -215,9 +208,9 @@ mr.ProviderManager = class extends mr.Module {
* and registers itself with PersistentDataManager.
* @param {!mr.MediaRouterService} mediaRouterService
* @param {!Array<!mr.Provider>} providers
- * @param {!mojo.MediaRouteProviderConfig=} config
+ * @param {!mojo.MediaRouteProviderConfig} config
*/
- initialize(mediaRouterService, providers, config = undefined) {
+ initialize(mediaRouterService, providers, config) {
this.mirrorServiceModules_.set(
mr.mirror.ServiceName.WEBRTC, mr.ModuleId.WEBRTC_STREAMING_SERVICE);
this.mirrorServiceModules_.set(
@@ -235,12 +228,7 @@ mr.ProviderManager = class extends mr.Module {
this.mediaRouterService_.onRouteMessagesReceived.bind(
this.mediaRouterService_));
this.registerAllProviders(providers, config);
- if (config && config.use_views_dialog !== undefined) {
- this.dialogType = config.use_views_dialog ? 'Views' : 'WebUI';
- }
- if (config && config.use_mirroring_service !== undefined) {
- this.useMirroringService_ = config.use_mirroring_service;
- }
+ this.config = config;
mr.PersistentDataManager.register(this);
mr.Module.onModuleLoaded(mr.ModuleId.PROVIDER_MANAGER, this);
@@ -1075,7 +1063,7 @@ mr.ProviderManager = class extends mr.Module {
provideSinks(providerName, sinks) {
const provider = this.getProviderByName(providerName);
if (!provider) {
- this.logger_.error(
+ this.logger_.info(
`provideSinks: Provider not found for providerName ${providerName}`);
return;
}
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager_test.js b/chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager_test.js
index 01fc7581191..8c6d3cbd97e 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager_test.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/manager/provider_manager_test.js
@@ -655,7 +655,7 @@ describe('Tests ProviderManager', function() {
providerManager
.updateMirroring(
mockProvider1, localRoute, sourceUrn, undefined, callback)
- .promise.catch(done);
+ .promise.catch(() => done());
});
});
@@ -947,7 +947,8 @@ describe('Tests ProviderManager', function() {
expect(routeId).toBe(routeIdToTerminate);
return Promise.reject(new Error('Some error'));
});
- providerManager.terminateRoute(routeIdToTerminate).then(done.fail, done);
+ providerManager.terminateRoute(routeIdToTerminate)
+ .then(done.fail, () => done());
});
it('and terminates a mirroring route', function(done) {
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_analytics.js b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_analytics.js
index 20ea156371e..3bbf7c66d6a 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_analytics.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_analytics.js
@@ -13,13 +13,6 @@ goog.require('mr.Analytics');
/**
- * Contains all common analytics logic for Mirroring.
- * @const {*}
- */
-mr.MirrorAnalytics = {};
-
-
-/**
* Histogram name for mirroring start failure.
* @private @const {string}
*/
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_service.js b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_service.js
index 76d3aa340a2..cd8e3f96f81 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_service.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_service.js
@@ -143,6 +143,7 @@ mr.mirror.Service = class extends mr.Module {
this.currentSession.setOnActivityUpdate(
this.mirrorServiceCallbacks.handleMirrorActivityUpdate.bind(
this.mirrorServiceCallbacks));
+ this.currentSession.onActivityUpdated();
return this.currentSession.start(/** @type {!MediaStream} */ (
this.currentMediaStream_.getMediaStream()));
})
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings.js b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings.js
index 74499bbacbc..ae720ef416f 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings.js
@@ -29,8 +29,6 @@ mr.mirror.VideoCodec = {
RTX: 'rtx'
};
-
-
/**
* Settings that affect capture and transport (via Cast Streaming or WebRTC).
* Generally, these should all be left unchanged from their defaults.
@@ -65,19 +63,33 @@ mr.mirror.VideoCodec = {
*/
mr.mirror.Settings = class {
constructor() {
+ // When all streaming endpoints support adaptive capture and/or we ship VP9
+ // support, we plan to raise these limits.
+ /**
+ * The absolute maximum width we are willing to capture.
+ * @const {number}
+ */
+ this.maxCaptureWidth = 1920;
+
+ /**
+ * The absolute maximum height we are willing to capture.
+ * @const {number}
+ */
+ this.maxCaptureHeight = 1080;
+
/**
* Maximum video width in pixels.
*
* @export {number}
*/
- this.maxWidth = 1920;
+ this.maxWidth = this.maxCaptureWidth;
/**
* Maximum video height in pixels.
*
* @export {number}
*/
- this.maxHeight = 1080;
+ this.maxHeight = this.maxCaptureHeight;
/**
* Minimum video width in pixels.
@@ -144,7 +156,7 @@ mr.mirror.Settings = class {
*
* @export {number}
*/
- this.maxLatencyMillis = 800;
+ this.maxLatencyMillis = 400;
/**
* Minimum end-to-end latency (in milliseconds). This allows cast streaming
@@ -300,8 +312,15 @@ mr.mirror.Settings = class {
clampMaxDimensionsToScreenSize_() {
const widthStep = 160;
const heightStep = 90;
- const screenWidth = mr.mirror.Settings.getScreenWidth();
- const screenHeight = mr.mirror.Settings.getScreenHeight();
+ let screenWidth = mr.mirror.Settings.getScreenWidth();
+ let screenHeight = mr.mirror.Settings.getScreenHeight();
+
+ // If the device is in portrait mode, then set capture dimensions
+ // based on landscape orientation. Otherwise the chosen capture dimensions
+ // are artificially low.
+ if (screenHeight > screenWidth) {
+ [screenWidth, screenHeight] = [screenHeight, screenWidth];
+ }
const x = this.maxWidth * screenHeight;
const y = this.maxHeight * screenWidth;
let clampedWidth = 0;
@@ -383,12 +402,12 @@ mr.mirror.Settings = class {
/** @return {number} */
static getScreenWidth() {
- return screen.width;
+ return Math.round(screen.width * window.devicePixelRatio);
}
/** @return {number} */
static getScreenHeight() {
- return screen.height;
+ return Math.round(screen.height * window.devicePixelRatio);
}
};
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings_test.js b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings_test.js
index 066e92f3198..09d58317a13 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings_test.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/mirror_settings_test.js
@@ -46,16 +46,16 @@ describe('Tests Mirror Settings', function() {
expect(settings.toJsonString()).toEqual(jsonBefore);
});
- it('clamps max dimensions to 1920x1080 screen size', function() {
- spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(1920);
- spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(1080);
+ it('clamps max dimensions from 1280x800 (16:10) screen size', function() {
+ spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(1280);
+ spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(800);
const settings = new mr.mirror.Settings();
settings.makeFinalAdjustmentsAndFreeze();
- expect(settings.maxWidth).toBe(1920);
- expect(settings.maxHeight).toBe(1080);
+ expect(settings.maxWidth).toBe(1280);
+ expect(settings.maxHeight).toBe(720);
});
- it('clamps max dimensions to 1366x768 screen size', function() {
+ it('clamps max dimensions from 1366x768 screen size', function() {
spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(1366);
spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(768);
const settings = new mr.mirror.Settings();
@@ -64,6 +64,71 @@ describe('Tests Mirror Settings', function() {
expect(settings.maxHeight).toBe(720);
});
+ it('clamps max dimensions from 768x1366 screen size', function() {
+ spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(768);
+ spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(1366);
+ const settings = new mr.mirror.Settings();
+ settings.makeFinalAdjustmentsAndFreeze();
+ expect(settings.maxWidth).toBe(1280);
+ expect(settings.maxHeight).toBe(720);
+ });
+
+ it('clamps max dimensions from 1920x1080 screen size', function() {
+ spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(1920);
+ spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(1080);
+ const settings = new mr.mirror.Settings();
+ settings.makeFinalAdjustmentsAndFreeze();
+ expect(settings.maxWidth).toBe(1920);
+ expect(settings.maxHeight).toBe(1080);
+ });
+
+ it('clamps max dimensions from 1546x2048 (2:3) screen size', function() {
+ spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(1546);
+ spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(2048);
+ const settings = new mr.mirror.Settings();
+ settings.makeFinalAdjustmentsAndFreeze();
+ expect(settings.maxWidth).toBe(1920);
+ expect(settings.maxHeight).toBe(1080);
+ });
+
+ it('clamps max dimensions from 2399x1598 (3:2) screen size', function() {
+ // This odd dimension is what is actually reported by Pixelbook.
+ spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(2399);
+ spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(1598);
+ const settings = new mr.mirror.Settings();
+ settings.makeFinalAdjustmentsAndFreeze();
+ expect(settings.maxWidth).toBe(1920);
+ expect(settings.maxHeight).toBe(1080);
+ });
+
+ it('clamps max dimensions from 2560x1080 (21:9) screen size', function() {
+ spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(2560);
+ spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(1080);
+ const settings = new mr.mirror.Settings();
+ settings.makeFinalAdjustmentsAndFreeze();
+ expect(settings.maxWidth).toBe(1920);
+ expect(settings.maxHeight).toBe(1080);
+ });
+
+ it('clamps max dimensions from 2560x1600 (16:10 "retina") screen size',
+ function() {
+ spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(2560);
+ spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(1080);
+ const settings = new mr.mirror.Settings();
+ settings.makeFinalAdjustmentsAndFreeze();
+ expect(settings.maxWidth).toBe(1920);
+ expect(settings.maxHeight).toBe(1080);
+ });
+
+ it('clamps max dimensions from 3840x2160 screen size', function() {
+ spyOn(mr.mirror.Settings, 'getScreenWidth').and.returnValue(3840);
+ spyOn(mr.mirror.Settings, 'getScreenHeight').and.returnValue(2160);
+ const settings = new mr.mirror.Settings();
+ settings.makeFinalAdjustmentsAndFreeze();
+ expect(settings.maxWidth).toBe(1920);
+ expect(settings.maxHeight).toBe(1080);
+ });
+
it('returns min size matching aspect ratio of max size', function() {
const settings = new mr.mirror.Settings();
settings.maxWidth = 1920;
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream.js b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream.js
index 9c88a1fdb1b..0421e169816 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream.js
@@ -155,15 +155,17 @@ mr.mirror.MirrorMediaStream = class {
* Requests a screen capture source from the user via a native dialog and
* returns the source ID, or rejects if a timeout is reached or the user
* cancels.
- * @param {Tab=} targetTab Optional tab that the stream is created for.
- * @param {number=} timeoutMillis The timeout in milliseconds.
+ * @param {boolean=} showAudioCheckbox If false, an audio-sharing checkbox
+ * is not shown, and audio is shared on supported platforms (Windows,
+ * CrOS).
* @return {!Promise<string>} Fulfilled with the source ID.
*/
- static requestScreenCaptureSourceId(
- targetTab,
- timeoutMillis = mr.mirror.MirrorMediaStream.WINDOW_PICKER_TIMEOUT_) {
+ static requestScreenCaptureSourceId(showAudioCheckbox = true) {
return new Promise((resolve, reject) => {
- const desktopChooserConfig = ['screen', 'audio'];
+ const desktopChooserConfig = ['screen'];
+ if (showAudioCheckbox) {
+ desktopChooserConfig.push('audio');
+ }
if (mr.PlatformUtils.getCurrentOS() == mr.PlatformUtils.OS.LINUX) {
desktopChooserConfig.push('window');
}
@@ -179,10 +181,10 @@ mr.mirror.MirrorMediaStream = class {
'timeout',
mr.MirrorAnalytics.CapturingFailure
.CAPTURE_DESKTOP_FAIL_ERROR_TIMEOUT));
- }, timeoutMillis);
+ }, mr.mirror.MirrorMediaStream.WINDOW_PICKER_TIMEOUT_);
// https://developer.chrome.com/extensions/desktopCapture#method-chooseDesktopMedia
requestId = chrome.desktopCapture.chooseDesktopMedia(
- desktopChooserConfig, targetTab || null, sourceId => {
+ desktopChooserConfig, null, sourceId => {
window.clearTimeout(timeoutId);
if (!sourceId) {
// User cancelled the desktop media selector prompt.
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream_test.js b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream_test.js
index 6c40c0dca96..88596bb9dfd 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream_test.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/mirror_services/stream_capture/mirror_media_stream_test.js
@@ -24,7 +24,8 @@ describe('mr.mirror.MirrorMediaStream', () => {
jasmine.createSpyObj('tabCapture', ['capture', 'captureOffscreenTab']);
chrome.desktopCapture = jasmine.createSpyObj(
'desktopCapture', ['chooseDesktopMedia', 'cancelChooseDesktopMedia']);
- spyOn(navigator.mediaDevices, 'getUserMedia');
+ navigator.mediaDevices =
+ jasmine.createSpyObj('mediaDevices', ['getUserMedia']);
spyOn(mr.PlatformUtils, 'getCurrentOS');
mediaStream = jasmine.createSpyObj(
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/mojo_externs.js b/chromium/chrome/browser/resources/media_router/extension/src/mojo_externs.js
index 32952faa72f..6fbcdf77095 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/mojo_externs.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/mojo_externs.js
@@ -6,6 +6,7 @@
* @fileoverview Closure definitions of Mojo service objects. Note that these
* definitions are bound only after chrome.mojoPrivate.requireAsync resolves
* in mojo.js.
+ * @externs
*/
@@ -129,28 +130,6 @@ mojo.Url = function() {};
/** @type {string} */
mojo.Url.prototype.url;
-
-
-/**
- * @constructor
- * @struct
- */
-mojo.DialMediaSink = function() {};
-
-
-/** @type {mojo.IPAddress} */
-mojo.DialMediaSink.prototype.ip_address;
-
-
-/** @type {string} */
-mojo.DialMediaSink.prototype.model_name;
-
-
-/** @type {mojo.Url} */
-mojo.DialMediaSink.prototype.app_url;
-
-
-
/**
* @constructor
* @struct
@@ -187,9 +166,6 @@ mojo.CastMediaSink.prototype.cast_channel_id;
mojo.SinkExtraData = function() {};
-/** @type {mojo.DialMediaSink} */
-mojo.SinkExtraData.prototype.dial_media_sink;
-
/** @type {mojo.CastMediaSink} */
mojo.SinkExtraData.prototype.cast_media_sink;
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils.js
index fe52d1d5ce2..08c372df0e7 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils.js
@@ -11,7 +11,6 @@ goog.module('mr.NetUtils');
goog.module.declareLegacyNamespace();
-
/** @const @private {!RegExp} */
exports.IPV4_REGEXP_ =
new RegExp('^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$');
@@ -78,16 +77,6 @@ exports.isPrivateIPv4Address = function(ipAddress) {
};
/**
- * @param {string} url A url.
- * @return {!HTMLAnchorElement} The result of parsing url.
- */
-exports.parseUrl = function(url) {
- const a = document.createElement('a');
- a.href = url;
- return /** @type {!HTMLAnchorElement} */ (a);
-};
-
-/**
* Non-exhaustive list of HTTP status codes. Add new codes as needed here.
* @enum {number}
*/
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils_test.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils_test.js
index 4143201990b..755facd3cdb 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils_test.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/providers/common/net_utils_test.js
@@ -47,15 +47,4 @@ describe('mr.NetUtils', () => {
expect(n.isPrivateIPv4Address('193.169.0.0')).toBe(false);
});
- it('parses a URL', () => {
- const url =
- n.parseUrl('https://www.example.com:8080/a/path?a_query#a_fragment');
- expect(url.protocol).toBe('https:');
- expect(url.hostname).toBe('www.example.com');
- expect(url.port).toBe('8080');
- expect(url.pathname).toBe('/a/path');
- expect(url.search).toBe('?a_query');
- expect(url.hash).toBe('#a_fragment');
- expect(url.host).toBe('www.example.com:8080');
- });
});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/common/sink_utils.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/common/sink_utils.js
index 830ecbe5895..0874d1b9282 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/common/sink_utils.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/providers/common/sink_utils.js
@@ -55,12 +55,6 @@ class SinkUtils {
*/
this.castControlPort = 0;
- /**
- * The last time cloud sinks were checked.
- * @type {number}
- */
- this.lastCloudSinkCheckTimeMillis = 0;
-
PersistentDataManager.register(this);
}
@@ -78,7 +72,7 @@ class SinkUtils {
* Generates ID from the receiver UUID and a per-profile token saved in
* localStorage.
*
- * Both DIAL and mDNS use this to generate receiver ID so that it is
+ * Cast uses this to generate a receiver ID that is
* consistent and can be used to deduplicate receivers. For a given token, the
* ID is the same for the same device no matter when it is discovered.
*
@@ -125,7 +119,6 @@ class SinkUtils {
'receiverIdToken': this.receiverIdToken_,
'fixedIpList': this.fixedIpList.join(','),
'castControlPort': this.castControlPort,
- 'lastCloudSinkCheckTimeMillis': this.lastCloudSinkCheckTimeMillis
}
];
}
@@ -150,8 +143,6 @@ class SinkUtils {
persistentData['fixedIpList'].split(',')) ||
[];
this.castControlPort = persistentData['castControlPort'] || 0;
- this.lastCloudSinkCheckTimeMillis =
- persistentData['lastCloudSinkCheckTimeMillis'] || 0;
}
}
}
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity.js
deleted file mode 100644
index 264e20928c6..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity.js
+++ /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.
-
-/**
- * @fileoverview DIAL activity (locally launched or discovered).
- */
-
-goog.provide('mr.dial.Activity');
-
-mr.dial.Activity = class {
- /**
- * @param {!mr.Route} route
- * @param {!string} appName
- */
- constructor(route, appName) {
- /** @type {!mr.Route} */
- this.route = route;
- /** @type {string} */
- this.appName = appName;
- }
-};
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity_records.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity_records.js
deleted file mode 100644
index 112ec31bd15..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity_records.js
+++ /dev/null
@@ -1,156 +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.
-
-goog.module('mr.dial.ActivityRecords');
-
-const ActivityCallbacks = goog.require('mr.dial.ActivityCallbacks');
-const PersistentData = goog.require('mr.PersistentData');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-
-
-/**
- * Keeps track of DIAL activities.
- * @implements {PersistentData}
- */
-const ActivityRecords = class {
- /**
- * @param {!ActivityCallbacks} activityCallbacks
- */
- constructor(activityCallbacks) {
- /**
- * Maps route ID to the corresponding Activity.
- * @private {!Map<string, !mr.dial.Activity>}
- */
- this.routeIdToAppInfo_ = new Map();
-
- /** @private @const {!ActivityCallbacks} */
- this.activityCallbacks_ = activityCallbacks;
- }
-
- /**
- * Restores routeIdToAppInfo_ from saved data.
- */
- init() {
- PersistentDataManager.register(this);
- }
-
- /**
- * Removes all activities.
- */
- clear() {
- this.routeIdToAppInfo_.clear();
- }
-
- /**
- * Adds a new activity. If the activity already exists, this is no-op.
- * @param {!mr.dial.Activity} activity
- */
- add(activity) {
- if (this.getByRouteId(activity.route.id)) {
- return;
- }
- this.routeIdToAppInfo_.set(activity.route.id, activity);
- this.activityCallbacks_.onActivityAdded(activity);
- }
-
- /**
- * Returns the activity corresponding to the given route ID, or null if there
- * is none.
- * @param {string} routeId
- * @return {?mr.dial.Activity}
- */
- getByRouteId(routeId) {
- return this.routeIdToAppInfo_.get(routeId) || null;
- }
-
- /**
- * Returns the activity corresponding to the given sink ID, or null if there
- * is none.
- * @param {string} sinkId
- * @return {?mr.dial.Activity}
- */
- getBySinkId(sinkId) {
- for (let [routeId, activity] of this.routeIdToAppInfo_) {
- if (activity.route.sinkId == sinkId) {
- return /** @type {!mr.dial.Activity} */ (activity);
- }
- }
- return null;
- }
-
- /**
- * Removes the activity associated with the given sink ID.
- * @param {string} sinkId
- */
- removeBySinkId(sinkId) {
- const activity = this.getBySinkId(sinkId);
- if (activity) {
- this.routeIdToAppInfo_.delete(activity.route.id);
- this.activityCallbacks_.onActivityRemoved(activity);
- }
- }
-
- /**
- * Removes the activity associated with the given route ID.
- * @param {string} routeId
- */
- removeByRouteId(routeId) {
- const activity = this.routeIdToAppInfo_.get(routeId);
- if (activity) {
- this.routeIdToAppInfo_.delete(routeId);
- this.activityCallbacks_.onActivityRemoved(activity);
- }
- }
-
- /**
- * Returns the list of routes associated with the current list of activities.
- * @return {!Array<!mr.Route>}
- */
- getRoutes() {
- return Array.from(
- this.routeIdToAppInfo_.values(), activity => activity.route);
- }
-
- /**
- * Returns the current list of acitvities.
- * @return {!Array<!mr.dial.Activity>}
- */
- getActivities() {
- return Array.from(this.routeIdToAppInfo_.values());
- }
-
- /**
- * Returns the number of activities.
- * @return {number}
- */
- getActivityCount() {
- return this.routeIdToAppInfo_.size;
- }
-
- /**
- * @override
- */
- getStorageKey() {
- return 'dial.ActivityRecords';
- }
-
- /**
- * @override
- */
- getData() {
- return [Array.from(this.routeIdToAppInfo_)];
- }
-
- /**
- * @override
- */
- loadSavedData() {
- const savedData = PersistentDataManager.getTemporaryData(this);
- if (savedData) {
- this.routeIdToAppInfo_ = new Map(savedData);
- }
- }
-};
-
-exports = ActivityRecords;
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity_records_test.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity_records_test.js
deleted file mode 100644
index 38ff262fba0..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_activity_records_test.js
+++ /dev/null
@@ -1,100 +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.
-
-goog.module('mr.dial.ActivityRecordsTest');
-goog.setTestOnly('mr.dial.ActivityRecordsTest');
-
-const Activity = goog.require('mr.dial.Activity');
-const ActivityRecords = goog.require('mr.dial.ActivityRecords');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const Route = goog.require('mr.Route');
-const UnitTestUtils = goog.require('mr.UnitTestUtils');
-
-describe('DIAL ActivityRecords Tests', function() {
- let records;
- let mockCallbacks;
- let activity1;
- let activity2;
-
- beforeEach(function() {
- UnitTestUtils.mockMojoApi();
- UnitTestUtils.mockChromeApi();
- let route = new Route(
- 'routeId1', 'presentationId1', 'sinkId1', null, false, 'description1',
- 'imageUrl1');
- activity1 = new Activity(route, 'app1');
- route = new Route(
- 'routeId2', 'presentationId2', 'sinkId2', null, true, 'description2',
- 'imageUrl2');
- activity2 = new Activity(route, 'app2');
- mockCallbacks = jasmine.createSpyObj(
- 'ActivityCallbacks',
- ['onActivityAdded', 'onActivityRemoved', 'onActivityUpdated']);
- records = new ActivityRecords(mockCallbacks);
- records.init();
- });
-
- afterEach(function() {
- PersistentDataManager.clear();
- UnitTestUtils.restoreChromeApi();
- });
-
- it('Add activity', function() {
- records.add(activity1);
- expect(records.getByRouteId(activity1.route.id)).toEqual(activity1);
- expect(mockCallbacks.onActivityAdded.calls.count()).toBe(1);
- expect(mockCallbacks.onActivityAdded).toHaveBeenCalledWith(activity1);
- records.add(activity1);
- expect(mockCallbacks.onActivityAdded.calls.count()).toBe(1);
- });
-
- it('Get activity and route', function() {
- records.add(activity1);
- expect(records.getByRouteId(activity1.route.id)).toEqual(activity1);
- expect(records.getBySinkId(activity1.route.sinkId)).toEqual(activity1);
- expect(records.getRoutes()).toEqual([activity1.route]);
- records.add(activity2);
- expect(records.getByRouteId(activity2.route.id)).toEqual(activity2);
- expect(records.getBySinkId(activity2.route.sinkId)).toEqual(activity2);
- expect(records.getRoutes()).toEqual([activity1.route, activity2.route]);
- });
-
- it('Remove activity', function() {
- records.add(activity1);
- records.add(activity2);
- records.removeByRouteId(activity2.route.id);
- expect(mockCallbacks.onActivityRemoved.calls.count()).toBe(1);
- expect(mockCallbacks.onActivityRemoved).toHaveBeenCalledWith(activity2);
- records.removeByRouteId(activity2.route.id);
- expect(mockCallbacks.onActivityRemoved.calls.count()).toBe(1);
- expect(records.getByRouteId(activity2.route.id)).toEqual(null);
- expect(records.getBySinkId(activity2.route.sinkId)).toEqual(null);
- expect(records.getRoutes()).toEqual([activity1.route]);
-
- records.removeBySinkId(activity1.route.sinkId);
- expect(mockCallbacks.onActivityRemoved.calls.count()).toBe(2);
- expect(mockCallbacks.onActivityRemoved).toHaveBeenCalledWith(activity1);
- expect(records.getRoutes()).toEqual([]);
- });
-
- it('Save without any data', function() {
- expect(records.getRoutes()).toEqual([]);
- PersistentDataManager.suspendForTest();
- records = new ActivityRecords(mockCallbacks);
- records.loadSavedData();
- expect(records.getRoutes()).toEqual([]);
- });
-
- it('Save with data', function() {
- records.add(activity1);
- records.add(activity2);
- PersistentDataManager.suspendForTest();
- records = new ActivityRecords(mockCallbacks);
- records.loadSavedData();
- expect(JSON.stringify(records.getRoutes())).toEqual(JSON.stringify([
- activity1.route, activity2.route
- ]));
- });
-
-});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_analytics.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_analytics.js
deleted file mode 100644
index 9abe0f835a5..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_analytics.js
+++ /dev/null
@@ -1,119 +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.
-
-/**
- * @fileoverview Defines UMA analytics specific to the DIAL provider.
- */
-
-goog.provide('mr.DialAnalytics');
-
-goog.require('mr.Analytics');
-
-
-/**
- * Contains all analytics logic for the DIAL provider.
- * @const {*}
- */
-mr.DialAnalytics = {};
-
-
-/** @enum {string} */
-mr.DialAnalytics.Metric = {
- DEVICE_DESCRIPTION_FAILURE: 'MediaRouter.Dial.Device.Description.Failure',
- DEVICE_DESCRIPTION_FROM_CACHE: 'MediaRouter.Dial.Device.Description.Cached',
- DIAL_CREATE_ROUTE: 'MediaRouter.Dial.Create.Route',
- NON_CAST_DISCOVERY: 'MediaRouter.Dial.Sink.Discovered.NonCast'
-};
-
-
-/**
- * Possible values for the route creation analytics.
- * @enum {number}
- */
-mr.DialAnalytics.DialRouteCreation = {
- FAILED_NO_SINK: 0,
- ROUTE_CREATED: 1,
- NO_APP_INFO: 2,
- FAILED_LAUNCH_APP: 3
-};
-
-
-/**
- * Possible values for device description failures.
- * @enum {number}
- */
-mr.DialAnalytics.DeviceDescriptionFailures = {
- ERROR: 0,
- PARSE: 1,
- EMPTY: 2
-};
-
-
-/**
- * Records analytics around route creation.
- * @param {mr.DialAnalytics.DialRouteCreation} value
- */
-mr.DialAnalytics.recordCreateRoute = function(value) {
- mr.Analytics.recordEnum(
- mr.DialAnalytics.Metric.DIAL_CREATE_ROUTE, value,
- mr.DialAnalytics.DialRouteCreation);
-};
-
-
-/**
- * Records a failure with the device description.
- * @param {!mr.DialAnalytics.DeviceDescriptionFailures} value The failure
- * reason.
- */
-mr.DialAnalytics.recordDeviceDescriptionFailure = function(value) {
- mr.Analytics.recordEnum(
- mr.DialAnalytics.Metric.DEVICE_DESCRIPTION_FAILURE, value,
- mr.DialAnalytics.DeviceDescriptionFailures);
-};
-
-
-/**
- * Records that device description was retreived from the cache.
- */
-mr.DialAnalytics.recordDeviceDescriptionFromCache = function() {
- mr.Analytics.recordEvent(
- mr.DialAnalytics.Metric.DEVICE_DESCRIPTION_FROM_CACHE);
-};
-
-
-/**
- * Records that a device was discovered by DIAL that didn't support the cast
- * protocol.
- */
-mr.DialAnalytics.recordNonCastDiscovery = function() {
- mr.Analytics.recordEvent(mr.DialAnalytics.Metric.NON_CAST_DISCOVERY);
-};
-
-
-/**
- * Histogram name for available DIAL devices count.
- * @private @const {string}
- */
-mr.DialAnalytics.AVAILABLE_DEVICES_COUNT_ =
- 'MediaRouter.Dial.AvailableDevicesCount';
-
-
-/**
- * Histogram name for known DIAL devices count.
- * @private @const {string}
- */
-mr.DialAnalytics.KNOWN_DEVICES_COUNT_ = 'MediaRouter.Dial.KnownDevicesCount';
-
-
-/**
- * Records device counts.
- * @param {!mr.DeviceCounts} deviceCounts
- */
-mr.DialAnalytics.recordDeviceCounts = function(deviceCounts) {
- mr.Analytics.recordSmallCount(
- mr.DialAnalytics.AVAILABLE_DEVICES_COUNT_,
- deviceCounts.availableDeviceCount);
- mr.Analytics.recordSmallCount(
- mr.DialAnalytics.KNOWN_DEVICES_COUNT_, deviceCounts.knownDeviceCount);
-};
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_analytics_test.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_analytics_test.js
deleted file mode 100644
index 37a762b4bf4..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_analytics_test.js
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-goog.setTestOnly();
-goog.require('mr.DialAnalytics');
-
-describe('Dial Analytics', function() {
-
- beforeEach(function() {
- chrome.metricsPrivate = jasmine.createSpyObj(
- ['recordSmallCount', 'recordUserAction', 'recordValue']);
- });
-
- it('should record a Dial.Create.Route result', function() {
- const testConfig = {
- 'metricName': 'MediaRouter.Dial.Create.Route',
- 'type': 'histogram-linear',
- 'min': 1,
- 'max': 4,
- 'buckets': 5
- };
- let numCalls = 0;
- for (key in mr.DialAnalytics.DialRouteCreation) {
- const value = mr.DialAnalytics.DialRouteCreation[key];
- mr.DialAnalytics.recordCreateRoute(value);
- expect(chrome.metricsPrivate.recordValue.calls.count()).toBe(++numCalls);
- expect(chrome.metricsPrivate.recordValue)
- .toHaveBeenCalledWith(testConfig, value);
- }
- });
-
- it('should not record an unknown Dial.Create.Route result', function() {
- mr.DialAnalytics.recordCreateRoute('test');
- expect(chrome.metricsPrivate.recordValue).not.toHaveBeenCalled();
- });
-
- it('should record a Dial.Device.Description.Failure result', function() {
- const testConfig = {
- 'metricName': 'MediaRouter.Dial.Device.Description.Failure',
- 'type': 'histogram-linear',
- 'min': 1,
- 'max': 3,
- 'buckets': 4
- };
- let numCalls = 0;
- for (key in mr.DialAnalytics.DeviceDescriptionFailures) {
- const value = mr.DialAnalytics.DeviceDescriptionFailures[key];
- mr.DialAnalytics.recordDeviceDescriptionFailure(value);
- expect(chrome.metricsPrivate.recordValue.calls.count()).toBe(++numCalls);
- expect(chrome.metricsPrivate.recordValue)
- .toHaveBeenCalledWith(testConfig, value);
- }
- });
-
- it('should not record an unknown Dial.Device.Description.Failure',
- function() {
- mr.DialAnalytics.recordDeviceDescriptionFailure('test');
- expect(chrome.metricsPrivate.recordValue).not.toHaveBeenCalled();
- });
-
- it('should record a Device Description From Cache action', function() {
- mr.DialAnalytics.recordDeviceDescriptionFromCache();
- expect(chrome.metricsPrivate.recordUserAction.calls.count()).toBe(1);
- expect(chrome.metricsPrivate.recordUserAction)
- .toHaveBeenCalledWith('MediaRouter.Dial.Device.Description.Cached');
- });
-
- it('should record a non-Cast Sink Discovery action', function() {
- mr.DialAnalytics.recordNonCastDiscovery();
- expect(chrome.metricsPrivate.recordUserAction.calls.count()).toBe(1);
- expect(chrome.metricsPrivate.recordUserAction)
- .toHaveBeenCalledWith('MediaRouter.Dial.Sink.Discovered.NonCast');
- });
-
- it('DeviceCounts is recorded with recordSmallCount', () => {
- const deviceCounts = {availableDeviceCount: 5, knownDeviceCount: 8};
- mr.DialAnalytics.recordDeviceCounts(deviceCounts);
- expect(chrome.metricsPrivate.recordSmallCount.calls.count()).toBe(2);
- let args = chrome.metricsPrivate.recordSmallCount.calls.argsFor(0);
- expect(args[0]).toBe(mr.DialAnalytics.AVAILABLE_DEVICES_COUNT_);
- expect(args[1]).toBe(deviceCounts.availableDeviceCount);
-
- args = chrome.metricsPrivate.recordSmallCount.calls.argsFor(1);
- expect(args[0]).toBe(mr.DialAnalytics.KNOWN_DEVICES_COUNT_);
- expect(args[1]).toBe(deviceCounts.knownDeviceCount);
- });
-});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_app_discovery_service.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_app_discovery_service.js
deleted file mode 100644
index d612fa90702..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_app_discovery_service.js
+++ /dev/null
@@ -1,480 +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.
-
-goog.module('mr.dial.AppDiscoveryService');
-
-const ActivityRecords = goog.require('mr.dial.ActivityRecords');
-const DialClient = goog.require('mr.dial.Client');
-const DialSink = goog.require('mr.dial.Sink');
-const DialSinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const Logger = goog.require('mr.Logger');
-const PersistentData = goog.require('mr.PersistentData');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const PromiseUtils = goog.require('mr.PromiseUtils');
-const SinkDiscoveryService = goog.require('mr.dial.SinkDiscoveryService');
-
-
-/**
- * Service for determining whether a sink supports a given DIAL app.
- * @implements {PersistentData}
- */
-const AppDiscoveryService = class {
- /**
- * @param {!SinkDiscoveryService} discoveryService
- * @param {!ActivityRecords} activityRecords
- */
- constructor(discoveryService, activityRecords) {
- /** @private @const {?Logger} */
- this.logger_ = Logger.getInstance('mr.dial.AppDiscoveryService');
-
- /**
- * Names of applications that are actively being queried for.
- * @private {!Set<string>}
- */
- this.registeredApps_ = new Set();
-
- /**
- * @private @const {!SinkDiscoveryService}
- */
- this.discoveryService_ = discoveryService;
-
- /**
- * @private @const {!ActivityRecords}
- */
- this.activityRecords_ = activityRecords;
-
- /**
- * Keeps track of pending requests to avoid duplication. Values are
- * Promises returning strings of the form <sink.getId()>:<appName>.
- * @private @const {!Map<string, !Promise<!DialClient.AppInfo>>}
- */
- this.pendingRequests_ = new Map();
-
- /**
- * DIAL clients used by this service. Keys are sink ids.
- * @private @const {!Map<string, !DialClient.Client>}
- */
- this.clientsBySinkId_ = new Map();
-
- /**
- * The timeout ID for the next scan.
- * @private {?number}
- */
- this.timeoutId_ = null;
-
- /**
- * Whether the service is running.
- * @private {boolean}
- */
- this.running_ = false;
- }
-
- init() {
- PersistentDataManager.register(this);
- }
-
- /**
- * Starts discovery.
- */
- start() {
- this.logger_.info('Starting periodic scanning.');
- if (!this.running_) {
- this.running_ = true;
- this.doScan_();
- }
- }
-
- /**
- * Stops discovery. Also aborts all outstanding discovery requests.
- */
- stop() {
- this.logger_.info('Stopping periodic scanning.');
- if (!this.running_) return;
- this.running_ = false;
- if (this.timeoutId_) {
- clearTimeout(this.timeoutId_);
- this.timeoutId_ = null;
- }
- this.pendingRequests_.clear();
- }
-
- /**
- * Registers an application name that should be queried. Starts periodic
- * scanning if it hasn't already started. Otherwise, issues an out-of-band
- * query for the app against all discovered sinks.
- * @param {string} appName
- */
- registerApp(appName) {
- if (this.registeredApps_.has(appName) &&
- !this.anyUnknownAppStatus_(appName)) {
- // No need to scan since status for appName is known for all sinks.
- return;
- }
-
- this.registeredApps_.add(appName);
-
- if (this.discoveryService_.getSinkCount() == 0) {
- // No sinks, no need to scan.
- return;
- }
- if (!this.running_) {
- this.start();
- } else {
- this.discoveryService_.getSinks().forEach(
- this.doScanSinkForApp_.bind(this, appName));
- }
- }
-
- /**
- * Unregisters an application name.
- * @param {string} appName
- */
- unregisterApp(appName) {
- this.registeredApps_.delete(appName);
- }
-
- /**
- * @return {!Array<string>}
- */
- getRegisteredApps() {
- return Array.from(this.registeredApps_);
- }
-
- /**
- * @return {number}
- */
- getAppCount() {
- return this.registeredApps_.size;
- }
-
- /**
- * Issues app info queries and updates sink app status and activities
- * according to results. Queries will be made for the following:
- * 1) All registered apps, against all discovered sinks. Note that a (app,
- * sink) combination is only queried if its status is unknown, or if enough
- * time has elapsed since its previous status was known.
- * 2) Each activity's app against its sink.
- * Once all queries have returned and all updates have been made, schedules a
- * scan in the future.
- * @private
- */
- doScan_() {
- this.logger_.info('Start app status scan.');
- const promises = [];
-
- // Scans all sinks against all registered apps.
- this.discoveryService_.getSinks().forEach(sink => {
- promises.push.apply(promises, this.scanSink(sink));
- });
-
- // Scans all activities.
- this.activityRecords_.getActivities().forEach(activity => {
- promises.push(this.scanActivity_(activity));
- });
-
- PromiseUtils.allSettled(promises).then(() => {
- if (this.running_ && !this.timeoutId_) {
- this.logger_.fine('Scan complete; scheduling for next scan.');
- // NOTE(imcheng): setTimeout with a large delay does not work well in
- // event pages. Instead we should be using chrome.alarms API, but note
- // that it is subject to a minmum delay of 1 minute.
- this.timeoutId_ = setTimeout(() => {
- this.doRescan_();
- }, AppDiscoveryService.CHECK_INTERVAL_MILLIS);
- }
- });
- }
-
- /**
- * Clears the timer and starts a round of scanning. Only valid when called
- * from a timer.
- * @private
- */
- doRescan_() {
- this.logger_.fine('Start app status scan (timer-based)');
- this.timeoutId_ = null;
- this.doScan_();
- }
-
- /**
- * Asynchronously scans a sink against all registered apps and updates its app
- * status map if needed.
- * @param {!DialSink} sink
- * @return {!Array<!Promise<void>>} If the sink does not support app
- * the getting app info, returns an empty array. Otherwise, returns a list
- * of Promises, each corresponding to a registered app, resolved when the
- * sink's app status has been updated.
- */
- scanSink(sink) {
- if (!sink.supportsAppAvailability()) {
- return [];
- }
-
- const promises = [];
- for (let appName of this.registeredApps_) {
- promises.push(this.doScanSinkForApp_(appName, sink));
- }
- return promises;
- }
-
- /**
- * Issues an app info query for the given app to the given sink, and updates
- * the sink's app status map with the response.
- * @param {string} appName
- * @param {!DialSink} sink
- * @return {!Promise<void>} Resolved when the sink's app status has been
- * updated.
- * @private
- */
- doScanSinkForApp_(appName, sink) {
- if (sink.getAppStatus(appName) != DialSinkAppStatus.UNKNOWN &&
- Date.now() - sink.getAppStatusTimeStamp(appName) <
- AppDiscoveryService.CACHE_PERIOD_) {
- // App status already known and not expired.
- return Promise.resolve();
- }
- if (!sink.supportsAppAvailability()) {
- return Promise.resolve();
- }
- this.logger_.fine(
- 'Querying ' + sink.getId() + ' for ' + appName +
- ' to update app status');
- return this.getAppInfo_(sink, appName)
- .then(
- appInfo => {
- const newAppStatus = this.getAvailabilityFromAppInfo_(appInfo);
- this.maybeUpdateAppStatus_(sink, appName, newAppStatus);
- },
- e => {
- // Some devices return NOT_FOUND for GetAppInfo to indicate the
- // app is unavailable.
- if (e instanceof DialClient.AppInfoNotFoundError) {
- this.maybeUpdateAppStatus_(
- sink, appName, DialSinkAppStatus.UNAVAILABLE);
- return;
- }
- this.logger_.warning(
- 'Failed to process app availability; ' + sink.getId() +
- ' does not support app availability');
- sink.setSupportsAppAvailability(false);
- });
- }
-
- /**
- * Issues an app info query for the given activity's app to the activity's
- * sink, and updates the activity records if the app is no longer running.
- * @param {!mr.dial.Activity} activity
- * @return {!Promise<void>} Resolved when the activity record has possibly
- * been updated.
- * @private
- */
- scanActivity_(activity) {
- const sink = this.discoveryService_.getSinkById(activity.route.sinkId);
- if (!sink) {
- this.logger_.warning(
- 'Activity refers to nonexistent sink: ' + activity.route.id);
- return Promise.resolve();
- }
- if (!sink.supportsAppAvailability()) {
- return Promise.resolve();
- }
- const appName = activity.appName;
- this.logger_.fine(
- 'Querying ' + sink.getId() + ' for ' + appName + ' to update activity');
- return this.getAppInfo_(sink, appName)
- .then(
- appInfo => this.maybeUpdateActivityRecord_(
- /** @type {!DialSink} */ (sink), appName, appInfo),
- e => this.doRemoveActivityRecord_(
- /** @type {!DialSink} */ (sink), appName));
- }
-
- /**
- * Gets the DIAL client associated with the given sink, or creates one if it
- * does not exist.
- * @param {!DialSink} sink
- * @return {!DialClient.Client} A client instance for the given sink.
- * @private
- */
- getDialClient_(sink) {
- let client = this.clientsBySinkId_.get(sink.getId());
- if (!client) {
- client = new DialClient.Client(sink);
- this.logger_.fine('Created DIAL client for ' + sink.getId());
- this.clientsBySinkId_.set(sink.getId(), client);
- }
- return client;
- }
-
- /**
- * Issues an app info query with the given sink's DIAL client. A query will
- * not be issued if there is already a same one pending.
- * @param {!DialSink} sink
- * @param {string} appName
- * @return {!Promise<!DialClient.AppInfo>} Resolved with the query response,
- * or rejected on error.
- * @private
- */
- getAppInfo_(sink, appName) {
- const requestId = AppDiscoveryService.getRequestId_(sink, appName);
- let promise = this.pendingRequests_.get(requestId);
- if (promise) {
- return promise;
- }
-
- promise = this.getDialClient_(sink).getAppInfo(appName);
- this.pendingRequests_.set(requestId, promise);
- const cleanup = () => {
- this.pendingRequests_.delete(requestId);
- };
- promise.then(cleanup, cleanup);
- return promise;
- }
-
- /**
- * Translates the given app info result into a DialSinkAppStatus value.
- * @param {!DialClient.AppInfo} appInfo
- * @return {DialSinkAppStatus}
- * @private
- */
- getAvailabilityFromAppInfo_(appInfo) {
- if (appInfo.name == 'Netflix') {
- return this.getAppStatusFromNetflixAppInfo_(appInfo);
- } else {
- switch (appInfo.state) {
- case DialClient.DialAppState.RUNNING:
- case DialClient.DialAppState.STOPPED:
- return DialSinkAppStatus.AVAILABLE;
- default:
- return DialSinkAppStatus.UNAVAILABLE;
- }
- }
- }
-
- /**
- * Returns app status from a Netflix app info.
- * @param {!DialClient.AppInfo} appInfo The app info from DIAL GET.
- * @return {DialSinkAppStatus}
- * @private
- */
- getAppStatusFromNetflixAppInfo_(appInfo) {
- const isNetflixWebsocket =
- appInfo.extraData && appInfo.extraData['capabilities'] == 'websocket';
- if (isNetflixWebsocket &&
- (appInfo.state == DialClient.DialAppState.RUNNING ||
- appInfo.state == DialClient.DialAppState.STOPPED)) {
- return DialSinkAppStatus.AVAILABLE;
- } else {
- return DialSinkAppStatus.UNAVAILABLE;
- }
- }
-
- /**
- * Returns the request ID to use for an app info request.
- * @param {!DialSink} sink
- * @param {string} appName
- * @return {string}
- * @private
- */
- static getRequestId_(sink, appName) {
- return sink.getId() + ':' + appName;
- }
-
- /**
- * Checks whether the status of an app on a sink has changed, and if so
- * notifies discovery service.
- * @param {!DialSink} sink
- * @param {string} appName
- * @param {DialSinkAppStatus} newAppStatus
- * @private
- */
- maybeUpdateAppStatus_(sink, appName, newAppStatus) {
- this.logger_.fine(
- 'Got app status ' + newAppStatus + ' from ' + sink.getId() + ' for ' +
- appName);
- const oldAppStatus = sink.getAppStatus(appName);
- sink.setAppStatus(appName, newAppStatus);
- if (newAppStatus != oldAppStatus) {
- this.discoveryService_.onAppStatusChanged(appName, sink);
- }
- }
-
- /**
- * Checks whether the given app is no longer running on the given sink, and if
- * so notifies activity records.
- * @param {!DialSink} sink
- * @param {string} appName
- * @param {!DialClient.AppInfo} appInfo
- * @private
- */
- maybeUpdateActivityRecord_(sink, appName, appInfo) {
- if (appInfo.state != DialClient.DialAppState.RUNNING) {
- this.doRemoveActivityRecord_(sink, appName);
- }
- }
-
- /**
- * Removes the activity record with the given sink and app name, if it exists.
- * @param {!DialSink} sink
- * @param {string} appName
- * @private
- */
- doRemoveActivityRecord_(sink, appName) {
- const activity = this.activityRecords_.getBySinkId(sink.getId());
- if (activity && activity.appName == appName) {
- this.activityRecords_.removeByRouteId(activity.route.id);
- }
- }
-
- /**
- * Checks if there is a sink whose status of appName is unknown.
- * @param {string} appName
- * @return {boolean}
- * @private
- */
- anyUnknownAppStatus_(appName) {
- return this.discoveryService_.getSinks().some(
- s => s.getAppStatus(appName) == DialSinkAppStatus.UNKNOWN);
- }
-
- /**
- * @override
- */
- getStorageKey() {
- return 'dial.AppDiscoveryService';
- }
-
- /**
- * @override
- */
- getData() {
- return [this.getRegisteredApps()];
- }
-
- /**
- * @override
- */
- loadSavedData() {
- const savedData = PersistentDataManager.getTemporaryData(this);
- this.registeredApps_ = new Set(savedData || []);
- }
-};
-
-
-/**
- * The interval for periodic scanning.
- * @package @const {number}
- */
-AppDiscoveryService.CHECK_INTERVAL_MILLIS = 60 * 1000;
-
-
-/**
- * The amount of time an availability result for an app (both AVAILABLE and
- * UNAVAILABLE) will be cached for.
- * @private @const {number}
- */
-AppDiscoveryService.CACHE_PERIOD_ = 60 * 60 * 1000;
-
-
-exports = AppDiscoveryService;
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_app_discovery_service_test.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_app_discovery_service_test.js
deleted file mode 100644
index cd7edeac16b..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_app_discovery_service_test.js
+++ /dev/null
@@ -1,362 +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.
-
-goog.module('mr.dial.AppDiscoveryServiceTest');
-goog.setTestOnly('mr.dial.AppDiscoveryServiceTest');
-
-const Activity = goog.require('mr.dial.Activity');
-const ActivityRecords = goog.require('mr.dial.ActivityRecords');
-const AppDiscoveryService = goog.require('mr.dial.AppDiscoveryService');
-const DialClient = goog.require('mr.dial.Client');
-const DialSink = goog.require('mr.dial.Sink');
-const DialSinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const Route = goog.require('mr.Route');
-const UnitTestUtils = goog.require('mr.UnitTestUtils');
-
-describe('DIAL AppDiscoveryService Tests', function() {
- let activityRecords;
- let service;
- let mockClock;
- let mockDiscoveryService;
- let mockActivityCallbacks;
- let sink1;
- let sink2;
- let sink3;
- let mockDialClient;
- let stoppedAppInfo;
- let runningAppInfo;
- let installableAppInfo;
- let stoppedAppInfoWithWebsocket;
-
- const setUpGetAppInfoResponse = function(appInfo) {
- mockDialClient.getAppInfo.and.callFake(() => Promise.resolve(appInfo));
- };
-
- const setUpGetAppInfoError = function() {
- mockDialClient.getAppInfo.and.callFake(
- () => Promise.reject(new Error('getAppInfo failed')));
- };
-
- const setUpGetAppInfoNotFoundError = function() {
- mockDialClient.getAppInfo.and.callFake(
- () => Promise.reject(new DialClient.AppInfoNotFoundError()));
- };
-
- beforeEach(function() {
- mockClock = UnitTestUtils.useMockClockAndPromises();
-
- mockDiscoveryService = jasmine.createSpyObj(
- 'discoveryService',
- ['getSinks', 'getSinkById', 'getSinkCount', 'onAppStatusChanged']);
- mockActivityCallbacks = jasmine.createSpyObj(
- 'activityCallbacks',
- ['onActivityAdded', 'onActivityRemoved', 'onActivityUpdated']);
- activityRecords = new ActivityRecords(mockActivityCallbacks);
- service = new AppDiscoveryService(mockDiscoveryService, activityRecords);
-
- sink1 = new DialSink('sink1', '1').setSupportsAppAvailability(true);
- sink2 = new DialSink('sink2', '2').setSupportsAppAvailability(true);
- sink3 = new DialSink('sink3', '3').setSupportsAppAvailability(false);
- mockDialClient = jasmine.createSpyObj('dialClient', ['getAppInfo']);
- spyOn(AppDiscoveryService.prototype, 'getDialClient_')
- .and.returnValue(mockDialClient);
- stoppedAppInfo = {'state': DialClient.DialAppState.STOPPED};
- runningAppInfo = {'state': DialClient.DialAppState.RUNNING};
- installableAppInfo = {'state': DialClient.DialAppState.INSTALLABLE};
- stoppedAppInfoWithWebsocket = {
- 'name': 'Netflix',
- 'state': DialClient.DialAppState.STOPPED,
- 'extraData': {'capabilities': 'websocket'}
- };
-
- chrome.runtime = {
- id: 'fakeId',
- getManifest: function() {
- return {version: 'fakeVersion'};
- }
- };
- });
-
- afterEach(function() {
- service.stop();
- UnitTestUtils.restoreRealClockAndPromises();
- PersistentDataManager.clear();
- });
-
- describe('Tests registerApp', function() {
- beforeEach(function() {
- mockDiscoveryService.getSinks.and.returnValue([sink1, sink2, sink3]);
- mockDiscoveryService.getSinkCount.and.returnValue(3);
- });
-
- const expectAppStatus = function(expectedAppStatus, appName) {
- service.init();
-
- expect(sink1.getAppStatus(appName)).toEqual(DialSinkAppStatus.UNKNOWN);
- expect(sink2.getAppStatus(appName)).toEqual(DialSinkAppStatus.UNKNOWN);
- expect(sink3.getAppStatus(appName)).toEqual(DialSinkAppStatus.UNKNOWN);
-
- service.registerApp(appName);
-
- service.start();
- // Let internal promises to resolve or reject.
- mockClock.tick(1);
-
- expect(sink1.getAppStatus(appName)).toEqual(expectedAppStatus);
- expect(sink2.getAppStatus(appName)).toEqual(expectedAppStatus);
- expect(sink3.getAppStatus(appName)).toEqual(DialSinkAppStatus.UNKNOWN);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
- };
-
- it('Response indicates app was stopped', function() {
- setUpGetAppInfoResponse(stoppedAppInfo);
- expectAppStatus(DialSinkAppStatus.AVAILABLE, 'YouTube');
- });
-
- it('Response indicates app was running', function() {
- setUpGetAppInfoResponse(runningAppInfo);
- expectAppStatus(DialSinkAppStatus.AVAILABLE, 'YouTube');
- });
-
- it('Response indicates app was installable', function() {
- setUpGetAppInfoResponse(installableAppInfo);
- expectAppStatus(DialSinkAppStatus.UNAVAILABLE, 'YouTube');
- });
-
- it('Response has invalid app info', function() {
- setUpGetAppInfoError();
- expectAppStatus(DialSinkAppStatus.UNKNOWN, 'YouTube');
- expect(sink1.supportsAppAvailability()).toBe(false);
- expect(sink2.supportsAppAvailability()).toBe(false);
- });
-
- it('Response indicates not found', function() {
- setUpGetAppInfoNotFoundError();
- expectAppStatus(DialSinkAppStatus.UNAVAILABLE, 'YouTube');
- });
-
- it('Netflix with special stopped info', function() {
- setUpGetAppInfoResponse(stoppedAppInfoWithWebsocket);
- expectAppStatus(DialSinkAppStatus.AVAILABLE, 'Netflix');
- });
-
- it('Netflix with normal stopped info', function() {
- stoppedAppInfo.name = 'Netflix';
- setUpGetAppInfoResponse(stoppedAppInfo);
- expectAppStatus(DialSinkAppStatus.UNAVAILABLE, 'Netflix');
- });
-
- it('No new query generated when registering existing app with known status',
- function() {
- setUpGetAppInfoResponse(stoppedAppInfo);
- expectAppStatus(DialSinkAppStatus.AVAILABLE, 'YouTube');
- // register again
- service.registerApp('YouTube');
- mockClock.tick(1);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
- // unregister does nothing because sink already had the app status.
- service.unregisterApp('YouTube');
- service.registerApp('YouTube');
- mockClock.tick(1);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
- // unless clear app status first.
- sink1.clearAppStatus();
- sink2.clearAppStatus();
- service.unregisterApp('YouTube');
- service.registerApp('YouTube');
- mockClock.tick(1);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(4);
- });
-
- it('No new query generated when register existing app with unknown status',
- function() {
- setUpGetAppInfoError();
- expectAppStatus(DialSinkAppStatus.UNKNOWN, 'YouTube');
- // Make sink1 have known status. But sink2 has unknown status.
- sink1.setAppStatus('YouTube', DialSinkAppStatus.UNAVAILABLE);
- // register again
- service.registerApp('YouTube');
- mockClock.tick(1);
- // No re-query
- expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
- });
- });
-
- describe('Tests app status caching and onAppStatusChanged', function() {
- beforeEach(function() {
- mockDiscoveryService.getSinks.and.returnValue([sink1]);
- mockDiscoveryService.getSinkCount.and.returnValue(1);
- });
-
- it('Known app status does not change during caching period', function() {
- service.init();
- setUpGetAppInfoResponse(stoppedAppInfo);
- expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
- service.registerApp('YouTube');
- service.start();
- mockClock.tick(1);
- expect(sink1.getAppStatus('YouTube'))
- .toEqual(DialSinkAppStatus.AVAILABLE);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
- expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
-
- // Make app unavailable
- setUpGetAppInfoNotFoundError();
- service.doScan_();
- mockClock.tick(1);
- // No new query and app is still available since cache is not expired.
- expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
- expect(sink1.getAppStatus('YouTube'))
- .toEqual(DialSinkAppStatus.AVAILABLE);
- expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
- });
-
- it('Does not re-query app status when getAppInfo throws error', function() {
- service.init();
- setUpGetAppInfoError();
- expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
- service.registerApp('YouTube');
- service.start();
- mockClock.tick(1);
- expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
- expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(0);
-
- service.doScan_();
- mockClock.tick(1);
- // No new query
- expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
- expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
- expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(0);
- });
-
- it('Cache expires, re-query, different status', function() {
- service.init();
- setUpGetAppInfoResponse(stoppedAppInfo);
- expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
- service.registerApp('YouTube');
- service.start();
- mockClock.tick(1);
- expect(sink1.getAppStatus('YouTube'))
- .toEqual(DialSinkAppStatus.AVAILABLE);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
- expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
-
- // Make app unavailable
- setUpGetAppInfoNotFoundError();
- // Make cache expire
- mockClock.tick(AppDiscoveryService.CACHE_PERIOD_);
- service.doScan_();
- mockClock.tick(1);
- // new query and app becomes unavailable
- expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
- expect(sink1.getAppStatus('YouTube'))
- .toEqual(DialSinkAppStatus.UNAVAILABLE);
- expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(2);
- });
-
- it('Cache expires, re-query, same status', function() {
- service.init();
- setUpGetAppInfoResponse(stoppedAppInfo);
- expect(sink1.getAppStatus('YouTube')).toEqual(DialSinkAppStatus.UNKNOWN);
- service.registerApp('YouTube');
- service.start();
- mockClock.tick(1);
- expect(sink1.getAppStatus('YouTube'))
- .toEqual(DialSinkAppStatus.AVAILABLE);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
- expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
-
- // Make cache expire
- mockClock.tick(AppDiscoveryService.CACHE_PERIOD_);
- service.doScan_();
- mockClock.tick(1);
- // New query and app becomes unavailable
- expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
- expect(sink1.getAppStatus('YouTube'))
- .toEqual(DialSinkAppStatus.AVAILABLE);
- // Did not trigger app status changed event
- expect(mockDiscoveryService.onAppStatusChanged.calls.count()).toBe(1);
- });
- });
-
- describe('Tests activity scanning', function() {
- beforeEach(function() {
- mockDiscoveryService.getSinks.and.returnValue([sink1, sink2, sink3]);
- mockDiscoveryService.getSinkCount.and.returnValue(3);
- mockDiscoveryService.getSinkById.and.returnValue(sink1);
-
- service.init();
- const route = Route.createRoute(
- 'presentationId', 'providerName', sink1.getId(), 'source', true,
- 'description', null);
- const activity = new Activity(route, 'YouTube');
- activityRecords.add(activity);
- expect(mockActivityCallbacks.onActivityAdded).toHaveBeenCalled();
- });
-
- it('Activity is removed when app is no longer running', function() {
- setUpGetAppInfoResponse(stoppedAppInfo);
- service.start();
- mockClock.tick(1);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
- expect(mockActivityCallbacks.onActivityRemoved.calls.count()).toBe(1);
- expect(activityRecords.getActivityCount()).toBe(0);
- });
-
- it('Activity is not removed when app is still running', function() {
- setUpGetAppInfoResponse(runningAppInfo);
- service.start();
- mockClock.tick(1);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(1);
- expect(mockActivityCallbacks.onActivityRemoved).not.toHaveBeenCalled();
- expect(activityRecords.getActivityCount()).toBe(1);
-
- // Trigger periodic rescan
- mockClock.tick(AppDiscoveryService.CHECK_INTERVAL_MILLIS + 1);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
- expect(mockActivityCallbacks.onActivityRemoved).not.toHaveBeenCalled();
- expect(activityRecords.getActivityCount()).toBe(1);
-
- // No more periodic rescan.
- service.stop();
- mockClock.tick(AppDiscoveryService.CHECK_INTERVAL_MILLIS + 1);
- expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
- });
-
- it('Activity scanning not duplicated with app scanning', function() {
- setUpGetAppInfoResponse(stoppedAppInfo);
- service.registerApp('YouTube');
- mockClock.tick(1);
- // One for sink1 and one for sink2. Activity scanning does not issue a
- // duplicated request. Both app status and activity status can be updated
- // with the same response.
- expect(mockDialClient.getAppInfo.calls.count()).toBe(2);
- expect(sink1.getAppStatus('YouTube'))
- .toEqual(DialSinkAppStatus.AVAILABLE);
- expect(sink2.getAppStatus('YouTube'))
- .toEqual(DialSinkAppStatus.AVAILABLE);
- expect(mockActivityCallbacks.onActivityRemoved.calls.count()).toBe(1);
- expect(activityRecords.getActivityCount()).toBe(0);
- });
- });
-
- it('Persistent with data', function() {
- mockDiscoveryService.getSinks.and.returnValue([]);
- mockDiscoveryService.getSinkCount.and.returnValue(0);
- const mockServiceToSuspend = new AppDiscoveryService(
- mockDiscoveryService, new ActivityRecords(mockActivityCallbacks));
- mockServiceToSuspend.init();
- mockServiceToSuspend.registerApp('app1');
- mockServiceToSuspend.registerApp('app2');
- PersistentDataManager.suspendForTest();
-
- const mockServiceToLoad = new AppDiscoveryService(
- mockDiscoveryService, new ActivityRecords(mockActivityCallbacks));
- mockServiceToLoad.loadSavedData();
- expect(mockServiceToLoad.getRegisteredApps()).toEqual(['app1', 'app2']);
- expect(mockServiceToLoad.getAppCount()).toEqual(2);
- });
-});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_client.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_client.js
deleted file mode 100644
index 443b700fa20..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_client.js
+++ /dev/null
@@ -1,355 +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.
-
-/**
- * @fileoverview Client wrapper for interacting with DIAL devices and data
- * structures for responses.
- */
-
-goog.module('mr.dial.Client');
-goog.module.declareLegacyNamespace();
-
-const Assertions = goog.require('mr.Assertions');
-const Logger = goog.require('mr.Logger');
-const NetUtils = goog.require('mr.NetUtils');
-const XhrManager = goog.require('mr.XhrManager');
-const XhrUtils = goog.require('mr.XhrUtils');
-
-/**
- * Possible states of a DIAL application.
- * @enum {string}
- */
-const DialAppState = {
- /** The app is running. */
- RUNNING: 'running',
- /** The app is not running. */
- STOPPED: 'stopped',
- /** The app can be installed. */
- INSTALLABLE: 'installable',
- /**
- * An error was encountered getting the state.
-
- */
- ERROR: 'error'
-};
-
-/**
- * The fallback path to use for DELETE requests in case the device does not
- * provide one.
- * @private @const {string}
- */
-const DEFAULT_RESOURCE_PATH_ = 'run';
-
-/**
- * Holds data parsed from a DIAL GET response.
- */
-const AppInfo = class {
- constructor() {
- /**
- * The application name. Mandatory.
- * @type {string}
- */
- this.name = 'unknown';
-
- /**
- * The reported state of the application.
- * @type {DialAppState}
- */
- this.state = DialAppState.ERROR;
-
- /**
- * If the application's state is INSTALLABLE, then the URL where the app
- * can be installed.
- * @type {?string}
- */
- this.installUrl = null;
-
- /**
- * Whether the DELETE operation is supported.
- * @type {boolean}
- */
- this.allowStop = true;
-
- /**
- * If the applications's state is RUNNING, a resource identifier for the
- * running application.
- * @type {?string}
- */
- this.resource = null;
-
- /**
- * Application-specific data included with the GET response that is not part
- * of the official specifciations.
- * @type {!Object<string, string>}
- */
- this.extraData = {};
- }
-};
-
-
-/**
- * Indicates that the DIAL sink returned NOT_FOUND in response to a GET request.
- */
-const AppInfoNotFoundError = class extends Error {
- constructor() {
- super();
- }
-};
-
-
-/**
- * Wrapper for a DIAL sink used for communicating with it.
- */
-const Client = class {
- /**
- * @param {!mr.dial.Sink} sink
- * @param {!XhrManager=} xhrManager Manager for all requests.
- */
- constructor(sink, xhrManager = Client.getXhrManager_()) {
- // NOTE(mfoltz,haibinlu): We do not assert if the sink supports DIAL,
- // since combined discovery uses DialClient to check app info to see if a
- // mDNS-discovered sink is also a DIAL sink.
- Assertions.assert(
- sink.getDialAppUrl(), 'Receiver must have a DIAL app URL set.');
-
- /** @private @const {!mr.dial.Sink} */
- this.sink_ = sink;
-
- /** @private @const {!XhrManager} */
- this.xhrManager_ = xhrManager;
-
- /** @private @const {?Logger} */
- this.logger_ = Logger.getInstance('mr.dial.Client');
- }
-
- /**
- * @param {!mr.dial.Sink} sink
- * @return {!Client}
- */
- static create(sink) {
- return new Client(sink);
- }
-
- /**
- * Returns the default XhrManager, creating it if necessary.
- * @return {!XhrManager}
- * @private
- */
- static getXhrManager_() {
- if (!Client.xhrManager_) {
- Client.xhrManager_ = new XhrManager(
- /* maxRequests */ 10,
- /* defaultTimeoutMillis */ 2000,
- /* defaultNumAttempts */ 1);
- }
- return Client.xhrManager_;
- }
-
- /**
- * @param {string} state A string representing a DIAL application state.
- * @return {DialAppState} The corresponding state or ERROR if the
- * state is invalid.
- * @private
- */
- static parseDialAppState_(state) {
- switch (state) {
- case 'running':
- return DialAppState.RUNNING;
- case 'stopped':
- return DialAppState.STOPPED;
- default:
- return DialAppState.ERROR;
- }
- }
-
- /**
- * Launches an application on the sink.
- * @param {string} appName Name of the DIAL application to launch.
- * @param {string} postData Data to include in the HTTP POST request.
- * @return {!Promise<void>} Fulfilled when the operation completes
- * successfully. Rejected otherwise.
- */
- launchApp(appName, postData) {
- return this.xhrManager_
- .send(
- this.getAppUrl_(appName), 'POST', postData, {timeoutMillis: 15000})
- .then(xhr => this.handleResponse_('launchApp', 'POST', xhr));
- }
-
- /**
- * Stops a running application on the sink.
- * @param {string} appName Name of the DIAL application to stop.
- * @return {!Promise<void>} Fulfilled when the operation completes
- * successfully. Rejected otherwise.
- */
- stopApp(appName) {
- return this.getAppInfo(appName)
- .then(
- appInfo => {
- // The URL used for stop is obtained from appending resource path
- // to the app URL. If the resource path is not available, then it
- // means the app is not running. It could also be that the device
- // is non-compliant. To account for this case, we will try to stop
- // the app anyway with a fallback path.
- if (!appInfo.resource) {
- this.logger_.warning(
- 'stopApp: Resource path for not available for app ' +
- appName + ': using fallback path.');
- return DEFAULT_RESOURCE_PATH_;
- }
- return appInfo.resource;
- },
- e => {
- // If getAppInfo fails, use a fallback path.
- this.logger_.warning(
- 'stopApp: getAppInfo failed: using fallback path.');
- return DEFAULT_RESOURCE_PATH_;
- })
- .then(
- path => this.xhrManager_.send(
- this.getAppUrl_(appName) + '/' + path, 'DELETE'))
- .then(xhr => this.handleResponse_('stopApp', 'DELETE', xhr));
- }
-
- /**
- * Gets information about a running application on the sink.
- * @param {string} appName Name of the DIAL application to get info from.
- * @return {!Promise<!AppInfo>} Fulfilled with AppInfo. Rejected if the
- * operation did not complete successfully. In the case of the sink
- * returning NOT_FOUND for the request, AppInfoNotFoundError will be
- * thrown.
- */
- getAppInfo(appName) {
- return this.xhrManager_
- .send(this.getAppUrl_(appName), 'GET', undefined, {numAttempts: 3})
- .then(xhr => this.handleGetAppInfoResponse_(appName, xhr));
- }
-
- /**
- * Parses the response from a Xhr GET request.
- * @param {string} appName App nam used in the request.
- * @param {!XMLHttpRequest} xhr
- * @return {!AppInfo}
- * @private
- */
- handleGetAppInfoResponse_(appName, xhr) {
- XhrUtils.logRawXhr(this.logger_, 'GetAppInfo', 'GET', xhr);
- if (!XhrUtils.isSuccess(xhr)) {
- if (xhr.status == NetUtils.HttpStatus.NOT_FOUND) {
- throw new AppInfoNotFoundError();
- } else {
- throw new Error(`Response error: ${xhr.status}`);
- }
- }
-
- const xml = XhrUtils.parseXml(xhr.responseText);
- if (!xml) {
- this.logger_.info('Invalid or empty response');
- throw new Error('Invalid or empty response');
- }
-
- const service = xml.getElementsByTagName('service');
- if (!service || service.length != 1) {
- this.logger_.info('Invalid GET response (invalid service)');
- throw new Error('Invalid GET response (invalid service)');
- }
- const appInfo = new AppInfo();
- for (var i = 0, l = service[0].childNodes.length; i < l; i++) {
- const node = service[0].childNodes[i];
- if (node.nodeName == 'state') {
- appInfo.state = Client.parseDialAppState_(node.textContent);
- } else if (node.nodeName == 'name') {
- appInfo.name = node.textContent;
- } else if (node.localName == 'link') {
- appInfo.resource = node.getAttribute('href');
- } else if (node.nodeName == 'options') {
- // The default value for allowStop is true per DIAL spec.
- appInfo.allowStop = (node.getAttribute('allowStop') != 'false');
- } else {
- appInfo.extraData[node.nodeName] = node.innerHTML;
- }
- }
-
- // Validate mandatory fields (name, state).
- if (appInfo.name == 'unknown') {
- this.logger_.info('GET response missing name value');
- throw new Error('GET response missing name value');
- }
-
- if (appInfo.name != appName) {
- this.logger_.info('GET app name mismatch');
- throw new Error('GET app name mismatch');
- }
-
- if (appInfo.state == DialAppState.ERROR) {
- this.logger_.info('GET response missing state value');
- throw new Error('GET response missing state value');
- }
-
- // Parse state.
- const installable = /installable=(.+)/.exec(appInfo.state);
- if (installable && installable[1]) {
- appInfo.state = DialAppState.INSTALLABLE;
- appInfo.installUrl = installable[1];
- } else if (
- appInfo.state == DialAppState.RUNNING ||
- appInfo.state == DialAppState.STOPPED) {
- // Valid state. Continue.
- } else {
- this.logger_.info('GET response has invalid state value');
- throw new Error('GET response has invalid state value');
- }
-
- // Success!
- return appInfo;
- }
-
- /**
- * Returns the URL used to communicate with a given DIAL application.
- * @param {string} appName The name of the DIAL application.
- * @return {string} The URL for the activity.
- * @private
- */
- getAppUrl_(appName) {
- let appUrl = this.sink_.getDialAppUrl();
- if (appUrl.charAt(appUrl.length - 1) != '/') {
- appUrl += '/';
- }
- return appUrl + appName;
- }
-
- /**
- * Logs the given response and returns a Promise that resolves if it indicates
- * success.
- * @param {string} action Name of the operation that created the request.
- * @param {string} method The HTTP method.
- * @param {!XMLHttpRequest} xhr
- * @return {!Promise<void>} Resolves if the response indicates success,
- * rejected otherwise.
- * @private
- */
- handleResponse_(action, method, xhr) {
- return new Promise((resolve, reject) => {
- XhrUtils.logRawXhr(this.logger_, action, method, xhr);
- if (XhrUtils.isSuccess(xhr)) {
- resolve();
- } else {
- reject(Error(xhr.statusText));
- }
- });
- }
-};
-
-
-/**
- * Lazily instantiated and shared between DialClient instances.
- * @private {?XhrManager}
- */
-Client.xhrManager_ = null;
-
-
-exports.AppInfo = AppInfo;
-exports.AppInfoNotFoundError = AppInfoNotFoundError;
-exports.Client = Client;
-exports.DialAppState = DialAppState;
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_client_test.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_client_test.js
deleted file mode 100644
index 129293e8f0e..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_client_test.js
+++ /dev/null
@@ -1,307 +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.
-
-goog.module('mr.dial.ClientTest');
-goog.setTestOnly('mr.dial.ClientTest');
-
-const DialClient = goog.require('mr.dial.Client');
-const DialSink = goog.require('mr.dial.Sink');
-const XhrUtils = goog.require('mr.XhrUtils');
-
-describe('Dial Client Tests', function() {
- let client;
- let mockXhrManager;
- let sink;
- const appUrl = 'http://198.0.0.100/apps';
-
-
- beforeEach(function() {
- sink = new DialSink('sink', 'sinkid');
- sink.setDialAppUrl(appUrl);
- mockXhrManager = jasmine.createSpyObj('XhrManager', ['send']);
- spyOn(XhrUtils, 'logRawXhr');
- client = new DialClient.Client(sink, mockXhrManager);
- });
-
- const setMockXhrResponse = function(xml) {
- mockXhrManager.send.and.returnValue(
- Promise.resolve({responseText: xml, status: 200}));
- };
-
- const setMockXhrErrorResponse = function() {
- mockXhrManager.send.and.returnValue(
- Promise.resolve({responseText: null, status: 403 /* Forbidden */}));
- };
-
- const setMockXhrNotFoundResponse = function() {
- mockXhrManager.send.and.returnValue(
- Promise.resolve({responseText: null, status: 404}));
- };
-
- const setMockXhrReject = function() {
- mockXhrManager.send.and.returnValue(
- Promise.reject(new Error('send failed')));
- };
-
- // Suppress Jasmine warning about a spec with no expectations.
- const noExpectations = function() {
- expect(true).toBe(true);
- };
-
- describe('Tests launchApp', function() {
- const expectLaunchAppFails = function(done) {
- client.launchApp('YouTube', 'v=12345678').then(() => {
- fail('launchApp unexpectedly succeeded.');
- }, done);
- };
-
- it('Resolves', done => {
- setMockXhrResponse('');
- client.launchApp('YouTube', 'v=12345678').then(() => {
- expect(mockXhrManager.send)
- .toHaveBeenCalledWith(
- appUrl + '/YouTube', 'POST', 'v=12345678', jasmine.any(Object));
- done();
- });
- });
-
- it('Rejects on error response', done => {
- setMockXhrErrorResponse();
- expectLaunchAppFails(done);
- noExpectations();
- });
-
- it('Rejects on send rejection', done => {
- setMockXhrReject();
- expectLaunchAppFails(done);
- noExpectations();
- });
- });
-
- describe('Tests stopApp', function() {
- const expectStopAppFails = function(done) {
- client.stopApp('YouTube').then(() => {
- fail('stopApp unexpectedly succeeded.');
- }, done);
- };
-
- it('Resolves', done => {
- // Set up the mock response for the GET request.
- setMockXhrResponse(VALID_GET_RESPONSE_);
- client.stopApp('YouTube').then(() => {
- expect(mockXhrManager.send.calls.count()).toEqual(2);
- expect(mockXhrManager.send.calls.argsFor(0)[0])
- .toEqual(appUrl + '/YouTube');
- expect(mockXhrManager.send.calls.argsFor(0)[1]).toEqual('GET');
- expect(mockXhrManager.send.calls.argsFor(1)[0])
- .toEqual(appUrl + '/YouTube/run');
- expect(mockXhrManager.send.calls.argsFor(1)[1]).toEqual('DELETE');
- done();
- });
- });
-
- it('Resolves with fallback path', done => {
- mockXhrManager.send.and.callFake((url, method) => {
- if (method === 'GET') {
- return Promise.reject(new Error('GET failed'));
- } else {
- return Promise.resolve({status: 200});
- }
- });
- client.stopApp('YouTube').then(() => {
- expect(mockXhrManager.send.calls.count()).toEqual(2);
- expect(mockXhrManager.send.calls.argsFor(1)[0])
- .toEqual(appUrl + '/YouTube/run');
- expect(mockXhrManager.send.calls.argsFor(1)[1]).toEqual('DELETE');
- done();
- });
- });
-
- it('Rejects on error response', done => {
- setMockXhrErrorResponse();
- expectStopAppFails(done);
- noExpectations();
- });
-
- it('Rejects on send rejection', done => {
- setMockXhrReject();
- expectStopAppFails(done);
- noExpectations();
- });
- });
-
- const expectMockSendGet = function() {
- expect(mockXhrManager.send)
- .toHaveBeenCalledWith(
- 'http://198.0.0.100/apps/YouTube', 'GET', undefined,
- jasmine.any(Object));
- };
-
- const VALID_GET_RESPONSE_ = '<?xml version="1.0" encoding="UTF-8"?>' +
- '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
- '<name>YouTube</name>' +
- '<options allowStop="false"/>' +
- '<state>running</state>' +
- '<link rel="run" href="run"/>' +
- '</service>';
-
- const VALID_GET_RESPONSE_EXTRA_DATA_ =
- '<?xml version="1.0" encoding="UTF-8"?>' +
- '<service xmlns="urn:dial-multiscreen-org:schemas:dial" xmlns:atom="http://www.w3.org/2005/Atom">' +
- '<name>YouTube</name>' +
- '<state>running</state>' +
- '<atom:link rel="run" href="run"/>' +
- '<port>8080</port>' +
- '<additionalData>' +
- '<screenId>e5n3112oskr42pg0td55b38nh4</screenId>' +
- '<otherField>2</otherField>' +
- '</additionalData>' +
- '</service>';
-
- const INVALID_GET_RESPONSE_NO_SERVICE_ =
- '<?xml version="1.0" encoding="UTF-8"?>';
-
- const INVALID_GET_RESPONSE_NO_STATE_ =
- '<?xml version="1.0" encoding="UTF-8"?>' +
- '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
- '<name>YouTube</name>' +
- '<options allowStop="true"/>' +
- '<link rel="run" href="run"/>' +
- '</service>';
-
- const INVALID_GET_RESPONSE_INVALID_STATE_ =
- '<?xml version="1.0" encoding="UTF-8"?>' +
- '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
- '<name>YouTube</name>' +
- '<options allowStop="true"/>' +
- '<state>xyzzy</state>' +
- '<link rel="run" href="run"/>' +
- '</service>';
-
- const INVALID_GET_RESPONSE_INSTALLABLE_ =
- '<?xml version="1.0" encoding="UTF-8"?>' +
- '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
- '<name>YouTube</name>' +
- '<options allowStop="true"/>' +
- '<state>installable=http://play.google.com/youtube</state>' +
- '<link rel="run" href="run"/>' +
- '</service>';
-
- const INVALID_GET_RESPONSE_NO_NAME_ =
- '<?xml version="1.0" encoding="UTF-8"?>' +
- '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
- '<options allowStop="true"/>' +
- '<state>running</state>' +
- '<link rel="run" href="run"/>' +
- '</service>';
-
- const INVALID_GET_RESPONSE_WRONG_APP_NAME_ =
- '<?xml version="1.0" encoding="UTF-8"?>' +
- '<service xmlns="urn:dial-multiscreen-org:schemas:dial">' +
- '<name>WrongAppName</name>' +
- '<options allowStop="true"/>' +
- '<state>running</state>' +
- '<link rel="run" href="run"/>' +
- '</service>';
-
- describe('Tests getAppInfo', function() {
- it('Returns info from valid response', done => {
- setMockXhrResponse(VALID_GET_RESPONSE_);
- client.getAppInfo('YouTube').then(appInfo => {
- expect(appInfo.name).toEqual('YouTube');
- expect(appInfo.state).toEqual('running');
- expect(appInfo.allowStop).toBe(false);
- expect(appInfo.resource).toEqual('run');
- expectMockSendGet();
- done();
- });
- });
-
- it('Returns info with extraData', done => {
- setMockXhrResponse(VALID_GET_RESPONSE_EXTRA_DATA_);
- client.getAppInfo('YouTube').then(appInfo => {
- expect(appInfo.name).toEqual('YouTube');
- expect(appInfo.state).toEqual('running');
- expect(appInfo.allowStop).toBe(true);
- expect(appInfo.resource).toEqual('run');
- expect(appInfo.extraData.port).toEqual('8080');
- expect(appInfo.extraData.additionalData)
- .toEqual(
- '<screenId xmlns="urn:dial-multiscreen-org:schemas:dial">' +
- 'e5n3112oskr42pg0td55b38nh4</screenId>' +
- '<otherField xmlns="urn:dial-multiscreen-org:schemas:dial">2' +
- '</otherField>');
- expectMockSendGet();
- done();
- });
- });
-
- const expectGetAppInfoFails = function(done) {
- client.getAppInfo('YouTube').then(
- _ => {
- fail('getAppInfo unexpectedly succeeded.');
- },
- e => {
- expectMockSendGet();
- done();
- });
- };
-
- const testInvalidResponse = function(response, done) {
- setMockXhrResponse(response);
- expectGetAppInfoFails(done);
- };
-
- it('Rejects on invalid response 1', done => {
- testInvalidResponse('blarg', done);
- });
-
- it('Rejects on invalid response 2', done => {
- testInvalidResponse(INVALID_GET_RESPONSE_NO_SERVICE_, done);
- });
-
- it('Rejects on invalid response 3', done => {
- testInvalidResponse(INVALID_GET_RESPONSE_NO_STATE_, done);
- });
-
- it('Rejects on invalid response 4', done => {
- testInvalidResponse(INVALID_GET_RESPONSE_NO_NAME_, done);
- });
-
- it('Rejects on invalid response 5', done => {
- testInvalidResponse(INVALID_GET_RESPONSE_INVALID_STATE_, done);
- });
-
- it('Rejects on invalid response 6', done => {
- testInvalidResponse(INVALID_GET_RESPONSE_INSTALLABLE_, done);
- });
-
- it('Rejects on mismatched app name', done => {
- testInvalidResponse(INVALID_GET_RESPONSE_WRONG_APP_NAME_, done);
- });
-
- it('Rejects on error response', done => {
- setMockXhrErrorResponse();
- expectGetAppInfoFails(done);
- });
-
- it('Rejects on send rejection', done => {
- setMockXhrReject();
- expectGetAppInfoFails(done);
- });
-
- it('Rejects with AppInfoNotFoundError', done => {
- setMockXhrNotFoundResponse();
- client.getAppInfo('YouTube').then(
- _ => {
- fail('getAppInfo unexpectedly succeeded.');
- },
- e => {
- expect(e instanceof DialClient.AppInfoNotFoundError).toBe(true);
- expectMockSendGet();
- done();
- });
- });
- });
-});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider.js
deleted file mode 100644
index f5c471a82a5..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider.js
+++ /dev/null
@@ -1,474 +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.
-
-goog.module('mr.DialProvider');
-goog.module.declareLegacyNamespace();
-
-const Activity = goog.require('mr.dial.Activity');
-const ActivityRecords = goog.require('mr.dial.ActivityRecords');
-const AppDiscoveryService = goog.require('mr.dial.AppDiscoveryService');
-const Assertions = goog.require('mr.Assertions');
-const CancellablePromise = goog.require('mr.CancellablePromise');
-const DeviceCountsProvider = goog.require('mr.DeviceCountsProvider');
-const DialAnalytics = goog.require('mr.DialAnalytics');
-const DialClient = goog.require('mr.dial.Client');
-const DialPresentationUrl = goog.require('mr.dial.PresentationUrl');
-const DialSink = goog.require('mr.dial.Sink');
-const Logger = goog.require('mr.Logger');
-const MediaSourceUtils = goog.require('mr.MediaSourceUtils');
-const PresentationConnectionState = goog.require('mr.PresentationConnectionState');
-const Provider = goog.require('mr.Provider');
-const ProviderCallbacks = goog.require('mr.dial.ProviderCallbacks');
-const ProviderManagerCallbacks = goog.require('mr.ProviderManagerCallbacks');
-const ProviderName = goog.require('mr.ProviderName');
-const Route = goog.require('mr.Route');
-const RouteRequestError = goog.require('mr.RouteRequestError');
-const RouteRequestResultCode = goog.require('mr.RouteRequestResultCode');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const SinkAvailability = goog.require('mr.SinkAvailability');
-const SinkDiscoveryService = goog.require('mr.dial.SinkDiscoveryService');
-const SinkList = goog.require('mr.SinkList');
-const SinkUtils = goog.require('mr.SinkUtils');
-
-/**
- * DIAL implementation of Media Route Provider.
- * @implements {Provider}
- * @implements {ProviderCallbacks}
- * @implements {DeviceCountsProvider}
- */
-const DialProvider = class {
- /**
- * @param {!ProviderManagerCallbacks} providerManagerCallbacks
- * @param {!SinkDiscoveryService=} sinkDiscoveryService
- * @param {!AppDiscoveryService=} appDiscoveryService
- * @final
- */
- constructor(
- providerManagerCallbacks, sinkDiscoveryService = undefined,
- appDiscoveryService = undefined) {
- /** @private @const {!ProviderManagerCallbacks} */
- this.providerManagerCallbacks_ = providerManagerCallbacks;
-
- /** @private @const {!SinkDiscoveryService} */
- this.sinkDiscoveryService_ =
- sinkDiscoveryService || new SinkDiscoveryService(this);
-
- /** @private @const {!ActivityRecords} */
- this.activityRecords_ = new ActivityRecords(this);
-
- /** @private {?AppDiscoveryService} */
- this.appDiscoveryService_ = appDiscoveryService || null;
-
- /** @private @const {?Logger} */
- this.logger_ = Logger.getInstance('mr.DialProvider');
- }
-
- /**
- * @override
- */
- getName() {
- return ProviderName.DIAL;
- }
-
- /**
- * @override
- */
- getDeviceCounts() {
- return this.sinkDiscoveryService_.getDeviceCounts();
- }
-
- /**
- * @override
- */
- initialize(config) {
- const sinkQueryEnabled =
- (config && config.enable_dial_sink_query == false) ? false : true;
- this.logger_.info('Dial sink query enabled: ' + sinkQueryEnabled + '...');
-
- this.activityRecords_.init();
- this.sinkDiscoveryService_.init();
-
- if (sinkQueryEnabled) {
- this.appDiscoveryService_ = this.appDiscoveryService_ ||
- new AppDiscoveryService(this.sinkDiscoveryService_,
- this.activityRecords_);
- this.appDiscoveryService_.init();
- } else {
- this.appDiscoveryService_ = null;
- }
-
- this.maybeStartAppDiscovery_();
- }
-
- /**
- * @override
- */
- getAvailableSinks(sourceUrn) {
- // Prevent SinkDiscoveryService to return cached available sinks.
- if (!this.appDiscoveryService_) {
- return SinkList.EMPTY;
- }
-
- this.logger_.fine('GetAvailableSinks for ' + sourceUrn);
- const dialMediaSource = DialPresentationUrl.create(sourceUrn);
- return dialMediaSource ?
- this.sinkDiscoveryService_.getSinksByAppName(dialMediaSource.appName) :
- SinkList.EMPTY;
- }
-
- /**
- * @override
- */
- startObservingMediaSinks(sourceUrn) {
- if (!this.appDiscoveryService_) {
- return;
- }
-
- const dialMediaSource = DialPresentationUrl.create(sourceUrn);
- if (dialMediaSource) {
- this.appDiscoveryService_.registerApp(dialMediaSource.appName);
- this.maybeStartAppDiscovery_();
- }
- }
-
- /**
- * @override
- */
- stopObservingMediaSinks(sourceUrn) {
- if (!this.appDiscoveryService_) {
- return;
- }
-
- const dialMediaSource = DialPresentationUrl.create(sourceUrn);
- if (dialMediaSource) {
- this.appDiscoveryService_.unregisterApp(dialMediaSource.appName);
- this.maybeStopAppDiscovery_();
- }
- }
-
- /**
- * @override
- */
- startObservingMediaRoutes(sourceUrn) {
- this.maybeStartAppDiscovery_();
- }
-
- /**
- * @override
- */
- stopObservingMediaRoutes(sourceUrn) {
- this.maybeStopAppDiscovery_();
- }
-
- /**
- * @private
- */
- maybeStopAppDiscovery_() {
- if (!this.appDiscoveryService_) {
- return;
- }
-
- if (this.sinkDiscoveryService_.getSinkCount() == 0 ||
- (this.appDiscoveryService_.getAppCount() == 0 &&
- this.activityRecords_.getActivityCount() == 0)) {
- this.appDiscoveryService_.stop();
- }
- }
-
- /**
- * @private
- */
- maybeStartAppDiscovery_() {
- if (!this.appDiscoveryService_) {
- return;
- }
-
- if (this.sinkDiscoveryService_.getSinkCount() > 0 &&
- (this.appDiscoveryService_.getAppCount() > 0 ||
- this.activityRecords_.getActivityCount() > 0)) {
- this.appDiscoveryService_.start();
- }
- }
-
- /**
- * @override
- */
- getSinkById(id) {
- const dialSink = this.sinkDiscoveryService_.getSinkById(id);
- return dialSink ? dialSink.getMrSink() : null;
- }
-
- /**
- * @override
- */
- getRoutes() {
- return this.activityRecords_.getRoutes();
- }
-
- /**
- * @override
- */
- createRoute(
- sourceUrn, sinkId, presentationId, offTheRecord, timeoutMillis,
- opt_origin, opt_tabId) {
- const sink = this.sinkDiscoveryService_.getSinkById(sinkId);
- if (!sink) {
- DialAnalytics.recordCreateRoute(
- DialAnalytics.DialRouteCreation.FAILED_NO_SINK);
- return CancellablePromise.reject(Error('Unkown sink: ' + sinkId));
- }
- SinkUtils.getInstance().recentLaunchedDevice =
- new SinkUtils.DeviceData(sink.getModelName(), sink.getIpAddress());
- const dialMediaSource = DialPresentationUrl.create(sourceUrn);
- if (!dialMediaSource) {
- return CancellablePromise.reject(Error('No app name set.'));
- }
- const appName = dialMediaSource.appName;
- const dialClient = this.newClient_(sink);
-
- return CancellablePromise.forPromise(
- /** @type {!Promise<!Route>} */
- (dialClient.getAppInfo(appName)
- .then(appInfo => {
- if (appInfo.state == DialClient.DialAppState.RUNNING) {
- return dialClient.stopApp(appName);
- }
- })
- .then(() => {
- return dialClient.launchApp(
- appName, dialMediaSource.launchParameter);
- })
- .then(() => {
- return this.addRoute(
- sinkId, sourceUrn, true, appName, presentationId,
- offTheRecord);
- })
- .catch(err => {
- DialAnalytics.recordCreateRoute(
- DialAnalytics.DialRouteCreation.FAILED_LAUNCH_APP);
- throw err;
- })));
- }
-
- /**
- * @override
- */
- joinRoute(
- sourceUrn, presentationId, offTheRecord, timeoutMillis, origin, tabId) {
- return CancellablePromise.reject(Error('Not supported'));
- }
-
- /**
- * @override
- */
- connectRouteByRouteId(sourceUrn, routeId, presentationId, origin, tabId) {
- return CancellablePromise.reject(Error('Not supported'));
- }
-
- /**
- * @override
- */
- detachRoute(routeId) {}
-
- /**
- * @param {string} sinkId
- * @param {?string} sourceUrn
- * @param {boolean} isLocal
- * @param {string} appName
- * @param {string} presentationId
- * @param {boolean} offTheRecord
- * @return {!Route} The route that was just added.
- */
- addRoute(sinkId, sourceUrn, isLocal, appName, presentationId, offTheRecord) {
- DialAnalytics.recordCreateRoute(
- DialAnalytics.DialRouteCreation.ROUTE_CREATED);
- const route = Route.createRoute(
- presentationId, this.getName(), sinkId, sourceUrn, isLocal, appName,
- null);
- route.offTheRecord = offTheRecord;
- this.activityRecords_.add(new Activity(route, appName));
- return route;
- }
-
- /**
- * @override
- */
- onSinkAdded(sink) {
- this.providerManagerCallbacks_.onSinkAvailabilityUpdated(
- this, SinkAvailability.PER_SOURCE);
- if (this.appDiscoveryService_) {
- this.maybeStartAppDiscovery_();
- this.appDiscoveryService_.scanSink(sink);
- }
- this.providerManagerCallbacks_.onSinksUpdated();
- SinkUtils.getInstance().recentDiscoveredDevice =
- new SinkUtils.DeviceData(sink.getModelName(), sink.getIpAddress());
- }
-
- /**
- * @override
- */
- onSinksRemoved(sinks) {
- if (this.sinkDiscoveryService_.getSinkCount() == 0) {
- this.providerManagerCallbacks_.onSinkAvailabilityUpdated(
- this, SinkAvailability.UNAVAILABLE);
- }
- this.maybeStopAppDiscovery_();
- sinks.forEach(sink => {
- this.activityRecords_.removeBySinkId(sink.getId());
- });
- this.providerManagerCallbacks_.onSinksUpdated();
- }
-
- /**
- * @override
- */
- onSinkUpdated(sink) {
- this.providerManagerCallbacks_.onSinksUpdated();
- }
-
- /**
- * @override
- */
- onActivityAdded(activity) {
- this.maybeStartAppDiscovery_();
- this.providerManagerCallbacks_.onRouteAdded(this, activity.route);
- }
-
- /**
- * @override
- */
- onActivityRemoved(activity) {
- const route = activity.route;
- if (route.isLocal) {
- this.providerManagerCallbacks_.onPresentationConnectionStateChanged(
- route.id, PresentationConnectionState.TERMINATED);
- }
- this.maybeStopAppDiscovery_();
- this.providerManagerCallbacks_.onRouteRemoved(this, route);
- }
-
- /**
- * @override
- */
- onActivityUpdated(activity) {
- this.providerManagerCallbacks_.onRouteUpdated(this, activity.route);
- }
-
- /**
- * @override
- */
- terminateRoute(routeId) {
- const activity = this.activityRecords_.getByRouteId(routeId);
- if (!activity) {
- return Promise.reject(new RouteRequestError(
- RouteRequestResultCode.ROUTE_NOT_FOUND,
- 'Route in DIAL provider not found for routeId ' + routeId));
- }
- this.activityRecords_.removeByRouteId(routeId);
- const sink = this.sinkDiscoveryService_.getSinkById(activity.route.sinkId);
- if (!sink) {
- return Promise.reject(new RouteRequestError(
- RouteRequestResultCode.ROUTE_NOT_FOUND,
- 'Sink in DIAL provider not found for sinkId ' +
- activity.route.sinkId));
- }
- return this.newClient_(sink).stopApp(activity.appName);
- }
-
- /**
- * @override
- */
- getMirrorSettings(sinkId) {
- throw new Error('Not implemented.');
- }
-
- /**
- * @override
- */
- getMirrorServiceName(sinkId) {
- return null;
- }
-
- /**
- * @override
- */
- onMirrorActivityUpdated(routeId) {}
-
- /**
- * @override
- */
- sendRouteMessage(routeId, message, opt_extraInfo) {
- return Promise.reject(Error('DIAL sending messages is not supported'));
- }
-
- /**
- * @override
- */
- sendRouteBinaryMessage(routeId, message) {
- return Promise.reject(Error('DIAL sending messages is not supported'));
- }
-
- /**
- * @override
- */
- canRoute(sourceUrn, sinkId) {
- const sink = this.sinkDiscoveryService_.getSinkById(sinkId);
- if (!sink) {
- return false;
- }
-
- if (MediaSourceUtils.isMirrorSource(sourceUrn)) {
- return false;
- }
-
- const dialMediaSource = DialPresentationUrl.create(sourceUrn);
- if (!dialMediaSource) {
- return false;
- }
- return sink.getAppStatus(dialMediaSource.appName) ==
- SinkAppStatus.AVAILABLE;
- }
-
- /**
- * @override
- */
- canJoin(sourceUrn, presentationId, route) {
- return false;
- }
-
- /**
- * @override
- */
- searchSinks(sourceUrn, searchCriteria) {
- // Not implemented.
- return Assertions.rejectNotImplemented();
- }
-
- /**
- * @override
- */
- createMediaRouteController(routeId, controllerRequest, observer) {
- // Not implemented.
- return Assertions.rejectNotImplemented();
- }
-
- /**
- * @override
- */
- provideSinks(sinks) {
- this.sinkDiscoveryService_.addSinks(sinks);
- }
-
- /**
- * @param {!DialSink} sink
- * @return {!DialClient.Client}
- * @private
- */
- newClient_(sink) {
- return new DialClient.Client(sink);
- }
-};
-
-exports = DialProvider;
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider_callbacks.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider_callbacks.js
deleted file mode 100644
index 2c7284922b0..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider_callbacks.js
+++ /dev/null
@@ -1,65 +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.
-
-/**
- * @fileoverview DIAL provider callbacks used for other DIAL services to inform
- * activity or sink updates.
- */
-
-goog.provide('mr.dial.ActivityCallbacks');
-goog.provide('mr.dial.ProviderCallbacks');
-goog.provide('mr.dial.SinkDiscoveryCallbacks');
-
-
-
-/**
- * @record
- */
-mr.dial.ActivityCallbacks = class {
- /**
- * @param {!mr.dial.Activity } activity
- */
- onActivityAdded(activity) {}
-
- /**
- * @param {!mr.dial.Activity } activity
- */
- onActivityRemoved(activity) {}
-
- /**
- * @param {!mr.dial.Activity } activity
- */
- onActivityUpdated(activity) {}
-};
-
-
-
-/**
- * @record
- */
-mr.dial.SinkDiscoveryCallbacks = class {
- /**
- * @param {!mr.dial.Sink} sink Sink that has been added.
- */
- onSinkAdded(sink) {}
-
- /**
- * @param {!Array.<!mr.dial.Sink>} sinks Sinks that have been removed.
- */
- onSinksRemoved(sinks) {}
-
- /**
- * @param {!mr.dial.Sink} sink Sink that has been updated.
- */
- onSinkUpdated(sink) {}
-};
-
-
-
-/**
- * @record
- * @extends {mr.dial.ActivityCallbacks}
- * @extends {mr.dial.SinkDiscoveryCallbacks}
- */
-mr.dial.ProviderCallbacks = class {};
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider_test.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider_test.js
deleted file mode 100644
index c82f8b9931e..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_provider_test.js
+++ /dev/null
@@ -1,256 +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.
-
-goog.module('mr.DialProviderTest');
-goog.setTestOnly('mr.DialProviderTest');
-
-const Activity = goog.require('mr.dial.Activity');
-const DialClient = goog.require('mr.dial.Client');
-const DialProvider = goog.require('mr.DialProvider');
-const DialSink = goog.require('mr.dial.Sink');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const PresentationConnectionState = goog.require('mr.PresentationConnectionState');
-const Route = goog.require('mr.Route');
-const SinkAvailability = goog.require('mr.SinkAvailability');
-
-
-describe('DialProvider tests', function() {
- let provider;
- let mockPmCallbacks;
- const pmCallbackMethods = [
- 'getRouteMessageEventTarget', 'getProviderFromRouteId',
- 'onPresentationConnectionClosed', 'onPresentationConnectionStateChanged',
- 'onRouteMessage', 'onRouteRemoved', 'onRouteAdded', 'onSinksUpdated',
- 'onSinkAvailabilityUpdated'
- ];
- let mockSinkDiscoveryService;
- const sinkDiscoveryServiceMethods =
- ['init', 'getSinkCount', 'init', 'getSinksByAppName', 'getSinkById'];
- let mockAppDiscoveryService;
- const appDiscoveryServiceMethods = [
- 'init', 'start', 'stop', 'registerApp', 'unregisterApp', 'getAppCount',
- 'scanSink'
- ];
- let mockDialClient;
-
- const appInfo = new DialClient.AppInfo();
- const youTubeUrl = 'dial:YouTube?postData=dj0xMjM=';
-
- beforeEach(function() {
- mockPmCallbacks =
- jasmine.createSpyObj('ProviderManagerCallbacks', pmCallbackMethods);
-
- mockSinkDiscoveryService = jasmine.createSpyObj(
- 'SinkDiscoveryService', sinkDiscoveryServiceMethods);
- mockAppDiscoveryService =
- jasmine.createSpyObj('AppDiscoveryService', appDiscoveryServiceMethods);
-
- provider = new DialProvider(
- mockPmCallbacks, mockSinkDiscoveryService, mockAppDiscoveryService);
- provider.initialize({enable_dial_discovery: true});
- expect(mockAppDiscoveryService.init).toHaveBeenCalled();
-
- const fakeDialSink = new DialSink('Fake DIAL sink', 'uniqueId');
- fakeDialSink.setDialAppUrl(youTubeUrl);
- mockDialClient = jasmine.createSpyObj(
- 'dialClient', ['getAppInfo', 'launchApp', 'stopApp']);
- spyOn(DialProvider.prototype, 'newClient_').and.returnValue(mockDialClient);
- mockSinkDiscoveryService.getSinkById.and.returnValue(fakeDialSink);
- appInfo.name = 'YouTube';
- appInfo.state = DialClient.DialAppState.STOPPED;
- mr.DialAnalytics.recordCreateRoute = jasmine.createSpy('recordCreateRoute');
- });
-
- afterEach(function() {
- PersistentDataManager.clear();
- });
-
- describe('startObservingMediaSinks Test', function() {
- it('Handles non-dial sink query', function() {
- provider.startObservingMediaSinks('urn:not-dial:YouTube');
- expect(mockAppDiscoveryService.registerApp).not.toHaveBeenCalled();
- });
-
- it('Handles valid dial sink query, no sinks', function() {
- mockSinkDiscoveryService.getSinkCount.and.returnValue(0);
- mockAppDiscoveryService.getAppCount.and.returnValue(1);
- provider.startObservingMediaSinks(youTubeUrl);
- expect(mockAppDiscoveryService.registerApp)
- .toHaveBeenCalledWith('YouTube');
- expect(mockAppDiscoveryService.start).not.toHaveBeenCalled();
- });
-
- it('Handles valid dial sink query, at least one sink', function() {
- mockSinkDiscoveryService.getSinkCount.and.returnValue(1);
- mockAppDiscoveryService.getAppCount.and.returnValue(1);
- provider.startObservingMediaSinks(youTubeUrl);
- expect(mockAppDiscoveryService.registerApp)
- .toHaveBeenCalledWith('YouTube');
- expect(mockAppDiscoveryService.start).toHaveBeenCalled();
- });
- });
-
- describe('stopObservingMediaSinks Test', function() {
- it('Handles non-dial sink query', function() {
- provider.stopObservingMediaSinks('urn:not-dial:YouTube');
- expect(mockAppDiscoveryService.unregisterApp).not.toHaveBeenCalled();
- });
-
- it('Handles valid dial sink query', function() {
- mockAppDiscoveryService.getAppCount.and.returnValue(0);
- provider.stopObservingMediaSinks(youTubeUrl);
- expect(mockAppDiscoveryService.unregisterApp)
- .toHaveBeenCalledWith('YouTube');
- });
-
- it('Handles valid dial sink query, app query remains', function() {
- mockAppDiscoveryService.getAppCount.and.returnValue(1);
- provider.stopObservingMediaSinks(youTubeUrl);
- expect(mockAppDiscoveryService.unregisterApp)
- .toHaveBeenCalledWith('YouTube');
- });
- });
-
- describe('onPresentationConnectionStateChanged Test', function() {
- it('Changes presentation state to terminated', function() {
- const route = provider.addRoute(
- 'sink1', youTubeUrl, true, 'app1', 'presentationId1');
- provider.onActivityRemoved(new Activity(route, 'app1'));
- expect(mockPmCallbacks.onPresentationConnectionStateChanged)
- .toHaveBeenCalledWith(
- route.id, PresentationConnectionState.TERMINATED);
- expect(mockPmCallbacks.onRouteRemoved).toHaveBeenCalled();
- });
-
- it('Does not change state for non-local presentation', function() {
- const route = provider.addRoute(
- 'sink1', youTubeUrl, false, 'app1', 'presentationId1');
- provider.onActivityRemoved(new Activity(route, 'app1'));
- expect(mockPmCallbacks.onPresentationConnectionStateChanged)
- .not.toHaveBeenCalled();
- expect(mockPmCallbacks.onRouteRemoved).toHaveBeenCalled();
- });
- });
-
- describe('createRoute Test', function() {
- it('Creates a route', function(done) {
- mockDialClient.getAppInfo.and.returnValue(Promise.resolve(appInfo));
- mockDialClient.launchApp.and.returnValue(Promise.resolve());
- provider.createRoute(youTubeUrl, 'sink1', 'presentationId1', false)
- .promise.then(
- route => {
- expect(route.sinkId).toBe('sink1');
- expect(route.mediaSource).toBe(youTubeUrl);
- expect(route.offTheRecord).toBe(false);
- expect(mr.DialAnalytics.recordCreateRoute)
- .toHaveBeenCalledWith(
- mr.DialAnalytics.DialRouteCreation.ROUTE_CREATED);
- done();
- },
- e => {
- done.fail('Unexpected error: ' + e.message);
- });
- });
-
- it('Creates an off-the-record route', function(done) {
- mockDialClient.getAppInfo.and.returnValue(Promise.resolve(appInfo));
- mockDialClient.launchApp.and.returnValue(Promise.resolve());
- provider.createRoute(youTubeUrl, 'sink1', 'presentationId1', true)
- .promise.then(
- route => {
- expect(route.sinkId).toBe('sink1');
- expect(route.mediaSource).toBe(youTubeUrl);
- expect(route.offTheRecord).toBe(true);
- expect(mr.DialAnalytics.recordCreateRoute)
- .toHaveBeenCalledWith(
- mr.DialAnalytics.DialRouteCreation.ROUTE_CREATED);
- done();
- },
- e => {
- done.fail('Unexpected error: ' + e.message);
- });
- });
-
- it('Fails to create a route when get app info fails', function(done) {
- mockDialClient.getAppInfo.and.returnValue(Promise.reject('fail'));
- provider.createRoute(youTubeUrl, 'sink1', 'presentationId1', true)
- .promise.then(done.fail, e => {
- expect(mr.DialAnalytics.recordCreateRoute)
- .toHaveBeenCalledWith(
- mr.DialAnalytics.DialRouteCreation.FAILED_LAUNCH_APP);
- done();
- });
- });
-
- it('Fails to create a route when launch app fails', function(done) {
- mockDialClient.getAppInfo.and.returnValue(Promise.resolve(appInfo));
- mockDialClient.launchApp.and.returnValue(Promise.reject('fail'));
- provider.createRoute(youTubeUrl, 'sink1', 'presentationId1', true)
- .promise.then(done.fail, e => {
- expect(mr.DialAnalytics.recordCreateRoute)
- .toHaveBeenCalledWith(
- mr.DialAnalytics.DialRouteCreation.FAILED_LAUNCH_APP);
- done();
- });
- });
-
- it('Starts and stop app discovery', function() {
- mockSinkDiscoveryService.getSinkCount.and.returnValue(1);
- let appCount = 0;
- mockAppDiscoveryService.getAppCount.and.callFake(() => appCount);
- const route = Route.createRoute(
- 'presentationId', 'providerName', 'sinkId', 'source', true,
- 'description', null);
- const activity = new Activity(route, 'YouTube');
- provider.activityRecords_.add(activity);
- expect(mockAppDiscoveryService.start).toHaveBeenCalled();
-
- appCount++;
- provider.startObservingMediaSinks(youTubeUrl);
- expect(mockAppDiscoveryService.registerApp)
- .toHaveBeenCalledWith('YouTube');
-
- appCount--;
- provider.stopObservingMediaSinks(youTubeUrl);
- expect(mockAppDiscoveryService.stop).not.toHaveBeenCalled();
-
- provider.activityRecords_.removeByRouteId(route.id);
- expect(mockAppDiscoveryService.stop).toHaveBeenCalled();
- });
-
- it('Sets SinkAvailability to UNAVAILABLE if no more sinks', () => {
- mockSinkDiscoveryService.getSinkCount.and.returnValue(0);
- // Note: This should also work if an non-empty list if passed in. For
- // simplicity, an empty list is used here.
- provider.onSinksRemoved([]);
- expect(mockPmCallbacks.onSinkAvailabilityUpdated)
- .toHaveBeenCalledWith(provider, SinkAvailability.UNAVAILABLE);
- });
- });
-
- describe('Disables Dial sink query', function() {
- beforeEach(function() {
- PersistentDataManager.clear();
- provider.initialize({enable_dial_sink_query: false});
- expect(mockAppDiscoveryService.start).not.toHaveBeenCalled();
- });
-
- it('Starting and stopping observing media sinks does nothing', function() {
- provider.startObservingMediaSinks(youTubeUrl);
- expect(mockAppDiscoveryService.registerApp).not.toHaveBeenCalled();
-
- provider.stopObservingMediaSinks(youTubeUrl);
- expect(mockAppDiscoveryService.unregisterApp).not.toHaveBeenCalled();
- });
-
- it('onSinkAdded does not start app discovery', function() {
- const sink = new DialSink('s1', 'sink1');
- provider.onSinkAdded(sink);
- expect(mockAppDiscoveryService.scanSink).not.toHaveBeenCalled();
-
- const sinkList = provider.getAvailableSinks();
- expect(sinkList.sinks.length).toBe(0);
- });
- });
-});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink.js
deleted file mode 100644
index 8cf0e1fe39d..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink.js
+++ /dev/null
@@ -1,309 +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.
-
-goog.module('mr.dial.Sink');
-goog.module.declareLegacyNamespace();
-
-const Sink = goog.require('mr.Sink');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-
-
-/**
- * A wrapper for Sink containing DIAL specific data.
- */
-const DialSink = class {
- /**
- * @param {string} friendlyName
- * @param {string} uniqueId
- * @final
- */
- constructor(friendlyName, uniqueId) {
- /** @private {?string} */
- this.ipAddress_ = null;
-
- /** @private {?number} */
- this.port_ = null;
-
- /** @private {?string} */
- this.dialAppUrl_ = null;
-
- /** @private {?string} */
- this.deviceDescriptionUrl_ = null;
-
- /** @private {?string} */
- this.modelName_ = null;
-
- /** @private @const {!Sink} */
- this.mrSink_ = new Sink(uniqueId, friendlyName);
-
- /**
- * Holds the status of applications that may be available on the sink.
- * Keys are application Names.
- * @private {!Object<string, SinkAppStatus>}
- */
- this.appStatusMap_ = {};
-
- /**
- * Holds the timestamp when the status of applications was set.
- * @private {!Object<string, number>}
- */
- this.appStatusTimeStamp_ = {};
-
- /** @private {boolean} */
- this.supportsAppAvailability_ = false;
- }
-
- /**
- * @return {!Sink}
- */
- getMrSink() {
- return this.mrSink_;
- }
-
- /**
- * @return {string} A human readable name for the sink.
- */
- getFriendlyName() {
- return this.mrSink_.friendlyName;
- }
-
- /**
- * @param {string} friendlyName
- * @return {!mr.dial.Sink} This sink.
- */
- setFriendlyName(friendlyName) {
- this.mrSink_.friendlyName = friendlyName;
- return this;
- }
-
- /**
- * @return {?string} sink model name if known.
- */
- getModelName() {
- return this.modelName_;
- }
-
- /**
- * @param {?string} modelName
- * @return {!mr.dial.Sink} This sink.
- */
- setModelName(modelName) {
- this.modelName_ = modelName;
- return this;
- }
-
- /**
- * @return {string} An identifier for this sink.
- */
- getId() {
- return this.mrSink_.id;
- }
-
- /**
- * @param {string} id
- * @return {!mr.dial.Sink} This sink.
- */
- setId(id) {
- this.mrSink_.id = id;
- return this;
- }
-
- /**
- * @return {boolean} Whether this sink supports queries for DIAL app
- * availability.
- */
- supportsAppAvailability() {
- return this.supportsAppAvailability_;
- }
-
- /**
- * Sets whether this sink supports DIAL app availability queries.
- * @param {boolean} availability
- * @return {!mr.dial.Sink} This sink.
- */
- setSupportsAppAvailability(availability) {
- this.supportsAppAvailability_ = availability;
- return this;
- }
-
- /**
- * Updates sink properties.
- * Fields that can be updated: friendlyName, dialAppUrl_,
- * deviceDescriptionUrl_, ipAddress_, port_.
- * @param {!mr.dial.Sink} sink
- * @return {boolean} Whether the update resulted in changes to the sink.
- */
- update(sink) {
- if (this.getId() != sink.getId()) {
- return false;
- }
-
- let updated = false;
-
- if (this.mrSink_.friendlyName != sink.mrSink_.friendlyName) {
- this.mrSink_.friendlyName = sink.mrSink_.friendlyName;
- updated = true;
- }
-
- if (this.dialAppUrl_ != sink.dialAppUrl_) {
- this.dialAppUrl_ = sink.dialAppUrl_;
- updated = true;
- }
-
- if (this.deviceDescriptionUrl_ != sink.deviceDescriptionUrl_) {
- this.deviceDescriptionUrl_ = sink.deviceDescriptionUrl_;
- updated = true;
- }
-
- if (this.ipAddress_ != sink.ipAddress_) {
- this.ipAddress_ = sink.ipAddress_;
- updated = true;
- }
-
- if (this.port_ != sink.port_) {
- this.port_ = sink.port_;
- updated = true;
- }
-
- return updated;
- }
-
- /**
- * @return {?string} The IP address of the sink, if any.
- */
- getIpAddress() {
- return this.ipAddress_;
- }
-
- /**
- * @param {?string} ipAddress The sink IP address.
- * @return {!mr.dial.Sink} This sink.
- */
- setIpAddress(ipAddress) {
- this.ipAddress_ = ipAddress;
- return this;
- }
-
- /**
- * @return {?number} The port number of the secure channel service.
- */
- getPort() {
- return this.port_;
- }
-
- /**
- * @param {?number} port
- * @return {!mr.dial.Sink} This sink.
- */
- setPort(port) {
- this.port_ = port;
- return this;
- }
-
- /**
- * @return {?string} The DIAL application URL, if any.
- */
- getDialAppUrl() {
- return this.dialAppUrl_;
- }
-
- /**
- * @param {string} url The DIAL app URL.
- * @return {!mr.dial.Sink} This sink.
- */
- setDialAppUrl(url) {
- this.dialAppUrl_ = url;
- return this;
- }
-
- /**
- * @return {?string} The DIAL device description URL, if any.
- */
- getDeviceDescriptionUrl() {
- return this.deviceDescriptionUrl_;
- }
-
- /**
- * @param {string} url The DIAL device description URL.
- * @return {!mr.dial.Sink} This sink.
- */
- setDeviceDescriptionUrl(url) {
- this.deviceDescriptionUrl_ = url;
- return this;
- }
-
- /**
- * Gets the availability of an application.
- * @param {string} appName
- * @return {SinkAppStatus} The status of the application, or null if it was
- * not set.
- */
- getAppStatus(appName) {
- return this.appStatusMap_[appName] || SinkAppStatus.UNKNOWN;
- }
-
- /**
- * Gets the time stamp of the availability of an application was set.
- * @param {string} appName
- * @return {?number} the number of milliseconds between midnight, January 1,
- * 1970 and the current time, or null if availability was not set.
- */
- getAppStatusTimeStamp(appName) {
- return this.appStatusTimeStamp_[appName] || null;
- }
-
- /**
- * Sets the availability of an application.
- * @param {string} appName
- * @param {SinkAppStatus} status
- * @return {!mr.dial.Sink} This sink.
- */
- setAppStatus(appName, status) {
- this.appStatusMap_[appName] = status;
- this.appStatusTimeStamp_[appName] = Date.now();
- return this;
- }
-
- /**
- * Clears all app status from the sink.
- * @return {!mr.dial.Sink} This sink.
- */
- clearAppStatus() {
- this.appStatusMap_ = {};
- this.appStatusTimeStamp_ = {};
- return this;
- }
-
- /**
- * @return {string} String suitable for fine logging.
- */
- toDebugString() {
- return 'name = ' + this.mrSink_.friendlyName +
- (this.ipAddress_ ? ', ip = ' + this.ipAddress_ : '') +
- (this.modelName_ ? ', model = ' + this.modelName_ : '') +
- ', apps = ' + JSON.stringify(this.appStatusMap_);
- }
-
- /**
- * Creates a new sink and copies the fields of the input sink to this.
- * @param {!Object<string, *>} sink The object containing data fields.
- * @return {!mr.dial.Sink} A newly created sink.
- */
- static createFrom(sink) {
- const newSink = new DialSink(sink.mrSink_.friendlyName, '');
- newSink.mrSink_.id = sink.mrSink_.id; // Override the sink ID.
- newSink.ipAddress_ = sink.ipAddress_;
- newSink.port_ = sink.port_;
- newSink.dialAppUrl_ = sink.dialAppUrl_;
- newSink.deviceDescriptionUrl_ = sink.deviceDescriptionUrl_;
- newSink.modelName_ = sink.modelName_;
- newSink.appStatusMap_ = sink.appStatusMap_;
- newSink.appStatusTimeStamp_ = sink.appStatusTimeStamp_;
- newSink.supportsAppAvailability_ = sink.supportsAppAvailability_;
- return newSink;
- }
-};
-
-
-exports = DialSink;
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_discovery_service.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_discovery_service.js
deleted file mode 100644
index 93d062e3519..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_discovery_service.js
+++ /dev/null
@@ -1,334 +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.
-
-goog.module('mr.dial.SinkDiscoveryService');
-goog.module.declareLegacyNamespace();
-
-const DeviceCounts = goog.require('mr.DeviceCounts');
-const DeviceCountsProvider = goog.require('mr.DeviceCountsProvider');
-const DialAnalytics = goog.require('mr.DialAnalytics');
-const DialSink = goog.require('mr.dial.Sink');
-const Logger = goog.require('mr.Logger');
-const PersistentData = goog.require('mr.PersistentData');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const SinkDiscoveryCallbacks = goog.require('mr.dial.SinkDiscoveryCallbacks');
-const SinkList = goog.require('mr.SinkList');
-
-
-/**
- * Implements local discovery using DIAL.
- * DIAL specification:
- * http://www.dial-multiscreen.org/dial-protocol-specification
- * @implements {PersistentData}
- * @implements {DeviceCountsProvider}
- */
-class SinkDiscoveryService {
- /**
- * @param {!SinkDiscoveryCallbacks} sinkCallBacks
- * @final
- */
- constructor(sinkCallBacks) {
- /**
- * @private @const {!SinkDiscoveryCallbacks}
- */
- this.sinkCallBacks_ = sinkCallBacks;
-
- /**
- * @private @const {?Logger}
- */
- this.logger_ = Logger.getInstance('mr.dial.SinkDiscoveryService');
-
- /**
- * The current set of *accessible* receivers, indexed by id.
- * @private @const {!Map<string, !DialSink>}
- */
- this.sinkMap_ = new Map();
-
- /**
- * The most recent snapshot of device counts.
- * Updated when a DIAL onDeviceList or onError event is received.
- * Part of PersistentData.
- * @private {!DeviceCounts}
- */
- this.deviceCounts_ = {availableDeviceCount: 0, knownDeviceCount: 0};
-
- /**
- * The last time device counts were recorded in DialAnalytics.
- * Persistent data.
- * @private {number}
- */
- this.deviceCountMetricsRecordTime_ = 0;
- }
-
- /**
- * Initializes the service. Must be called before any other methods.
- */
- init() {
- PersistentDataManager.register(this);
- }
-
- /**
- * Add |sinks| to sink map. Remove outdated sinks that are in sink map but not
- * in |sinks|.
- * @param {!Array<!mojo.Sink>} sinks list of sinks discovered by Media Router.
- */
- addSinks(sinks) {
- this.logger_.info('addSinks returned ' + sinks.length + ' sinks');
- this.logger_.fine(() => '....the list is: ' + JSON.stringify(sinks));
-
- const oldSinkIds = new Set(this.sinkMap_.keys());
- sinks.forEach(mojoSink => {
- const dialSink = SinkDiscoveryService.convertSink_(mojoSink);
- this.mayAddSink_(dialSink);
- oldSinkIds.delete(dialSink.getId());
- });
-
- let removedSinks = [];
- oldSinkIds.forEach(sinkId => {
- const sink = this.sinkMap_.get(sinkId);
- removedSinks.push(sink);
- this.sinkMap_.delete(sinkId);
- });
-
- if (removedSinks.length > 0) {
- this.sinkCallBacks_.onSinksRemoved(removedSinks);
- }
-
- // Record device count for feedback.
- const sinkCount = this.getSinkCount();
- this.deviceCounts_ = {
- availableDeviceCount: sinkCount,
- knownDeviceCount: sinkCount
- };
- }
-
- /**
- * Updates deviceCounts_ with the given counts, and reports to analytics if
- * applicable.
- * @param {number} availableDeviceCount
- * @param {number} knownDeviceCount
- * @private
- */
- recordDeviceCounts_(availableDeviceCount, knownDeviceCount) {
- this.deviceCounts_ = {
- availableDeviceCount: availableDeviceCount,
- knownDeviceCount: knownDeviceCount
- };
- if (Date.now() - this.deviceCountMetricsRecordTime_ <
- SinkDiscoveryService.DEVICE_COUNT_METRIC_THRESHOLD_MS_) {
- return;
- }
- DialAnalytics.recordDeviceCounts(this.deviceCounts_);
- this.deviceCountMetricsRecordTime_ = Date.now();
- }
-
- /**
- * Adds or updates an existing sink with the given sink.
- * @param {!DialSink} sink The new or updated sink.
- * @private
- */
- mayAddSink_(sink) {
- this.logger_.fine('mayAddSink, id = ' + sink.getId());
- const sinkToUpdate = this.sinkMap_.get(sink.getId());
- if (sinkToUpdate) {
- if (sinkToUpdate.update(sink)) {
- this.logger_.fine('Updated sink ' + sinkToUpdate.getId());
- this.sinkCallBacks_.onSinkUpdated(sinkToUpdate);
- }
- } else {
- this.logger_.fine(
- () => `Adding new sink ${sink.getId()}: ${sink.toDebugString()}`);
- this.sinkMap_.set(sink.getId(), sink);
- this.sinkCallBacks_.onSinkAdded(sink);
- }
- }
-
- /**
- * Converts a mojo.Sink to a DialSink.
- * @param {!mojo.Sink} mojoSink returned by Media Router at browser side.
- * @return {!DialSink} DIAL sink.
- * @private
- */
- static convertSink_(mojoSink) {
-
- const uniqueId = mojoSink.sink_id;
- const extraData = mojoSink.extra_data.dial_media_sink;
- const isDiscoveryOnly =
- SinkDiscoveryService.isDiscoveryOnly_(extraData.model_name);
-
- const ip_address = extraData.ip_address.address_bytes ?
- extraData.ip_address.address_bytes.join('.') :
- extraData.ip_address.address.join('.');
- return new DialSink(mojoSink.name, uniqueId)
- .setIpAddress(ip_address)
- .setDialAppUrl(extraData.app_url.url)
- .setModelName(extraData.model_name)
- .setSupportsAppAvailability(!isDiscoveryOnly);
- }
-
- /**
- * Returns true if DIAL (SSDP) was only used to discover this sink, and it is
- * not expected to support other DIAL features (app discovery, activity
- * discovery, etc.)
- * @param {string} modelName
- * @return {boolean}
- * @private
- */
- static isDiscoveryOnly_(modelName) {
- return SinkDiscoveryService.DISCOVERY_ONLY_RE_.test(modelName);
- }
-
- /**
- * Returns the sink with the given ID, or null if not found.
- * @param {string} sinkId
- * @return {?DialSink}
- */
- getSinkById(sinkId) {
- return this.sinkMap_.get(sinkId) || null;
- }
-
- /**
- * Returns sinks that report availability of the given app name.
- * @param {string} appName
- * @return {!SinkList}
- */
- getSinksByAppName(appName) {
- const sinks = [];
- this.sinkMap_.forEach(dialSink => {
- if (dialSink.getAppStatus(appName) == SinkAppStatus.AVAILABLE)
- sinks.push(dialSink.getMrSink());
- });
- return new SinkList(
- sinks, SinkDiscoveryService.APP_ORIGIN_WHITELIST_[appName]);
- }
-
- /**
- * Returns current sinks.
- * @return {!Array<!DialSink>}
- */
- getSinks() {
- return Array.from(this.sinkMap_.values());
- }
-
- /**
- * @override
- */
- getDeviceCounts() {
- return this.deviceCounts_;
- }
-
- /**
- * @return {number}
- */
- getSinkCount() {
- return this.sinkMap_.size;
- }
-
- /**
- * Invoked when the app status of a sink changes.
- * @param {string} appName
- * @param {!DialSink} sink The sink whose status changed.
- */
- onAppStatusChanged(appName, sink) {
- this.sinkCallBacks_.onSinkUpdated(sink);
- }
-
- /**
- * @override
- */
- getStorageKey() {
- return 'dial.DialSinkDiscoveryService';
- }
-
- /**
- * @override
- */
- getData() {
- return [
- new SinkDiscoveryService.PersistentData_(
- Array.from(this.sinkMap_), this.deviceCounts_),
- {'deviceCountMetricsRecordTime': this.deviceCountMetricsRecordTime_}
- ];
- }
-
- /**
- * @override
- */
- loadSavedData() {
- const tempData =
- /** @type {?SinkDiscoveryService.PersistentData_} */ (
- PersistentDataManager.getTemporaryData(this));
- if (tempData) {
- for (const entry of tempData.sinks) {
- this.sinkMap_.set(entry[0], DialSink.createFrom(entry[1]));
- }
- this.deviceCounts_ = tempData.deviceCounts;
- }
-
- const permanentData = PersistentDataManager.getPersistentData(this);
- if (permanentData) {
- this.deviceCountMetricsRecordTime_ =
- permanentData['deviceCountMetricsRecordTime'];
- }
- }
-}
-
-
-/**
- * @private @const {!Object<string, !Array<string>>}
- */
-SinkDiscoveryService.APP_ORIGIN_WHITELIST_ = {
- 'YouTube': [
- 'https://tv.youtube.com', 'https://tv-green-qa.youtube.com',
- 'https://tv-release-qa.youtube.com', 'https://web-green-qa.youtube.com',
- 'https://web-release-qa.youtube.com', 'https://www.youtube.com'
- ],
- 'Netflix': ['https://www.netflix.com'],
- 'Pandora': ['https://www.pandora.com'],
- 'Radio': ['https://www.pandora.com'],
- 'Hulu': ['https://www.hulu.com'],
- 'Vimeo': ['https://www.vimeo.com'],
- 'Dailymotion': ['https://www.dailymotion.com'],
- 'com.dailymotion': ['https://www.dailymotion.com'],
-};
-
-
-/**
- * Matches DIAL model names that only support discovery.
-
- * @private @const {!RegExp}
- */
-SinkDiscoveryService.DISCOVERY_ONLY_RE_ =
- new RegExp('Eureka Dongle|Chromecast Audio|Chromecast Ultra', 'i');
-
-/**
- * How long to wait between device counts metrics are recorded. Set to 1 hour.
- * @private @const {number}
- */
-SinkDiscoveryService.DEVICE_COUNT_METRIC_THRESHOLD_MS_ = 60 * 60 * 1000;
-
-
-/**
- * @private
- */
-SinkDiscoveryService.PersistentData_ = class {
- /**
- * @param {!Array} sinks
- * @param {!DeviceCounts} deviceCounts
- */
- constructor(sinks, deviceCounts) {
- /**
- * @const {!Array}
- */
- this.sinks = sinks;
-
- /**
- * @const {!DeviceCounts}
- */
- this.deviceCounts = deviceCounts;
- }
-};
-
-exports = SinkDiscoveryService;
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_discovery_service_test.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_discovery_service_test.js
deleted file mode 100644
index 1aad198346c..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_discovery_service_test.js
+++ /dev/null
@@ -1,163 +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.
-
-goog.module('mr.dial.SinkDiscoveryServiceTest');
-goog.setTestOnly('mr.dial.SinkDiscoveryServiceTest');
-
-const DialAnalytics = goog.require('mr.DialAnalytics');
-const PersistentDataManager = goog.require('mr.PersistentDataManager');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-const SinkDiscoveryService = goog.require('mr.dial.SinkDiscoveryService');
-const UnitTestUtils = goog.require('mr.UnitTestUtils');
-
-describe('DIAL SinkDiscoveryService Tests', function() {
- let service;
- let mockClock;
- let mockSinkCallbacks;
-
- beforeEach(function() {
- mockClock = UnitTestUtils.useMockClockAndPromises();
- mockSinkCallbacks = jasmine.createSpyObj(
- 'SinkCallbacks', ['onSinkAdded', 'onSinksRemoved', 'onSinkUpdated']);
-
- chrome.metricsPrivate = {
- recordTime: jasmine.createSpy('recordTime'),
- recordMediumTime: jasmine.createSpy('recordMediumTime'),
- recordLongTime: jasmine.createSpy('recordLongTime'),
- recordUserAction: jasmine.createSpy('recordUserAction')
- };
-
- service = new SinkDiscoveryService(mockSinkCallbacks);
- spyOn(DialAnalytics, 'recordDeviceCounts');
- });
-
- afterEach(function() {
- UnitTestUtils.restoreRealClockAndPromises();
- PersistentDataManager.clear();
- });
-
-
- /**
- * Creates mojo sink instances.
- * @param {number} numSinks The number of mojo sinks to create.
- * @return {!Array<!mojo.Sink>} The mojo sinks.
- */
- function createMojoSinks(numSinks) {
- const mojoSinks = [];
- for (var i = 1; i <= numSinks; i++) {
- const dialMediaSink = {
- ip_address: {address_bytes: [127, 0, 0, i]},
- model_name: 'Eureka Dongle',
- app_url: {url: 'http://127.0.0.' + i + ':8008/apps'}
- };
-
- mojoSinks.push({
- sink_id: 'sinkId ' + i,
- name: 'TV ' + i,
- extra_data: {dial_media_sink: dialMediaSink}
- });
- }
- return mojoSinks;
- }
-
- describe('addSinks tests', function() {
- beforeEach(function() {
- service.init();
- });
-
- it('add mojo sinks to sink map', function() {
- expect(service.getSinks().length).toBe(0);
- const mojoSinks = createMojoSinks(1);
- service.addSinks(mojoSinks);
-
- // sinks were added
- const actualSinks = service.getSinks();
- expect(actualSinks.length).toBe(1);
-
- const actualSink = actualSinks[0];
- const mojoSink = mojoSinks[0];
- const extraData = mojoSink.extra_data.dial_media_sink;
- expect(actualSink.getFriendlyName()).toEqual(mojoSink.name);
- expect(actualSink.getIpAddress())
- .toEqual(extraData.ip_address.address_bytes.join('.'));
- expect(actualSink.getDialAppUrl()).toEqual(extraData.app_url.url);
- expect(actualSink.getModelName()).toEqual(extraData.model_name);
- expect(actualSink.supportsAppAvailability()).toEqual(false);
-
- // add-sink-events were fired.
- expect(mockSinkCallbacks.onSinkAdded.calls.count()).toBe(1);
- expect(mockSinkCallbacks.onSinksRemoved.calls.count()).toBe(0);
- });
-
- it('remove outdated sinks', function() {
- expect(service.getSinks().length).toBe(0);
- const mojoSinks = createMojoSinks(3);
- // First round discover sink 1, 2, 3
- service.addSinks(mojoSinks);
-
- // Second round discover sink 1
- const mojoSinks2 = createMojoSinks(1);
- service.addSinks(mojoSinks2);
- expect(mockSinkCallbacks.onSinkAdded.calls.count()).toBe(3);
-
- // 2 devices were removed
- expect(mockSinkCallbacks.onSinksRemoved.calls.count()).toBe(1);
- const sinks = mockSinkCallbacks.onSinksRemoved.calls.argsFor(0)[0];
- expect(sinks.length).toBe(2);
- expect(sinks[0].getFriendlyName()).toEqual(mojoSinks[1].name);
- expect(sinks[1].getFriendlyName()).toEqual(mojoSinks[2].name);
-
- expect(mockSinkCallbacks.onSinkUpdated.calls.count()).toBe(0);
- });
-
- it('Gets sinks by app name', function() {
- const mojoSinks = createMojoSinks(3);
- service.addSinks(mojoSinks);
- service.getSinkById(mojoSinks[0].sink_id)
- .setAppStatus('YouTube', SinkAppStatus.AVAILABLE);
- service.getSinkById(mojoSinks[1].sink_id)
- .setAppStatus('Netflix', SinkAppStatus.AVAILABLE);
- service.getSinkById(mojoSinks[1].sink_id)
- .setAppStatus('YouTube', SinkAppStatus.AVAILABLE);
- service.getSinkById(mojoSinks[2].sink_id)
- .setAppStatus('Pandora', SinkAppStatus.UNAVAILABLE);
- expect(service.getSinksByAppName('YouTube').sinks.length).toBe(2);
- expect(service.getSinksByAppName('Netflix').sinks.length).toBe(1);
- expect(service.getSinksByAppName('Netflix').sinks[0].id)
- .toEqual(mojoSinks[1].sink_id);
- expect(service.getSinksByAppName('Pandora').sinks.length).toBe(0);
- });
-
- });
-
- it('Saves PersistentData without any data', function() {
- service.init();
- expect(service.getSinks()).toEqual([]);
- PersistentDataManager.suspendForTest();
- service = new SinkDiscoveryService(mockSinkCallbacks);
- service.loadSavedData();
- expect(service.getSinks()).toEqual([]);
- });
-
- it('Saves PersistentData with data', function() {
- service.init();
- service.addSinks(createMojoSinks(3));
- mockClock.tick(1);
- const sinks = service.getSinks();
- expect(sinks.length).toBe(3);
- const expectedDeviceCounts = {availableDeviceCount: 3, knownDeviceCount: 3};
- expect(service.getDeviceCounts()).toEqual(expectedDeviceCounts);
-
- PersistentDataManager.suspendForTest();
- service = new SinkDiscoveryService(mockSinkCallbacks);
- service.loadSavedData();
- const restoredSinks = service.getSinks();
- expect(restoredSinks.length).toBe(3);
- expect(service.getDeviceCounts()).toEqual(expectedDeviceCounts);
- for (let index = 0; index < 3; index++) {
- expect(sinks[0].getId()).toEqual(restoredSinks[0].getId());
- }
- });
-
-});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_test.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_test.js
deleted file mode 100644
index 03a467550bd..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/dial_sink_test.js
+++ /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.
-
-goog.module('mr.dial.SinkTest');
-goog.setTestOnly('mr.dial.SinkTest');
-
-const DialSink = goog.require('mr.dial.Sink');
-const MockClock = goog.require('mr.MockClock');
-const Sink = goog.require('mr.Sink');
-const SinkAppStatus = goog.require('mr.dial.SinkAppStatus');
-
-describe('DIAL Sink Tests', function() {
- let mockClock;
-
- beforeEach(function() {
- mockClock = new MockClock(true);
- });
-
- afterEach(function() {
- mockClock.uninstall();
- });
-
- it('Gets and sets fields', function() {
- const sink = new DialSink('name', 'id1');
- expect(sink.getMrSink()).toEqual(new Sink('id1', 'name'));
-
- expect(sink.getId()).toEqual('id1');
- sink.setId('id2');
- expect(sink.getId()).toEqual('id2');
-
- expect(sink.getIpAddress()).toBeNull();
- sink.setIpAddress('192.168.111.1');
- expect(sink.getIpAddress()).toEqual('192.168.111.1');
-
- expect(sink.getDialAppUrl()).toBeNull();
- sink.setDialAppUrl('http://192.168.111.1/apps');
- expect(sink.getDialAppUrl()).toEqual('http://192.168.111.1/apps');
-
- expect(sink.getDeviceDescriptionUrl()).toBeNull();
- sink.setDeviceDescriptionUrl('http://192.168.111.1/desc');
- expect(sink.getDeviceDescriptionUrl()).toEqual('http://192.168.111.1/desc');
-
- expect(sink.getModelName()).toBeNull();
- sink.setModelName('chromecast');
- expect(sink.getModelName()).toEqual('chromecast');
-
- expect(sink.getFriendlyName()).toEqual('name');
- sink.setFriendlyName('newname');
- expect(sink.getFriendlyName()).toEqual('newname');
-
- expect(sink.getPort()).toEqual(null);
- sink.setPort(8009);
- expect(sink.getPort()).toEqual(8009);
- });
-
- it('Gets and sets sink app status', function() {
- const sink = new DialSink('name', 'uniqueId');
- expect(sink.getAppStatus('youtube')).toBe(SinkAppStatus.UNKNOWN);
- expect(sink.getAppStatusTimeStamp('youtube')).toBe(null);
-
- mockClock.tick(10);
- const now1 = Date.now();
- sink.setAppStatus('youtube', SinkAppStatus.AVAILABLE);
- mockClock.tick(10);
- const now2 = Date.now();
- sink.setAppStatus('app2', SinkAppStatus.UNAVAILABLE);
- expect(sink.getAppStatus('youtube')).toBe(SinkAppStatus.AVAILABLE);
- expect(sink.getAppStatusTimeStamp('youtube')).toBe(now1);
- expect(sink.getAppStatus('app2')).toBe(SinkAppStatus.UNAVAILABLE);
- expect(sink.getAppStatusTimeStamp('app2')).toBe(now2);
-
- sink.clearAppStatus();
- expect(sink.getAppStatus('youtube')).toBe(SinkAppStatus.UNKNOWN);
- expect(sink.getAppStatusTimeStamp('youtube')).toBe(null);
- expect(sink.getAppStatus('app2')).toBe(SinkAppStatus.UNKNOWN);
- expect(sink.getAppStatusTimeStamp('app2')).toBe(null);
- });
-
- it('Updates sink from another sink', function() {
- const sink = new DialSink('name', 'uniqueId')
- .setDialAppUrl('http://192.168.111.1/apps')
- .setPort(8009)
- .setDeviceDescriptionUrl('http://192.168.111.1/desc');
-
- let updatedSink = new DialSink('name2', 'uniqueId');
- expect(sink.update(updatedSink)).toBe(true);
- expect(sink.getFriendlyName()).toEqual('name2');
-
- updatedSink = new DialSink('name', 'uniqueId')
- .setDialAppUrl('http://192.168.111.1/apps/app2');
- expect(sink.update(updatedSink)).toBe(true);
- expect(sink.getDialAppUrl()).toEqual('http://192.168.111.1/apps/app2');
-
- updatedSink = new DialSink('name', 'uniqueId').setId('id2');
- expect(sink.update(updatedSink)).toBe(false);
- });
-
- it('Updates ip address', function() {
- const sink = new DialSink('name', 'uniqueId').setIpAddress('192.168.111.1');
- const updatedSink =
- new DialSink('name', 'uniqueId').setIpAddress('192.168.111.2');
- expect(sink.update(updatedSink)).toBe(true);
- expect(sink.getIpAddress()).toEqual('192.168.111.2');
- });
-
- it('Updates device description url', function() {
- const sink = new DialSink('name', 'uniqueId')
- .setDeviceDescriptionUrl('http://192.168.111.1/desc');
- const updatedSink =
- new DialSink('name', 'uniqueId')
- .setDeviceDescriptionUrl('http://192.168.111.2/desc');
- expect(sink.update(updatedSink)).toBe(true);
- expect(sink.getDeviceDescriptionUrl()).toEqual('http://192.168.111.2/desc');
- });
-
- it('Creates sink from an Object', function() {
- const sink = new DialSink('name', 'uniqueId')
- .setDialAppUrl('http://192.168.111.1/apps')
- .setPort(8009)
- .setDeviceDescriptionUrl('http://192.168.111.1/desc')
- .setAppStatus('youtube', SinkAppStatus.AVAILABLE)
- .setIpAddress('192.168.111.1')
- .setModelName('chromecast');
- expect(DialSink.createFrom(sink)).toEqual(sink);
- });
-});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/presentation_url.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/presentation_url.js
deleted file mode 100644
index 203b40e134f..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/presentation_url.js
+++ /dev/null
@@ -1,146 +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.
-
-goog.module('mr.dial.PresentationUrl');
-
-const Logger = goog.require('mr.Logger');
-const base64 = goog.require('mr.base64');
-
-
-/**
- * Represents a DIAL media source containing information specific to a DIAL
- * launch.
- */
-const PresentationUrl = class {
- /**
- * @param {string} appName The DIAL application name.
- * @param {string=} launchParameter DIAL application launch parameter.
- */
- constructor(appName, launchParameter = '') {
- /** @const {string} */
- this.appName = appName;
- /** @const {string} */
- this.launchParameter = launchParameter;
- }
-
- /**
- * Generates a DIAL Presentation URL using given parameters.
- * @param {string} dialAppName Name of the DIAL app.
- * @param {?string} dialPostData base-64 encoded string of the data for the
- * DIAL launch.
- * @return {string}
- */
- static getPresentationUrlAsString(dialAppName, dialPostData) {
- const url = new URL('dial:' + dialAppName);
- if (dialPostData) {
- url.searchParams.set('postData', dialPostData);
- }
- return url.toString();
- }
-
- /**
- * Constructs a DIAL media source from a URL. The URL can take on the new
- * format (with dial: protocol) or the old format (with https: protocol).
- * @param {string} urlString The media source URL.
- * @return {?PresentationUrl} A DIAL media source if the parse was
- * successful, null otherwise.
- */
- static create(urlString) {
- let url;
- try {
- url = new URL(urlString);
- } catch (err) {
- PresentationUrl.logger_.info('Invalid URL: ' + urlString);
- return null;
- }
- switch (url.protocol) {
- case 'dial:':
- return PresentationUrl.parseDialUrl_(url);
- case 'https:':
-
- return PresentationUrl.parseLegacyUrl_(url);
- default:
- PresentationUrl.logger_.fine('Unhandled protocol: ' + url.protocol);
- return null;
- }
- }
-
- /**
- * Parses the given URL using the new DIAL URL format, which takes the form:
- * dial:<App name>?postData=<base64-encoded launch parameters>
- * @param {!URL} url
- * @return {?PresentationUrl}
- * @private
- */
- static parseDialUrl_(url) {
- const appName = url.pathname;
- if (!appName.match(/^\w+$/)) {
- PresentationUrl.logger_.warning('Invalid app name: ' + appName);
- return null;
- }
- let postData = url.searchParams.get('postData') || undefined;
- if (postData) {
- try {
- postData = base64.decodeString(postData);
- } catch (err) {
- PresentationUrl.logger_.warning(
- 'Invalid base64 encoded postData:' + postData);
- return null;
- }
- }
- return new PresentationUrl(appName, postData);
- }
-
- /**
- * Parses the given URL using the legacy format specified in
- * http://goo.gl/8qKAE7
- * Example:
- * http://www.youtube.com/tv#__dialAppName__=YouTube/__dialPostData__=dj0xMjM=
- * @param {!URL} url
- * @return {?PresentationUrl}
- * @private
- */
- static parseLegacyUrl_(url) {
- // Parse URI and get fragment.
- const fragment = url.hash;
- if (!fragment) return null;
- let appName = PresentationUrl.APP_NAME_REGEX_.exec(fragment);
- appName = appName ? appName[1] : null;
- if (!appName) return null;
- appName = decodeURIComponent(appName);
-
- let postData = PresentationUrl.LAUNCH_PARAM_REGEX_.exec(fragment);
- postData = postData ? postData[1] : undefined;
- if (postData) {
- try {
- postData = base64.decodeString(postData);
- } catch (err) {
- PresentationUrl.logger_.warning(
- 'Invalid base64 encoded postData:' + postData);
- return null;
- }
- }
- return new PresentationUrl(appName, postData);
- }
-};
-
-
-/** @const @private {?Logger} */
-PresentationUrl.logger_ = Logger.getInstance('mr.dial.PresentationUrl');
-
-
-/** @const {string} */
-PresentationUrl.URN_PREFIX = 'urn:dial-multiscreen-org:dial:application:';
-
-
-/** @private @const {!RegExp} */
-PresentationUrl.APP_NAME_REGEX_ =
- /__dialAppName__=([A-Za-z0-9-._~!$&'()*+,;=%]+)/;
-
-
-/** @private @const {!RegExp} */
-PresentationUrl.LAUNCH_PARAM_REGEX_ = /__dialPostData__=([A-Za-z0-9]+={0,2})/;
-
-
-exports = PresentationUrl;
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/presentation_url_test.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/presentation_url_test.js
deleted file mode 100644
index 4477e5ee404..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/presentation_url_test.js
+++ /dev/null
@@ -1,75 +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.
-
-goog.module('PresentationUrlTest');
-goog.setTestOnly('PresentationUrlTest');
-
-const PresentationUrl = goog.require('mr.dial.PresentationUrl');
-
-describe('Tests PresentationUrl', function() {
- it('Does not create from empty input', function() {
- expect(PresentationUrl.create('')).toBeNull();
- });
-
- it('Creates from a valid URL', function() {
- expect(PresentationUrl.create(
- 'https://www.youtube.com/tv#__dialAppName__=YouTube'))
- .toEqual(new PresentationUrl('YouTube'));
- });
-
- it('Creates from a valid URL with launch parameters', function() {
- expect(PresentationUrl.create(
- 'https://www.youtube.com/tv#' +
- '__dialAppName__=YouTube/__dialPostData__=dj0xMjM='))
- .toEqual(new PresentationUrl('YouTube', 'v=123'));
- expect(PresentationUrl.create(
- 'https://www.youtube.com/tv#' +
- '__dialAppName__=YouTube/__dialPostData__=dj1NSnlKS3d6eEZwWQ=='))
- .toEqual(new PresentationUrl('YouTube', 'v=MJyJKwzxFpY'));
- });
-
- it('Does not create from an invalid URL', function() {
- expect(PresentationUrl.create(
- 'https://www.youtube.com/tv#___emanPpaLiad__=YouTube'))
- .toBeNull();
- });
-
- it('Does not create from an invalid postData', function() {
- expect(PresentationUrl.create(
- 'https://www.youtube.com/tv#___emanPpaLiad__=YouTube' +
- '/__dialPostData__=dj1=N'))
- .toBeNull();
- });
-
- it('Creates from DIAL URL', () => {
- expect(PresentationUrl.create('dial:YouTube'))
- .toEqual(new PresentationUrl('YouTube'));
- expect(PresentationUrl.create('dial:YouTube?foo=bar'))
- .toEqual(new PresentationUrl('YouTube'));
- expect(PresentationUrl.create('dial:YouTube?foo=bar&postData=dj0xMjM='))
- .toEqual(new PresentationUrl('YouTube', 'v=123'));
- expect(PresentationUrl.create('dial:YouTube?postData=dj0xMjM%3D'))
- .toEqual(new PresentationUrl('YouTube', 'v=123'));
- });
-
- it('Does not create from invalid DIAL URL', () => {
- expect(PresentationUrl.create('dial:')).toBeNull();
- expect(PresentationUrl.create('dial://')).toBeNull();
- expect(PresentationUrl.create('dial://YouTube')).toBeNull();
- expect(
- PresentationUrl.create('dial:YouTube?postData=notEncodedProperly111'))
- .toBeNull();
- });
-
- it('Does not create from URL of unknown protocol', () => {
- expect(PresentationUrl.create('unknown:YouTube')).toBeNull();
- });
-
- it('getPresentationUrl returns DIAL presentation URLs', () => {
- expect(PresentationUrl.getPresentationUrlAsString('YouTube', null))
- .toEqual('dial:YouTube');
- expect(PresentationUrl.getPresentationUrlAsString('YouTube', 'dj0xMjM='))
- .toEqual('dial:YouTube?postData=dj0xMjM%3D');
- });
-});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/sink_app_status.js b/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/sink_app_status.js
deleted file mode 100644
index 5acd9a9a8fa..00000000000
--- a/chromium/chrome/browser/resources/media_router/extension/src/providers/dial/sink_app_status.js
+++ /dev/null
@@ -1,23 +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.
-
-/**
- * @fileoverview The availability of an app on a sink.
- */
-
-goog.provide('mr.dial.SinkAppStatus');
-
-
-/**
- * Tracks the availability of an app on a sink. Apps start out in an
- * UNKNOWN status and are changed to AVAILABLE or UNAVAILABLE once the status is
- * known, i.e. after we query the sink for the app.
- *
- * @enum {string}
- */
-mr.dial.SinkAppStatus = {
- AVAILABLE: 'available',
- UNAVAILABLE: 'unavailable',
- UNKNOWN: 'unknown'
-};
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/utils/analytics.js b/chromium/chrome/browser/resources/media_router/extension/src/utils/analytics.js
index 8761cc404d7..dc7dcfa99bd 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/utils/analytics.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/utils/analytics.js
@@ -218,10 +218,6 @@ mr.LongTiming.logger_ = mr.Logger.getInstance('mr.LongTiming');
mr.LongTiming.ONE_HOUR_ = 60 * 60 * 1000;
-/** @const {*} */
-mr.Analytics = {};
-
-
/**
* @const {mr.Logger}
* @private
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics.js b/chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics.js
index f9fbde5e388..ce105f0fb7a 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics.js
@@ -23,8 +23,8 @@ mr.EventAnalytics.Event = {
MEDIA_ROUTER: 0,
CAST_CHANNEL_ON_ERROR: 1,
CAST_CHANNEL_ON_MESSAGE: 2,
- DIAL_ON_DEVICE_LIST: 3,
- DIAL_ON_ERROR: 4,
+ DIAL_ON_DEVICE_LIST: 3, // Obsolete
+ DIAL_ON_ERROR: 4, // Obsolete
GCM_ON_MESSAGE: 5,
IDENTITY_ON_SIGN_IN_CHANGED: 6,
MDNS_ON_SERVICE_LIST: 7,
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics_test.js b/chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics_test.js
index 5be671d2ccb..b0b7bec2578 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics_test.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/utils/event_analytics_test.js
@@ -15,13 +15,12 @@ describe('Tests EventAnalytics', () => {
describe('Test recordEvent', () => {
it('should record only the first event', () => {
spyOn(mr.Analytics, 'recordEnum');
- mr.EventAnalytics.recordEvent(mr.EventAnalytics.Event.DIAL_ON_ERROR);
mr.EventAnalytics.recordEvent(mr.EventAnalytics.Event.TABS_ON_UPDATED);
expect(mr.Analytics.recordEnum.calls.count()).toEqual(1);
expect(mr.Analytics.recordEnum)
.toHaveBeenCalledWith(
'MediaRouter.Provider.WakeEvent',
- mr.EventAnalytics.Event.DIAL_ON_ERROR, mr.EventAnalytics.Event);
+ mr.EventAnalytics.Event.TABS_ON_UPDATED, mr.EventAnalytics.Event);
});
});
});
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils.js b/chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils.js
index e0392b46cf4..e24ac97eec0 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils.js
@@ -11,8 +11,6 @@ goog.provide('mr.MediaSourceUtils');
goog.require('mr.Config');
-
-
/**
* @param {string} sourceUrn
* @return {boolean} True if it is a mirror URN.
@@ -30,20 +28,19 @@ mr.MediaSourceUtils.isMirrorSource = function(sourceUrn) {
* is not a Cast custom receiver app.
*/
mr.MediaSourceUtils.isPresentationSource = function(sourceUrn) {
-
- if (!sourceUrn.startsWith('http:') && !sourceUrn.startsWith('https:')) {
+ try {
+ const url = new URL(sourceUrn);
+ // Protocol must be http or https.
+ if (url.protocol != 'http:' && url.protocol != 'https:') {
+ return false;
+ }
+
+ // Must not be a custom Cast receiver app.
+ return url.hash.indexOf(mr.MediaSourceUtils.CAST_APP_ID_) == -1;
+ } catch (err) {
+ // Invalid URL.
return false;
}
- // Use the DOM to parse sourceUrn.
- const link = document.createElement('a');
- link.href = sourceUrn;
- // Protocol must be http or https.
- if (link.protocol != 'http:' && link.protocol != 'https:') {
- return false;
- }
-
- // Must not be a custom Cast receiver app.
- return link.hash.indexOf(mr.MediaSourceUtils.CAST_APP_ID_) == -1;
};
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils_test.js b/chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils_test.js
index 9647921874f..cc1a5241f28 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils_test.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/utils/media_source_utils_test.js
@@ -37,6 +37,9 @@ describe('Tests MediaSourceUtils', function() {
});
it('should return false for cast receiver app', function() {
+ expect(mr.MediaSourceUtils.isPresentationSource('cast:deadbeef'))
+ .toBe(false);
+ // Legacy URL, no longer used by the SDK.
expect(mr.MediaSourceUtils.isPresentationSource(
'http://www.google.com/cast#__castAppId__=deadbeef'))
.toBe(false);
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/utils/unit_test_utils.js b/chromium/chrome/browser/resources/media_router/extension/src/utils/unit_test_utils.js
index f154aff875c..4ec4440ab82 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/utils/unit_test_utils.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/utils/unit_test_utils.js
@@ -153,7 +153,7 @@ mr.UnitTestUtils.mockChromeApi = function() {
},
sendMessage: jasmine.createSpy('chrome.runtime.sendMessage spy'),
},
- mdns: {onSerivceList: jasmine.createSpy('chrome.mdns.onServiceList spy')},
+ mdns: {onServiceList: jasmine.createSpy('chrome.mdns.onServiceList spy')},
metricsPrivate: {
recordMediumTime:
jasmine.createSpy('chrome.metricsPrivate.recordMediumTime spy'),
diff --git a/chromium/chrome/browser/resources/media_router/extension/src/webrtc/peer_connection_analytics.js b/chromium/chrome/browser/resources/media_router/extension/src/webrtc/peer_connection_analytics.js
index 69b5e3fabd8..6664f8a709c 100644
--- a/chromium/chrome/browser/resources/media_router/extension/src/webrtc/peer_connection_analytics.js
+++ b/chromium/chrome/browser/resources/media_router/extension/src/webrtc/peer_connection_analytics.js
@@ -11,10 +11,6 @@ goog.provide('mr.webrtc.PeerConnectionAnalytics');
goog.require('mr.Timing');
-/** @const {*} */
-mr.webrtc.PeerConnectionAnalytics = {};
-
-
/**
* Histogram name for time taken to gather ICE candidates, from the start of
* candidate gethering to the time the last candidate is reported.
diff --git a/chromium/chrome/browser/resources/media_router/media_router_internals.css b/chromium/chrome/browser/resources/media_router/media_router_internals.css
index 4de242fd2e8..0b27f4ace25 100644
--- a/chromium/chrome/browser/resources/media_router/media_router_internals.css
+++ b/chromium/chrome/browser/resources/media_router/media_router_internals.css
@@ -2,6 +2,11 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
-#sink-status-div {
+body {
+ font-size: large;
+}
+
+.status {
+ font-family: monospace;
white-space: pre-wrap;
}
diff --git a/chromium/chrome/browser/resources/media_router/media_router_internals.html b/chromium/chrome/browser/resources/media_router/media_router_internals.html
index 751c30eae0d..1668cf472c9 100644
--- a/chromium/chrome/browser/resources/media_router/media_router_internals.html
+++ b/chromium/chrome/browser/resources/media_router/media_router_internals.html
@@ -2,10 +2,14 @@
<html lang="en">
<head>
<meta charset="utf-8">
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<link rel="stylesheet" href="media_router_internals.css">
<script type="module" src="media_router_internals.js"></script>
</head>
<body>
- <div id="sink-status-div"></div>
+ <h1>Media Router</h1>
+ <div id="sink-status-div" class="status"></div>
+ <h1>Cast Media Route Provider</h1>
+ <div id="cast-status-div" class="status"></div>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/media_router/media_router_internals.js b/chromium/chrome/browser/resources/media_router/media_router_internals.js
index 28e32f80548..2e96359800c 100644
--- a/chromium/chrome/browser/resources/media_router/media_router_internals.js
+++ b/chromium/chrome/browser/resources/media_router/media_router_internals.js
@@ -7,8 +7,12 @@ import {$} from 'chrome://resources/js/util.m.js';
// Handles user events for the Media Router Internals UI.
document.addEventListener('DOMContentLoaded', function() {
- sendWithPromise('getStatus').then(status => {
- const jsonStatus = JSON.stringify(status, null, /* spacing level = */ 2);
- $('sink-status-div').textContent = jsonStatus;
+ sendWithPromise('getState').then(status => {
+ $('sink-status-div').textContent =
+ JSON.stringify(status, null, /* spacing level = */ 2);
+ });
+ sendWithPromise('getProviderState', 'CAST').then(status => {
+ $('cast-status-div').textContent =
+ JSON.stringify(status, null, /* spacing level = */ 2);
});
});
diff --git a/chromium/chrome/browser/resources/net_internals/browser_bridge.js b/chromium/chrome/browser/resources/net_internals/browser_bridge.js
index af5a225cbf9..fb05bc76ede 100644
--- a/chromium/chrome/browser/resources/net_internals/browser_bridge.js
+++ b/chromium/chrome/browser/resources/net_internals/browser_bridge.js
@@ -35,7 +35,7 @@ const BrowserBridge = (function() {
* Wraps |chrome.send|.
* TODO(mattm): remove this and switch things to use chrome.send directly.
*/
- send: function(value1, value2) {
+ send(value1, value2) {
if (arguments.length == 1) {
chrome.send(value1);
} else if (arguments.length == 2) {
@@ -45,63 +45,63 @@ const BrowserBridge = (function() {
}
},
- sendReloadProxySettings: function() {
+ sendReloadProxySettings() {
this.send('reloadProxySettings');
},
- sendClearBadProxies: function() {
+ sendClearBadProxies() {
this.send('clearBadProxies');
},
- sendClearHostResolverCache: function() {
+ sendClearHostResolverCache() {
this.send('clearHostResolverCache');
},
- sendHSTSQuery: function(domain) {
+ sendHSTSQuery(domain) {
this.send('hstsQuery', [domain]);
},
- sendHSTSAdd: function(domain, sts_include_subdomains) {
+ sendHSTSAdd(domain, sts_include_subdomains) {
this.send('hstsAdd', [domain, sts_include_subdomains]);
},
- sendDomainSecurityPolicyDelete: function(domain) {
+ sendDomainSecurityPolicyDelete(domain) {
this.send('domainSecurityPolicyDelete', [domain]);
},
- sendExpectCTQuery: function(domain) {
+ sendExpectCTQuery(domain) {
this.send('expectCTQuery', [domain]);
},
- sendExpectCTAdd: function(domain, report_uri, enforce) {
+ sendExpectCTAdd(domain, report_uri, enforce) {
this.send('expectCTAdd', [domain, report_uri, enforce]);
},
- sendExpectCTTestReport: function(report_uri) {
+ sendExpectCTTestReport(report_uri) {
this.send('expectCTTestReport', [report_uri]);
},
- sendCloseIdleSockets: function() {
+ sendCloseIdleSockets() {
this.send('closeIdleSockets');
},
- sendFlushSocketPools: function() {
+ sendFlushSocketPools() {
this.send('flushSocketPools');
},
- importONCFile: function(fileContent, passcode) {
+ importONCFile(fileContent, passcode) {
this.send('importONCFile', [fileContent, passcode]);
},
- storeDebugLogs: function() {
+ storeDebugLogs() {
this.send('storeDebugLogs');
},
- storeCombinedDebugLogs: function() {
+ storeCombinedDebugLogs() {
this.send('storeCombinedDebugLogs');
},
- setNetworkDebugMode: function(subsystem) {
+ setNetworkDebugMode(subsystem) {
this.send('setNetworkDebugMode', [subsystem]);
},
@@ -109,47 +109,47 @@ const BrowserBridge = (function() {
// Messages received from the browser.
//--------------------------------------------------------------------------
- receive: function(command, params) {
+ receive(command, params) {
this[command](params);
},
- receivedHSTSResult: function(info) {
+ receivedHSTSResult(info) {
for (let i = 0; i < this.hstsObservers_.length; i++) {
this.hstsObservers_[i].onHSTSQueryResult(info);
}
},
- receivedExpectCTResult: function(info) {
+ receivedExpectCTResult(info) {
for (let i = 0; i < this.expectCTObservers_.length; i++) {
this.expectCTObservers_[i].onExpectCTQueryResult(info);
}
},
- receivedExpectCTTestReportResult: function(result) {
+ receivedExpectCTTestReportResult(result) {
for (let i = 0; i < this.expectCTObservers_.length; i++) {
this.expectCTObservers_[i].onExpectCTTestReportResult(result);
}
},
- receivedONCFileParse: function(error) {
+ receivedONCFileParse(error) {
for (let i = 0; i < this.crosONCFileParseObservers_.length; i++) {
this.crosONCFileParseObservers_[i].onONCFileParse(error);
}
},
- receivedStoreDebugLogs: function(status) {
+ receivedStoreDebugLogs(status) {
for (let i = 0; i < this.storeDebugLogsObservers_.length; i++) {
this.storeDebugLogsObservers_[i].onStoreDebugLogs(status);
}
},
- receivedStoreCombinedDebugLogs: function(status) {
+ receivedStoreCombinedDebugLogs(status) {
for (let i = 0; i < this.storeDebugLogsObservers_.length; i++) {
this.storeDebugLogsObservers_[i].onStoreCombinedDebugLogs(status);
}
},
- receivedSetNetworkDebugMode: function(status) {
+ receivedSetNetworkDebugMode(status) {
for (let i = 0; i < this.setNetworkDebugModeObservers_.length; i++) {
this.setNetworkDebugModeObservers_[i].onSetNetworkDebugMode(status);
}
@@ -163,7 +163,7 @@ const BrowserBridge = (function() {
*
* observer.onHSTSQueryResult(result);
*/
- addHSTSObserver: function(observer) {
+ addHSTSObserver(observer) {
this.hstsObservers_.push(observer);
},
@@ -173,7 +173,7 @@ const BrowserBridge = (function() {
*
* observer.onExpectCTQueryResult(result);
*/
- addExpectCTObserver: function(observer) {
+ addExpectCTObserver(observer) {
this.expectCTObservers_.push(observer);
},
@@ -183,7 +183,7 @@ const BrowserBridge = (function() {
*
* observer.onONCFileParse(error);
*/
- addCrosONCFileParseObserver: function(observer) {
+ addCrosONCFileParseObserver(observer) {
this.crosONCFileParseObservers_.push(observer);
},
@@ -194,7 +194,7 @@ const BrowserBridge = (function() {
* observer.onStoreDebugLogs(status);
* observer.onStoreCombinedDebugLogs(status);
*/
- addStoreDebugLogsObserver: function(observer) {
+ addStoreDebugLogsObserver(observer) {
this.storeDebugLogsObservers_.push(observer);
},
@@ -204,7 +204,7 @@ const BrowserBridge = (function() {
*
* observer.onSetNetworkDebugMode(status);
*/
- addSetNetworkDebugModeObserver: function(observer) {
+ addSetNetworkDebugModeObserver(observer) {
this.setNetworkDebugModeObservers_.push(observer);
},
};
diff --git a/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.js b/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.js
index 763a301d2ff..5e5bcd4ad09 100644
--- a/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.js
+++ b/chromium/chrome/browser/resources/net_internals/domain_security_policy_view.js
@@ -130,7 +130,7 @@ const DomainSecurityPolicyView = (function() {
// Inherit the superclass's methods.
__proto__: superClass.prototype,
- onSubmitHSTSAdd_: function(event) {
+ onSubmitHSTSAdd_(event) {
g_browser.sendHSTSAdd(this.addStsInput_.value, this.addStsCheck_.checked);
g_browser.sendHSTSQuery(this.addStsInput_.value);
this.queryStsInput_.value = this.addStsInput_.value;
@@ -139,18 +139,18 @@ const DomainSecurityPolicyView = (function() {
event.preventDefault();
},
- onSubmitDelete_: function(event) {
+ onSubmitDelete_(event) {
g_browser.sendDomainSecurityPolicyDelete(this.deleteInput_.value);
this.deleteInput_.value = '';
event.preventDefault();
},
- onSubmitHSTSQuery_: function(event) {
+ onSubmitHSTSQuery_(event) {
g_browser.sendHSTSQuery(this.queryStsInput_.value);
event.preventDefault();
},
- onHSTSQueryResult: function(result) {
+ onHSTSQueryResult(result) {
if (result.error != undefined) {
this.queryStsOutputDiv_.innerHTML = '';
const s = addNode(this.queryStsOutputDiv_, 'span');
@@ -225,7 +225,7 @@ const DomainSecurityPolicyView = (function() {
yellowFade(this.queryStsOutputDiv_);
},
- onSubmitExpectCTAdd_: function(event) {
+ onSubmitExpectCTAdd_(event) {
g_browser.sendExpectCTAdd(
this.addExpectCTInput_.value, this.addExpectCTReportUriInput_.value,
this.addExpectCTEnforceCheck_.checked);
@@ -237,12 +237,12 @@ const DomainSecurityPolicyView = (function() {
event.preventDefault();
},
- onSubmitExpectCTQuery_: function(event) {
+ onSubmitExpectCTQuery_(event) {
g_browser.sendExpectCTQuery(this.queryExpectCTInput_.value);
event.preventDefault();
},
- onExpectCTQueryResult: function(result) {
+ onExpectCTQueryResult(result) {
if (result.error != undefined) {
this.queryExpectCTOutputDiv_.innerHTML = '';
const s = addNode(this.queryExpectCTOutputDiv_, 'span');
@@ -284,12 +284,12 @@ const DomainSecurityPolicyView = (function() {
yellowFade(this.queryExpectCTOutputDiv_);
},
- onSubmitExpectCTTestReport_: function(event) {
+ onSubmitExpectCTTestReport_(event) {
g_browser.sendExpectCTTestReport(this.testExpectCTReportInput_.value);
event.preventDefault();
},
- onExpectCTTestReportResult: function(result) {
+ onExpectCTTestReportResult(result) {
if (result == 'success') {
addTextNode(this.testExpectCTOutputDiv_, 'Test report succeeded');
} else {
diff --git a/chromium/chrome/browser/resources/net_internals/events_view.js b/chromium/chrome/browser/resources/net_internals/events_view.js
index 8d901b76c05..85ce8116ec9 100644
--- a/chromium/chrome/browser/resources/net_internals/events_view.js
+++ b/chromium/chrome/browser/resources/net_internals/events_view.js
@@ -52,7 +52,7 @@ const EventsView = (function() {
* being dragged. When this happens, we may not receive a list of files for
* security reasons, which is why we allow the |files| array to be empty.
*/
- onDrag: function(event) {
+ onDrag(event) {
// NOTE: Use Array.prototype.indexOf here is necessary while WebKit
// decides which type of data structure dataTransfer.types will be
// (currently between DOMStringList and Array). These have different APIs
@@ -67,7 +67,7 @@ const EventsView = (function() {
* Called when something is dropped onto the drop target. If it's a single
* file, redirect to the events tab to show the depreciation message.
*/
- onDrop: function(event) {
+ onDrop(event) {
const indexOf = Array.prototype.indexOf;
if (indexOf.call(event.dataTransfer.types, 'Files') == -1 ||
event.dataTransfer.files.length != 1) {
diff --git a/chromium/chrome/browser/resources/net_internals/main.js b/chromium/chrome/browser/resources/net_internals/main.js
index d2345977bb1..9d019121599 100644
--- a/chromium/chrome/browser/resources/net_internals/main.js
+++ b/chromium/chrome/browser/resources/net_internals/main.js
@@ -54,11 +54,11 @@ const MainView = (function() {
__proto__: superClass.prototype,
// This is exposed for testing.
- tabSwitcher: function() {
+ tabSwitcher() {
return this.tabSwitcher_;
},
- initTabs_: function() {
+ initTabs_() {
this.tabIdToHash_ = {};
this.hashToTabId_ = {};
@@ -102,7 +102,7 @@ const MainView = (function() {
* changed. It will update the current URL to reflect the new active tab,
* so the back can be used to return to previous view.
*/
- onTabSwitched_: function(oldTabId, newTabId) {
+ onTabSwitched_(oldTabId, newTabId) {
// Change the URL to match the new tab.
const newTabHash = this.tabIdToHash_[newTabId];
const parsed = parseUrlHash_(window.location.hash);
@@ -111,7 +111,7 @@ const MainView = (function() {
}
},
- onUrlHashChange_: function() {
+ onUrlHashChange_() {
const parsed = parseUrlHash_(window.location.hash);
if (!parsed) {
diff --git a/chromium/chrome/browser/resources/net_internals/sockets_view.js b/chromium/chrome/browser/resources/net_internals/sockets_view.js
index 54d2b6f82c1..4bc6269d087 100644
--- a/chromium/chrome/browser/resources/net_internals/sockets_view.js
+++ b/chromium/chrome/browser/resources/net_internals/sockets_view.js
@@ -45,11 +45,11 @@ const SocketsView = (function() {
// Inherit the superclass's methods.
__proto__: superClass.prototype,
- closeIdleSockets: function() {
+ closeIdleSockets() {
g_browser.sendCloseIdleSockets();
},
- flushSocketPools: function() {
+ flushSocketPools() {
g_browser.sendFlushSocketPools();
}
};
diff --git a/chromium/chrome/browser/resources/net_internals/tab_switcher_view.js b/chromium/chrome/browser/resources/net_internals/tab_switcher_view.js
index deed08763ac..c8f95e3b925 100644
--- a/chromium/chrome/browser/resources/net_internals/tab_switcher_view.js
+++ b/chromium/chrome/browser/resources/net_internals/tab_switcher_view.js
@@ -53,7 +53,7 @@ const TabSwitcherView = (function() {
// Override methods in View
// ---------------------------------------------
- setGeometry: function(left, top, width, height) {
+ setGeometry(left, top, width, height) {
superClass.prototype.setGeometry.call(this, left, top, width, height);
const tabListNode = $(TAB_LIST_ID);
@@ -76,7 +76,7 @@ const TabSwitcherView = (function() {
}
},
- show: function(isVisible) {
+ show(isVisible) {
superClass.prototype.show.call(this, isVisible);
const activeView = this.getActiveTabView();
if (activeView) {
@@ -94,7 +94,7 @@ const TabSwitcherView = (function() {
* @param {!View} view The tab's actual contents.
* @param {string} name The name for the menu item that selects the tab.
*/
- addTab: function(tabId, view, name, hash) {
+ addTab(tabId, view, name, hash) {
if (!tabId) {
throw Error('Must specify a non-false tabId');
}
@@ -113,7 +113,7 @@ const TabSwitcherView = (function() {
this.tabListWidth_ = $(TAB_LIST_ID).offsetWidth;
},
- showTabLink: function(tabId, isVisible) {
+ showTabLink(tabId, isVisible) {
const wasActive = this.activeTabId_ == tabId;
setNodeDisplay(this.tabIdToLink_[tabId], isVisible);
@@ -131,19 +131,19 @@ const TabSwitcherView = (function() {
}
},
- getAllTabViews: function() {
+ getAllTabViews() {
return this.tabIdToView_;
},
- getTabView: function(tabId) {
+ getTabView(tabId) {
return this.tabIdToView_[tabId];
},
- getActiveTabView: function() {
+ getActiveTabView() {
return this.tabIdToView_[this.activeTabId_];
},
- getActiveTabId: function() {
+ getActiveTabId() {
return this.activeTabId_;
},
@@ -153,7 +153,7 @@ const TabSwitcherView = (function() {
* (2) Update the dropdown menu's current selection.
* (3) Invoke the optional onTabSwitched callback.
*/
- switchToTab: function(tabId) {
+ switchToTab(tabId) {
const newView = this.getTabView(tabId);
if (!newView) {
diff --git a/chromium/chrome/browser/resources/net_internals/view.js b/chromium/chrome/browser/resources/net_internals/view.js
index da5998ef7bd..0d95709f54d 100644
--- a/chromium/chrome/browser/resources/net_internals/view.js
+++ b/chromium/chrome/browser/resources/net_internals/view.js
@@ -20,7 +20,7 @@ const View = (function() {
/**
* Called to reposition the view on the page. Measurements are in pixels.
*/
- setGeometry: function(left, top, width, height) {
+ setGeometry(left, top, width, height) {
this.left_ = left;
this.top_ = top;
this.width_ = width;
@@ -30,11 +30,11 @@ const View = (function() {
/**
* Called to show/hide the view.
*/
- show: function(isVisible) {
+ show(isVisible) {
this.isVisible_ = isVisible;
},
- isVisible: function() {
+ isVisible() {
return this.isVisible_;
},
@@ -44,35 +44,35 @@ const View = (function() {
* Called to check if an observer needs the data it is
* observing to be actively updated.
*/
- isActive: function() {
+ isActive() {
return this.isVisible();
},
- getLeft: function() {
+ getLeft() {
return this.left_;
},
- getTop: function() {
+ getTop() {
return this.top_;
},
- getWidth: function() {
+ getWidth() {
return this.width_;
},
- getHeight: function() {
+ getHeight() {
return this.height_;
},
- getRight: function() {
+ getRight() {
return this.getLeft() + this.getWidth();
},
- getBottom: function() {
+ getBottom() {
return this.getTop() + this.getHeight();
},
- setParameters: function(params) {},
+ setParameters(params) {},
/**
* Called when loading a log file, after clearing all events, but before
@@ -82,14 +82,14 @@ const View = (function() {
* values. It's included separately so most views don't have to depend on
* its specifics.
*/
- onLoadLogStart: function(polledData, tabData, logDump) {},
+ onLoadLogStart(polledData, tabData, logDump) {},
/**
* Called as the final step of loading a log file. Arguments are the same
* as onLoadLogStart. Returns true to indicate the tab should be shown,
* false otherwise.
*/
- onLoadLogFinish: function(polledData, tabData, logDump) {
+ onLoadLogFinish(polledData, tabData, logDump) {
return false;
}
};
@@ -130,14 +130,14 @@ const DivView = (function() {
// Inherit the superclass's methods.
__proto__: superClass.prototype,
- setGeometry: function(left, top, width, height) {
+ setGeometry(left, top, width, height) {
superClass.prototype.setGeometry.call(this, left, top, width, height);
this.node_.style.position = 'absolute';
setNodePosition(this.node_, left, top, width, height);
},
- show: function(isVisible) {
+ show(isVisible) {
superClass.prototype.show.call(this, isVisible);
setNodeDisplay(this.node_, isVisible);
},
@@ -145,7 +145,7 @@ const DivView = (function() {
/**
* Returns the wrapped DIV
*/
- getNode: function() {
+ getNode() {
return this.node_;
}
};
@@ -182,17 +182,17 @@ const WindowView = (function() {
// Inherit the superclass's methods.
__proto__: superClass.prototype,
- setGeometry: function(left, top, width, height) {
+ setGeometry(left, top, width, height) {
superClass.prototype.setGeometry.call(this, left, top, width, height);
this.childView_.setGeometry(left, top, width, height);
},
- show: function() {
+ show() {
superClass.prototype.show.call(this, isVisible);
this.childView_.show(isVisible);
},
- resetGeometry: function() {
+ resetGeometry() {
this.setGeometry(
0, 0, document.documentElement.clientWidth,
document.documentElement.clientHeight);
@@ -242,7 +242,7 @@ const VerticalSplitView = (function() {
// Inherit the superclass's methods.
__proto__: superClass.prototype,
- setGeometry: function(left, top, width, height) {
+ setGeometry(left, top, width, height) {
superClass.prototype.setGeometry.call(this, left, top, width, height);
const fixedHeight = this.topView_.getHeight();
@@ -252,7 +252,7 @@ const VerticalSplitView = (function() {
left, top + fixedHeight, width, height - fixedHeight);
},
- show: function(isVisible) {
+ show(isVisible) {
superClass.prototype.show.call(this, isVisible);
this.topView_.show(isVisible);
@@ -304,7 +304,7 @@ const HorizontalSplitView = (function() {
// Inherit the superclass's methods.
__proto__: superClass.prototype,
- setGeometry: function(left, top, width, height) {
+ setGeometry(left, top, width, height) {
superClass.prototype.setGeometry.call(this, left, top, width, height);
const fixedWidth = this.leftView_.getWidth();
@@ -314,7 +314,7 @@ const HorizontalSplitView = (function() {
left + fixedWidth, top, width - fixedWidth, height);
},
- show: function(isVisible) {
+ show(isVisible) {
superClass.prototype.show.call(this, isVisible);
this.leftView_.show(isVisible);
diff --git a/chromium/chrome/browser/resources/network_speech_synthesis/tts_extension.js b/chromium/chrome/browser/resources/network_speech_synthesis/tts_extension.js
index 8a984dbb769..7ecbbec5617 100644
--- a/chromium/chrome/browser/resources/network_speech_synthesis/tts_extension.js
+++ b/chromium/chrome/browser/resources/network_speech_synthesis/tts_extension.js
@@ -76,7 +76,7 @@ TtsExtension.prototype = {
* This is the main function called to initialize this extension.
* Initializes data structures and adds event listeners.
*/
- init: function() {
+ init() {
// Get voices from manifest.
const voices = chrome.app.getDetails().tts_engine.voices;
for (let i = 0; i < voices.length; i++) {
@@ -111,7 +111,7 @@ TtsExtension.prototype = {
* in the Chrome ttsEngine extension API.
* @private
*/
- onSpeak_: function(utterance, options, callback) {
+ onSpeak_(utterance, options, callback) {
// Truncate the utterance if it's too long. Both Chrome's tts
// extension api and the web speech api specify 32k as the
// maximum limit for an utterance.
@@ -195,7 +195,7 @@ TtsExtension.prototype = {
* TTS client.
* @private
*/
- onStop_: function() {
+ onStop_() {
if (this.currentUtterance_) {
this.audioElement_.pause();
this.currentUtterance_.callback({
@@ -213,7 +213,7 @@ TtsExtension.prototype = {
* then begin playing the audio element.
* @private
*/
- onStart_: function() {
+ onStart_() {
if (this.currentUtterance_) {
if (this.currentUtterance_.options.volume !== undefined) {
// Both APIs use the same range for volume, between 0.0 and 1.0.
@@ -229,7 +229,7 @@ TtsExtension.prototype = {
* Pauses audio if we're in the middle of an utterance.
* @private
*/
- onPause_: function() {
+ onPause_() {
if (this.currentUtterance_) {
this.audioElement_.pause();
}
@@ -240,7 +240,7 @@ TtsExtension.prototype = {
* Resumes audio if we're in the middle of an utterance.
* @private
*/
- onResume_: function() {
+ onResume_() {
if (this.currentUtterance_) {
this.audioElement_.play();
}
diff --git a/chromium/chrome/browser/resources/new_tab_page/.eslintrc.js b/chromium/chrome/browser/resources/new_tab_page/.eslintrc.js
new file mode 100644
index 00000000000..9c84e103640
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/.eslintrc.js
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/new_tab_page/BUILD.gn b/chromium/chrome/browser/resources/new_tab_page/BUILD.gn
index 7123b75a318..d7bb922bdf5 100644
--- a/chromium/chrome/browser/resources/new_tab_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/new_tab_page/BUILD.gn
@@ -8,8 +8,16 @@ import("//tools/polymer/polymer.gni")
js_type_check("closure_compile") {
is_polymer3 = true
deps = [
+ ":app",
":browser_proxy",
- ":manager",
+ ":customize_dialog",
+ ":fakebox",
+ ":grid",
+ ":logo",
+ ":theme_icon",
+ ":untrusted_iframe",
+ ":utils",
+ ":voice_search_overlay",
]
}
@@ -22,22 +30,200 @@ js_library("browser_proxy") {
externs_list = [ "externs.js" ]
}
-js_library("manager") {
+js_library("app") {
deps = [
":browser_proxy",
+ ":most_visited",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:event_tracker.m",
+ ]
+}
+
+js_library("most_visited") {
+ deps = [
+ ":browser_proxy",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ "//ui/webui/resources/cr_elements/cr_toast:cr_toast.m",
"//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_outline_manager.m",
+ ]
+}
+
+js_library("customize_dialog") {
+ deps = [
+ ":customize_backgrounds",
+ ":customize_shortcuts",
+ ":customize_themes",
+ ":utils",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ ]
+}
+
+js_library("customize_backgrounds") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
+js_library("customize_themes") {
+ deps = [
+ ":grid",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
+js_library("mini_page") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
+js_library("customize_shortcuts") {
+ deps = [
+ ":browser_proxy",
+ ":mini_page",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_toggle:cr_toggle.m",
+ ]
+}
+
+js_library("theme_icon") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
+js_library("grid") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
+js_library("voice_search_overlay") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
+js_library("utils") {
+}
+
+js_library("untrusted_iframe") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
+js_library("fakebox") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+}
+
+js_library("logo") {
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
}
-polymer_modulizer("manager") {
- js_file = "manager.js"
- html_file = "manager.html"
+polymer_modulizer("app") {
+ js_file = "app.js"
+ html_file = "app.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("customize_dialog") {
+ js_file = "customize_dialog.js"
+ html_file = "customize_dialog.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("mini_page") {
+ js_file = "mini_page.js"
+ html_file = "mini_page.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("most_visited") {
+ js_file = "most_visited.js"
+ html_file = "most_visited.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("customize_shortcuts") {
+ js_file = "customize_shortcuts.js"
+ html_file = "customize_shortcuts.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("customize_backgrounds") {
+ js_file = "customize_backgrounds.js"
+ html_file = "customize_backgrounds.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("customize_themes") {
+ js_file = "customize_themes.js"
+ html_file = "customize_themes.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("theme_icon") {
+ js_file = "theme_icon.js"
+ html_file = "theme_icon.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("grid") {
+ js_file = "grid.js"
+ html_file = "grid.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("voice_search_overlay") {
+ js_file = "voice_search_overlay.js"
+ html_file = "voice_search_overlay.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("untrusted_iframe") {
+ js_file = "untrusted_iframe.js"
+ html_file = "untrusted_iframe.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("fakebox") {
+ js_file = "fakebox.js"
+ html_file = "fakebox.html"
+ html_type = "v3-ready"
+}
+
+polymer_modulizer("logo") {
+ js_file = "logo.js"
+ html_file = "logo.html"
html_type = "v3-ready"
}
group("polymer3_elements") {
- deps = [
- ":manager_module",
+ public_deps = [
+ ":app_module",
+ ":customize_backgrounds_module",
+ ":customize_dialog_module",
+ ":customize_shortcuts_module",
+ ":customize_themes_module",
+ ":fakebox_module",
+ ":grid_module",
+ ":logo_module",
+ ":mini_page_module",
+ ":most_visited_module",
+ ":theme_icon_module",
+ ":untrusted_iframe_module",
+ ":voice_search_overlay_module",
]
}
diff --git a/chromium/chrome/browser/resources/new_tab_page/OWNERS b/chromium/chrome/browser/resources/new_tab_page/OWNERS
index 01245124161..b6e70040c88 100644
--- a/chromium/chrome/browser/resources/new_tab_page/OWNERS
+++ b/chromium/chrome/browser/resources/new_tab_page/OWNERS
@@ -1,5 +1,4 @@
aee@chromium.org
-dbeam@chromium.org
mahmadi@chromium.org
tiborg@chromium.org
diff --git a/chromium/chrome/browser/resources/new_tab_page/app.html b/chromium/chrome/browser/resources/new_tab_page/app.html
new file mode 100644
index 00000000000..d6ab6b198f2
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/app.html
@@ -0,0 +1,225 @@
+<style include="cr-shared-style">
+ :host {
+ --ntp-theme-shortcut-background-color: rgb(229, 231, 232);
+ --ntp-theme-text-color: var(--google-grey-800);
+ --ntp-theme-text-shadow: none;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ :host {
+ --ntp-theme-shortcut-background-color: var(--google-grey-refresh-100);
+ --ntp-theme-text-color: white;
+ }
+ }
+
+ :host([show-background-image_]) {
+ --ntp-theme-text-shadow: 0 0 16px rgba(0, 0, 0, .3);
+ }
+
+ #background {
+ height: 100%;
+ position: relative;
+ width: 100%;
+ }
+
+ #background > * {
+ height: 100%;
+ position: absolute;
+ top: 0;
+ width: 100%;
+ }
+
+ #backgroundImage {
+ border: none;
+ }
+
+ #backgroundGradient {
+ background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.3));
+ }
+
+ #content {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ }
+
+ #oneGoogleBar {
+ pointer-events: none;
+ }
+
+ #oneGoogleBarSpacer {
+ height: 56px;
+ width: 100%;
+ }
+
+ #logo {
+ margin-bottom: 38px;
+ }
+
+ ntp-fakebox {
+ margin-bottom: 32px;
+ }
+
+ ntp-most-visited[dark] {
+ --icon-button-color-active: var(--google-grey-refresh-300);
+ --icon-button-color: white;
+ --tile-hover-color: rgba(255, 255, 255, .1);
+ }
+
+ #promo {
+ bottom: 16px;
+ height: 35px;
+ left: 0;
+ position: fixed;
+ right: 0;
+ width: 100%;
+ }
+
+ #customizeButtonContainer {
+ background-color: var(--ntp-background-override-color);
+ border-radius: calc(0.5 * var(--cr-button-height));
+ bottom: 16px;
+ position: absolute;
+ }
+
+ :host-context([dir='ltr']) #customizeButtonContainer {
+ right: 16px;
+ }
+
+ :host-context([dir='rtl']) #customizeButtonContainer {
+ left: 16px;
+ }
+
+ #customizeButton {
+ border: none;
+ border-radius: calc(0.5 * var(--cr-button-height));
+ box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 1px 2px rgba(0, 0, 0, 0.23);
+ font-weight: 400;
+ }
+
+ #customizeIcon {
+ -webkit-mask-image: url(icons/icon_pencil.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--text-color);
+ height: 16px;
+ margin-inline-end: 8px;
+ width: 16px;
+ }
+
+ #backgroundImageAttribution {
+ border-radius: 8px;
+ bottom: 16px;
+ color: var(--ntp-theme-text-color);
+ line-height: 20px;
+ max-width: 50vw;
+ padding: 8px;
+ position: absolute;
+ text-shadow: var(--ntp-theme-text-shadow);
+ }
+
+ :host-context([dir='ltr']) #backgroundImageAttribution {
+ left: 16px;
+ }
+
+ :host-context([dir='rtl']) #backgroundImageAttribution {
+ right: 16px;
+ }
+
+ #backgroundImageAttribution:hover {
+ background: rgba(var(--google-grey-900-rgb), .1);
+ }
+
+ #backgroundImageAttribution1Container {
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ }
+
+ #linkIcon {
+ -webkit-mask-image: url(icons/link.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--ntp-theme-text-color);
+ height: 16px;
+ margin-inline-end: 8px;
+ width: 16px;
+ }
+
+ #backgroundImageAttribution1,
+ #backgroundImageAttribution2 {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ #backgroundImageAttribution1 {
+ font-size: 0.875rem;
+ }
+
+ #backgroundImageAttribution2 {
+ font-size: 0.75rem;
+ }
+</style>
+<div id="background"
+ style="background-color: [[rgbOrInherit_(theme_.backgroundColor)]];
+ --ntp-theme-text-color: [[rgbOrInherit_(theme_.shortcutTextColor)]];
+ --ntp-theme-shortcut-background-color:
+ [[rgbOrInherit_(theme_.shortcutBackgroundColor)]];
+ --ntp-logo-color: [[rgbOrInherit_(theme_.logoColor)]];">
+ <ntp-untrusted-iframe id="backgroundImage" path="[[backgroundImagePath_]]"
+ hidden="[[!showBackgroundImage_]]">
+ </ntp-untrusted-iframe>
+ <div id="backgroundGradient" hidden="[[!showBackgroundImage_]]"></div>
+ <div id="content">
+ <div id="oneGoogleBarSpacer"></div>
+ <ntp-logo id="logo" doodle-allowed$="[[doodleAllowed_]]"
+ single-colored$="[[singleColoredLogo_]]">
+ </ntp-logo>
+ <ntp-fakebox id="fakebox" on-open-voice-search="onVoiceSearchClick_">
+ </ntp-fakebox>
+ <ntp-most-visited id="mostVisited" dark$="[[theme_.isDark]]">
+ </ntp-most-visited>
+ <dom-if if="[[showCustomizeDialog_]]" restamp>
+ <template>
+ <ntp-customize-dialog on-close="onCustomizeDialogClose_"
+ theme="[[theme_]]">
+ </ntp-customize-dialog>
+ </template>
+ </dom-if>
+ <dom-if if="[[showVoiceSearchOverlay_]]" restamp>
+ <template>
+ <ntp-voice-search-overlay on-close="onVoiceSearchOverlayClose_">
+ </ntp-voice-search-overlay>
+ </template>
+ </dom-if>
+ <ntp-untrusted-iframe id="promo" path="promo" hidden$="[[!promoLoaded_]]">
+ </ntp-untrusted-iframe>
+ <!-- cr-button is transparent on hover. This leads to incorrect results when
+ a custom background is set. Therefore, wrap customize button in
+ container to enfore solid background color. -->
+ <div id="customizeButtonContainer">
+ <cr-button id="customizeButton" on-click="onCustomizeClick_">
+ <div id="customizeIcon"></div>
+ $i18n{customizeButton}
+ </cr-button>
+ </div>
+ <a id="backgroundImageAttribution"
+ href="[[theme_.backgroundImageAttributionUrl.url]]"
+ hidden="[[!theme_.backgroundImageAttribution1]]">
+ <div id="backgroundImageAttribution1Container">
+ <div id="linkIcon"></div>
+ <div id="backgroundImageAttribution1">
+ [[theme_.backgroundImageAttribution1]]
+ </div>
+ </div>
+ <div id="backgroundImageAttribution2"
+ hidden="[[!theme_.backgroundImageAttribution2]]">
+ [[theme_.backgroundImageAttribution2]]
+ </div>
+ </a>
+ </div>
+ <ntp-untrusted-iframe id="oneGoogleBar" path="one-google-bar"
+ hidden$="[[!oneGoogleBarLoaded_]]">
+ </ntp-untrusted-iframe>
+</div>
diff --git a/chromium/chrome/browser/resources/new_tab_page/app.js b/chromium/chrome/browser/resources/new_tab_page/app.js
new file mode 100644
index 00000000000..f5a695ffdc4
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/app.js
@@ -0,0 +1,229 @@
+// Copyright 2019 The Chromium 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 './strings.m.js';
+import './most_visited.js';
+import './customize_dialog.js';
+import './voice_search_overlay.js';
+import './untrusted_iframe.js';
+import './fakebox.js';
+import './logo.js';
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/shared_style_css.m.js';
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {EventTracker} from 'chrome://resources/js/event_tracker.m.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {BrowserProxy} from './browser_proxy.js';
+import {skColorToRgb} from './utils.js';
+
+class AppElement extends PolymerElement {
+ static get is() {
+ return 'ntp-app';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @private */
+ oneGoogleBarLoaded_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /** @private */
+ promoLoaded_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /** @private {!newTabPage.mojom.Theme} */
+ theme_: Object,
+
+ /** @private */
+ showCustomizeDialog_: Boolean,
+
+ /** @private */
+ showVoiceSearchOverlay_: Boolean,
+
+ /** @private */
+ showBackgroundImage_: {
+ computed: 'computeShowBackgroundImage_(theme_)',
+ reflectToAttribute: true,
+ type: Boolean,
+ },
+
+ /** @private */
+ backgroundImagePath_: {
+ computed: 'computeBackgroundImagePath_(theme_)',
+ type: String,
+ },
+
+ /** @private */
+ doodleAllowed_: {
+ computed: 'computeDoodleAllowed_(showBackgroundImage_, theme_)',
+ type: Boolean,
+ },
+
+ /** @private */
+ singleColoredLogo_: {
+ computed: 'computeSingleColoredLogo_(theme_)',
+ type: Boolean,
+ },
+ };
+ }
+
+ constructor() {
+ super();
+ /** @private {!newTabPage.mojom.PageCallbackRouter} */
+ this.callbackRouter_ = BrowserProxy.getInstance().callbackRouter;
+ /** @private {?number} */
+ this.setThemeListenerId_ = null;
+ /** @private {!EventTracker} */
+ this.eventTracker_ = new EventTracker();
+ }
+
+ /** @override */
+ connectedCallback() {
+ super.connectedCallback();
+ this.setThemeListenerId_ =
+ this.callbackRouter_.setTheme.addListener(theme => {
+ this.theme_ = theme;
+ });
+ this.eventTracker_.add(window, 'message', ({data}) => {
+ // Something in OneGoogleBar is sending a message that is received here.
+ // Need to ignore it.
+ if (typeof data !== 'object') {
+ return;
+ }
+ if ('frameType' in data) {
+ if (data.frameType === 'promo') {
+ this.handlePromoMessage_(data);
+ } else if (data.frameType === 'one-google-bar') {
+ this.handleOneGoogleBarMessage_(data);
+ }
+ }
+ });
+ }
+
+ /** @override */
+ disconnectedCallback() {
+ super.disconnectedCallback();
+ this.callbackRouter_.removeListener(assert(this.setThemeListenerId_));
+ this.eventTracker_.removeAll();
+ }
+
+ /** @private */
+ onVoiceSearchClick_() {
+ this.showVoiceSearchOverlay_ = true;
+ }
+
+ /** @private */
+ onCustomizeClick_() {
+ this.showCustomizeDialog_ = true;
+ }
+
+ /** @private */
+ onCustomizeDialogClose_() {
+ this.showCustomizeDialog_ = false;
+ }
+
+ /** @private */
+ onVoiceSearchOverlayClose_() {
+ this.showVoiceSearchOverlay_ = false;
+ }
+
+ /**
+ * @param {skia.mojom.SkColor} skColor
+ * @return {string}
+ * @private
+ */
+ rgbOrInherit_(skColor) {
+ return skColor ? skColorToRgb(skColor) : 'inherit';
+ }
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeShowBackgroundImage_() {
+ return !!this.theme_ && !!this.theme_.backgroundImageUrl;
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ computeBackgroundImagePath_() {
+ if (!this.theme_ || !this.theme_.backgroundImageUrl) {
+ return '';
+ }
+ return `image?${this.theme_.backgroundImageUrl.url}`;
+ }
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeDoodleAllowed_() {
+ return !this.showBackgroundImage_ &&
+ (!this.theme_ ||
+ this.theme_.type === newTabPage.mojom.ThemeType.DEFAULT);
+ }
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeSingleColoredLogo_() {
+ return this.theme_ && !!this.theme_.logoColor;
+ }
+
+ /**
+ * Handles messages from the OneGoogleBar iframe. The messages that are
+ * handled include show bar on load and activate/deactivate.
+ * The activate/deactivate controls if the OneGoogleBar accepts mouse events,
+ * though other events need to be forwarded to support touch.
+ * @param {!Object} data
+ * @private
+ */
+ handleOneGoogleBarMessage_(data) {
+ if (data.messageType === 'loaded') {
+ this.oneGoogleBarLoaded_ = true;
+ this.eventTracker_.add(window, 'mousemove', ({x, y}) => {
+ this.$.oneGoogleBar.postMessage({type: 'mousemove', x, y});
+ });
+ } else if (data.messageType === 'activate') {
+ this.$.oneGoogleBar.style.pointerEvents = 'unset';
+ } else if (data.messageType === 'deactivate') {
+ this.$.oneGoogleBar.style.pointerEvents = 'none';
+ }
+ }
+
+ /**
+ * Handle messages from promo iframe. This shows the promo on load and sets
+ * up the show/hide logic (in case there is an overlap with most-visited
+ * tiles).
+ * @param {!Object} data
+ * @private
+ */
+ handlePromoMessage_(data) {
+ if (data.messageType === 'loaded') {
+ this.promoLoaded_ = true;
+ const onResize = () => {
+ const hidePromo = this.$.mostVisited.getBoundingClientRect().bottom >=
+ this.$.promo.offsetTop;
+ this.$.promo.style.opacity = hidePromo ? 0 : 1;
+ };
+ this.eventTracker_.add(window, 'resize', onResize);
+ onResize();
+ }
+ }
+}
+
+customElements.define(AppElement.is, AppElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/browser_proxy.js b/chromium/chrome/browser/resources/new_tab_page/browser_proxy.js
index 118827046d4..7744ba398a4 100644
--- a/chromium/chrome/browser/resources/new_tab_page/browser_proxy.js
+++ b/chromium/chrome/browser/resources/new_tab_page/browser_proxy.js
@@ -3,7 +3,12 @@
// found in the LICENSE file.
import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js';
+import 'chrome://resources/mojo/url/mojom/url.mojom-lite.js';
+
+import './skcolor.mojom-lite.js';
import './new_tab_page.mojom-lite.js';
+
import {addSingletonGetter} from 'chrome://resources/js/cr.m.js';
export class BrowserProxy {
@@ -19,6 +24,46 @@ export class BrowserProxy {
this.callbackRouter.$.bindNewPipeAndPassRemote(),
this.handler.$.bindNewPipeAndPassReceiver());
}
+
+ /** @param {string} href */
+ navigate(href) {
+ window.location.href = href;
+ }
+
+ /**
+ * @param {function()} callback
+ * @param {number} duration
+ * @return {number}
+ */
+ setTimeout(callback, duration) {
+ return window.setTimeout(callback, duration);
+ }
+
+ /** @param {number} id */
+ clearTimeout(id) {
+ window.clearTimeout(id);
+ }
+
+ /** @return {number} */
+ random() {
+ return Math.random();
+ }
+
+ /**
+ * @param {string} path
+ * @return {string}
+ */
+ createUntrustedIframeSrc(path) {
+ return `chrome-untrusted://new-tab-page/${path}`;
+ }
+
+ /**
+ * @param {string} query
+ * @return {!MediaQueryList}
+ */
+ matchMedia(query) {
+ return window.matchMedia(query);
+ }
}
addSingletonGetter(BrowserProxy);
diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.html b/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.html
new file mode 100644
index 00000000000..c5ce1225f07
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.html
@@ -0,0 +1,60 @@
+<style>
+ #container {
+ padding: 4px;
+ }
+
+ ntp-grid {
+ --ntp-grid-gap: 8px;
+ }
+
+ .tile {
+ cursor: pointer;
+ outline-width: 0;
+ }
+
+ ntp-untrusted-iframe {
+ pointer-events: none;
+ }
+
+ :host-context(.focus-outline-visible) .tile:focus {
+ box-shadow: 0 0 0 2px var(--ntp-focus-shadow-color);
+ }
+
+ .image {
+ border-radius: 4px;
+ display: block;
+ height: 176px;
+ width: 176px;
+ }
+
+ .label {
+ color: var(--ntp-primary-text-color);
+ margin-bottom: 4px;
+ margin-top: 3px;
+ min-height: 30px;
+ }
+</style>
+<ntp-grid id="collections" columns="3" hidden="[[selectedCollection]]">
+ <dom-repeat id="collectionsRepeat" items="[[collections_]]">
+ <template>
+ <div class="tile" tabindex="0" title="[[item.label]]" role="button"
+ on-click="onCollectionClick_">
+ <ntp-untrusted-iframe class="image"
+ path="image?[[item.previewImageUrl.url]]">
+ </ntp-untrusted-iframe>
+ <div class="label">[[item.label]]</div>
+ </div>
+ </template>
+ </dom-repeat>
+</ntp-grid>
+<ntp-grid id="images" columns="3" hidden="[[!selectedCollection]]">
+ <dom-repeat items="[[images_]]">
+ <template>
+ <div class="tile" tabindex="0" title="[[item.label]]" role="button">
+ <ntp-untrusted-iframe class="image"
+ path="image?[[item.previewImageUrl.url]]">
+ </ntp-untrusted-iframe>
+ </div>
+ </template>
+ </dom-repeat>
+</ntp-grid>
diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.js b/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.js
new file mode 100644
index 00000000000..6779355f321
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/customize_backgrounds.js
@@ -0,0 +1,76 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import './grid.js';
+import './untrusted_iframe.js';
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {BrowserProxy} from './browser_proxy.js';
+
+/** Element that lets the user configure the background. */
+class CustomizeBackgroundsElement extends PolymerElement {
+ static get is() {
+ return 'ntp-customize-backgrounds';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @private {newTabPage.mojom.BackgroundCollection} */
+ selectedCollection: {
+ notify: true,
+ observer: 'onSelectedCollectionChange_',
+ type: Object,
+ value: null,
+ },
+
+ /** @private {!Array<!newTabPage.mojom.BackgroundCollection>} */
+ collections_: Array,
+
+ /** @private {!Array<!newTabPage.mojom.BackgroundImage>} */
+ images_: Array,
+ };
+ }
+
+ constructor() {
+ super();
+ BrowserProxy.getInstance().handler.getBackgroundCollections().then(
+ ({collections}) => {
+ this.collections_ = collections;
+ });
+ }
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onCollectionClick_(e) {
+ this.selectedCollection = this.$.collectionsRepeat.itemForElement(e.target);
+ }
+
+ /** @private */
+ async onSelectedCollectionChange_() {
+ this.images_ = [];
+ if (!this.selectedCollection) {
+ return;
+ }
+ const collectionId = this.selectedCollection.id;
+ const {images} =
+ await BrowserProxy.getInstance().handler.getBackgroundImages(
+ collectionId);
+ // We check the IDs match since the user may have already moved to a
+ // different collection before the results come back.
+ if (!this.selectedCollection ||
+ this.selectedCollection.id !== collectionId) {
+ return;
+ }
+ this.images_ = images;
+ }
+}
+
+customElements.define(
+ CustomizeBackgroundsElement.is, CustomizeBackgroundsElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_dialog.html b/chromium/chrome/browser/resources/new_tab_page/customize_dialog.html
new file mode 100644
index 00000000000..218fbacfab8
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/customize_dialog.html
@@ -0,0 +1,190 @@
+<style include="cr-icons">
+ ::part(dialog) {
+ min-width: 800px;
+ }
+
+ :host {
+ --border-width: 1px;
+ }
+
+ div[slot=title] {
+ align-items: center;
+ color: var(--ntp-primary-text-color);
+ display: flex;
+ flex-direction: row;
+ height: 80px;
+ padding: 0;
+ }
+
+ div[slot=body] {
+ color: var(--cr-primary-text-color);
+ display: flex;
+ flex-direction: row;
+ overflow: hidden;
+ padding: 0;
+ }
+
+ #menuContainer,
+ #pagesContainer {
+ max-height: 391px;
+ overflow: hidden;
+ }
+
+ #leftTitleSpacer,
+ #menuContainer {
+ flex-basis: 232px;
+ }
+
+ #title,
+ #pagesContainer {
+ flex-grow: 1;
+ }
+
+ #menu,
+ #pages {
+ height: calc(100% - 2 * var(--border-width));
+ overflow: auto;
+ }
+
+ #pages > iron-pages {
+ min-height: 389px;
+ }
+
+ div[scroll-border] {
+ border-bottom: var(--border-width) solid var(--ntp-border-color);
+ }
+
+ div[scroll-border]:not([show]) {
+ --ntp-border-color: transparent;
+ }
+
+ #menu {
+ display: flex;
+ flex-direction: column;
+ }
+
+ .menu-item {
+ align-items: center;
+ border-radius: 0 16px 16px 0;
+ color: var(--ntp-primary-text-color);
+ cursor: pointer;
+ display: flex;
+ flex-direction: row;
+ flex-shrink: 0;
+ font-size: 14px;
+ height: 32px;
+ margin-bottom: 16px;
+ outline: none;
+ width: 192px;
+ }
+
+ :host-context([dir=rtl]) .menu-item {
+ border-radius: 16px 0 0 16px;
+ }
+
+ .menu-item:hover,
+ .menu-item:focus {
+ background-color: var(--ntp-hover-background-color);
+ }
+
+ .menu-item:active {
+ background-color: var(--ntp-active-background-color);
+ }
+
+ .menu-item[selected] {
+ background-color: var(--ntp-selected-background-color);
+ color: var(--ntp-selected-primary-text-color);
+ }
+
+ .menu-item-icon {
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--ntp-primary-text-color);
+ height: 20px;
+ margin-inline-end: 16px;
+ margin-inline-start: 24px;
+ width: 20px;
+ }
+
+ .menu-item[selected] .menu-item-icon {
+ background-color: var(--ntp-selected-primary-text-color);
+ }
+
+ #backgroundsIcon {
+ -webkit-mask-image: url(icons/backgrounds.svg);
+ }
+
+ #shortcutsIcon {
+ -webkit-mask-image: url(icons/link.svg);
+ }
+
+ #themesIcon {
+ -webkit-mask-image: url(icons/colors.svg);
+ }
+
+ #backButton {
+ --cr-icon-button-fill-color: var(--ntp-primary-text-color);
+ margin-inline-end: 4px;
+ /* So that the arrow aligns with the grid. */
+ margin-inline-start: -12px;
+ }
+</style>
+<cr-dialog id="dialog" show-on-attach>
+ <div slot="title">
+ <div id="leftTitleSpacer"></div>
+ <div id="title">
+ <div id="titleText" hidden="[[showTitleNavigation_]]">
+ $i18n{customizeThisPage}
+ </div>
+ <div id="titleNavigation" hidden="[[!showTitleNavigation_]]">
+ <cr-icon-button id="backButton" class="icon-arrow-back"
+ on-click="onBackClick_" title="$i18n{backButton}">
+ </cr-icon-button>
+ [[selectedCollection_.label]]
+ </div>
+ </div>
+ </div>
+ <div slot="body">
+ <div id="menuContainer">
+ <div id="menu">
+ <iron-selector selected-attribute="selected"
+ attr-for-selected="page-name" selected="{{selectedPage_}}"
+ on-keydown="onMenuItemKeyDown_">
+ <div class="menu-item" page-name="backgrounds" tabindex="0">
+ <div id="backgroundsIcon" class="menu-item-icon"></div>
+ $i18n{backgroundsMenuItem}
+ </div>
+ <div class="menu-item" page-name="shortcuts" tabindex="0">
+ <div id="shortcutsIcon" class="menu-item-icon"></div>
+ $i18n{shortcutsMenuItem}
+ </div>
+ <div class="menu-item" page-name="themes" tabindex="0">
+ <div id="themesIcon" class="menu-item-icon"></div>
+ $i18n{themesMenuItem}
+ </div>
+ </iron-selector>
+ </div>
+ </div>
+ <div id="pagesContainer">
+ <div id="pages">
+ <iron-pages selected="[[selectedPage_]]" attr-for-selected="page-name">
+ <ntp-customize-backgrounds id="backgrounds" page-name="backgrounds"
+ selected-collection="{{selectedCollection_}}">
+ </ntp-customize-backgrounds>
+ <ntp-customize-shortcuts page-name="shortcuts">
+ </ntp-customize-shortcuts>
+ <ntp-customize-themes page-name="themes" theme="[[theme]]">
+ </ntp-customize-themes>
+ </iron-pages>
+ </div>
+ </div>
+ </div>
+ <div slot="button-container">
+ <cr-button class="cancel-button" on-click="onCancelClick_">
+ $i18n{cancelButton}
+ </cr-button>
+ <cr-button class="action-button" on-click="onDoneClick_">
+ $i18n{doneButton}
+ </cr-button>
+ </div>
+</cr-dialog>
diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_dialog.js b/chromium/chrome/browser/resources/new_tab_page/customize_dialog.js
new file mode 100644
index 00000000000..64d1dc6b590
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/customize_dialog.js
@@ -0,0 +1,124 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
+import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
+import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
+import './customize_backgrounds.js';
+import './customize_shortcuts.js';
+import './customize_themes.js';
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {BrowserProxy} from './browser_proxy.js';
+import {createScrollBorders} from './utils.js';
+
+/**
+ * Dialog that lets the user customize the NTP such as the background color or
+ * image.
+ */
+class CustomizeDialogElement extends PolymerElement {
+ static get is() {
+ return 'ntp-customize-dialog';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @type {!newTabPage.mojom.Theme} */
+ theme: Object,
+
+ /** @private */
+ selectedPage_: {
+ type: String,
+ value: 'backgrounds',
+ observer: 'onSelectedPageChange_',
+ },
+
+ /** @private {newTabPage.mojom.BackgroundCollection} */
+ selectedCollection_: Object,
+
+ /** @private */
+ showTitleNavigation_: {
+ type: Boolean,
+ computed:
+ 'computeShowTitleNavigation_(selectedPage_, selectedCollection_)',
+ value: false,
+ },
+ };
+ }
+
+ constructor() {
+ super();
+ /** @private {newTabPage.mojom.PageHandlerRemote} */
+ this.pageHandler_ = BrowserProxy.getInstance().handler;
+ /** @private {!Array<!IntersectionObserver>} */
+ this.intersectionObservers_ = [];
+ }
+
+ /** @override */
+ disconnectedCallback() {
+ super.disconnectedCallback();
+ this.intersectionObservers_.forEach(observer => {
+ observer.disconnect();
+ });
+ this.intersectionObservers_ = [];
+ }
+
+ /** @override */
+ ready() {
+ super.ready();
+ this.intersectionObservers_ = [
+ this.$.menu,
+ this.$.pages,
+ ].map(createScrollBorders);
+ }
+
+ /** @private */
+ onCancelClick_() {
+ this.pageHandler_.revertThemeChanges();
+ this.$.dialog.cancel();
+ }
+
+ /** @private */
+ onDoneClick_() {
+ this.pageHandler_.confirmThemeChanges();
+ this.shadowRoot.querySelector('ntp-customize-shortcuts').apply();
+ this.$.dialog.close();
+ }
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onMenuItemKeyDown_(e) {
+ if (!['Enter', ' '].includes(e.key)) {
+ return;
+ }
+ e.preventDefault();
+ e.stopPropagation();
+ this.selectedPage_ = e.target.getAttribute('page-name');
+ }
+
+ /** @private */
+ onSelectedPageChange_() {
+ this.$.pages.scrollTop = 0;
+ }
+
+ /** @private */
+ computeShowTitleNavigation_() {
+ return this.selectedPage_ === 'backgrounds' && this.selectedCollection_;
+ }
+
+ /** @private */
+ onBackClick_() {
+ this.selectedCollection_ = null;
+ }
+}
+
+customElements.define(CustomizeDialogElement.is, CustomizeDialogElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_shortcuts.html b/chromium/chrome/browser/resources/new_tab_page/customize_shortcuts.html
new file mode 100644
index 00000000000..7689938f87a
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/customize_shortcuts.html
@@ -0,0 +1,274 @@
+<style include="cr-icons">
+ :host {
+ line-height: 20px;
+ }
+
+ #options {
+ display: flex;
+ }
+
+ .option {
+ margin-inline-end: 9px;
+ width: 268px;
+ }
+
+ .option-image {
+ border: 1px solid var(--ntp-border-color);
+ border-radius: 4px;
+ box-sizing: border-box;
+ cursor: pointer;
+ height: 176px;
+ outline: none;
+ position: relative;
+ width: 268px;
+ }
+
+ .selected .option-image {
+ background-color: var(--ntp-selected-background-color);
+ border-color: var(--ntp-selected-border-color);
+ }
+
+ .option-mini {
+ background-color: var(--ntp-background-override-color);
+ border: 1px solid var(--ntp-border-color);
+ border-radius: 4px;
+ box-sizing: border-box;
+ height: 144px;
+ position: absolute;
+ right: 40px;
+ top: 16px;
+ width: 144px;
+ }
+
+ html[dir=rtl] .option-mini {
+ left: 40px;
+ right: unset;
+ }
+
+ .selected .option-mini {
+ border-color: transparent;
+ box-shadow: 0 1px 3px 0 rgba(var(--google-grey-800-rgb), .3),
+ 0 4px 8px 3px rgba(var(--google-grey-800-rgb), .15);
+ }
+
+ @media (prefers-color-scheme: dark) {
+ .selected .option-mini {
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .3),
+ 0 4px 8px 3px rgba(0, 0, 0, .15);
+ }
+ }
+
+ ntp-mini-page {
+ --mini-page-shortcut-color: var(--google-grey-refresh-500);
+ }
+
+ .selected ntp-mini-page {
+ --mini-page-shortcut-color: var(--ntp-selected-border-color);
+ }
+
+ .option-icon {
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background: 96px 96px var(--ntp-border-color);
+ height: 96px;
+ left: 16px;
+ position: absolute;
+ top: 48px;
+ width: 96px;
+ }
+
+ #optionCustomLinks .option-icon {
+ -webkit-mask-image: url(icons/account_circle.svg);
+ }
+
+ #optionMostVisited .option-icon {
+ -webkit-mask-image: url(icons/generic_globe.svg);
+ }
+
+ html[dir=rtl] .option-icon {
+ right: 16px;
+ }
+
+ .selected .option-icon {
+ background-color: var(--ntp-selected-light-background-color);
+ }
+
+ @media (prefers-color-scheme: dark) {
+ .selected .option-icon {
+ background-color: var(--ntp-selected-border-color);
+ }
+ }
+
+ .option-image .selected-circle {
+ box-shadow: 0 3px 6px 1px rgba(0, 0, 0, .16),
+ 0 1px 2px 1px rgba(0, 0, 0, .23);
+ height: 22px;
+ left: 209px;
+ top: 9px;
+ width: 22px;
+ }
+
+ html[dir=rtl] .option-image .selected-circle {
+ left: 0;
+ right: 209px;
+ }
+
+ .option-image .selected-check {
+ left: initial;
+ right: 32px;
+ top: 6px;
+ }
+
+ html[dir=rtl] .option-image .selected-check {
+ left: 32px;
+ right: initial;
+ }
+
+ .option-title {
+ font-weight: bold;
+ margin: 8px 0;
+ }
+
+ #hide {
+ align-items: center;
+ border: 1px solid var(--ntp-border-color);
+ border-radius: 4px;
+ box-sizing: border-box;
+ display: flex;
+ height: 64px;
+ margin-top: 24px;
+ max-width: 544px;
+ width: 100%;
+ }
+
+ #hide.selected {
+ background-color: var(--ntp-selected-background-color);
+ border-color: var(--ntp-selected-border-color);
+ color: var(--ntp-selected-border-color);
+ }
+
+ #hideIcon {
+ margin-inline-end: 20px;
+ margin-inline-start: 24px;
+ }
+
+ .selected #hideIcon {
+ background-color: var(--ntp-selected-border-color);
+ }
+
+ #hideTitleContainer {
+ flex-grow: 1;
+ }
+
+ #hideTitle {
+ font-weight: bold;
+ }
+
+ cr-toggle {
+ margin-inline-end: 20px;
+ }
+
+ .selected-circle {
+ background: var(--ntp-background-override-color) no-repeat center;
+ border-radius: 50%;
+ display: none;
+ height: 22px;
+ left: 66px;
+ position: absolute;
+ top: 46px;
+ width: 22px;
+ }
+
+ html[dir=rtl] .selected-circle {
+ left: auto;
+ right: 66px;
+ }
+
+ .selected-check {
+ background: url(icons/check_circle.svg) no-repeat center;
+ background-size: 28px 28px;
+ display: none;
+ height: 28px;
+ left: 63px;
+ position: absolute;
+ top: 43px;
+ width: 28px;
+ }
+
+ .selected :-webkit-any(.selected-circle, .selected-check) {
+ display: block;
+ }
+
+ html[dir=rtl] .selected-check {
+ left: auto;
+ right: 63px;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ .selected-check {
+ background: transparent;
+ }
+ }
+
+ /* We use ::after without content to provide the masked check element. */
+ @media (prefers-color-scheme: dark) {
+ .selected-check::after {
+ -webkit-mask-image: url(icons/check_circle.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 28px;
+ background-color: var(--google-blue-refresh-300);
+ content: '';
+ display: block;
+ height: 28px;
+ left: 0;
+ position: absolute;
+ top: 0;
+ width: 28px;
+ }
+ }
+</style>
+<div id="options">
+ <div id="optionCustomLinks"
+ class$="option [[getCustomLinksSelected_(customLinksEnabled_, hide_)]]">
+ <div id="optionCustomLinksButton" class="option-image" tabindex="0"
+ role="button"
+ aria-pressed$="[[getCustomLinksAriaPressed_(customLinksEnabled_,
+ hide_)]]"
+ title="$i18n{myShortcuts}" on-click="onCustomLinksClick_">
+ <div class="option-icon"></div>
+ <div class="option-mini">
+ <ntp-mini-page></ntp-mini-page>
+ </div>
+ <div class="selected-circle"></div>
+ <div class="selected-check"></div>
+ </div>
+ <div class="option-title">$i18n{myShortcuts}</div>
+ $i18n{shortcutsCurated}
+ </div>
+ <div id="optionMostVisited"
+ class$="option [[getMostVisitedSelected_(customLinksEnabled_, hide_)]]">
+ <div id="optionMostVisitedButton" class="option-image" tabindex="0"
+ role="button"
+ aria-pressed$="[[getMostVisitedAriaPressed_(customLinksEnabled_,
+ hide_)]]"
+ title="$i18n{mostVisited}" on-click="onMostVisitedClick_">
+ <div class="option-icon"></div>
+ <div class="option-mini">
+ <ntp-mini-page></ntp-mini-page>
+ </div>
+ <div class="selected-circle"></div>
+ <div class="selected-check"></div>
+ </div>
+ <div class="option-title">$i18n{mostVisited}</div>
+ $i18n{shortcutsSuggested}
+ </div>
+</div>
+<div id="hide" class$="[[getHideClass_(hide_)]]">
+ <div id="hideIcon" class="cr-icon icon-visibility-off"></div>
+ <div id="hideTitleContainer">
+ <div id="hideTitle">$i18n{hideShortcuts}</div>
+ $i18n{hideShortcutsDesc}
+ </div>
+ <cr-toggle id="hideToggle" title="$i18n{hideShortcuts}" checked="[[hide_]]"
+ on-change="onHideChange_"></cr-toggle>
+</div>
diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_shortcuts.js b/chromium/chrome/browser/resources/new_tab_page/customize_shortcuts.js
new file mode 100644
index 00000000000..6aef1a199f1
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/customize_shortcuts.js
@@ -0,0 +1,130 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import './mini_page.js';
+import 'chrome://resources/cr_elements/cr_icons_css.m.js';
+import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js';
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {BrowserProxy} from './browser_proxy.js';
+
+/** Element that lets the user configure shortcut settings. */
+class CustomizeShortcutsElement extends PolymerElement {
+ static get is() {
+ return 'ntp-customize-shortcuts';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @private */
+ customLinksEnabled_: Boolean,
+
+ /** @private */
+ hide_: Boolean,
+ };
+ }
+
+ constructor() {
+ super();
+ const {callbackRouter, handler} = BrowserProxy.getInstance();
+ /** @private {!newTabPage.mojom.PageCallbackRouter} */
+ this.callbackRouter_ = callbackRouter;
+ /** @private {newTabPage.mojom.PageHandlerRemote} */
+ this.pageHandler_ = handler;
+ /** @private {?number} */
+ this.setMostVisitedInfoListenerId_ = null;
+ }
+
+ /** @override */
+ connectedCallback() {
+ super.connectedCallback();
+ this.setMostVisitedInfoListenerId_ =
+ this.callbackRouter_.setMostVisitedInfo.addListener(info => {
+ this.customLinksEnabled_ = info.customLinksEnabled;
+ this.hide_ = !info.visible;
+ });
+ this.pageHandler_.updateMostVisitedInfo();
+ }
+
+ /** @override */
+ disconnectedCallback() {
+ super.disconnectedCallback();
+ this.callbackRouter_.removeListener(
+ assert(this.setMostVisitedInfoListenerId_));
+ }
+
+ apply() {
+ this.pageHandler_.setMostVisitedSettings(
+ this.customLinksEnabled_, /* visible= */ !this.hide_);
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getCustomLinksAriaPressed_() {
+ return !this.hide_ && this.customLinksEnabled_ ? 'true' : 'false';
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getCustomLinksSelected_() {
+ return !this.hide_ && this.customLinksEnabled_ ? 'selected' : '';
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getHideClass_() {
+ return this.hide_ ? 'selected' : '';
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getMostVisitedAriaPressed_() {
+ return !this.hide_ && !this.customLinksEnabled_ ? 'true' : 'false';
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getMostVisitedSelected_() {
+ return !this.hide_ && !this.customLinksEnabled_ ? 'selected' : '';
+ }
+
+ /** @private */
+ onCustomLinksClick_() {
+ this.customLinksEnabled_ = true;
+ this.hide_ = false;
+ }
+
+ /**
+ * @param {!CustomEvent<boolean>} e
+ * @private
+ */
+ onHideChange_(e) {
+ this.hide_ = e.detail;
+ }
+
+
+ /** @private */
+ onMostVisitedClick_() {
+ this.customLinksEnabled_ = false;
+ this.hide_ = false;
+ }
+}
+
+customElements.define(CustomizeShortcutsElement.is, CustomizeShortcutsElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_themes.html b/chromium/chrome/browser/resources/new_tab_page/customize_themes.html
new file mode 100644
index 00000000000..bd90bd9f961
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/customize_themes.html
@@ -0,0 +1,146 @@
+<style>
+ #thirdPartyThemeContainer {
+ width: 100%;
+ }
+
+ #thirdPartyTheme {
+ align-items: center;
+ border-radius: 5px;
+ border: 1px solid var(--ntp-border-color);
+ color: var(--ntp-primary-text-color);
+ display: flex;
+ flex-direction: row;
+ margin-bottom: 24px;
+ padding: 0 16px;
+ }
+
+ #thirdPartyBrushIcon {
+ -webkit-mask-image: url(icons/brush.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--ntp-primary-text-color);
+ height: 24px;
+ margin-inline-end: 20px;
+ width: 24px;
+ }
+
+ #thirdPartyThemeNameContainer {
+ flex-grow: 1;
+ margin-inline-end: 24px;
+ }
+
+ #thirdPartyThemeName {
+ font-weight: bold;
+ }
+
+ #thirdPartyLink {
+ -webkit-mask-image: url(chrome://resources/images/open_in_new.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--ntp-primary-text-color);
+ height: 20px;
+ margin-inline-end: 24px;
+ width: 20px;
+ }
+
+ #uninstallThirdPartyButton {
+ margin: 16px 0;
+ }
+
+ #themesContainer {
+ --ntp-grid-gap: 20px;
+ padding: 3px;
+ }
+
+ #themesContainer > * {
+ outline-width: 0;
+ }
+
+ :host-context(.focus-outline-visible) #themesContainer > *:focus {
+ box-shadow: 0 0 0 2px rgba(var(--google-blue-600-rgb), .4);
+ }
+
+ #autogeneratedThemeContainer {
+ display: flex;
+ position: relative;
+ }
+
+ #colorPickerIcon {
+ -webkit-mask-image: url(icons/colorize.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--google-grey-refresh-700);
+ height: 20px;
+ left: calc(50% - 10px);
+ position: absolute;
+ top: calc(50% - 10px);
+ width: 20px;
+ }
+
+ #autogeneratedTheme {
+ --ntp-theme-icon-frame-color: var(--google-grey-refresh-100);
+ --ntp-theme-icon-active-tab-color: white;
+ --ntp-theme-icon-stroke-color: var(--google-grey-refresh-300);
+ }
+
+ #defaultTheme {
+ --ntp-theme-icon-frame-color: rgb(222, 225, 230);
+ --ntp-theme-icon-active-tab-color: white;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ #defaultTheme {
+ --ntp-theme-icon-frame-color: rgb(var(--google-grey-900-rgb));
+ --ntp-theme-icon-active-tab-color: rgb(50, 54, 57);
+ }
+ }
+
+</style>
+<div id="thirdPartyThemeContainer" hidden="[[!isThirdPartyTheme_(theme)]]">
+ <div id="thirdPartyTheme">
+ <div id="thirdPartyBrushIcon"></div>
+ <div id="thirdPartyThemeNameContainer">
+ <div id="thirdPartyThemeName" >
+ [[theme.info.thirdPartyThemeInfo.name]]
+ </div>
+ <div>
+ $i18n{thirdPartyThemeDescription}
+ </div>
+ </div>
+ <a id="thirdPartyLink" target="_blank"
+ href$="[[getThirdPartyLink_(theme.info.thirdPartyThemeInfo.id)]]">
+ </a>
+ <cr-button id="uninstallThirdPartyButton"
+ on-click="onUninstallThirdPartyThemeClick_">
+ $i18n{uninstallThirdPartyThemeButton}
+ </cr-button>
+ </div>
+</div>
+<input id="colorPicker" type="color" on-change="onCustomFrameColorChange_"
+ hidden>
+</input>
+<ntp-grid id="themesContainer" columns="6">
+ <div id="autogeneratedThemeContainer" tabindex="0"
+ on-click="onAutogeneratedThemeClick_">
+ <ntp-theme-icon id="autogeneratedTheme" title="$i18n{colorPickerLabel}"
+ selected$="[[isThemeIconSelected_('autogenerated', theme)]]">
+ </ntp-theme-icon>
+ <div id="colorPickerIcon"></div>
+ </div>
+ <ntp-theme-icon id="defaultTheme" title="$i18n{defaultThemeLabel}"
+ on-click="onDefaultThemeClick_" tabindex="0"
+ selected$="[[isThemeIconSelected_('default', theme)]]">
+ </ntp-theme-icon>
+ <dom-repeat id="themes" items="[[chromeThemes_]]">
+ <template>
+ <ntp-theme-icon title="[[item.label]]" on-click="onChromeThemeClick_"
+ style="--ntp-theme-icon-frame-color:
+ [[skColorToRgb_(item.colors.frame)]];
+ --ntp-theme-icon-active-tab-color:
+ [[skColorToRgb_(item.colors.activeTab)]];"
+ tabindex="0"
+ selected$="[[isThemeIconSelected_(item.id, theme)]]">
+ </ntp-theme-icon>
+ </template>
+ </dom-repeat>
+</ntp-grid>
diff --git a/chromium/chrome/browser/resources/new_tab_page/customize_themes.js b/chromium/chrome/browser/resources/new_tab_page/customize_themes.js
new file mode 100644
index 00000000000..1fab40bd1d2
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/customize_themes.js
@@ -0,0 +1,151 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import './grid.js';
+import './theme_icon.js';
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {BrowserProxy} from './browser_proxy.js';
+import {hexColorToSkColor, skColorToRgb} from './utils.js';
+
+/** Element that lets the user configure the theme. */
+class CustomizeThemesElement extends PolymerElement {
+ static get is() {
+ return 'ntp-customize-themes';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @type {!newTabPage.mojom.Theme} */
+ theme: {
+ type: Object,
+ observer: 'onThemeChange_',
+ },
+
+ /** @private {!Array<!newTabPage.mojom.ChromeTheme>} */
+ chromeThemes_: Array,
+ };
+ }
+
+ constructor() {
+ super();
+ /** @private {newTabPage.mojom.PageHandlerRemote} */
+ this.pageHandler_ = BrowserProxy.getInstance().handler;
+ this.pageHandler_.getChromeThemes().then(({chromeThemes}) => {
+ this.chromeThemes_ = chromeThemes;
+ });
+ }
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onCustomFrameColorChange_(e) {
+ this.pageHandler_.applyAutogeneratedTheme(
+ hexColorToSkColor(e.target.value));
+ }
+
+ /** @private */
+ onAutogeneratedThemeClick_() {
+ this.$.colorPicker.click();
+ }
+
+ /** @private */
+ onDefaultThemeClick_() {
+ this.pageHandler_.applyDefaultTheme();
+ }
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onChromeThemeClick_(e) {
+ this.pageHandler_.applyChromeTheme(
+ this.$.themes.itemForElement(e.target).id);
+ }
+
+ /** private */
+ onThemeChange_() {
+ if (this.theme.type !== newTabPage.mojom.ThemeType.AUTOGENERATED) {
+ return;
+ }
+ const rgbFrameColor =
+ skColorToRgb(this.theme.info.autogeneratedThemeColors.frame);
+ const rgbActiveTabColor =
+ skColorToRgb(this.theme.info.autogeneratedThemeColors.activeTab);
+ this.$.autogeneratedTheme.style.setProperty(
+ '--ntp-theme-icon-frame-color', rgbFrameColor);
+ this.$.autogeneratedTheme.style.setProperty(
+ '--ntp-theme-icon-stroke-color', rgbFrameColor);
+ this.$.autogeneratedTheme.style.setProperty(
+ '--ntp-theme-icon-active-tab-color', rgbActiveTabColor);
+ this.$.colorPickerIcon.style.setProperty(
+ 'background-color', skColorToRgb(this.theme.shortcutTextColor));
+ }
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onUninstallThirdPartyThemeClick_(e) {
+ this.pageHandler_.applyDefaultTheme();
+ this.pageHandler_.confirmThemeChanges();
+ }
+
+ /**
+ * @param {string|number} id
+ * @return {boolean}
+ * @private
+ */
+ isThemeIconSelected_(id) {
+ if (!this.theme) {
+ return false;
+ }
+ if (id === 'autogenerated') {
+ return this.theme.type === newTabPage.mojom.ThemeType.AUTOGENERATED;
+ } else if (id === 'default') {
+ return this.theme.type === newTabPage.mojom.ThemeType.DEFAULT;
+ } else {
+ return this.theme.type === newTabPage.mojom.ThemeType.CHROME &&
+ id === this.theme.info.chromeThemeId;
+ }
+ }
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isThirdPartyTheme_() {
+ return this.theme.type === newTabPage.mojom.ThemeType.THIRD_PARTY;
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getThirdPartyLink_() {
+ if (!this.isThirdPartyTheme_()) {
+ return '';
+ }
+ return 'https://chrome.google.com/webstore/detail/' +
+ this.theme.info.thirdPartyThemeInfo.id;
+ }
+
+ /**
+ * @param {skia.mojom.SkColor} skColor
+ * @return {string}
+ * @private
+ */
+ skColorToRgb_(skColor) {
+ return skColorToRgb(skColor);
+ }
+}
+
+customElements.define(CustomizeThemesElement.is, CustomizeThemesElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/fakebox.html b/chromium/chrome/browser/resources/new_tab_page/fakebox.html
new file mode 100644
index 00000000000..ef01fba11c6
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/fakebox.html
@@ -0,0 +1,126 @@
+<style>
+ :host {
+ --ntp-fakebox-height: 44px;
+ background-color: white;
+ border-radius: calc(0.5 * var(--ntp-fakebox-height));
+ box-shadow: 0 1px 6px 0 rgba(32, 33, 36, .28);
+ height: var(--ntp-fakebox-height);
+ position: relative;
+ width: 337px;
+ }
+
+ @media (min-width: 560px) {
+ :host {
+ width: 449px;
+ }
+ }
+
+ @media (min-width: 672px) {
+ :host {
+ width: 561px;
+ }
+ }
+
+ :host([hidden_]) {
+ visibility: hidden;
+ }
+
+ :host > * {
+ bottom: 0;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+
+ #controls {
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ left: 16px;
+ pointer-events: none;
+ right: 16px;
+ }
+
+ input {
+ border: 0;
+ opacity: 0;
+ padding: 0;
+ width: 100%;
+ }
+
+ #searchIcon {
+ -webkit-mask-image: url(chrome://resources/images/icon_search.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--ntp-secondary-text-color);
+ height: 21px;
+ width: 21px;
+ }
+
+ @keyframes blink {
+ 0% {
+ opacity: 1;
+ }
+ 61.55% {
+ opacity: 0;
+ }
+ }
+
+ #fakeCursor {
+ background-color: var(--ntp-secondary-text-color);
+ height: 1rem;
+ margin-inline-start: 11px;
+ visibility: hidden;
+ width: 1px;
+ }
+
+ :host([focused_]) #fakeCursor {
+ animation: blink 1.3s step-end infinite;
+ visibility: visible;
+ }
+
+ :host([dragged_]) #fakeCursor {
+ visibility: visible;
+ }
+
+ #hint {
+ color: var(--ntp-secondary-text-color);
+ flex-grow: 1;
+ font-size: 1rem;
+ margin-inline-start: 3px;
+ }
+
+ :host([focused_]) #hint,
+ :host([dragged_]) #hint {
+ visibility: hidden;
+ }
+
+ #voiceSearchButton {
+ background: url(icons/googlemic_clr_24px.svg) no-repeat center;
+ background-size: 21px 21px;
+ border: none;
+ cursor: pointer;
+ height: 21px;
+ outline: none;
+ padding: 0;
+ pointer-events: auto;
+ width: 21px;
+ }
+
+ :host-context(.focus-outline-visible) #voiceSearchButton:focus {
+ box-shadow: 0 0 0 2px var(--ntp-focus-shadow-color);
+ }
+</style>
+<input id="input" on-mousedown="onMousedown_" on-paste="onPaste_"
+ on-dragenter="onDragenter_" on-dragleave="onDragleave_" on-drop="onDrop_"
+ autocomplete="off" tabindex="-1" type="url" aria-hidden="true">
+</input>
+<div id="controls">
+ <div id="searchIcon"></div>
+ <div id="fakeCursor"></div>
+ <div id="hint">$i18n{searchBoxHint}</div>
+ <button id="voiceSearchButton" on-click="onVoiceSearchClick_"
+ title="$i18n{voiceSearchButtonLabel}">
+ </button>
+</div>
diff --git a/chromium/chrome/browser/resources/new_tab_page/fakebox.js b/chromium/chrome/browser/resources/new_tab_page/fakebox.js
new file mode 100644
index 00000000000..621159904f8
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/fakebox.js
@@ -0,0 +1,125 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {BrowserProxy} from './browser_proxy.js';
+
+// A fake search box that moves focus and input to the omnibox when interacted
+// with.
+class FakeboxElement extends PolymerElement {
+ static get is() {
+ return 'ntp-fakebox';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @private */
+ focused_: {
+ reflectToAttribute: true,
+ type: Boolean,
+ },
+
+ /** @private */
+ hidden_: {
+ reflectToAttribute: true,
+ type: Boolean,
+ },
+
+ /** @private */
+ dragged_: {
+ reflectToAttribute: true,
+ type: Boolean,
+ },
+ };
+ }
+
+ constructor() {
+ super();
+ /** @private {newTabPage.mojom.PageHandlerRemote} */
+ this.pageHandler_ = BrowserProxy.getInstance().handler;
+ /** @private {!newTabPage.mojom.PageCallbackRouter} */
+ this.callbackRouter_ = BrowserProxy.getInstance().callbackRouter;
+ /** @private {?number} */
+ this.setFakeboxFocusedListenerId_ = null;
+ /** @private {?number} */
+ this.setFakeboxVisibleListenerId_ = null;
+ }
+
+ /** @override */
+ connectedCallback() {
+ super.connectedCallback();
+ this.setFakeboxFocusedListenerId_ =
+ this.callbackRouter_.setFakeboxFocused.addListener(focused => {
+ this.focused_ = focused;
+ this.dragged_ = false;
+ });
+ this.setFakeboxVisibleListenerId_ =
+ this.callbackRouter_.setFakeboxVisible.addListener(visible => {
+ this.hidden_ = !visible;
+ });
+ }
+
+ /** @override */
+ disconnectedCallback() {
+ super.disconnectedCallback();
+ this.callbackRouter_.removeListener(
+ assert(this.setFakeboxFocusedListenerId_));
+ this.callbackRouter_.removeListener(
+ assert(this.setFakeboxVisibleListenerId_));
+ }
+
+ /** @private */
+ onMousedown_() {
+ this.pageHandler_.focusOmnibox();
+ }
+
+ /**
+ * @param {Event} e
+ * @private
+ */
+ onPaste_(e) {
+ e.preventDefault();
+ const text = e.clipboardData.getData('text/plain');
+ if (!text) {
+ return;
+ }
+ this.pageHandler_.pasteIntoOmnibox(text);
+ }
+
+ /** @private */
+ onDragenter_() {
+ this.dragged_ = true;
+ }
+
+ /** @private */
+ onDragleave_() {
+ this.dragged_ = false;
+ }
+
+ /**
+ * @param {Event} e
+ * @private
+ */
+ onDrop_(e) {
+ e.preventDefault();
+ const text = e.dataTransfer.getData('text/plain');
+ if (!text) {
+ return;
+ }
+ this.pageHandler_.focusOmnibox();
+ this.pageHandler_.pasteIntoOmnibox(text);
+ }
+
+ /** @private */
+ onVoiceSearchClick_() {
+ this.dispatchEvent(new Event('open-voice-search'));
+ }
+}
+
+customElements.define(FakeboxElement.is, FakeboxElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/grid.html b/chromium/chrome/browser/resources/new_tab_page/grid.html
new file mode 100644
index 00000000000..92119115c0a
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/grid.html
@@ -0,0 +1,21 @@
+<style>
+ :host {
+ --ntp-grid-gap: 0px;
+ }
+
+ #grid {
+ display: grid;
+ grid-column-gap: var(--ntp-grid-gap);
+ grid-row-gap: var(--ntp-grid-gap);
+ grid-template-columns: repeat(var(--columns), auto);
+ width: fit-content;
+ }
+
+ ::slotted(*) {
+ align-self: center;
+ justify-self: center;
+ }
+</style>
+<div id="grid" on-keydown="onKeyDown_" style="--columns: [[columns]];">
+ <slot id="items"></slot>
+</div>
diff --git a/chromium/chrome/browser/resources/new_tab_page/grid.js b/chromium/chrome/browser/resources/new_tab_page/grid.js
new file mode 100644
index 00000000000..7d7aa357eb2
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/grid.js
@@ -0,0 +1,82 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+// Displays children in a two-dimensional grid and supports focusing children
+// with arrow keys.
+class GridElement extends PolymerElement {
+ static get is() {
+ return 'ntp-grid';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @type {number} */
+ columns: {
+ type: Number,
+ value: 1,
+ },
+ };
+ }
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onKeyDown_(e) {
+ if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(e.key)) {
+ e.preventDefault();
+ const items = this.$.items.assignedElements().filter(
+ (el) =>
+ (!!(el.offsetWidth || el.offsetHeight ||
+ el.getClientRects().length)));
+ const currentIndex = items.indexOf(e.target);
+ const isRtl = window.getComputedStyle(this)['direction'] === 'rtl';
+ const bottomRowColumns = items.length % this.columns;
+ const direction = ['ArrowRight', 'ArrowDown'].includes(e.key) ? 1 : -1;
+ const inEdgeRow = direction === 1 ?
+ currentIndex >= items.length - bottomRowColumns :
+ currentIndex < this.columns;
+ let delta = 0;
+ switch (e.key) {
+ case 'ArrowLeft':
+ case 'ArrowRight':
+ delta = direction * (isRtl ? -1 : 1);
+ break;
+ case 'ArrowUp':
+ case 'ArrowDown':
+ delta = direction * (inEdgeRow ? bottomRowColumns : this.columns);
+ break;
+ }
+ // Handle cases where we move to an empty space in a non-full bottom row
+ // and have to jump to the next row.
+ if (e.key === 'ArrowUp' && inEdgeRow &&
+ currentIndex >= bottomRowColumns) {
+ delta -= this.columns;
+ } else if (
+ e.key === 'ArrowDown' && !inEdgeRow &&
+ currentIndex + delta >= items.length) {
+ delta += bottomRowColumns;
+ }
+ const mod = function(m, n) {
+ return ((m % n) + n) % n;
+ };
+ const newIndex = mod(currentIndex + delta, items.length);
+ items[newIndex].focus();
+ }
+
+ if (['Enter', ' '].includes(e.key)) {
+ e.preventDefault();
+ e.stopPropagation();
+ e.target.click();
+ }
+ }
+}
+
+customElements.define(GridElement.is, GridElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/account_circle.svg b/chromium/chrome/browser/resources/new_tab_page/icons/account_circle.svg
new file mode 100644
index 00000000000..2e0cc46fe19
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/account_circle.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="#626262"><path d="M24 4C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4zm0 6c3.31 0 6 2.69 6 6 0 3.32-2.69 6-6 6s-6-2.68-6-6c0-3.31 2.69-6 6-6zm0 28.4c-5.01 0-9.41-2.56-12-6.44.05-3.97 8.01-6.16 12-6.16s11.94 2.19 12 6.16c-2.59 3.88-6.99 6.44-12 6.44z"/><path d="M0 0h48v48H0z" fill="none"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/backgrounds.svg b/chromium/chrome/browser/resources/new_tab_page/icons/backgrounds.svg
new file mode 100644
index 00000000000..56d60758a68
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/backgrounds.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2V4zm6 9l-4 5h12l-3-4-2.03 2.71L10 13zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5zM20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2zm0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z" id="a"/></defs><use xlink:href="#a"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/brush.svg b/chromium/chrome/browser/resources/new_tab_page/icons/brush.svg
new file mode 100644
index 00000000000..f6d29d556ac
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/brush.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M7 14c-1.66 0-3 1.34-3 3 0 1.31-1.16 2-2 2 .92 1.22 2.49 2 4 2 2.21 0 4-1.79 4-4 0-1.66-1.34-3-3-3zm13.71-9.37l-1.34-1.34a.996.996 0 0 0-1.41 0L9 12.25 11.75 15l8.96-8.96a.996.996 0 0 0 0-1.41z"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/check_circle.svg b/chromium/chrome/browser/resources/new_tab_page/icons/check_circle.svg
new file mode 100644
index 00000000000..229cedea3a9
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/check_circle.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 48 48" fill="#4285F4"><path d="M0 0h48v48H0z" fill="none"/><path d="M24 4C12.95 4 4 12.95 4 24c0 11.04 8.95 20 20 20 11.04 0 20-8.96 20-20 0-11.05-8.96-20-20-20zm-4 30L10 24l2.83-2.83L20 28.34l15.17-15.17L38 16 20 34z"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/colorize.svg b/chromium/chrome/browser/resources/new_tab_page/icons/colorize.svg
new file mode 100644
index 00000000000..984de18801f
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/colorize.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path fill="none" d="M0 0h24v24H0V0z"/><path d="M17.66 5.41l.92.92-2.69 2.69-.92-.92 2.69-2.69M17.67 3c-.26 0-.51.1-.71.29l-3.12 3.12-1.93-1.91-1.41 1.41 1.42 1.42L3 16.25V21h4.75l8.92-8.92 1.42 1.42 1.41-1.41-1.92-1.92 3.12-3.12c.4-.4.4-1.03.01-1.42l-2.34-2.34c-.2-.19-.45-.29-.7-.29zM6.92 19L5 17.08l8.06-8.06 1.92 1.92L6.92 19z"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/colors.svg b/chromium/chrome/browser/resources/new_tab_page/icons/colors.svg
new file mode 100644
index 00000000000..e7f9fc46a19
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/colors.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><path d="M12 3a9 9 0 0 0 0 18c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" id="a"/></defs><use xlink:href="#a"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/generic_globe.svg b/chromium/chrome/browser/resources/new_tab_page/icons/generic_globe.svg
new file mode 100644
index 00000000000..ec0b19ca19c
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/generic_globe.svg
@@ -0,0 +1 @@
+<svg width="24" height="24" xmlns="http://www.w3.org/2000/svg"><path d="M12 2c5.52 0 10 4.48 10 10s-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2zM4 12h4.4c3.407.022 4.922 1.73 4.543 5.127H9.488v2.47a8.004 8.004 0 0010.498-8.083C19.327 12.504 18.332 13 17 13c-2.137 0-3.206-.916-3.206-2.75h-3.748c-.274-2.728.683-4.092 2.87-4.092 0-.975.327-1.597.811-1.97A8.004 8.004 0 004 12z" fill="#3C4043"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/googlemic_clr_24px.svg b/chromium/chrome/browser/resources/new_tab_page/icons/googlemic_clr_24px.svg
new file mode 100644
index 00000000000..05068f863ff
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/googlemic_clr_24px.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path fill="#4285F4" d="M12 15c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v7c0 1.66 1.34 3 3 3z"/><path fill="#34A853" d="M11 18.92h2V22h-2z"/><path fill="#F4B400" d="M7 12H5c0 1.93.78 3.68 2.05 4.95l1.41-1.41C7.56 14.63 7 13.38 7 12z"/><path fill="#EA4335" d="M12 17c-1.38 0-2.63-.56-3.54-1.47l-1.41 1.41A6.99 6.99 0 0 0 12.01 19c3.87 0 6.98-3.14 6.98-7h-2c0 2.76-2.23 5-4.99 5z"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/header.svg b/chromium/chrome/browser/resources/new_tab_page/icons/header.svg
new file mode 100644
index 00000000000..e5b1f63dfb7
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/header.svg
@@ -0,0 +1 @@
+<svg width="130" height="40" xmlns="http://www.w3.org/2000/svg"><g fill="#000" fill-rule="evenodd"><path d="M39.972 16.969c-4.685 0-8.62-3.81-8.62-8.485C31.352 3.81 35.287 0 39.972 0c2.593 0 4.438 1.012 5.826 2.342l-1.635 1.631c-.995-.93-2.346-1.658-4.191-1.658-3.424 0-6.1 2.752-6.1 6.17 0 3.416 2.676 6.169 6.1 6.169 2.219 0 3.48-.894 4.292-1.695.667-.665 1.096-1.613 1.26-2.916h-5.552V7.719h7.817c.082.41.128.911.128 1.449 0 1.74-.475 3.891-2.01 5.422-1.497 1.55-3.396 2.379-5.935 2.379zm17.79-5.367c0-1.983-1.41-3.333-3.038-3.333-1.63 0-3.039 1.359-3.039 3.333 0 1.956 1.41 3.333 3.039 3.333 1.629 0 3.038-1.368 3.038-3.333zm2.37 0c0 3.168-2.425 5.5-5.408 5.5-2.984 0-5.41-2.332-5.41-5.5 0-3.186 2.426-5.5 5.41-5.5 2.983 0 5.409 2.314 5.409 5.5zm9.683 0c0-1.983-1.41-3.333-3.039-3.333-1.63 0-3.039 1.359-3.039 3.333 0 1.956 1.41 3.333 3.039 3.333 1.63.01 3.039-1.368 3.039-3.333zm2.361 0c0 3.168-2.425 5.5-5.41 5.5-2.974 0-5.408-2.332-5.408-5.5 0-3.186 2.425-5.5 5.409-5.5s5.41 2.314 5.41 5.5zm9.533.016c0-1.93-1.277-3.348-2.9-3.348-1.648 0-3.025 1.409-3.025 3.348 0 1.912 1.377 3.302 3.026 3.302 1.622 0 2.899-1.39 2.899-3.302zm2.102-5.178v9.843c0 4.052-2.365 5.708-5.164 5.708-2.637 0-4.212-1.784-4.81-3.238l2.074-.87c.372.898 1.278 1.949 2.736 1.949 1.795 0 2.899-1.125 2.899-3.22v-.786h-.082c-.533.668-1.567 1.244-2.863 1.244-2.718 0-5.2-2.388-5.2-5.461 0-3.092 2.491-5.507 5.2-5.507 1.296 0 2.33.585 2.863 1.226h.082V6.44h2.265zm2.041 10.254V.602h2.45v16.092h-2.45zm5.98-5.267L96.72 9.39c-.273-.689-1.075-1.166-2.033-1.166-1.222 0-2.917 1.083-2.855 3.204zm5.736 1.984l1.86 1.249c-.602.9-2.052 2.442-4.56 2.442-3.108 0-5.342-2.415-5.342-5.5 0-3.269 2.26-5.5 5.078-5.5 2.836 0 4.222 2.268 4.678 3.498l.246.625-7.303 3.048c.556 1.102 1.431 1.671 2.653 1.671 1.223 0 2.07-.615 2.69-1.533z"/><rect y="30" width="130" height="10" rx="5"/></g></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/icon_pencil.svg b/chromium/chrome/browser/resources/new_tab_page/icons/icon_pencil.svg
new file mode 100644
index 00000000000..b3dc49f1c3d
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/icon_pencil.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04a.996.996 0 0 0 0-1.41l-2.34-2.34a.996.996 0 0 0-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/><path d="M0 0h24v24H0z" fill="none"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/link.svg b/chromium/chrome/browser/resources/new_tab_page/icons/link.svg
new file mode 100644
index 00000000000..6f1d5f40ca4
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/link.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="none" fill-rule="evenodd"><path d="M0 0h16v16H0z"/><path fill="#fff" fill-rule="nonzero" d="M1.52 8A2.482 2.482 0 0 1 4 5.52h3.2V4H4C1.792 4 0 5.792 0 8s1.792 4 4 4h3.2v-1.52H4A2.482 2.482 0 0 1 1.52 8zm3.28.8h6.4V7.2H4.8v1.6zM12 4H8.8v1.52H12A2.482 2.482 0 0 1 14.48 8 2.482 2.482 0 0 1 12 10.48H8.8V12H12c2.208 0 4-1.792 4-4s-1.792-4-4-4z"/></g></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/mic.svg b/chromium/chrome/browser/resources/new_tab_page/icons/mic.svg
new file mode 100644
index 00000000000..9fa6c62b07e
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/mic.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M17 11.998c0 2.76-2.23 5-4.99 5l-.002.002a4.994 4.994 0 0 1-4.979-5h-2c0 3.52 2.59 6.433 5.98 6.92v3.078h.01V22h2v-3.08h-.01A6.982 6.982 0 0 0 19 11.998z"/><path fill="none" d="M0 0h24v24H0z"/><path d="M12 15c1.66 0 2.99-1.34 2.99-3L15 5c0-1.66-1.34-3-3-3S9 3.34 9 5v7c0 1.66 1.34 3 3 3z"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/icons/shortcut_circles.svg b/chromium/chrome/browser/resources/new_tab_page/icons/shortcut_circles.svg
new file mode 100644
index 00000000000..5f0822cab15
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/icons/shortcut_circles.svg
@@ -0,0 +1 @@
+<svg width="116" height="42" xmlns="http://www.w3.org/2000/svg"><path d="M6.009 11.38a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15zm52.034 0a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15zm-26.017 0a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15zm52.035 0a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15zm26.017 0a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15zM6.008 41.114a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15zm52.035 0a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15zm-26.017 0a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15zm52.035 0a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15zm26.017 0a5.575 5.575 0 110-11.15 5.575 5.575 0 010 11.15z" fill="#000" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/chromium/chrome/browser/resources/new_tab_page/logo.html b/chromium/chrome/browser/resources/new_tab_page/logo.html
new file mode 100644
index 00000000000..3b90291fbf7
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/logo.html
@@ -0,0 +1,46 @@
+<style>
+ :host(:not([hidden])) {
+ display: inline-block;
+ }
+
+ #singleColoredLogo,
+ #multiColoredLogo {
+ height: 92px;
+ margin-top: 108px;
+ width: 272px;
+ }
+
+ #singleColoredLogo {
+ -webkit-mask-image: url(chrome://resources/images/google_logo.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--ntp-logo-color);
+ }
+
+ #multiColoredLogo {
+ background-image: url(chrome://resources/images/google_logo.svg);
+ }
+
+ #iframe {
+ height: var(--height, 200px);
+ transition-duration: var(--duration, 100ms);
+ transition-property: height, width;
+ width: var(--width, 500px);
+ }
+</style>
+<iron-pages selected="[[mode_]]" attr-for-selected="id">
+ <div id="logo">
+ <!-- TODO(crbug.com/1039910): Add flower if doodle available. -->
+ <div id="singleColoredLogo" hidden="[[!singleColored]]"></div>
+ <div id="multiColoredLogo" hidden="[[singleColored]]"></div>
+ </div>
+ <div id="doodle">
+ <img id="image" src="[[imageUrl_]]" hidden="[[!imageUrl_]]"></img>
+ <ntp-untrusted-iframe id="iframe" path="[[iframeUrl_]]"
+ hidden="[[!iframeUrl_]]"
+ style="--duration: [[valueOrUnset_(duration_)]];
+ --height: [[valueOrUnset_(height_)]];
+ --width: [[valueOrUnset_(width_)]];">
+ </ntp-untrusted-iframe>
+ </div>
+</iron-pages>
diff --git a/chromium/chrome/browser/resources/new_tab_page/logo.js b/chromium/chrome/browser/resources/new_tab_page/logo.js
new file mode 100644
index 00000000000..e0ca6af58d2
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/logo.js
@@ -0,0 +1,167 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
+import './untrusted_iframe.js';
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {EventTracker} from 'chrome://resources/js/event_tracker.m.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {BrowserProxy} from './browser_proxy.js';
+
+// Shows the Google logo or a doodle if available.
+class LogoElement extends PolymerElement {
+ static get is() {
+ return 'ntp-logo';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /**
+ * If true displays doodle if one is available instead of Google logo.
+ * @type {boolean}
+ */
+ doodleAllowed: {
+ reflectToAttribute: true,
+ type: Boolean,
+ value: true,
+ },
+
+ /**
+ * If true displays the Google logo single-colored.
+ * @type {boolean}
+ */
+ singleColored: {
+ reflectToAttribute: true,
+ type: Boolean,
+ value: false,
+ },
+
+ /** @private */
+ loaded_: Boolean,
+
+ /** @private */
+ doodle_: Object,
+
+ /** @private */
+ mode_: {
+ computed: 'computeMode_(doodleAllowed, loaded_, doodle_)',
+ type: Boolean,
+ },
+
+ /** @private */
+ imageUrl_: {
+ computed: 'computeImageUrl_(doodle_)',
+ type: String,
+ },
+
+ /** @private */
+ iframeUrl_: {
+ computed: 'computeIframeUrl_(doodle_)',
+ type: String,
+ },
+
+ /** @private */
+ duration_: {
+ type: String,
+ value: null,
+ },
+
+ /** @private */
+ height_: {
+ type: String,
+ value: null,
+ },
+
+ /** @private */
+ width_: {
+ type: String,
+ value: null,
+ },
+ };
+ }
+
+ constructor() {
+ super();
+ /** @private {!EventTracker} */
+ this.eventTracker_ = new EventTracker();
+ BrowserProxy.getInstance().handler.getDoodle().then(({doodle}) => {
+ this.doodle_ = doodle;
+ this.loaded_ = true;
+ });
+ }
+
+ /** @override */
+ connectedCallback() {
+ super.connectedCallback();
+ this.eventTracker_.add(window, 'message', ({data}) => {
+ if (data['cmd'] !== 'resizeDoodle') {
+ return;
+ }
+ this.duration_ = assert(data.duration);
+ this.height_ = assert(data.height);
+ this.width_ = assert(data.width);
+ });
+ }
+
+ /** @override */
+ disconnectedCallback() {
+ super.disconnectedCallback();
+ this.eventTracker_.removeAll();
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ computeMode_() {
+ if (this.doodleAllowed) {
+ if (!this.loaded_) {
+ return 'none';
+ }
+ if (this.doodle_ &&
+ /* We hide interactive doodles when offline. Otherwise, the iframe
+ would show an ugly error page. */
+ (!this.doodle_.content.url || window.navigator.onLine)) {
+ return 'doodle';
+ }
+ }
+ return 'logo';
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ computeImageUrl_() {
+ return (this.doodle_ && this.doodle_.content.image) ?
+ this.doodle_.content.image :
+ '';
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ computeIframeUrl_() {
+ return (this.doodle_ && this.doodle_.content.url) ?
+ `iframe?${this.doodle_.content.url.url}` :
+ '';
+ }
+
+ /**
+ * @param {string} value
+ * @return {string}
+ * @private
+ */
+ valueOrUnset_(value) {
+ return value || 'unset';
+ }
+}
+
+customElements.define(LogoElement.is, LogoElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/manager.html b/chromium/chrome/browser/resources/new_tab_page/manager.html
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/chromium/chrome/browser/resources/new_tab_page/manager.html
+++ /dev/null
diff --git a/chromium/chrome/browser/resources/new_tab_page/manager.js b/chromium/chrome/browser/resources/new_tab_page/manager.js
deleted file mode 100644
index c6d0b832f07..00000000000
--- a/chromium/chrome/browser/resources/new_tab_page/manager.js
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {assert} from 'chrome://resources/js/assert.m.js';
-import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-
-import {BrowserProxy} from './browser_proxy.js';
-
-class ManagerUI extends PolymerElement {
- static get is() {
- return 'manager-ui';
- }
-
- static get template() {
- return html`{__html_template__}`;
- }
-
- constructor() {
- super();
- const browserProxy = BrowserProxy.getInstance();
- /** @private {newTabPage.mojom.PageCallbackRouter} */
- this.mojoEventTarget_ = browserProxy.callbackRouter;
- /** @private {newTabPage.mojom.PageHandlerInterface} */
- this.mojoHandler_ = browserProxy.handler;
- }
-}
-
-customElements.define(ManagerUI.is, ManagerUI);
diff --git a/chromium/chrome/browser/resources/new_tab_page/mini_page.html b/chromium/chrome/browser/resources/new_tab_page/mini_page.html
new file mode 100644
index 00000000000..4c4cfbeb308
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/mini_page.html
@@ -0,0 +1,35 @@
+<style>
+ :host {
+ --mini-page-shortcut-color: var(--google-grey-refresh-300);
+ }
+
+ .mini-page {
+ margin: auto;
+ padding-top: 26px;
+ width: fit-content;
+ }
+
+ .mini-header {
+ -webkit-mask-image: url(icons/header.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--google-grey-refresh-300);
+ height: 40px;
+ width: 130px;
+ }
+
+ .mini-shortcuts {
+ -webkit-mask-image: url(icons/shortcut_circles.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--mini-page-shortcut-color);
+ height: 42px;
+ margin-inline-start: 7px;
+ margin-top: 12px;
+ width: 116px;
+ }
+</style>
+<div class="mini-page">
+ <div class="mini-header"></div>
+ <div class="mini-shortcuts"></div>
+</div>
diff --git a/chromium/chrome/browser/resources/new_tab_page/mini_page.js b/chromium/chrome/browser/resources/new_tab_page/mini_page.js
new file mode 100644
index 00000000000..607efd2ca9a
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/mini_page.js
@@ -0,0 +1,18 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+/** Element used to display a stylized NTP image. */
+class MiniPageElement extends PolymerElement {
+ static get is() {
+ return 'ntp-mini-page';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+}
+
+customElements.define(MiniPageElement.is, MiniPageElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/most_visited.html b/chromium/chrome/browser/resources/new_tab_page/most_visited.html
new file mode 100644
index 00000000000..3c09c59a78c
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/most_visited.html
@@ -0,0 +1,216 @@
+<style include="cr-hidden-style cr-icons">
+ :host {
+ --icon-size: 48px;
+ --tile-size: 112px;
+ --tile-margin: 16px;
+ --icon-button-color: var(--google-grey-600);
+ --icon-button-color-active: var(--google-grey-refresh-700);
+ --tile-hover-color: rgba(var(--google-grey-900-rgb), .1);
+ }
+
+ #container {
+ --content-width: calc(var(--column-count) * var(--tile-size)
+ /* We add an extra pixel because rounding errors on different zooms can
+ * make the width shorter than it should be. */
+ + 1px);
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ overflow: hidden;
+ transition: opacity 300ms ease-in-out;
+ width: calc(var(--content-width) + 12px);
+ }
+
+ #addShortCutIcon {
+ -webkit-mask-image: url(chrome://resources/images/add.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--ntp-theme-text-color);
+ height: 24px;
+ width: 24px;
+ }
+
+ .tile,
+ #addShortcut {
+ -webkit-tap-highlight-color: transparent;
+ align-items: center;
+ border-radius: 4px;
+ box-sizing: border-box;
+ cursor: pointer;
+ display: flex;
+ flex-direction: column;
+ height: var(--tile-size);
+ margin-bottom: var(--tile-margin);
+ opacity: 1;
+ padding-top: var(--tile-margin);
+ position: relative;
+ text-decoration: none;
+ transition-duration: 300ms;
+ transition-property: left, top;
+ transition-timing-function: ease-in-out;
+ user-select: none;
+ width: var(--tile-size);
+ }
+
+ :host-context(html:not(.focus-outline-visible)) .tile,
+ :host-context(html:not(.focus-outline-visible)) #addShortcut {
+ outline: none;
+ }
+
+ :host(:not([reordering_])) .tile:hover,
+ :host(:not([reordering_])) #addShortcut:hover,
+ .force-hover {
+ background-color: var(--tile-hover-color);
+ }
+
+ .tile-icon {
+ align-items: center;
+ background-color: var(--ntp-theme-shortcut-background-color);
+ border-radius: 50%;
+ display: flex;
+ height: var(--icon-size);
+ justify-content: center;
+ width: var(--icon-size);
+ }
+
+ .tile-icon img {
+ height: 32px;
+ width: 32px;
+ }
+
+ .tile-title {
+ color: var(--ntp-theme-text-color);
+ margin-top: 16px;
+ overflow: hidden;
+ text-align: center;
+ text-overflow: ellipsis;
+ text-shadow: var(--ntp-theme-text-shadow);
+ white-space: nowrap;
+ width: 88px;
+ }
+
+ .title-rtl {
+ direction: rtl;
+ }
+
+ .title-ltr {
+ direction: ltr;
+ }
+
+ .tile.dragging {
+ background-color: var(--tile-hover-color);
+ transition-property: none;
+ z-index: 1;
+ }
+
+ cr-icon-button {
+ --cr-icon-button-fill-color: var(--icon-button-color);
+ --cr-icon-button-size: 28px;
+ margin: 4px 2px;
+ opacity: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ transition-property: opacity;
+ }
+
+ :host-context([dir=rtl]) cr-icon-button {
+ left: 0;
+ right: unset;
+ }
+
+ :host(:not([reordering_])) .tile:hover cr-icon-button,
+ .force-hover cr-icon-button {
+ opacity: 1;
+ transition-delay: 500ms;
+ }
+
+ :host(:not([reordering_])) cr-icon-button:active,
+ :host-context(.focus-outline-visible):host(:not([reordering_]))
+ cr-icon-button:focus,
+ :host(:not([reordering_])) cr-icon-button:hover {
+ --cr-icon-button-fill-color: var(--icon-button-color-active);
+ opacity: 1;
+ transition-delay: 0s;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ :host {
+ --icon-button-color: var(--google-grey-400);
+ --icon-button-color-active: var(--google-grey-200);
+ --tile-hover-color: rgba(255, 255, 255, .1);
+ }
+ }
+</style>
+<div id="container" style="--column-count: [[columnCount_]];">
+ <dom-repeat id="tiles" items="[[tiles_]]">
+ <template>
+ <a class="tile" draggable="true" href$="[[item.url.url]]"
+ title$="[[item.title]]" on-dragstart="onDragStart_"
+ on-touchstart="onTouchStart_"
+ hidden$="[[isHidden_(index, columnCount_)]]"
+ on-keydown="onTileKeyDown_">
+ <cr-icon-button class$="[[getTileIconButtonIcon_(customLinksEnabled_)]]"
+ on-click="onTileIconButtonClick_" tabindex="0"></cr-icon-button>
+ <div class="tile-icon">
+ <img src$="[[getFaviconUrl_(item.url)]]" draggable="false"></img>
+ </div>
+ <div class$="tile-title [[getTileTitleDirectionClass_(item)]]">
+ [[item.title]]
+ </div>
+ </a>
+ </template>
+ </dom-repeat>
+ <a id="addShortcut" tabindex="0" on-click="onAdd_" hidden$="[[!showAdd_]]"
+ title="$i18n{addLinkTitle}" on-keydown="onAddShortcutKeyDown_">
+ <div class="tile-icon">
+ <div id="addShortCutIcon" draggable="false"></div>
+ </div>
+ <div class="tile-title">$i18n{addLinkTitle}</div>
+ </a>
+ <cr-dialog id="dialog" on-close="onDialogClose_">
+ <div slot="title">[[dialogTitle_]]</div>
+ <div slot="body">
+ <cr-input id="dialogInputName" class$="[[dialogTileTitleDirectionClass_]]"
+ label="$i18n{nameField}" value="{{dialogTileTitle_}}"
+ spellcheck="false" autofocus></cr-input>
+ <cr-input id="dialogInputUrl" label="$i18n{urlField}"
+ value="{{dialogTileUrl_}}" invalid="[[dialogTileUrlInvalid_]]"
+ error-message="$i18n{invalidUrl}" spellcheck="false" type="url">
+ </cr-input>
+ </div>
+ <div slot="button-container">
+ <cr-button class="cancel-button" on-click="onDialogCancel_">
+ $i18n{linkCancel}
+ </cr-button>
+ <cr-button class="action-button" on-click="onSave_"
+ disabled$="[[!dialogTileUrl_]]">
+ $i18n{linkDone}
+ </cr-button>
+ </div>
+ </cr-dialog>
+ <cr-action-menu id="actionMenu">
+ <button id="actionMenuEdit" class="dropdown-item" on-click="onEdit_">
+ $i18n{editLinkTitle}
+ </button>
+ <button id="actionMenuRemove" class="dropdown-item" on-click="onRemove_">
+ $i18n{linkRemove}
+ </button>
+ </cr-action-menu>
+</div>
+<cr-toast id="toast" duration="10000">
+ <div>[[toastContent_]]</div>
+ <dom-if if="showToastButtons_">
+ <template>
+ <cr-button id="undo" aria-label="$i18n{undoDescription}"
+ on-click="onUndoClick_">
+ $i18n{undo}
+ </cr-button>
+ <cr-button id="restore"
+ aria-label$="[[getRestoreButtonText_(customLinksEnabled_)]]"
+ on-click="onRestoreDefaultsClick_">
+ [[getRestoreButtonText_(customLinksEnabled_)]]
+ </cr-button>
+ </template>
+ </dom-if>
+</cr-toast>
diff --git a/chromium/chrome/browser/resources/new_tab_page/most_visited.js b/chromium/chrome/browser/resources/new_tab_page/most_visited.js
new file mode 100644
index 00000000000..5d41829de26
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/most_visited.js
@@ -0,0 +1,756 @@
+// Copyright 2019 The Chromium 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 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.m.js';
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
+import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
+import 'chrome://resources/cr_elements/cr_icons_css.m.js';
+import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
+import 'chrome://resources/cr_elements/cr_toast/cr_toast.m.js';
+import 'chrome://resources/cr_elements/hidden_style_css.m.js';
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import 'chrome://resources/mojo/mojo/public/mojom/base/text_direction.mojom-lite.js';
+import './strings.m.js';
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {isMac} from 'chrome://resources/js/cr.m.js';
+import {FocusOutlineManager} from 'chrome://resources/js/cr/ui/focus_outline_manager.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {Debouncer, html, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {BrowserProxy} from './browser_proxy.js';
+
+/**
+ * @enum {number}
+ * @const
+ */
+const ScreenWidth = {
+ NARROW: 0,
+ MEDIUM: 1,
+ WIDE: 2,
+};
+
+/**
+ * @param {!HTMLElement} tile
+ * @private
+ */
+function resetTilePosition(tile) {
+ tile.style.position = '';
+ tile.style.left = '';
+ tile.style.top = '';
+}
+
+/**
+ * @param {!HTMLElement} tile
+ * @param {!{x: number, y: number}} point
+ * @private
+ */
+function setTilePosition(tile, {x, y}) {
+ tile.style.position = 'absolute';
+ tile.style.left = `${x}px`;
+ tile.style.top = `${y}px`;
+}
+
+/**
+ * @param {!Array<!DOMRect>} rects
+ * @param {number} x
+ * @param {number} y
+ * @return {number}
+ * @private
+ */
+function getHitIndex(rects, x, y) {
+ return rects.findIndex(
+ r => x >= r.left && x <= r.right && y >= r.top && y <= r.bottom);
+}
+
+class MostVisitedElement extends PolymerElement {
+ static get is() {
+ return 'ntp-most-visited';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @private */
+ columnCount_: {
+ type: Boolean,
+ computed: `computeColumnCount_(tiles_, screenWidth_, maxTiles_,
+ visible_)`,
+ },
+
+ /** @private */
+ customLinksEnabled_: Boolean,
+
+ /** @private */
+ dialogTileTitle_: String,
+
+ /** @private */
+ dialogTileTitleDirectionClass_: String,
+
+ /** @private */
+ dialogTileUrl_: String,
+
+ /** @private */
+ dialogTileUrlInvalid_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /** @private */
+ dialogTitle_: String,
+
+ /** @private */
+ isRtl_: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+
+ /**
+ * Used to hide hover style and cr-icon-button of tiles while the tiles
+ * are being reordered.
+ * @private
+ */
+ reordering_: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+
+ /** @private */
+ maxTiles_: {
+ type: Number,
+ computed: 'computeMaxTiles_(visible_, customLinksEnabled_)',
+ },
+
+ /** @private */
+ showAdd_: {
+ type: Boolean,
+ value: false,
+ computed: 'computeShowAdd_(tiles_, columnCount_, customLinksEnabled_)',
+ },
+
+ /** @private */
+ showToastButtons_: Boolean,
+
+ /** @private {!ScreenWidth} */
+ screenWidth_: Number,
+
+ /** @private {!Array<!newTabPage.mojom.MostVisitedTile>} */
+ tiles_: Array,
+
+ /** @private */
+ toastContent_: String,
+
+ /** @private */
+ visible_: Boolean,
+ };
+ }
+
+ /** @private {!Array<!HTMLElement>} */
+ get tileElements_() {
+ return /** @type {!Array<!HTMLElement>} */ (
+ Array.from(this.shadowRoot.querySelectorAll('.tile:not([hidden])')));
+ }
+
+ constructor() {
+ super();
+ /** @private {boolean} */
+ this.adding_ = false;
+ const {callbackRouter, handler} = BrowserProxy.getInstance();
+ /** @private {!newTabPage.mojom.PageCallbackRouter} */
+ this.callbackRouter_ = callbackRouter;
+ /** @private {newTabPage.mojom.PageHandlerRemote} */
+ this.pageHandler_ = handler;
+ /** @private {?number} */
+ this.setMostVisitedInfoListenerId_ = null;
+ /** @private {number} */
+ this.actionMenuTargetIndex_ = -1;
+
+ /**
+ * This is the position of the mouse with respect to the top-left corner
+ * of the tile being dragged.
+ * @private {(!{x: number, y: number}|null)}
+ */
+ this.dragOffset_ = null;
+ /** @private {!Array<!DOMRect>} */
+ this.tileRects_ = [];
+ }
+
+ /** @override */
+ connectedCallback() {
+ super.connectedCallback();
+ /** @private {boolean} */
+ this.isRtl_ = window.getComputedStyle(this)['direction'] === 'rtl';
+ this.setMostVisitedInfoListenerId_ =
+ this.callbackRouter_.setMostVisitedInfo.addListener(info => {
+ this.visible_ = info.visible;
+ this.customLinksEnabled_ = info.customLinksEnabled;
+ this.tiles_ = info.tiles.slice(0, 10);
+ });
+ this.pageHandler_.updateMostVisitedInfo();
+ FocusOutlineManager.forDocument(document);
+ }
+
+ /** @override */
+ disconnectedCallback() {
+ super.disconnectedCallback();
+ this.callbackRouter_.removeListener(
+ assert(this.setMostVisitedInfoListenerId_));
+ this.mediaListenerWideWidth_.removeListener(
+ assert(this.boundOnWidthChange_));
+ this.mediaListenerMediumWidth_.removeListener(
+ assert(this.boundOnWidthChange_));
+ this.ownerDocument.removeEventListener(
+ 'keydown', this.boundOnDocumentKeyDown_);
+ }
+
+ /** @override */
+ ready() {
+ super.ready();
+
+ /** @private {!Function} */
+ this.boundOnWidthChange_ = this.updateScreenWidth_.bind(this);
+ const {matchMedia} = BrowserProxy.getInstance();
+ /** @private {!MediaQueryList} */
+ this.mediaListenerWideWidth_ = matchMedia('(min-width: 672px)');
+ this.mediaListenerWideWidth_.addListener(this.boundOnWidthChange_);
+ /** @private {!MediaQueryList} */
+ this.mediaListenerMediumWidth_ = matchMedia('(min-width: 560px)');
+ this.mediaListenerMediumWidth_.addListener(this.boundOnWidthChange_);
+ this.updateScreenWidth_();
+ /** @private {!function(Event)} */
+ this.boundOnDocumentKeyDown_ = e =>
+ this.onDocumentKeyDown_(/** @type {!KeyboardEvent} */ (e));
+ this.ownerDocument.addEventListener(
+ 'keydown', this.boundOnDocumentKeyDown_);
+ }
+
+ /** @private */
+ clearForceHover_() {
+ const forceHover = this.shadowRoot.querySelector('.force-hover');
+ if (forceHover) {
+ forceHover.classList.remove('force-hover');
+ }
+ }
+
+ /**
+ * @return {number}
+ * @private
+ */
+ computeColumnCount_() {
+ if (!this.visible_) {
+ return 0;
+ }
+
+ let maxColumns = 3;
+ if (this.screenWidth_ === ScreenWidth.WIDE) {
+ maxColumns = 5;
+ } else if (this.screenWidth_ === ScreenWidth.MEDIUM) {
+ maxColumns = 4;
+ }
+
+ const shortcutCount = this.tiles_ ? this.tiles_.length : 0;
+ const canShowAdd = this.maxTiles_ > shortcutCount;
+ const tileCount =
+ Math.min(this.maxTiles_, shortcutCount + (canShowAdd ? 1 : 0));
+ const columnCount = tileCount <= maxColumns ?
+ tileCount :
+ Math.min(maxColumns, Math.ceil(tileCount / 2));
+ return columnCount || 3;
+ }
+
+ /**
+ * @return {number}
+ * @private
+ */
+ computeMaxTiles_() {
+ return !this.visible_ ? 0 : (this.customLinksEnabled_ ? 10 : 8);
+ }
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ computeShowAdd_() {
+ return this.customLinksEnabled_ && this.tiles_ &&
+ this.tiles_.length < this.columnCount_ * 2;
+ }
+
+ /**
+ * If a pointer is over a tile rect that is different from the one being
+ * dragged, the dragging tile is moved to the new position. The reordering
+ * is done in the DOM and the by the |reorderMostVisitedTile()| call. This is
+ * done to prevent flicking between the time when the tiles are moved back to
+ * their original positions (by removing position absolute) and when the
+ * tiles are updated via a |setMostVisitedTiles()| call.
+ *
+ * |reordering_| is not set to false when the tiles are reordered. The callers
+ * will need to set it to false. This is necessary to handle a mouse drag
+ * issue.
+ * @param {number} x
+ * @param {number} y
+ * @private
+ */
+ dragEnd_(x, y) {
+ this.dragOffset_ = null;
+ const dragElement = this.shadowRoot.querySelector('.tile.dragging');
+ if (!dragElement) {
+ this.reordering_ = false;
+ return;
+ }
+ const dragIndex = this.$.tiles.modelForElement(dragElement).index;
+ dragElement.classList.remove('dragging');
+ this.tileElements_.forEach(resetTilePosition);
+ resetTilePosition(/** @type {!HTMLElement} */ (this.$.addShortcut));
+ const dropIndex = getHitIndex(this.tileRects_, x, y);
+ if (dragIndex !== dropIndex && dropIndex > -1) {
+ const [draggingTile] = this.tiles_.splice(dragIndex, 1);
+ this.tiles_.splice(dropIndex, 0, draggingTile);
+ this.notifySplices('tiles_', [
+ {
+ index: dragIndex,
+ removed: [draggingTile],
+ addedCount: 0,
+ object: this.tiles_,
+ type: 'splice',
+ },
+ {
+ index: dropIndex,
+ removed: [],
+ addedCount: 1,
+ object: this.tiles_,
+ type: 'splice',
+ },
+ ]);
+ this.pageHandler_.reorderMostVisitedTile(draggingTile.url, dropIndex);
+ }
+ }
+
+ /**
+ * The positions of the tiles are updated based on the location of the
+ * pointer.
+ * @param {number} x
+ * @param {number} y
+ * @private
+ */
+ dragOver_(x, y) {
+ const dragElement = this.shadowRoot.querySelector('.tile.dragging');
+ if (!dragElement) {
+ this.reordering_ = false;
+ return;
+ }
+ const dragIndex = this.$.tiles.modelForElement(dragElement).index;
+ setTilePosition(/** @type {!HTMLElement} */ (dragElement), {
+ x: x - this.dragOffset_.x,
+ y: y - this.dragOffset_.y,
+ });
+ const dropIndex = getHitIndex(this.tileRects_, x, y);
+ this.tileElements_.forEach((element, i) => {
+ let positionIndex;
+ if (i === dragIndex) {
+ return;
+ } else if (dropIndex === -1) {
+ positionIndex = i;
+ } else if (dragIndex < dropIndex && dragIndex <= i && i <= dropIndex) {
+ positionIndex = i - 1;
+ } else if (dragIndex > dropIndex && dragIndex >= i && i >= dropIndex) {
+ positionIndex = i + 1;
+ } else {
+ positionIndex = i;
+ }
+ setTilePosition(
+ /** @type {!HTMLElement} */ (element),
+ this.tileRects_[positionIndex]);
+ });
+ }
+
+ /**
+ * Sets up tile reordering for both drag and touch events. This method stores
+ * the following to be used in |dragOver_()| and |dragEnd_()|.
+ * |dragOffset_|: This is the mouse/touch offset with respect to the
+ * top/left corner of the tile being dragged. It is used to update the
+ * dragging tile location during the drag.
+ * |reordering_|: This is property/attribute used to hide the hover style
+ * and cr-icon-button of the tiles while they are being reordered.
+ * |tileRects_|: This is the rects of the tiles before the drag start. It is
+ * to determine which tile the pointer is over while dragging.
+ * @param {!HTMLElement} dragElement
+ * @param {number} x
+ * @param {number} y
+ * @private
+ */
+ dragStart_(dragElement, x, y) {
+ // Need to clear the tile that has a forced hover style for when the drag
+ // started without moving the mouse after the last drag/drop.
+ this.clearForceHover_();
+
+ dragElement.classList.add('dragging');
+ const dragElementRect = dragElement.getBoundingClientRect();
+ this.dragOffset_ = {
+ x: x - dragElementRect.x,
+ y: y - dragElementRect.y,
+ };
+ const tileElements = this.tileElements_;
+ // Get all the rects first before setting the absolute positions.
+ this.tileRects_ = tileElements.map(t => t.getBoundingClientRect());
+ if (this.showAdd_) {
+ const element = /** @type {!HTMLElement} */ (this.$.addShortcut);
+ setTilePosition(element, element.getBoundingClientRect());
+ }
+ tileElements.forEach((tile, i) => {
+ setTilePosition(tile, this.tileRects_[i]);
+ });
+ this.reordering_ = true;
+ }
+
+ /**
+ * @param {!url.mojom.Url} url
+ * @return {string}
+ * @private
+ */
+ getFaviconUrl_(url) {
+ const faviconUrl = new URL('chrome://favicon2/');
+ faviconUrl.searchParams.set('size', '32');
+ faviconUrl.searchParams.set('scale_factor', '2x');
+ faviconUrl.searchParams.set('show_fallback_monogram', '');
+ faviconUrl.searchParams.set('page_url', url.url);
+ return faviconUrl.href;
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getRestoreButtonText_() {
+ return loadTimeData.getString(
+ this.customLinksEnabled_ ? 'restoreDefaultLinks' :
+ 'restoreThumbnailsShort');
+ }
+
+ /**
+ * @param {!newTabPage.mojom.MostVisitedTile} tile
+ * @return {string}
+ * @private
+ */
+ getTileTitleDirectionClass_(tile) {
+ return tile.titleDirection === mojoBase.mojom.TextDirection.RIGHT_TO_LEFT ?
+ 'title-rtl' :
+ 'title-ltr';
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getTileIconButtonIcon_() {
+ return this.customLinksEnabled_ ? 'icon-more-vert' : 'icon-clear';
+ }
+
+ /**
+ * @param {number} index
+ * @return {boolean}
+ * @private
+ */
+ isHidden_(index) {
+ return index >= this.columnCount_ * 2;
+ }
+
+ /** @private */
+ onAdd_() {
+ this.dialogTitle_ = loadTimeData.getString('addLinkTitle');
+ this.dialogTileTitle_ = '';
+ this.dialogTileTitleDirectionClass_ = '';
+ this.dialogTileUrl_ = '';
+ this.dialogTileUrlInvalid_ = false;
+ this.adding_ = true;
+ this.$.dialog.showModal();
+ }
+
+ /**
+ * @param {!KeyboardEvent} e
+ * @private
+ */
+ onAddShortcutKeyDown_(e) {
+ if (e.altKey || e.shiftKey || e.metaKey || e.ctrlKey) {
+ return;
+ }
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ this.onAdd_();
+ }
+
+ if (!this.tiles_ || this.tiles_.length === 0) {
+ return;
+ }
+ const backKey = this.isRtl_ ? 'ArrowRight' : 'ArrowLeft';
+ if (e.key === backKey || e.key === 'ArrowUp') {
+ this.tileFocus_(this.tiles_.length - 1);
+ }
+ }
+
+ /** @private */
+ onDialogCancel_() {
+ this.actionMenuTargetIndex_ = -1;
+ this.$.dialog.cancel();
+ }
+
+ /** @private */
+ onDialogClose_() {
+ if (this.adding_) {
+ this.$.addShortcut.focus();
+ }
+ this.adding_ = false;
+ }
+
+ /**
+ * @param {!KeyboardEvent} e
+ * @private
+ */
+ onDocumentKeyDown_(e) {
+ if (e.altKey || e.shiftKey) {
+ return;
+ }
+
+ const modifier = isMac ? e.metaKey && !e.ctrlKey : e.ctrlKey && !e.metaKey;
+ if (modifier && e.key === 'z') {
+ e.preventDefault();
+ this.pageHandler_.undoMostVisitedTileAction();
+ this.$.toast.hide();
+ }
+ }
+
+ /**
+ * @param {!DragEvent} e
+ * @private
+ */
+ onDragStart_(e) {
+ // |dataTransfer| is null in tests.
+ if (e.dataTransfer) {
+ // Remove the ghost image that appears when dragging.
+ e.dataTransfer.setDragImage(new Image(), 0, 0);
+ }
+
+ this.dragStart_(/** @type {!HTMLElement} */ (e.target), e.x, e.y);
+ const dragOver = e => {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'move';
+ this.dragOver_(e.x, e.y);
+ };
+ this.ownerDocument.addEventListener('dragover', dragOver);
+ this.ownerDocument.addEventListener('dragend', e => {
+ this.ownerDocument.removeEventListener('dragover', dragOver);
+ this.dragEnd_(e.x, e.y);
+ const dropIndex = getHitIndex(this.tileRects_, e.x, e.y);
+ if (dropIndex !== -1) {
+ this.tileElements_[dropIndex].classList.add('force-hover');
+ }
+ this.addEventListener('pointermove', () => {
+ this.clearForceHover_();
+ // When |reordering_| is true, the normal hover style is not shown.
+ // After a drop, the element that has hover is not correct. It will be
+ // after the mouse moves.
+ this.reordering_ = false;
+ }, {once: true});
+ }, {once: true});
+ }
+
+ /** @private */
+ onEdit_() {
+ this.$.actionMenu.close();
+ this.dialogTitle_ = loadTimeData.getString('editLinkTitle');
+ const tile = this.tiles_[this.actionMenuTargetIndex_];
+ this.dialogTileTitle_ = tile.title;
+ this.dialogTileTitleDirectionClass_ =
+ this.getTileTitleDirectionClass_(tile);
+ this.dialogTileUrl_ = tile.url.url;
+ this.dialogTileUrlInvalid_ = false;
+ this.$.dialog.showModal();
+ }
+
+ /** @private */
+ onRestoreDefaultsClick_() {
+ this.$.toast.hide();
+ this.pageHandler_.restoreMostVisitedDefaults();
+ }
+
+ /** @private */
+ async onRemove_() {
+ this.$.actionMenu.close();
+ await this.tileRemove_(this.actionMenuTargetIndex_);
+ this.actionMenuTargetIndex_ = -1;
+ }
+
+ /** @private */
+ async onSave_() {
+ let newUrl;
+ try {
+ newUrl = new URL(
+ this.dialogTileUrl_.includes('://') ?
+ this.dialogTileUrl_ :
+ `https://${this.dialogTileUrl_}/`);
+ if (!['http:', 'https:'].includes(newUrl.protocol)) {
+ throw new Error();
+ }
+ } catch (e) {
+ this.dialogTileUrlInvalid_ = true;
+ return;
+ }
+
+ this.dialogTileUrlInvalid_ = false;
+
+ this.$.dialog.close();
+ let newTitle = this.dialogTileTitle_.trim();
+ if (newTitle.length === 0) {
+ newTitle = this.dialogTileUrl_;
+ }
+ if (this.adding_) {
+ const {success} = await this.pageHandler_.addMostVisitedTile(
+ {url: newUrl.href}, newTitle);
+ this.toast_(success ? 'linkAddedMsg' : 'linkCantCreate', success);
+ } else {
+ const {url, title} = this.tiles_[this.actionMenuTargetIndex_];
+ if (url.url !== newUrl.href || title !== newTitle) {
+ const {success} = await this.pageHandler_.updateMostVisitedTile(
+ url, {url: newUrl.href}, newTitle);
+ this.toast_(success ? 'linkEditedMsg' : 'linkCantEdit', success);
+ }
+ this.actionMenuTargetIndex_ = -1;
+ }
+ }
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onTileIconButtonClick_(e) {
+ e.preventDefault();
+ const {index} = this.$.tiles.modelForElement(e.target.parentElement);
+ if (this.customLinksEnabled_) {
+ this.actionMenuTargetIndex_ = index;
+ this.$.actionMenu.showAt(e.target);
+ } else {
+ this.tileRemove_(index);
+ }
+ }
+
+ /**
+ * @param {!KeyboardEvent} e
+ * @private
+ */
+ onTileKeyDown_(e) {
+ if (e.altKey || e.shiftKey || e.metaKey || e.ctrlKey) {
+ return;
+ }
+
+ if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight' &&
+ e.key !== 'ArrowUp' && e.key !== 'ArrowDown' && e.key !== 'Delete') {
+ return;
+ }
+
+ const {index} = this.$.tiles.modelForElement(e.target);
+ if (e.key === 'Delete') {
+ this.tileRemove_(index);
+ return;
+ }
+
+ const advanceKey = this.isRtl_ ? 'ArrowLeft' : 'ArrowRight';
+ const delta = (e.key === advanceKey || e.key === 'ArrowDown') ? 1 : -1;
+ this.tileFocus_(Math.max(0, index + delta));
+ }
+
+ /** @private */
+ onUndoClick_() {
+ this.$.toast.hide();
+ this.pageHandler_.undoMostVisitedTileAction();
+ }
+
+ /**
+ * @param {!TouchEvent} e
+ * @private
+ */
+ onTouchStart_(e) {
+ if (this.reordering_) {
+ return;
+ }
+ const tileElement = /** @type {HTMLElement} */ (e.composedPath().find(
+ el => el.classList && el.classList.contains('tile')));
+ if (!tileElement) {
+ return;
+ }
+ const {pageX, pageY} = e.changedTouches[0];
+ this.dragStart_(tileElement, pageX, pageY);
+ const touchMove = e => {
+ const {pageX, pageY} = e.changedTouches[0];
+ this.dragOver_(pageX, pageY);
+ };
+ const touchEnd = e => {
+ this.ownerDocument.removeEventListener('touchmove', touchMove);
+ tileElement.removeEventListener('touchend', touchEnd);
+ tileElement.removeEventListener('touchcancel', touchEnd);
+ const {pageX, pageY} = e.changedTouches[0];
+ this.dragEnd_(pageX, pageY);
+ this.reordering_ = false;
+ };
+ this.ownerDocument.addEventListener('touchmove', touchMove);
+ tileElement.addEventListener('touchend', touchEnd, {once: true});
+ tileElement.addEventListener('touchcancel', touchEnd, {once: true});
+ }
+
+ /**
+ * @param {number} index
+ * @private
+ */
+ tileFocus_(index) {
+ if (index < 0) {
+ return;
+ }
+ const tileElements = this.tileElements_;
+ if (index < tileElements.length) {
+ tileElements[index].focus();
+ } else if (this.showAdd_ && index === tileElements.length) {
+ this.$.addShortcut.focus();
+ }
+ }
+
+ /**
+ * @param {string} msgId
+ * @param {boolean} showButtons
+ * @private
+ */
+ toast_(msgId, showButtons) {
+ this.toastContent_ = loadTimeData.getString(msgId);
+ this.showToastButtons_ = showButtons;
+ this.$.toast.show();
+ }
+
+ /**
+ * @param {number} index
+ * @return {!Promise}
+ * @private
+ */
+ async tileRemove_(index) {
+ const {title, url} = this.tiles_[index];
+ this.pageHandler_.deleteMostVisitedTile(url);
+ this.toast_('linkRemovedMsg', /* showButtons= */ true);
+ this.tileFocus_(index);
+ }
+
+ /** @private */
+ updateScreenWidth_() {
+ if (this.mediaListenerWideWidth_.matches) {
+ this.screenWidth_ = ScreenWidth.WIDE;
+ } else if (this.mediaListenerMediumWidth_.matches) {
+ this.screenWidth_ = ScreenWidth.MEDIUM;
+ } else {
+ this.screenWidth_ = ScreenWidth.NARROW;
+ }
+ }
+}
+
+customElements.define(MostVisitedElement.is, MostVisitedElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/new_tab_page.html b/chromium/chrome/browser/resources/new_tab_page/new_tab_page.html
index d446fc0c309..393cdb7242a 100644
--- a/chromium/chrome/browser/resources/new_tab_page/new_tab_page.html
+++ b/chromium/chrome/browser/resources/new_tab_page/new_tab_page.html
@@ -11,12 +11,15 @@
}
body {
+ background: $i18n{backgroundColor};
margin: 0;
}
</style>
</head>
<body>
- <manager-ui></manager-ui>
- <script type="module" src="manager.js"></script>
+ <ntp-app></ntp-app>
+ <script type="module" src="app.js"></script>
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+ <link rel="stylesheet" href="shared_vars.css">
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd b/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd
index 29d569b2790..3ffb582ae0a 100644
--- a/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd
+++ b/chromium/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd
@@ -12,18 +12,103 @@
</outputs>
<release seq="1">
<includes>
+ <include name="IDR_NEW_TAB_PAGE_SKCOLOR_MOJO_LITE_JS"
+ file="${root_gen_dir}/skia/public/mojom/skcolor.mojom-lite.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
<include name="IDR_NEW_TAB_PAGE_MOJO_LITE_JS"
file="${root_gen_dir}/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom-lite.js"
use_base_dir="false" type="BINDATA" compress="gzip" />
- <include name="IDR_NEW_TAB_PAGE_MANAGER_JS"
- file="${root_gen_dir}/chrome/browser/resources/new_tab_page/manager.js"
+ <include name="IDR_NEW_TAB_PAGE_APP_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/app.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_MOST_VISITED_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/most_visited.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_CUSTOMIZE_DIALOG_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/customize_dialog.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_VOICE_SEARCH_OVERLAY_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/voice_search_overlay.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_CUSTOMIZE_BACKGROUNDS_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/customize_backgrounds.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_CUSTOMIZE_SHORTCUTS_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/customize_shortcuts.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_CUSTOMIZE_THEMES_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/customize_themes.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_THEME_ICON_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/theme_icon.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_GRID_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/grid.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_UNTRUSTED_IFRAME_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/untrusted_iframe.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_ACCOUNT_CIRCLE_SVG"
+ file="icons/account_circle.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_BRUSH_ICON_SVG"
+ file="icons/brush.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_CHECK_CIRCLE_SVG"
+ file="icons/check_circle.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_GENERIC_GLOBE_SVG"
+ file="icons/generic_globe.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_PENCIL_ICON_SVG"
+ file="icons/icon_pencil.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_LINK_ICON_SVG"
+ file="icons/link.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_BACKGROUNDS_ICON_SVG"
+ file="icons/backgrounds.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_COLORS_ICON_SVG"
+ file="icons/colors.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_COLORIZE_ICON_SVG"
+ file="icons/colorize.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_SHORTCUT_CIRCLES_SVG"
+ file="icons/shortcut_circles.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_HEADER_SVG"
+ file="icons/header.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_GOOGLE_MIC_SVG"
+ file="icons/googlemic_clr_24px.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_MIC_SVG"
+ file="icons/mic.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_LINK_SVG"
+ file="icons/link.svg" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_MINI_PAGE_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/mini_page.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_FAKEBOX_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/fakebox.js"
+ use_base_dir="false" type="BINDATA" compress="gzip" />
+ <include name="IDR_NEW_TAB_PAGE_LOGO_JS"
+ file="${root_gen_dir}/chrome/browser/resources/new_tab_page/logo.js"
use_base_dir="false" type="BINDATA" compress="gzip" />
</includes>
<structures>
<structure name="IDR_NEW_TAB_PAGE_NEW_TAB_PAGE_HTML"
file="new_tab_page.html" type="chrome_html" compress="gzip" />
+ <structure name="IDR_NEW_TAB_PAGE_SHARED_VARS_CSS"
+ file="shared_vars.css" type="chrome_html" compress="gzip" />
<structure name="IDR_NEW_TAB_PAGE_BROWSER_PROXY_JS"
file="browser_proxy.js" type="chrome_html" compress="gzip" />
+ <structure name="IDR_NEW_TAB_PAGE_UTILS_JS"
+ file="utils.js" type="chrome_html" compress="gzip" />
+ <structure name="IDR_NEW_TAB_PAGE_UNTRUSTED_ONE_GOOGLE_BAR_HTML"
+ file="untrusted/one_google_bar.html" type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_NEW_TAB_PAGE_UNTRUSTED_ONE_GOOGLE_BAR_JS"
+ file="untrusted/one_google_bar.js" type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_HTML"
+ file="untrusted/promo.html" type="chrome_html" compress="gzip" />
+ <structure name="IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_JS"
+ file="untrusted/promo.js" type="chrome_html" compress="gzip" />
+ <structure name="IDR_NEW_TAB_PAGE_UNTRUSTED_IMAGE_HTML"
+ file="untrusted/image.html" type="chrome_html" compress="gzip" />
+ <structure name="IDR_NEW_TAB_PAGE_UNTRUSTED_IFRAME_HTML"
+ file="untrusted/iframe.html" type="chrome_html" compress="gzip" />
</structures>
</release>
</grit>
diff --git a/chromium/chrome/browser/resources/new_tab_page/shared_vars.css b/chromium/chrome/browser/resources/new_tab_page/shared_vars.css
new file mode 100644
index 00000000000..eaffc0a0af1
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/shared_vars.css
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* TODO(aee): this file should probably be turned into a module that imports
+ * 'ui/webui/resources/shared_vars_css.m.js'.
+ */
+html {
+ --ntp-active-background-color: rgba(var(--google-grey-900-rgb), .16);
+ --ntp-background-override-color: white;
+ --ntp-border-color: var(--google-grey-refresh-300);
+ --ntp-focus-shadow-color: rgba(var(--google-blue-600-rgb), .4);
+ --ntp-hover-background-color: rgba(var(--google-grey-900-rgb), .1);
+ --ntp-primary-text-color: var(--google-grey-refresh-700);
+ --ntp-secondary-text-color: var(--google-grey-600);
+ --ntp-secondary-text-hover-color: var(--google-grey-refresh-700);
+ --ntp-selected-background-color: rgba(var(--google-blue-refresh-700-rgb), .16);
+ --ntp-selected-border-color: var(--google-blue-600);
+ --ntp-selected-light-background-color: rgba(var(--google-blue-600-rgb), .24);
+ --ntp-selected-primary-text-color: var(--google-blue-refresh-700);
+}
+
+@media (prefers-color-scheme: dark) {
+ html {
+ --ntp-active-background-color: rgba(var(--google-grey-200-rgb), .16);
+ --ntp-background-override-color: var(--google-grey-900);
+ --ntp-border-color: var(--google-grey-refresh-700);
+ --ntp-focus-shadow-color: rgba(var(--google-blue-refresh-300-rgb), .5);
+ --ntp-hover-background-color: rgba(var(--google-grey-200-rgb), .1);
+ --ntp-primary-text-color: var(--google-grey-refresh-300);
+ --ntp-secondary-text-color: var(--google-grey-refresh-500);
+ --ntp-secondary-text-hover-color: var(--google-grey-200);
+ --ntp-selected-background-color: rgba(var(--google-blue-refresh-300-rgb), .16);
+ --ntp-selected-border-color: var(--google-blue-refresh-300);
+ --ntp-selected-light-background-color: rgba(var(--google-blue-refresh-300-rgb), .24);
+ --ntp-selected-primary-text-color: var(--google-blue-refresh-300);
+ }
+}
diff --git a/chromium/chrome/browser/resources/new_tab_page/theme_icon.html b/chromium/chrome/browser/resources/new_tab_page/theme_icon.html
new file mode 100644
index 00000000000..eed43bffbb4
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/theme_icon.html
@@ -0,0 +1,63 @@
+<style>
+ :host,
+ svg {
+ height: 72px;
+ width: 72px;
+ }
+
+ #ring {
+ fill: rgba(var(--google-blue-600-rgb), 0.4);
+ visibility: hidden;
+ }
+
+ #checkMark {
+ visibility: hidden;
+ }
+
+ :host([selected]) #ring,
+ :host([selected]) #checkMark {
+ visibility: visible;
+ }
+
+ #circle {
+ fill: url(#gradient);
+ stroke: var(--ntp-theme-icon-stroke-color,
+ var(--ntp-theme-icon-frame-color));
+ stroke-width: 1;
+ }
+
+ #leftColor {
+ stop-color: var(--ntp-theme-icon-active-tab-color);
+ }
+
+ #rightColor {
+ stop-color: var(--ntp-theme-icon-frame-color);
+ }
+
+ #checkMark circle {
+ fill: var(--ntp-selected-border-color);
+ }
+
+ #checkMark path {
+ fill: var(--ntp-background-override-color);
+ }
+</style>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <defs>
+ <linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="32" y1="32"
+ x2="32.08" y2="32">
+ <stop id="leftColor" offset="0%"></stop>
+ <stop id="rightColor" offset="100%"></stop>
+ </linearGradient>
+ </defs>
+ <circle id="ring" cx="36" cy="36" r="36"></circle>
+ <circle id="circle" cx="36" cy="36" r="32"></circle>
+ <g id="checkMark" transform="translate(48.5, 3.5)">
+ <circle cx="10" cy="10" r="10"></circle>
+ <path d="m 2.9885708,9.99721 5.0109458,4.98792 0.00275,-0.003
+ 0.024151,0.0227 8.9741604,-9.01557 -1.431323,-1.42476 -7.5742214,7.6092
+ -3.6031671,-3.58665 z">
+ </path>
+ </g>
+</svg>
diff --git a/chromium/chrome/browser/resources/new_tab_page/theme_icon.js b/chromium/chrome/browser/resources/new_tab_page/theme_icon.js
new file mode 100644
index 00000000000..817082803cb
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/theme_icon.js
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+/**
+ * Represents a theme. Displayed as a circle with each half colored based on
+ * the custom CSS properties |--ntp-theme-icon-frame-color| and
+ * |--ntp-theme-icon-active-tab-color|. Can be selected by setting the
+ * |selected| attribute.
+ */
+class ThemeIconElement extends PolymerElement {
+ static get is() {
+ return 'ntp-theme-icon';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+}
+
+customElements.define(ThemeIconElement.is, ThemeIconElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted/iframe.html b/chromium/chrome/browser/resources/new_tab_page/untrusted/iframe.html
new file mode 100644
index 00000000000..43ee39396d2
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/untrusted/iframe.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+ <head>
+ <style>
+ html,
+ body,
+ iframe {
+ height: 100%;
+ width: 100%;
+ }
+
+ body {
+ margin: 0
+ }
+
+ iframe {
+ border: none;
+ }
+ </style>
+ </head>
+ <body>
+ <iframe src="$i18nRaw{url}"></iframe>
+ </body>
+</html>
diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted/image.html b/chromium/chrome/browser/resources/new_tab_page/untrusted/image.html
new file mode 100644
index 00000000000..b6e86cb3169
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/untrusted/image.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html>
+ <head>
+ <style>
+ html,
+ body {
+ height: 100%;
+ width: 100%;
+ }
+
+ body {
+ background-image: url($i18nRaw{url});
+ background-position: center;
+ background-size: cover;
+ margin: 0
+ }
+ </style>
+ </head>
+ <body></body>
+</html>
diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html b/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html
new file mode 100644
index 00000000000..ae67db29484
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html>
+ <head>
+ <style>
+ body {
+ margin: 0;
+ overflow: hidden;
+ }
+
+ $i18nRaw{inHeadStyle}
+ </style>
+ <script>$i18nRaw{inHeadScript}</script>
+ </head>
+ <body>
+ $i18nRaw{barHtml}
+ <script>$i18nRaw{afterBarScript}</script>
+ $i18nRaw{endOfBodyHtml}
+ <script>$i18nRaw{endOfBodyScript}</script>
+ <script src="one_google_bar.js"></script>
+ </body>
+</html>
diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js b/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js
new file mode 100644
index 00000000000..e0c0cee628c
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/untrusted/one_google_bar.js
@@ -0,0 +1,62 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * The following |messageType|'s are sent to the parent frame:
+ * - loaded: initial load
+ * - deactivate: the pointer is not over OneGoogleBar content
+ * - activate: the pointer is over OneGoogleBar content
+ *
+ * TODO(crbug.com/1039913): add support for light/dark theme. add support for
+ * forwarding touch events when OneGoogleBar is active.
+ *
+ * @param {string} messageType
+ */
+function postMessage(messageType) {
+ window.parent.postMessage(
+ {frameType: 'one-google-bar', messageType}, 'chrome://new-tab-page');
+}
+
+// Tracks if the OneGoogleBar is active and should accept pointer events.
+let isActive;
+
+/**
+ * @param {number} x
+ * @param {number} y
+ */
+function updateActiveState(x, y) {
+ const shouldBeActive = document.elementFromPoint(x, y).tagName !== 'HTML';
+ if (shouldBeActive === isActive) {
+ return;
+ }
+ isActive = shouldBeActive;
+ postMessage(shouldBeActive ? 'activate' : 'deactivate');
+}
+
+// Handle messages from parent frame which include forwarded mousemove events.
+// The OneGoogleBar is loaded in an iframe on top of the embedder parent frame.
+// The mousemove events are used to determine if the OneGoogleBar should be
+// active or not.
+// TODO(crbug.com/1039913): add support for touch which does not send mousemove
+// events.
+window.addEventListener('message', ({data}) => {
+ if (data.type === 'mousemove') {
+ updateActiveState(data.x, data.y);
+ }
+});
+
+window.addEventListener('mousemove', ({x, y}) => {
+ updateActiveState(x, y);
+});
+
+document.addEventListener('DOMContentLoaded', () => {
+ // TODO(crbug.com/1039913): remove after OneGoogleBar links are updated.
+ // Updates <a>'s so they load on the top frame instead of the iframe.
+ document.body.querySelectorAll('a').forEach(el => {
+ if (el.target !== '_blank') {
+ el.target = '_top';
+ }
+ });
+ postMessage('loaded');
+});
diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted/promo.html b/chromium/chrome/browser/resources/new_tab_page/untrusted/promo.html
new file mode 100644
index 00000000000..2fd986f6f8e
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/untrusted/promo.html
@@ -0,0 +1,96 @@
+<!doctype html>
+<html>
+ <head>
+ <style>
+ html {
+ --google-blue-400-rgb: 107, 165, 237; /* #6ba5ed */
+ --google-blue-400: rgb(var(--google-blue-400-rgb));
+ --google-blue-600-rgb: 26, 115, 232; /* #1a73e8 */
+ --google-blue-600: rgb(var(--google-blue-600-rgb));
+ --google-grey-200-rgb: 232, 234, 237; /* #e8eaed */
+ --google-grey-200: rgb(var(--google-grey-200-rgb));
+ --google-grey-900-rgb: 32, 33, 36; /* #202124 */
+ --google-grey-900: rgb(var(--google-grey-900-rgb));
+ --google-grey-refresh-300-rgb: 218, 220, 224; /* #dadce0 */
+ --google-grey-refresh-300: rgb(var(--google-grey-refresh-300-rgb));
+ --google-grey-refresh-700-rgb: 95, 99, 104; /* #5f6368 */
+ --google-grey-refresh-700: rgb(var(--google-grey-refresh-700-rgb));
+ }
+
+ body {
+ margin: auto;
+ overflow: hidden;
+ width: fit-content;
+ }
+
+ body * {
+ font-family: Roboto, arial, sans-serif;
+ }
+
+ body > div {
+ background-color: white;
+ border: 1px solid var(--google-grey-refresh-300);
+ border-radius: 16px;
+ box-sizing: border-box;
+ color: var(--google-grey-refresh-700);
+ display: inline-block;
+ font-size: 12px;
+ height: 32px;
+ line-height: 30px;
+ margin-bottom: 0;
+ max-width: 537px;
+ overflow: hidden;
+ padding: 0 16px;
+ pointer-events: all;
+ position: relative;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ body > div {
+ background-color: var(--google-grey-900);
+ border-color: rgba(0, 0, 0, .1);
+ color: var(--google-grey-200);
+ }
+ }
+
+ body > div > a {
+ color: var(--google-blue-600);
+ text-decoration: none;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ body > div > a {
+ color: var(--google-blue-400);
+ }
+ }
+
+ body > div > img {
+ border-radius: 50%;
+ height: 24px;
+ margin-bottom: 2px;
+ margin-inline-end: 8px;
+ margin-inline-start: -12px;
+ object-fit: cover;
+ vertical-align: middle;
+ width: 24px;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ body > div > img {
+ background-color: var(--google-grey-200);
+ }
+ }
+ </style>
+ </head>
+ <body>
+ <!--
+ This is the promo HTML which includes a <style> and <div> tags. The
+ <style> element is removed since the styling needs to be overridden.
+ The <div> contains one or more <span>, <a> and <img> elements.
+ -->
+ $i18nRaw{data}
+ <script src="promo.js"></script>
+ </body>
+</html>
diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted/promo.js b/chromium/chrome/browser/resources/new_tab_page/untrusted/promo.js
new file mode 100644
index 00000000000..de53758beaa
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/untrusted/promo.js
@@ -0,0 +1,23 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(crbug.com/1057147): add tests for chrome-untrusted://new-tab-page files.
+document.addEventListener('DOMContentLoaded', () => {
+ // Remove the <style> from the raw promo since we want to style the promo
+ // ourselves.
+ const styleElement = document.querySelector('body > style');
+ if (styleElement) {
+ styleElement.remove();
+ }
+ // The <a> elements need to open in the top frame since the promo is loaded
+ // in an <iframe>.
+ document.body.querySelectorAll('a').forEach(el => {
+ if (el.target !== '_blank') {
+ el.target = '_top';
+ }
+ });
+ // Inform the embedder that the promo has loaded and can be displayed.
+ window.parent.postMessage(
+ {frameType: 'promo', messageType: 'loaded'}, 'chrome://new-tab-page');
+});
diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.html b/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.html
new file mode 100644
index 00000000000..212f6d13acb
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.html
@@ -0,0 +1,13 @@
+<style>
+ :host(:not([hidden])) {
+ display: inline-block;
+ }
+
+ #iframe {
+ border: none;
+ border-radius: inherit;
+ height: inherit;
+ width: inherit;
+ }
+</style>
+<iframe id="iframe" src="[[src_]]"></iframe>
diff --git a/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.js b/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.js
new file mode 100644
index 00000000000..f40c0cd58cc
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/untrusted_iframe.js
@@ -0,0 +1,48 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {BrowserProxy} from './browser_proxy.js';
+
+class UntrustedIframeElement extends PolymerElement {
+ static get is() {
+ return 'ntp-untrusted-iframe';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @type {string} */
+ path: {
+ reflectToAttribute: true,
+ type: String,
+ },
+
+ /** @private */
+ src_: {
+ type: String,
+ computed: 'computeSrc_(path)',
+ },
+ };
+ }
+
+ /**
+ * Sends message to iframe.
+ * @param {*} message
+ */
+ postMessage(message) {
+ this.$.iframe.contentWindow.postMessage(
+ message, 'chrome-untrusted://new-tab-page');
+ }
+
+ /** @private */
+ computeSrc_() {
+ return BrowserProxy.getInstance().createUntrustedIframeSrc(this.path);
+ }
+}
+
+customElements.define(UntrustedIframeElement.is, UntrustedIframeElement);
diff --git a/chromium/chrome/browser/resources/new_tab_page/utils.js b/chromium/chrome/browser/resources/new_tab_page/utils.js
new file mode 100644
index 00000000000..72fffb416b7
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/utils.js
@@ -0,0 +1,73 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Converts an SkColor object to a string in the form
+ * "rgb(<red>, <green>, <blue>)".
+ * Note: Can only convert opaque SkColors.
+ * @param {skia.mojom.SkColor} skColor The input color.
+ * @return {string} The rgb string.
+ */
+export function skColorToRgb(skColor) {
+ // Bail on transparent colors.
+ if (skColor.value < 0xff000000) {
+ return 'rgb(0, 0, 0)';
+ }
+ const r = (skColor.value >> 16) & 0xff;
+ const g = (skColor.value >> 8) & 0xff;
+ const b = skColor.value & 0xff;
+ return `rgb(${r}, ${g}, ${b})`;
+}
+
+/**
+ * Converts a string of the form "#rrggbb" to an SkColor object.
+ * @param {string} hexColor The color string.
+ * @return {!skia.mojom.SkColor} The SkColor object,
+ */
+export function hexColorToSkColor(hexColor) {
+ if (!/^#[0-9a-f]{6}$/.test(hexColor)) {
+ return {value: 0};
+ }
+ const r = parseInt(hexColor.substring(1, 3), 16);
+ const g = parseInt(hexColor.substring(3, 5), 16);
+ const b = parseInt(hexColor.substring(5, 7), 16);
+ return {value: 0xff000000 + (r << 16) + (g << 8) + b};
+}
+
+/**
+ * Given a |container| that has scrollable content, <div>'s before and after the
+ * |container| are created with an attribute "scroll-border". These <div>'s are
+ * updated to have an attribute "show" when there is more content in the
+ * direction of the "scroll-border". Styling is left to the caller.
+ *
+ * Returns an |IntersectionObserver| so the caller can disconnect the observer
+ * when needed.
+ * @param {!HTMLElement} container
+ * @return {!IntersectionObserver}
+ */
+export function createScrollBorders(container) {
+ const topProbe = document.createElement('div');
+ container.prepend(topProbe);
+ const bottomProbe = document.createElement('div');
+ container.append(bottomProbe);
+ const topBorder = document.createElement('div');
+ topBorder.toggleAttribute('scroll-border', true);
+ container.parentNode.insertBefore(topBorder, container);
+ const bottomBorder = document.createElement('div');
+ bottomBorder.toggleAttribute('scroll-border', true);
+ container.parentNode.insertBefore(bottomBorder, container.nextSibling);
+ const observer = new IntersectionObserver(entries => {
+ entries.forEach(({target, intersectionRatio}) => {
+ const show = intersectionRatio === 0;
+ if (target === topProbe) {
+ topBorder.toggleAttribute('show', show);
+ } else if (target === bottomProbe) {
+ bottomBorder.toggleAttribute('show', show);
+ }
+ });
+ }, {root: container});
+ observer.observe(topProbe);
+ observer.observe(bottomProbe);
+ return observer;
+}
diff --git a/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.html b/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.html
new file mode 100644
index 00000000000..88dd7098ac5
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.html
@@ -0,0 +1,246 @@
+<style>
+ :host {
+ --receiving-audio-color: var(--google-red-refresh-500);
+ --speak-shown-duration: 2s;
+ }
+
+ .display-stack {
+ display: grid;
+ }
+
+ .display-stack > * {
+ grid-column-start: 1;
+ grid-row-start: 1;
+ }
+
+ #dialog {
+ align-items: center;
+ background-color: var(--ntp-background-override-color);
+ border: none;
+ display: flex;
+ height: 100%;
+ justify-content: center;
+ left: 0;
+ margin: 0;
+ padding: 0;
+ top: 0;
+ width: 100%;
+ }
+
+ #closeButton {
+ background: none;
+ border: none;
+ color: var(--ntp-secondary-text-color);
+ cursor: pointer;
+ font-family: inherit;
+ font-size: 26px;
+ height: 15px;
+ line-height: 0;
+ outline: none;
+ padding: 0;
+ position: absolute;
+ top: 16px;
+ width: 15px;
+ }
+
+ #closeButton:hover {
+ color: var(--ntp-secondary-text-hover-color);
+ }
+
+ :host-context(.focus-outline-visible) #closeButton:focus {
+ box-shadow: 0 0 0 2px var(--ntp-focus-shadow-color);
+ }
+
+ :host-context([dir='ltr']) #closeButton {
+ right: 16px;
+ }
+
+ :host-context([dir='rtl']) #closeButton {
+ left: 16px;
+ }
+
+ #content {
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 660px;
+ }
+
+ #texts {
+ color: var(--ntp-secondary-text-color);
+ flex-grow: 1;
+ font-size: 32px;
+ text-align: start;
+ }
+
+ *[text] {
+ transition-delay: 200ms;
+ transition-duration: 500ms;
+ transition-property: opacity, padding-inline-start;
+ transition-timing-function: ease-out;
+ visibility: hidden;
+ width: 100%;
+ }
+
+ *[text='waiting'],
+ *[text='speak'] {
+ opacity: 0;
+ padding-inline-start: 50px;
+ }
+
+ *[text][visible] {
+ opacity: 1;
+ padding-inline-start: 0;
+ visibility: visible;
+ }
+
+ *[text='speak'][visible] #speak {
+ opacity: 0;
+ transition: opacity 0ms var(--speak-shown-duration);
+ }
+
+ *[text='speak'] #listening {
+ opacity: 0;
+ }
+
+ *[text='speak'][visible] #listening {
+ opacity: 1;
+ transition: opacity 750ms ease-out var(--speak-shown-duration);
+ }
+
+ #finalResult {
+ color: var(--ntp-primary-text-color);
+ }
+
+ #errors,
+ #errorLinks {
+ display: inline;
+ }
+
+ #errorLinks a {
+ color: var(--cr-link-color);
+ font-size: 18px;
+ font-weight: 500;
+ margin-inline-start: 0.25em;
+ text-decoration: none;
+ }
+
+ #micContainer {
+ --mic-button-size: 165px;
+ --mic-container-size: 300px;
+ align-items: center;
+ flex-shrink: 0;
+ height: var(--mic-container-size);
+ justify-items: center;
+ width: var(--mic-container-size);
+ }
+
+ #micVolume {
+ --mic-volume-size: calc(var(--mic-button-size) +
+ var(--mic-volume-level) * (var(--mic-container-size) -
+ var(--mic-button-size)));
+ align-items: center;
+ background-color: var(--ntp-border-color);
+ border-radius: 50%;
+ display: flex;
+ height: var(--mic-volume-size);
+ justify-content: center;
+ transition-duration: var(--mic-volume-duration);
+ transition-property: height, width;
+ transition-timing-function: ease-in-out;
+ width: var(--mic-volume-size);
+ }
+
+ #micVolumeCutout {
+ background-color: var(--ntp-background-override-color);
+ border-radius: 50%;
+ height: var(--mic-button-size);
+ width: var(--mic-button-size);
+ }
+
+ #micButton {
+ border-radius: 50%;
+ height: var(--mic-button-size);
+ transition: background-color 200ms ease-in-out;
+ width: var(--mic-button-size);
+ }
+
+ .receiving #micButton {
+ background-color: var(--receiving-audio-color);
+ border-color: var(--receiving-audio-color);
+ }
+
+ #micIcon {
+ -webkit-mask-image: url(icons/mic.svg);
+ -webkit-mask-repeat: no-repeat;
+ -webkit-mask-size: 100%;
+ background-color: var(--ntp-border-color);
+ height: 80px;
+ transition: background-color 200ms ease-in-out;
+ width: 80px;
+ }
+
+ .listening #micIcon {
+ background-color: var(--receiving-audio-color);
+ }
+
+ .receiving #micIcon {
+ background-color: white;
+ }
+</style>
+<dialog id="dialog" on-close="onOverlayClose_" on-click="onOverlayClick_">
+ <button id="closeButton" tabindex="0" title="$i18n{close}">×</button>
+ <div id="content">
+ <iron-selector id="texts" selected="[[getText_(state_)]]"
+ attr-for-selected="text" fallback-selection="none" aria-live="polite"
+ selected-attribute="visible" class="display-stack">
+ <div text="none"></div>
+ <div text="waiting">$i18n{waiting}</div>
+ <div text="speak" class="display-stack">
+ <div id="speak">$i18n{speak}</div>
+ <div id="listening">$i18n{listening}</div>
+ </div>
+ <div text="result">
+ <span id="finalResult">[[finalResult_]]</span>
+ <span>[[interimResult_]]</span>
+ </div>
+ <div text="error">
+ <iron-pages id="errors" selected="[[error_]]" attr-for-selected="error"
+ fallback-selection="7">
+ <span error="1">$i18n{noVoice}</span>
+ <span error="2">$i18n{audioError}</span>
+ <span error="3">$i18n{networkError}</span>
+ <span error="4">$i18n{permissionError}</span>
+ <span error="5">$i18n{languageError}</span>
+ <span error="6">$i18n{noTranslation}</span>
+ <span error="7">$i18n{otherError}</span>
+ </iron-pages>
+ <iron-pages id="errorLinks" selected="[[getErrorLink_(error_)]]"
+ attr-for-selected="link" fallback-selection="none">
+ <span link="none"></span>
+ <a link="learn-more" target="_blank" href="[[helpUrl_]]"><!--
+ -->$i18n{learnMore}
+ </a>
+ <a link="details" target="_blank" href="[[helpUrl_]]"><!--
+ -->$i18n{details}
+ </a>
+ <a link="try-again" id="retryLink" href="#"
+ on-click="onRetryClick_"><!--
+ -->$i18n{tryAgain}
+ </a>
+ </iron-pages>
+ </div>
+ </iron-selector>
+ <div id="micContainer" class$="[[getMicClass_(state_)]] display-stack">
+ <div id="micVolume"
+ style="--mic-volume-level: [[micVolumeLevel_]];
+ --mic-volume-duration: [[micVolumeDuration_]]ms;">
+ <div id="micVolumeCutout">
+ </div>
+ </div>
+ <cr-button id="micButton" on-click="onRetryClick_">
+ <div id="micIcon"></div>
+ </cr-button>
+ </div>
+ </div>
+</dialog>
diff --git a/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.js b/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.js
new file mode 100644
index 00000000000..278fac75e41
--- /dev/null
+++ b/chromium/chrome/browser/resources/new_tab_page/voice_search_overlay.js
@@ -0,0 +1,491 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js';
+import 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js';
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {BrowserProxy} from './browser_proxy.js';
+
+/**
+ * Threshold for considering an interim speech transcript result as "confident
+ * enough". The more confident the API is about a transcript, the higher the
+ * confidence (number between 0 and 1).
+ * @type {number}
+ */
+const RECOGNITION_CONFIDENCE_THRESHOLD = 0.5;
+
+/**
+ * Maximum number of characters recognized before force-submitting a query.
+ * Includes characters of non-confident recognition transcripts.
+ * @type {number}
+ */
+const QUERY_LENGTH_LIMIT = 120;
+
+/**
+ * Time in milliseconds to wait before closing the UI if no interaction has
+ * occurred.
+ * @type {number}
+ */
+const IDLE_TIMEOUT_MS = 8000;
+
+/**
+ * Time in milliseconds to wait before closing the UI after an error has
+ * occurred. This is a short timeout used when no click-target is present.
+ * @type {number}
+ */
+const ERROR_TIMEOUT_SHORT_MS = 3000;
+
+/**
+ * Time in milliseconds to wait before closing the UI after an error has
+ * occurred. This is a longer timeout used when there is a click-target is
+ * present.
+ * @type {number}
+ */
+const ERROR_TIMEOUT_LONG_MS = 8000;
+
+/**
+ * The minimum transition time for the volume rings.
+ * @private
+ */
+const VOLUME_ANIMATION_DURATION_MIN_MS = 170;
+
+/**
+ * The range of the transition time for the volume rings.
+ * @private
+ */
+const VOLUME_ANIMATION_DURATION_RANGE_MS = 10;
+
+/**
+ * The set of controller states.
+ * @enum {number}
+ * @private
+ */
+const State = {
+ // Initial state before voice recognition has been set up.
+ UNINITIALIZED: -1,
+ // Indicates that speech recognition has started, but no audio has yet
+ // been captured.
+ STARTED: 0,
+ // Indicates that audio is being captured by the Web Speech API, but no
+ // speech has yet been recognized. UI indicates that audio is being captured.
+ AUDIO_RECEIVED: 1,
+ // Indicates that speech has been recognized by the Web Speech API, but no
+ // resulting transcripts have yet been received back. UI indicates that audio
+ // is being captured and is pulsating audio button.
+ SPEECH_RECEIVED: 2,
+ // Indicates speech has been successfully recognized and text transcripts have
+ // been reported back. UI indicates that audio is being captured and is
+ // displaying transcripts received so far.
+ RESULT_RECEIVED: 3,
+ // Indicates that speech recognition has failed due to an error (or a no match
+ // error) being received from the Web Speech API. A timeout may have occurred
+ // as well. UI displays the error message.
+ ERROR_RECEIVED: 4,
+ // Indicates speech recognition has received a final search query but the UI
+ // has not yet redirected. The UI is displaying the final query.
+ RESULT_FINAL: 5,
+};
+
+/**
+ * The set of possible recognition errors.
+ * @enum {!number}
+ */
+const Error = {
+ ABORTED: 0,
+ NO_SPEECH: 1,
+ AUDIO_CAPTURE: 2,
+ NETWORK: 3,
+ NOT_ALLOWED: 4,
+ LANGUAGE_NOT_SUPPORTED: 5,
+ NO_MATCH: 6,
+ OTHER: 7,
+};
+
+/**
+ * Returns the error type based on the error string received from the webkit
+ * speech recognition API.
+ * @param {string} webkitError The error string received from the webkit speech
+ * recognition API.
+ * @return {!Error} The appropriate error state from the Error enum.
+ */
+function toError(webkitError) {
+ switch (webkitError) {
+ case 'aborted':
+ return Error.ABORTED;
+ case 'audio-capture':
+ return Error.AUDIO_CAPTURE;
+ case 'language-not-supported':
+ return Error.LANGUAGE_NOT_SUPPORTED;
+ case 'network':
+ return Error.NETWORK;
+ case 'no-speech':
+ return Error.NO_SPEECH;
+ case 'not-allowed':
+ case 'service-not-allowed':
+ return Error.NOT_ALLOWED;
+ default:
+ return Error.OTHER;
+ }
+}
+
+/**
+ * Returns a timeout based on the error received from the webkit speech
+ * recognition API.
+ * @param {Error} error An error from the Error enum.
+ * @return {number} The appropriate timeout in MS for displaying the error.
+ */
+function getErrorTimeout(error) {
+ switch (error) {
+ case Error.AUDIO_CAPTURE:
+ case Error.NO_SPEECH:
+ case Error.NOT_ALLOWED:
+ case Error.NO_MATCH:
+ return ERROR_TIMEOUT_LONG_MS;
+ default:
+ return ERROR_TIMEOUT_SHORT_MS;
+ }
+}
+
+// Overlay that lats the user perform voice searches.
+class VoiceSearchOverlayElement extends PolymerElement {
+ static get is() {
+ return 'ntp-voice-search-overlay';
+ }
+
+ static get template() {
+ return html`{__html_template__}`;
+ }
+
+ static get properties() {
+ return {
+ /** @private */
+ interimResult_: String,
+
+ /** @private */
+ finalResult_: String,
+
+ /** @private */
+ state_: {
+ type: Number,
+ value: State.UNINITIALIZED,
+ },
+
+ /** @private */
+ error_: Number,
+
+ /** @private */
+ helpUrl_: {
+ type: String,
+ readOnly: true,
+ value: `https://support.google.com/chrome/?` +
+ `p=ui_voice_search&hl=${window.navigator.language}`,
+ },
+
+ /** @private */
+ micVolumeLevel_: {
+ type: Number,
+ value: 0,
+ },
+
+ /** @private */
+ micVolumeDuration_: {
+ type: Number,
+ value: VOLUME_ANIMATION_DURATION_MIN_MS,
+ },
+ };
+ }
+
+ constructor() {
+ super();
+ /** @private {webkitSpeechRecognition} */
+ this.voiceRecognition_ = new webkitSpeechRecognition();
+ this.voiceRecognition_.continuous = false;
+ this.voiceRecognition_.interimResults = true;
+ this.voiceRecognition_.lang = window.navigator.language;
+ this.voiceRecognition_.onaudiostart = this.onAudioStart_.bind(this);
+ this.voiceRecognition_.onspeechstart = this.onSpeechStart_.bind(this);
+ this.voiceRecognition_.onresult = this.onResult_.bind(this);
+ this.voiceRecognition_.onend = this.onEnd_.bind(this);
+ this.voiceRecognition_.onerror = (e) => {
+ this.onError_(toError(e.error));
+ };
+ this.voiceRecognition_.onnomatch = () => {
+ this.onError_(Error.NO_MATCH);
+ };
+ /** @private {number|undefined} */
+ this.timerId_ = undefined;
+ }
+
+ /** @override */
+ connectedCallback() {
+ super.connectedCallback();
+ this.$.dialog.showModal();
+ this.start();
+ }
+
+ /** @private */
+ start() {
+ this.voiceRecognition_.start();
+ this.state_ = State.STARTED;
+ this.resetIdleTimer_();
+ }
+
+ /** @private */
+ onOverlayClose_() {
+ this.voiceRecognition_.abort();
+ this.dispatchEvent(new Event('close'));
+ }
+
+ /** @private */
+ onOverlayClick_() {
+ this.$.dialog.close();
+ }
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onRetryClick_(e) {
+ if (this.state_ !== State.ERROR_RECEIVED ||
+ this.error_ !== Error.NO_MATCH) {
+ return;
+ }
+ e.stopPropagation();
+ this.start();
+ }
+
+ /** @private */
+ resetIdleTimer_() {
+ BrowserProxy.getInstance().clearTimeout(this.timerId_);
+ this.timerId_ = BrowserProxy.getInstance().setTimeout(
+ this.onIdleTimeout_.bind(this), IDLE_TIMEOUT_MS);
+ }
+
+ /** @private */
+ onIdleTimeout_() {
+ if (this.state_ === State.RESULT_FINAL) {
+ // Waiting for query redirect.
+ return;
+ }
+ if (this.finalResult_) {
+ // Query what we recognized so far.
+ this.onFinalResult_();
+ return;
+ }
+ this.voiceRecognition_.abort();
+ this.onError_(Error.NO_MATCH);
+ }
+
+ /**
+ * @param {number} duration
+ * @private
+ */
+ resetErrorTimer_(duration) {
+ BrowserProxy.getInstance().clearTimeout(this.timerId_);
+ this.timerId_ = BrowserProxy.getInstance().setTimeout(
+ this.onOverlayClick_.bind(this), duration);
+ }
+
+ /** @private */
+ onAudioStart_() {
+ this.resetIdleTimer_();
+ this.state_ = State.AUDIO_RECEIVED;
+ }
+
+ /** @private */
+ onSpeechStart_() {
+ this.resetIdleTimer_();
+ this.state_ = State.SPEECH_RECEIVED;
+ this.animateVolume_();
+ }
+
+ /**
+ * @param {SpeechRecognitionEvent} e
+ * @private
+ */
+ onResult_(e) {
+ this.resetIdleTimer_();
+
+ switch (this.state_) {
+ case State.STARTED:
+ // Network bugginess (the onspeechstart packet was lost).
+ this.onAudioStart_();
+ this.onSpeechStart_();
+ break;
+ case State.AUDIO_RECEIVED:
+ // Network bugginess (the onaudiostart packet was lost).
+ this.onSpeechStart_();
+ break;
+ case State.SPEECH_RECEIVED:
+ case State.RESULT_RECEIVED:
+ // Normal, expected states for processing results.
+ break;
+ default:
+ // Not expecting results in any other states.
+ return;
+ }
+
+ const results = e.results;
+ if (results.length === 0) {
+ return;
+ }
+ this.state_ = State.RESULT_RECEIVED;
+ this.interimResult_ = '';
+ this.finalResult_ = '';
+
+ const finalResult = results[e.resultIndex];
+ // Process final results.
+ if (finalResult.isFinal) {
+ this.finalResult_ = finalResult[0].transcript;
+ this.onFinalResult_();
+ return;
+ }
+
+ // Process interim results.
+ for (let j = 0; j < results.length; j++) {
+ const result = results[j][0];
+ if (result.confidence > RECOGNITION_CONFIDENCE_THRESHOLD) {
+ this.finalResult_ += result.transcript;
+ } else {
+ this.interimResult_ += result.transcript;
+ }
+ }
+
+ // Force-stop long queries.
+ if (this.interimResult_.length > QUERY_LENGTH_LIMIT) {
+ this.onFinalResult_();
+ }
+ }
+
+ /** @private */
+ onFinalResult_() {
+ if (!this.finalResult_) {
+ this.onError_(Error.NO_MATCH);
+ return;
+ }
+ this.state_ = State.RESULT_FINAL;
+ const searchParams = new URLSearchParams();
+ searchParams.append('q', this.finalResult_);
+ // Add a parameter to indicate that this request is a voice search.
+ searchParams.append('gs_ivs', '1');
+ // Build the query URL.
+ const queryUrl =
+ new URL('/search', loadTimeData.getString('googleBaseUrl'));
+ queryUrl.search = searchParams.toString();
+ BrowserProxy.getInstance().navigate(queryUrl.href);
+ }
+
+ /** @private */
+ onEnd_() {
+ switch (this.state_) {
+ case State.STARTED:
+ this.onError_(Error.AUDIO_CAPTURE);
+ return;
+ case State.AUDIO_RECEIVED:
+ this.onError_(Error.NO_SPEECH);
+ return;
+ case State.SPEECH_RECEIVED:
+ case State.RESULT_RECEIVED:
+ this.onError_(Error.NO_MATCH);
+ return;
+ case State.ERROR_RECEIVED:
+ case State.RESULT_FINAL:
+ return;
+ default:
+ this.onError_(Error.OTHER);
+ return;
+ }
+ }
+
+ /**
+ * @param {Error} error
+ * @private
+ */
+ onError_(error) {
+ if (error === Error.ABORTED) {
+ // We are in the process of closing voice search.
+ return;
+ }
+ this.error_ = error;
+ this.state_ = State.ERROR_RECEIVED;
+ this.resetErrorTimer_(getErrorTimeout(error));
+ }
+
+ /** @private */
+ animateVolume_() {
+ this.micVolumeLevel_ = 0;
+ this.micVolumeDuration_ = VOLUME_ANIMATION_DURATION_MIN_MS;
+ if (this.state_ !== State.SPEECH_RECEIVED &&
+ this.state_ !== State.RESULT_RECEIVED) {
+ return;
+ }
+ this.micVolumeLevel_ = BrowserProxy.getInstance().random();
+ this.micVolumeDuration_ = Math.round(
+ VOLUME_ANIMATION_DURATION_MIN_MS +
+ BrowserProxy.getInstance().random() *
+ VOLUME_ANIMATION_DURATION_RANGE_MS);
+ BrowserProxy.getInstance().setTimeout(
+ this.animateVolume_.bind(this), this.micVolumeDuration_);
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getText_() {
+ switch (this.state_) {
+ case State.STARTED:
+ return 'waiting';
+ case State.AUDIO_RECEIVED:
+ case State.SPEECH_RECEIVED:
+ return 'speak';
+ case State.RESULT_RECEIVED:
+ case State.RESULT_FINAL:
+ return 'result';
+ case State.ERROR_RECEIVED:
+ return 'error';
+ default:
+ return 'none';
+ }
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getErrorLink_() {
+ switch (this.error_) {
+ case Error.NO_SPEECH:
+ case Error.AUDIO_CAPTURE:
+ return 'learn-more';
+ case Error.NOT_ALLOWED:
+ return 'details';
+ case Error.NO_MATCH:
+ return 'try-again';
+ default:
+ return 'none';
+ }
+ }
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getMicClass_() {
+ switch (this.state_) {
+ case State.AUDIO_RECEIVED:
+ return 'listening';
+ case State.SPEECH_RECEIVED:
+ case State.RESULT_RECEIVED:
+ return 'receiving';
+ default:
+ return '';
+ }
+ }
+}
+
+customElements.define(VoiceSearchOverlayElement.is, VoiceSearchOverlayElement);
diff --git a/chromium/chrome/browser/resources/notifications_internals/BUILD.gn b/chromium/chrome/browser/resources/notifications_internals/BUILD.gn
index bd68968e98d..021f90a7b4b 100644
--- a/chromium/chrome/browser/resources/notifications_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/notifications_internals/BUILD.gn
@@ -21,7 +21,5 @@ js_library("notifications_internals") {
}
js_library("notifications_internals_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
diff --git a/chromium/chrome/browser/resources/ntp4/BUILD.gn b/chromium/chrome/browser/resources/ntp4/BUILD.gn
index 3ca4ed2fd05..25c15b8a758 100644
--- a/chromium/chrome/browser/resources/ntp4/BUILD.gn
+++ b/chromium/chrome/browser/resources/ntp4/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":apps_page",
- ]
+ deps = [ ":apps_page" ]
}
js_library("apps_page") {
diff --git a/chromium/chrome/browser/resources/ntp4/OWNERS b/chromium/chrome/browser/resources/ntp4/OWNERS
index 4f3a2ad14f9..690a9f1a025 100644
--- a/chromium/chrome/browser/resources/ntp4/OWNERS
+++ b/chromium/chrome/browser/resources/ntp4/OWNERS
@@ -1,4 +1,3 @@
-dbeam@chromium.org
estade@chromium.org
rbyers@chromium.org
diff --git a/chromium/chrome/browser/resources/ntp4/apps_page.js b/chromium/chrome/browser/resources/ntp4/apps_page.js
index 460883b526e..8ec435a9cea 100644
--- a/chromium/chrome/browser/resources/ntp4/apps_page.js
+++ b/chromium/chrome/browser/resources/ntp4/apps_page.js
@@ -41,7 +41,7 @@ cr.define('ntp', function() {
cr.addSingletonGetter(AppContextMenu);
AppContextMenu.prototype = {
- initialize: function() {
+ initialize() {
const menu = new cr.ui.Menu;
cr.ui.decorate(menu, cr.ui.Menu);
menu.classList.add('app-context-menu');
@@ -103,7 +103,7 @@ cr.define('ntp', function() {
* that acts as the item's label.
* @private
*/
- appendMenuItem_: function(opt_textId) {
+ appendMenuItem_(opt_textId) {
const button =
/** @type {!HTMLButtonElement} */ (document.createElement('button'));
this.menu.appendChild(button);
@@ -121,7 +121,7 @@ cr.define('ntp', function() {
* the associated launch ID.
* @private
*/
- forAllLaunchTypes_: function(f) {
+ forAllLaunchTypes_(f) {
// Order matters: index matches launchType id.
const launchTypes = [
this.launchPinnedTab_, this.launchRegularTab_, this.launchFullscreen_,
@@ -141,7 +141,7 @@ cr.define('ntp', function() {
* Does all the necessary setup to show the menu for the given app.
* @param {ntp.App} app The App object that will be showing a context menu.
*/
- setupForApp: function(app) {
+ setupForApp(app) {
this.app_ = app;
this.launch_.textContent = app.appData.title;
@@ -181,7 +181,7 @@ cr.define('ntp', function() {
},
/** @private */
- onActivate_: function() {
+ onActivate_() {
chrome.send('launchApp', [this.app_.appId, APP_LAUNCH.NTP_APPS_MENU]);
},
@@ -189,7 +189,7 @@ cr.define('ntp', function() {
* @param {Event} e
* @private
*/
- onLaunchTypeChanged_: function(e) {
+ onLaunchTypeChanged_(e) {
const pressed = e.currentTarget;
const app = this.app_;
let targetLaunchType = pressed;
@@ -209,34 +209,34 @@ cr.define('ntp', function() {
},
/** @private */
- onShowOptions_: function() {
+ onShowOptions_() {
window.location = this.app_.appData.optionsUrl;
},
/** @private */
- onShowDetails_: function() {
+ onShowDetails_() {
let url = this.app_.appData.detailsUrl;
url = appendParam(url, 'utm_source', 'chrome-ntp-launcher');
window.location = url;
},
/** @private */
- onUninstall_: function() {
+ onUninstall_() {
chrome.send('uninstallApp', [this.app_.appData.id]);
},
/** @private */
- onCreateShortcut_: function() {
+ onCreateShortcut_() {
chrome.send('createAppShortcut', [this.app_.appData.id]);
},
/** @private */
- onInstallLocally_: function() {
+ onInstallLocally_() {
chrome.send('installAppLocally', [this.app_.appData.id]);
},
/** @private */
- onShowAppInfo_: function() {
+ onShowAppInfo_() {
chrome.send('showAppInfo', [this.app_.appData.id]);
}
};
@@ -266,7 +266,7 @@ cr.define('ntp', function() {
* setter functions.
* @suppress {deprecated}
*/
- initialize: function(appData) {
+ initialize(appData) {
this.appData = appData;
assert(this.appData_.id, 'Got an app without an ID');
this.id = this.appData_.id;
@@ -349,7 +349,7 @@ cr.define('ntp', function() {
*
* @param {boolean=} opt_animate Whether the removal should be animated.
*/
- remove: function(opt_animate) {
+ remove(opt_animate) {
// Unset the ID immediately, because the app is already gone. But leave
// the tile on the page as it animates out.
this.id = '';
@@ -361,7 +361,7 @@ cr.define('ntp', function() {
* icon until loadIcon() is called (for performance reasons; we don't want
* to load icons until we have to).
*/
- setIcon: function() {
+ setIcon() {
let src = this.useSmallIcon_ ? this.appData_.icon_small :
this.appData_.icon_big;
if (!this.appData_.enabled || !this.appData_.isLocallyInstalled ||
@@ -377,7 +377,7 @@ cr.define('ntp', function() {
* Shows the icon for the app. That is, it causes chrome to load the app
* icon resource.
*/
- loadIcon: function() {
+ loadIcon() {
if (this.appImgSrc_) {
this.appImg_.src = this.appImgSrc_;
this.appImg_.classList.remove('invisible');
@@ -394,7 +394,7 @@ cr.define('ntp', function() {
* @param {number} y The y-position.
* animate.
*/
- setBounds: function(size, x, y) {
+ setBounds(size, x, y) {
const imgSize = size * APP_IMG_SIZE_FRACTION;
this.appImgContainer_.style.width = this.appImgContainer_.style.height =
toCssPx(this.useSmallIcon_ ? 16 : imgSize);
@@ -418,7 +418,7 @@ cr.define('ntp', function() {
},
/** @private */
- onBlur_: function() {
+ onBlur_() {
this.classList.remove('click-focus');
this.appContents_.classList.remove('suppress-active');
},
@@ -428,7 +428,7 @@ cr.define('ntp', function() {
* @param {Event} e The click/auxclick event.
* @private
*/
- onClick_: function(e) {
+ onClick_(e) {
if (/** @type {MouseEvent} */ (e).button > 1) {
return;
}
@@ -447,7 +447,7 @@ cr.define('ntp', function() {
* @param {Event} e The key event.
* @private
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
if (e.key == 'Enter') {
chrome.send('launchApp', [
this.appId, APP_LAUNCH.NTP_APPS_MAXIMIZED, '', 0, e.altKey, e.ctrlKey,
@@ -467,7 +467,7 @@ cr.define('ntp', function() {
* @param {HTMLElement} node The node that should be clickable.
* @private
*/
- addLaunchClickTarget_: function(node) {
+ addLaunchClickTarget_(node) {
node.classList.add('launch-click-target');
node.addEventListener('click', this.onClick_.bind(this));
node.addEventListener('auxclick', this.onClick_.bind(this));
@@ -481,7 +481,7 @@ cr.define('ntp', function() {
* @param {Event} e The mousedown event.
* @private
*/
- onMousedown_: function(e) {
+ onMousedown_(e) {
// If the current platform uses middle click to autoscroll and this
// mousedown isn't handled, onClick_() will never fire. crbug.com/142939
if (e.button == 1) {
@@ -505,7 +505,7 @@ cr.define('ntp', function() {
* Change the appData and update the appearance of the app.
* @param {AppInfo} appData The new data object that describes the app.
*/
- replaceAppData: function(appData) {
+ replaceAppData(appData) {
this.appData_ = appData;
this.setIcon();
this.loadIcon();
@@ -544,14 +544,14 @@ cr.define('ntp', function() {
* the user can drag it onto the trash and expect something to happen).
* @return {boolean} True if the app can be uninstalled.
*/
- canBeRemoved: function() {
+ canBeRemoved() {
return this.appData_.mayDisable;
},
/**
* Uninstalls the app after it's been dropped on the trash.
*/
- removeFromChrome: function() {
+ removeFromChrome() {
chrome.send('uninstallApp', [this.appData_.id, true]);
this.tile.tilePage.removeTile(this.tile, true);
},
@@ -560,7 +560,7 @@ cr.define('ntp', function() {
* Called when a drag is starting on the tile. Updates dataTransfer with
* data for this tile.
*/
- setDragData: function(dataTransfer) {
+ setDragData(dataTransfer) {
dataTransfer.setData('Text', this.appData_.title);
dataTransfer.setData('URL', this.appData_.url);
},
@@ -600,7 +600,7 @@ cr.define('ntp', function() {
AppsPage.prototype = {
__proto__: TilePage.prototype,
- initialize: function() {
+ initialize() {
this.classList.add('apps-page');
this.addEventListener('cardselected', this.onCardSelected_);
@@ -614,7 +614,7 @@ cr.define('ntp', function() {
* Highlight a newly installed app as it's added to the NTP.
* @param {AppInfo} appData The data object that describes the app.
*/
- insertAndHighlightApp: function(appData) {
+ insertAndHighlightApp(appData) {
ntp.getCardSlider().selectCardByValue(this);
this.content_.scrollTop = this.content_.scrollHeight;
this.insertApp(appData, true);
@@ -626,7 +626,7 @@ cr.define('ntp', function() {
* @param {Object} appData The data that describes the app.
* @param {boolean} animate Whether to animate the insertion.
*/
- insertApp: function(appData, animate) {
+ insertApp(appData, animate) {
let index = this.tileElements_.length;
for (let i = 0; i < this.tileElements_.length; i++) {
if (appData.app_launch_ordinal <
@@ -644,7 +644,7 @@ cr.define('ntp', function() {
* first time this is called, we load all the app icons.
* @private
*/
- onCardSelected_: function() {
+ onCardSelected_() {
const apps = /** @type {NodeList<ntp.App>} */ (
this.querySelectorAll('.app.icon-loading'));
for (let i = 0; i < apps.length; i++) {
@@ -657,7 +657,7 @@ cr.define('ntp', function() {
* @param {Event} e The tilePage:tile_added event.
* @private
*/
- onTileAdded_: function(e) {
+ onTileAdded_(e) {
assert(e.currentTarget == this);
assert(e.addedTile.firstChild instanceof App);
if (this.classList.contains('selected-card')) {
@@ -670,7 +670,7 @@ cr.define('ntp', function() {
* the bubbles.
* @private
*/
- onScroll_: function() {
+ onScroll_() {
if (!this.selected) {
return;
}
@@ -681,7 +681,7 @@ cr.define('ntp', function() {
},
/** @override */
- doDragOver: function(e) {
+ doDragOver(e) {
// Only animatedly re-arrange if the user is currently dragging an app.
const tile = ntp.getCurrentlyDraggingTile();
if (tile && tile.querySelector('.app')) {
@@ -693,7 +693,7 @@ cr.define('ntp', function() {
},
/** @override */
- shouldAcceptDrag: function(e) {
+ shouldAcceptDrag(e) {
if (ntp.getCurrentlyDraggingTile()) {
return true;
}
@@ -705,7 +705,7 @@ cr.define('ntp', function() {
},
/** @override */
- addDragData: function(dataTransfer, index) {
+ addDragData(dataTransfer, index) {
let sourceId = -1;
const currentlyDraggingTile = ntp.getCurrentlyDraggingTile();
if (currentlyDraggingTile) {
@@ -740,7 +740,7 @@ cr.define('ntp', function() {
* data.
* @private
*/
- addOutsideData_: function(dataTransfer) {
+ addOutsideData_(dataTransfer) {
const url = dataTransfer.getData('url');
assert(url);
@@ -774,7 +774,7 @@ cr.define('ntp', function() {
* @param {Object} data The data object describing the link. Must have |url|
* and |title| members.
*/
- generateAppForLink: function(data) {
+ generateAppForLink(data) {
assert(data.url != undefined);
assert(data.title != undefined);
const pageIndex = ntp.getAppsPageIndex(this);
@@ -782,7 +782,7 @@ cr.define('ntp', function() {
},
/** @override */
- tileMoved: function(draggedTile) {
+ tileMoved(draggedTile) {
if (!(draggedTile.firstChild instanceof App)) {
return;
}
@@ -802,7 +802,7 @@ cr.define('ntp', function() {
},
/** @override */
- setDropEffect: function(dataTransfer) {
+ setDropEffect(dataTransfer) {
const tile = ntp.getCurrentlyDraggingTile();
if (tile && tile.querySelector('.app')) {
ntp.setCurrentDropEffect(dataTransfer, 'move');
diff --git a/chromium/chrome/browser/resources/ntp4/dot_list.js b/chromium/chrome/browser/resources/ntp4/dot_list.js
index d37ff53dfbc..38da7aa77de 100644
--- a/chromium/chrome/browser/resources/ntp4/dot_list.js
+++ b/chromium/chrome/browser/resources/ntp4/dot_list.js
@@ -25,7 +25,7 @@ cr.define('ntp', function() {
DotList.prototype = {
__proto__: HTMLUListElement.prototype,
- decorate: function() {
+ decorate() {
this.addEventListener('keydown', this.onKeyDown_.bind(this));
navDots = this.getElementsByClassName('dot');
},
@@ -43,7 +43,7 @@ cr.define('ntp', function() {
* element.
* @param {!Event} e The KeyboardEvent.
*/
- onKeyDown_: function(e) {
+ onKeyDown_(e) {
if (hasKeyModifiers(e)) {
return;
}
diff --git a/chromium/chrome/browser/resources/ntp4/incognito_tab.html b/chromium/chrome/browser/resources/ntp4/incognito_tab.html
index f690ec9a1f1..b666b0c65a4 100644
--- a/chromium/chrome/browser/resources/ntp4/incognito_tab.html
+++ b/chromium/chrome/browser/resources/ntp4/incognito_tab.html
@@ -13,7 +13,7 @@
<script>
// Until themes can clear the cache, force-reload the theme stylesheet.
document.write('<link id="incognitothemecss" rel="stylesheet" ' +
- 'href="chrome://theme/css/incognito_new_tab_theme.css?' +
+ 'href="chrome://theme/css/incognito_tab_theme.css?' +
Date.now() + '">');
</script>
</head>
@@ -39,7 +39,8 @@ document.write('<link id="incognitothemecss" rel="stylesheet" ' +
icon-aria-label="$i18n{cookieControlsTitle}"
icon-class="$i18n{cookieControlsToolTipIcon}"
tooltip-text="$i18n{cookieControlsTooltipText}"
- style="cursor: pointer;" $i18n{hideTooltipIcon}></cr-tooltip-icon>
+ role="link" style="cursor: pointer;" $i18n{hideTooltipIcon}>
+ </cr-tooltip-icon>
<cr-toggle id="cookie-controls-toggle"
aria-label="$i18n{cookieControlsTitle}"
$i18n{cookieControlsToggleChecked} dark></cr-toggle>
diff --git a/chromium/chrome/browser/resources/ntp4/incognito_tab.js b/chromium/chrome/browser/resources/ntp4/incognito_tab.js
index d6cc6fc6061..f9b4218a89a 100644
--- a/chromium/chrome/browser/resources/ntp4/incognito_tab.js
+++ b/chromium/chrome/browser/resources/ntp4/incognito_tab.js
@@ -3,25 +3,34 @@
// found in the LICENSE file.
window.addEventListener('load', function() {
+ let cookieSettingsUrl;
+
cr.addWebUIListener('theme-changed', themeData => {
document.documentElement.setAttribute(
'hascustombackground', themeData.hasCustomBackground);
$('incognitothemecss').href =
- 'chrome://theme/css/incognito_new_tab_theme.css?' + Date.now();
+ 'chrome://theme/css/incognito_tab_theme.css?' + Date.now();
});
chrome.send('observeThemeChanges');
cr.addWebUIListener('cookie-controls-changed', dict => {
$('cookie-controls-tooltip-icon').hidden = !dict.enforced;
+ $('cookie-controls-tooltip-icon').iconClass = dict.icon;
$('cookie-controls-toggle').disabled = dict.enforced;
$('cookie-controls-toggle').checked = dict.checked;
- $('cookie-controls-toggle').iconClass = dict.icon;
+ cookieSettingsUrl = dict.cookieSettingsUrl;
});
$('cookie-controls-toggle').addEventListener('change', event => {
chrome.send('cookieControlsToggleChanged', [event.detail]);
});
+ // Make cookie-controls-tooltip-icon respond to the enter key.
+ $('cookie-controls-tooltip-icon').addEventListener('keyup', event => {
+ if (event.key === 'Enter') {
+ $('cookie-controls-tooltip-icon').click();
+ }
+ });
$('cookie-controls-tooltip-icon').onclick = () => {
- window.location.href = 'chrome://settings/content/cookies';
+ window.location.href = cookieSettingsUrl;
};
chrome.send('observeCookieControlsSettingsChanges');
});
@@ -30,7 +39,7 @@ window.addEventListener('load', function() {
// from the C++ side.
const ntp = {
/** @param {string} attached */
- setBookmarkBarAttached: function(attached) {
+ setBookmarkBarAttached(attached) {
document.documentElement.setAttribute('bookmarkbarattached', attached);
},
};
diff --git a/chromium/chrome/browser/resources/ntp4/new_incognito_tab_theme.css b/chromium/chrome/browser/resources/ntp4/incognito_tab_theme.css
index e6c6a69ec75..e6c6a69ec75 100644
--- a/chromium/chrome/browser/resources/ntp4/new_incognito_tab_theme.css
+++ b/chromium/chrome/browser/resources/ntp4/incognito_tab_theme.css
diff --git a/chromium/chrome/browser/resources/ntp4/nav_dot.js b/chromium/chrome/browser/resources/ntp4/nav_dot.js
index 8193fe15190..501ef789bdf 100644
--- a/chromium/chrome/browser/resources/ntp4/nav_dot.js
+++ b/chromium/chrome/browser/resources/ntp4/nav_dot.js
@@ -32,7 +32,7 @@ cr.define('ntp', function() {
NavDot.prototype = {
__proto__: HTMLLIElement.prototype,
- initialize: function(page, title, titleIsEditable, animate) {
+ initialize(page, title, titleIsEditable, animate) {
this.className = 'dot';
this.setAttribute('role', 'button');
@@ -96,7 +96,7 @@ cr.define('ntp', function() {
* transition the element to 0 width.
* @param {boolean=} opt_animate Whether to animate the removal or not.
*/
- remove: function(opt_animate) {
+ remove(opt_animate) {
if (opt_animate) {
this.classList.add('small');
} else {
@@ -107,7 +107,7 @@ cr.define('ntp', function() {
/**
* Navigates the card slider to the page for this dot.
*/
- switchToPage: function() {
+ switchToPage() {
ntp.getCardSlider().selectCardByValue(this.page_, true);
},
@@ -115,7 +115,7 @@ cr.define('ntp', function() {
* Handler for keydown event on the dot.
* @param {Event} e The KeyboardEvent.
*/
- onKeyDown_: function(e) {
+ onKeyDown_(e) {
if (e.key == 'Enter') {
this.onClick_(e);
e.stopPropagation();
@@ -127,7 +127,7 @@ cr.define('ntp', function() {
* @param {Event} e The click event.
* @private
*/
- onClick_: function(e) {
+ onClick_(e) {
this.switchToPage();
// The explicit focus call is necessary because of overriding the default
// handling in onInputMouseDown_.
@@ -143,7 +143,7 @@ cr.define('ntp', function() {
* @param {Event} e The click event.
* @private
*/
- onDoubleClick_: function(e) {
+ onDoubleClick_(e) {
if (this.titleIsEditable_) {
this.input_.disabled = false;
this.input_.focus();
@@ -156,7 +156,7 @@ cr.define('ntp', function() {
* @param {Event} e The click event.
* @private
*/
- onInputMouseDown_: function(e) {
+ onInputMouseDown_(e) {
if (this.ownerDocument.activeElement != this.input_) {
e.preventDefault();
}
@@ -167,7 +167,7 @@ cr.define('ntp', function() {
* @param {Event} e The click event.
* @private
*/
- onInputKeyDown_: function(e) {
+ onInputKeyDown_(e) {
switch (e.key) {
case 'Escape': // Escape cancels edits.
this.input_.value = this.displayTitle;
@@ -182,19 +182,19 @@ cr.define('ntp', function() {
* @param {Event} e The blur event.
* @private
*/
- onInputBlur_: function(e) {
+ onInputBlur_(e) {
window.getSelection().removeAllRanges();
this.displayTitle = this.input_.value;
ntp.saveAppPageName(this.page_, this.displayTitle);
this.input_.disabled = true;
},
- shouldAcceptDrag: function(e) {
+ shouldAcceptDrag(e) {
return this.page_.shouldAcceptDrag(e);
},
/** @override */
- doDragEnter: function(e) {
+ doDragEnter(e) {
const self = this;
function navPageClearTimeout() {
self.switchToPage();
@@ -206,7 +206,7 @@ cr.define('ntp', function() {
},
/** @override */
- doDragOver: function(e) {
+ doDragOver(e) {
// Prevent default handling so the <input> won't act as a drag target.
e.preventDefault();
@@ -218,7 +218,7 @@ cr.define('ntp', function() {
},
/** @override */
- doDrop: function(e) {
+ doDrop(e) {
e.stopPropagation();
const tile = ntp.getCurrentlyDraggingTile();
if (tile && tile.tilePage != this.page_) {
@@ -230,7 +230,7 @@ cr.define('ntp', function() {
},
/** @override */
- doDragLeave: function(e) {
+ doDragLeave(e) {
this.cancelDelayedSwitch_();
},
@@ -238,7 +238,7 @@ cr.define('ntp', function() {
* Cancels the timer for page switching.
* @private
*/
- cancelDelayedSwitch_: function() {
+ cancelDelayedSwitch_() {
if (this.dragNavTimeout) {
window.clearTimeout(this.dragNavTimeout);
this.dragNavTimeout = null;
@@ -250,7 +250,7 @@ cr.define('ntp', function() {
* @param {Event} e The transition end event.
* @private
*/
- onTransitionEnd_: function(e) {
+ onTransitionEnd_(e) {
if (e.propertyName === 'max-width' && this.classList.contains('small')) {
this.parentNode.removeChild(this);
}
diff --git a/chromium/chrome/browser/resources/ntp4/page_list_view.js b/chromium/chrome/browser/resources/ntp4/page_list_view.js
index b9e093a44e1..ec7160a65a0 100644
--- a/chromium/chrome/browser/resources/ntp4/page_list_view.js
+++ b/chromium/chrome/browser/resources/ntp4/page_list_view.js
@@ -143,7 +143,7 @@ cr.define('ntp', function() {
* @param {!ntp.PageSwitcher|undefined} opt_pageSwitcherEnd Optional end
* page switcher button.
*/
- initialize: function(
+ initialize(
pageList, dotList, cardSliderFrame, opt_trash, opt_pageSwitcherStart,
opt_pageSwitcherEnd) {
this.pageList = pageList;
@@ -239,7 +239,7 @@ cr.define('ntp', function() {
* When opt_refNode is falsey, |page| will just be appended to the end of
* the page list.
*/
- appendTilePage: function(page, title, titleIsEditable, opt_refNode) {
+ appendTilePage(page, title, titleIsEditable, opt_refNode) {
if (opt_refNode) {
const refIndex = this.getTilePageIndex(opt_refNode);
this.cardSlider.addCardAtIndex(page, refIndex);
@@ -268,7 +268,7 @@ cr.define('ntp', function() {
* @param {AppInfo} appData The data for the app. This contains page and
* position indices.
*/
- appMoved: function(appData) {
+ appMoved(appData) {
const app = /** @type {ntp.App} */ ($(appData.id));
assert(app, 'trying to move an app that doesn\'t exist');
app.remove(false);
@@ -285,7 +285,7 @@ cr.define('ntp', function() {
* false if the app is being disabled.
* @param {boolean} fromPage True if the removal was from the current page.
*/
- appRemoved: function(appData, isUninstall, fromPage) {
+ appRemoved(appData, isUninstall, fromPage) {
const app = /** @type {ntp.App} */ ($(appData.id));
assert(app, 'trying to remove an app that doesn\'t exist');
@@ -300,7 +300,7 @@ cr.define('ntp', function() {
* @return {boolean} If the page is still starting up.
* @private
*/
- isStartingUp_: function() {
+ isStartingUp_() {
return document.documentElement.classList.contains('starting-up');
},
@@ -320,7 +320,7 @@ cr.define('ntp', function() {
* @param {{apps: Array<AppInfo>, appPageNames: Array<string>}} data
* An object with all the data on available applications.
*/
- getAppsCallback: function(data) {
+ getAppsCallback(data) {
const startTime = Date.now();
// Remember this to select the correct card when done rebuilding.
@@ -429,7 +429,7 @@ cr.define('ntp', function() {
* @param {boolean=} opt_highlight Whether the app about to be added should
* be highlighted.
*/
- appAdded: function(appData, opt_highlight) {
+ appAdded(appData, opt_highlight) {
if (appData.id == this.highlightAppId) {
opt_highlight = true;
this.highlightAppId = null;
@@ -463,7 +463,7 @@ cr.define('ntp', function() {
* @param {Object} data An object with all the data on available
* applications.
*/
- appsPrefChangedCallback: function(data) {
+ appsPrefChangedCallback(data) {
for (let i = 0; i < data.apps.length; ++i) {
$(data.apps[i].id).appData = data.apps[i];
}
@@ -479,7 +479,7 @@ cr.define('ntp', function() {
* Invoked whenever the pages in apps-page-list have changed so that
* the Slider knows about the new elements.
*/
- updateSliderCards: function() {
+ updateSliderCards() {
const pageNo = Math.max(
0, Math.min(this.cardSlider.currentCard, this.tilePages.length - 1));
this.cardSlider.setCards(
@@ -492,7 +492,7 @@ cr.define('ntp', function() {
* Called whenever tiles should be re-arranging themselves out of the way
* of a moving or insert tile.
*/
- enterRearrangeMode: function() {
+ enterRearrangeMode() {
const tempPage = new ntp.AppsPage();
tempPage.classList.add('temporary');
const pageName = loadTimeData.getString('appDefaultPageName');
@@ -510,7 +510,7 @@ cr.define('ntp', function() {
/**
* Invoked whenever some app is released
*/
- leaveRearrangeMode: function() {
+ leaveRearrangeMode() {
const tempPage = /** @type {ntp.AppsPage} */ (
document.querySelector('.tile-page.temporary'));
if (tempPage) {
@@ -534,7 +534,7 @@ cr.define('ntp', function() {
* Callback for the 'pagelayout' event.
* @param {Event} e The event.
*/
- onPageLayout_: function(e) {
+ onPageLayout_(e) {
if (Array.prototype.indexOf.call(this.tilePages, e.currentTarget) !=
this.cardSlider.currentCard) {
return;
@@ -548,7 +548,7 @@ cr.define('ntp', function() {
* layout of the current card, and updates the aria-label attributes of
* the page switchers.
*/
- updatePageSwitchers: function() {
+ updatePageSwitchers() {
if (!this.pageSwitcherStart || !this.pageSwitcherEnd) {
return;
}
@@ -594,7 +594,7 @@ cr.define('ntp', function() {
* @return {number} The index of |page| or -1 if it is not in the
* collection.
*/
- getAppsPageIndex: function(page) {
+ getAppsPageIndex(page) {
return Array.prototype.indexOf.call(this.appsPages, page);
},
@@ -603,7 +603,7 @@ cr.define('ntp', function() {
* @param {Event} e The cardSlider:card_changed event.
* @private
*/
- onCardChanged_: function(e) {
+ onCardChanged_(e) {
const page = e.cardSlider.currentCardValue;
// Don't change shownPage until startup is done (and page changes actually
@@ -631,7 +631,7 @@ cr.define('ntp', function() {
* @param {number} shownPageIndex The new shown page index.
* @private
*/
- setShownPage_: function(shownPageIndex) {
+ setShownPage_(shownPageIndex) {
assert(shownPageIndex >= 0);
this.shownPageIndex = shownPageIndex;
chrome.send('pageSelected', [this.shownPageIndex]);
@@ -642,7 +642,7 @@ cr.define('ntp', function() {
* card accordingly.
* @param {Event} e A card removed or added event.
*/
- onCardAdded_: function(e) {
+ onCardAdded_(e) {
// When the second arg passed to insertBefore is falsey, it acts just like
// appendChild.
this.pageList.insertBefore(e.addedCard, this.tilePages[e.addedIndex]);
@@ -654,7 +654,7 @@ cr.define('ntp', function() {
* accordingly.
* @param {Event} e A card removed or added event.
*/
- onCardRemoved_: function(e) {
+ onCardRemoved_(e) {
e.removedCard.parentNode.removeChild(e.removedCard);
this.onCardAddedOrRemoved_();
},
@@ -663,7 +663,7 @@ cr.define('ntp', function() {
* Called when a card is removed or added.
* @private
*/
- onCardAddedOrRemoved_: function() {
+ onCardAddedOrRemoved_() {
if (this.isStartingUp_()) {
return;
}
@@ -679,7 +679,7 @@ cr.define('ntp', function() {
* @param {ntp.AppsPage} appPage The app page for which we wish to save.
* @param {string} name The name of the page.
*/
- saveAppPageName: function(appPage, name) {
+ saveAppPageName(appPage, name) {
const index = this.getAppsPageIndex(appPage);
assert(index != -1);
chrome.send('saveAppPageName', [name, index]);
@@ -689,7 +689,7 @@ cr.define('ntp', function() {
* Window resize handler.
* @private
*/
- onWindowResize_: function(e) {
+ onWindowResize_(e) {
this.cardSlider.resize(this.sliderFrame.offsetWidth);
this.updatePageSwitchers();
},
@@ -699,7 +699,7 @@ cr.define('ntp', function() {
* not offline-enabled to be grayscale if the browser is offline.
* @private
*/
- updateOfflineEnabledApps_: function() {
+ updateOfflineEnabledApps_() {
const apps = /** @type {!NodeList<!ntp.App>} */ (
document.querySelectorAll('.app'));
for (let i = 0; i < apps.length; ++i) {
@@ -716,7 +716,7 @@ cr.define('ntp', function() {
* @param {Event} e The KeyboardEvent.
* @private
*/
- onDocKeyDown_: function(e) {
+ onDocKeyDown_(e) {
if (!e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) {
return;
}
@@ -744,7 +744,7 @@ cr.define('ntp', function() {
* @return {number} The index of |page| or -1 if it is not in the
* collection.
*/
- getTilePageIndex: function(page) {
+ getTilePageIndex(page) {
return Array.prototype.indexOf.call(this.tilePages, page);
},
@@ -753,7 +753,7 @@ cr.define('ntp', function() {
* @param {ntp.TilePage} page The page to be removed.
* @param {boolean=} opt_animate If the removal should be animated.
*/
- removeTilePageAndDot_: function(page, opt_animate) {
+ removeTilePageAndDot_(page, opt_animate) {
if (page.navigationDot) {
page.navigationDot.remove(opt_animate);
}
diff --git a/chromium/chrome/browser/resources/ntp4/page_switcher.js b/chromium/chrome/browser/resources/ntp4/page_switcher.js
index fc2a4a0d816..c77d08e5246 100644
--- a/chromium/chrome/browser/resources/ntp4/page_switcher.js
+++ b/chromium/chrome/browser/resources/ntp4/page_switcher.js
@@ -18,7 +18,7 @@ cr.define('ntp', function() {
PageSwitcher.prototype = {
__proto__: HTMLButtonElement.prototype,
- decorate: function(el) {
+ decorate(el) {
el.__proto__ = PageSwitcher.prototype;
el.addEventListener('click', el.activate_);
@@ -32,7 +32,7 @@ cr.define('ntp', function() {
* Activate the switcher (go to the next card).
* @private
*/
- activate_: function() {
+ activate_() {
ntp.getCardSlider().selectCard(this.nextCardIndex_(), true);
},
@@ -40,7 +40,7 @@ cr.define('ntp', function() {
* Calculate the index of the card that this button will switch to.
* @private
*/
- nextCardIndex_: function() {
+ nextCardIndex_() {
const cardSlider = ntp.getCardSlider();
const index = cardSlider.currentCard + this.direction_;
const numCards = cardSlider.cardCount - 1;
@@ -53,7 +53,7 @@ cr.define('ntp', function() {
* @param {NodeList} dots The dot elements which display the names of the
* cards.
*/
- updateButtonAccessibleLabel: function(dots) {
+ updateButtonAccessibleLabel(dots) {
const currentIndex = ntp.getCardSlider().currentCard;
const nextCardIndex = this.nextCardIndex_();
if (nextCardIndex == currentIndex) {
@@ -77,7 +77,7 @@ cr.define('ntp', function() {
this.setAttribute('aria-label', ariaLabel);
},
- shouldAcceptDrag: function(e) {
+ shouldAcceptDrag(e) {
// Only allow page switching when a drop could happen on the page being
// switched to.
const nextPage =
@@ -85,16 +85,16 @@ cr.define('ntp', function() {
return nextPage.shouldAcceptDrag(e);
},
- doDragEnter: function(e) {
+ doDragEnter(e) {
this.scheduleDelayedSwitch_(e);
this.doDragOver(e);
},
- doDragLeave: function(e) {
+ doDragLeave(e) {
this.cancelDelayedSwitch_();
},
- doDragOver: function(e) {
+ doDragOver(e) {
e.preventDefault();
const targetPage = ntp.getCardSlider().currentCardValue;
if (targetPage.shouldAcceptDrag(e)) {
@@ -102,7 +102,7 @@ cr.define('ntp', function() {
}
},
- doDrop: function(e) {
+ doDrop(e) {
e.stopPropagation();
this.cancelDelayedSwitch_();
@@ -125,7 +125,7 @@ cr.define('ntp', function() {
* cancelled by cancelDelayedSwitch_.
* @private
*/
- scheduleDelayedSwitch_: function(e) {
+ scheduleDelayedSwitch_(e) {
// Stop switching when the next page can't be dropped onto.
const nextPage =
ntp.getCardSlider().getCardAtIndex(this.nextCardIndex_());
@@ -146,7 +146,7 @@ cr.define('ntp', function() {
* Cancels the timer that activates the switcher while dragging.
* @private
*/
- cancelDelayedSwitch_: function() {
+ cancelDelayedSwitch_() {
if (this.dragNavTimeout_) {
window.clearTimeout(this.dragNavTimeout_);
this.dragNavTimeout_ = null;
diff --git a/chromium/chrome/browser/resources/ntp4/tile_page.js b/chromium/chrome/browser/resources/ntp4/tile_page.js
index 600fc1f09b4..0b7837e8337 100644
--- a/chromium/chrome/browser/resources/ntp4/tile_page.js
+++ b/chromium/chrome/browser/resources/ntp4/tile_page.js
@@ -51,7 +51,7 @@ cr.define('ntp', function() {
Tile.prototype = {
__proto__: HTMLDivElement.prototype,
- initialize: function(contents) {
+ initialize(contents) {
// 'real' as opposed to doppleganger.
this.className = 'tile real';
this.appendChild(contents);
@@ -81,7 +81,7 @@ cr.define('ntp', function() {
* @param {number} x The x coordinate, in pixels.
* @param {number} y The y coordinate, in pixels.
*/
- setGridPosition: function(x, y) {
+ setGridPosition(x, y) {
this.gridX = x;
this.gridY = y;
this.moveTo(x, y);
@@ -92,7 +92,7 @@ cr.define('ntp', function() {
* @param {number} x The x coordinate, in pixels.
* @param {number} y The y coordinate, in pixels.
*/
- moveTo: function(x, y) {
+ moveTo(x, y) {
// left overrides right in LTR, and right takes precedence in RTL.
this.style.left = toCssPx(x);
this.style.right = toCssPx(x);
@@ -104,7 +104,7 @@ cr.define('ntp', function() {
* @param {Event} e The event for the drag.
* @private
*/
- onDragStart_: function(e) {
+ onDragStart_(e) {
// The user may start dragging again during a previous drag's finishing
// animation.
if (this.classList.contains('dragging')) {
@@ -145,7 +145,7 @@ cr.define('ntp', function() {
* @param {Event} e The event for the drag.
* @private
*/
- onDragMove_: function(e) {
+ onDragMove_(e) {
if (e.view != window || (e.x == 0 && e.y == 0)) {
this.dragClone.hidden = true;
return;
@@ -161,7 +161,7 @@ cr.define('ntp', function() {
* @param {Event} e The event for the drag.
* @private
*/
- onDragEnd_: function(e) {
+ onDragEnd_(e) {
this.dragClone.hidden = false;
this.dragClone.classList.add('placing');
@@ -223,7 +223,7 @@ cr.define('ntp', function() {
* @param {number} x x-axis offset, in pixels.
* @param {number} y y-axis offset, in pixels.
*/
- showDoppleganger: function(x, y) {
+ showDoppleganger(x, y) {
// We always have to clear the previous doppleganger to make sure we get
// style updates for the contents of this tile.
this.clearDoppleganger();
@@ -250,7 +250,7 @@ cr.define('ntp', function() {
/**
* Destroys the current doppleganger.
*/
- clearDoppleganger: function() {
+ clearDoppleganger() {
if (this.doppleganger_) {
this.removeChild(this.doppleganger_);
this.doppleganger_ = null;
@@ -261,7 +261,7 @@ cr.define('ntp', function() {
* Returns status of doppleganger.
* @return {boolean} True if there is a doppleganger showing for |this|.
*/
- hasDoppleganger: function() {
+ hasDoppleganger() {
return !!this.doppleganger_;
},
@@ -271,7 +271,7 @@ cr.define('ntp', function() {
* the next drag starts (if the user starts a 2nd drag very quickly).
* @private
*/
- finalizeDrag_: function() {
+ finalizeDrag_() {
assert(this.classList.contains('dragging'));
const clone = this.dragClone;
@@ -290,7 +290,7 @@ cr.define('ntp', function() {
* resting spot.
* @param {Event} e The transition end event.
*/
- onDragCloneTransitionEnd_: function(e) {
+ onDragCloneTransitionEnd_(e) {
if (this.classList.contains('dragging') &&
(e.propertyName == 'left' || e.propertyName == 'top' ||
e.propertyName == 'transform')) {
@@ -302,7 +302,7 @@ cr.define('ntp', function() {
* Called when an app is removed from Chrome. Animates its disappearance.
* @param {boolean=} opt_animate Whether the animation should be animated.
*/
- doRemove: function(opt_animate) {
+ doRemove(opt_animate) {
if (opt_animate) {
this.firstChild.classList.add('removing-tile-contents');
} else {
@@ -314,7 +314,7 @@ cr.define('ntp', function() {
* Callback for the animationend event on the tile's contents.
* @param {Event} e The event object.
*/
- onContentsAnimationEnd_: function(e) {
+ onContentsAnimationEnd_(e) {
if (this.firstChild.classList.contains('new-tile-contents')) {
this.firstChild.classList.remove('new-tile-contents');
}
@@ -407,7 +407,7 @@ cr.define('ntp', function() {
TilePage.prototype = {
__proto__: HTMLDivElement.prototype,
- initialize: function() {
+ initialize() {
this.className = 'tile-page';
// Div that acts as a custom scrollbar. The scrollbar has to live
@@ -523,7 +523,7 @@ cr.define('ntp', function() {
*
* TODO(dbeam): this method now conflicts with HTMLElement#remove(). Rename.
*/
- remove: function() {
+ remove() {
// This checks arguments.length as most remove functions have a boolean
// |opt_animate| argument, but that's not necesarilly applicable to
// removing a tilePage. Selecting a different card in an animated way and
@@ -540,7 +540,7 @@ cr.define('ntp', function() {
* instance is removed from the DOM.
* @private
*/
- tearDown_: function() {
+ tearDown_() {
this.eventTracker.removeAll();
},
@@ -550,7 +550,7 @@ cr.define('ntp', function() {
* @param {boolean} animate If true, the append will be animated.
* @protected
*/
- appendTile: function(tileElement, animate) {
+ appendTile(tileElement, animate) {
this.addTileAt(tileElement, this.tileElements_.length, animate);
},
@@ -562,7 +562,7 @@ cr.define('ntp', function() {
* animated (other tiles, if they must reposition, do not animate).
* @protected
*/
- addTileAt: function(tileElement, index, animate) {
+ addTileAt(tileElement, index, animate) {
this.classList.remove('animating-tile-page');
if (animate) {
tileElement.classList.add('new-tile-contents');
@@ -595,7 +595,7 @@ cr.define('ntp', function() {
* @param {number} index The index of the tile that was added.
* @param {boolean} wasAnimated Whether the removal was animated.
*/
- fireAddedEvent: function(tile, index, wasAnimated) {
+ fireAddedEvent(tile, index, wasAnimated) {
const e = document.createEvent('Event');
e.initEvent('tilePage:tile_added', true, true);
e.addedIndex = index;
@@ -610,7 +610,7 @@ cr.define('ntp', function() {
* @param {boolean=} opt_dontNotify Whether a page should be removed if the
* last tile is removed from it.
*/
- removeTile: function(tile, opt_animate, opt_dontNotify) {
+ removeTile(tile, opt_animate, opt_dontNotify) {
if (opt_animate) {
this.classList.add('animating-tile-page');
}
@@ -633,7 +633,7 @@ cr.define('ntp', function() {
* @param {number} oldIndex Where the tile was positioned before removal.
* @param {boolean} wasAnimated Whether the removal was animated.
*/
- fireRemovedEvent: function(tile, oldIndex, wasAnimated) {
+ fireRemovedEvent(tile, oldIndex, wasAnimated) {
const e = document.createEvent('Event');
e.initEvent('tilePage:tile_removed', true, true);
e.removedIndex = oldIndex;
@@ -645,7 +645,7 @@ cr.define('ntp', function() {
/**
* Removes all tiles from the page.
*/
- removeAllTiles: function() {
+ removeAllTiles() {
this.tileGrid_.innerHTML = '';
},
@@ -654,7 +654,7 @@ cr.define('ntp', function() {
* @param {Event} e A custom cardselected event.
* @private
*/
- handleCardSelection_: function(e) {
+ handleCardSelection_(e) {
this.updateFocusableElement();
// When we are selected, we re-calculate the layout values. (See comment
@@ -667,7 +667,7 @@ cr.define('ntp', function() {
* @param {Event} e A custom carddeselected event.
* @private
*/
- handleCardDeselection_: function(e) {
+ handleCardDeselection_(e) {
if (this.currentFocusElement_) {
this.currentFocusElement_.tabIndex = -1;
}
@@ -678,7 +678,7 @@ cr.define('ntp', function() {
* @param {Event} e The focus event.
* @private
*/
- handleFocus_: function(e) {
+ handleFocus_(e) {
if (this.focusableElements_.length == 0) {
return;
}
@@ -692,7 +692,7 @@ cr.define('ntp', function() {
* @param {Event} e The focus event.
* @private
*/
- handleMouseDown_: function(e) {
+ handleMouseDown_(e) {
const focusable =
findAncestorByClass(/** @type {Element} */ (e.target), 'focusable');
if (focusable) {
@@ -707,7 +707,7 @@ cr.define('ntp', function() {
* @param {Event} e The focus event.
* @private
*/
- handleKeyDown_: function(e) {
+ handleKeyDown_(e) {
// We only handle up, down, left, right without control keys.
if (e.metaKey || e.shiftKey || e.altKey || e.ctrlKey) {
return;
@@ -762,7 +762,7 @@ cr.define('ntp', function() {
* for tab focus, and the previously-focused element not eligible.
* @protected
*/
- updateFocusableElement: function() {
+ updateFocusableElement() {
if (this.focusableElements_.length == 0 || !this.selected) {
this.focusElementIndex_ = -1;
return;
@@ -786,7 +786,7 @@ cr.define('ntp', function() {
* focus element, if any, no longer eligible for tab focus.
* @private
*/
- updateFocusElement_: function() {
+ updateFocusElement_() {
this.updateFocusableElement();
if (this.focusElementIndex_ >= 0) {
this.focusableElements_[this.focusElementIndex_].focus();
@@ -809,7 +809,7 @@ cr.define('ntp', function() {
* hidden, but call before being shown.
* @private
*/
- calculateLayoutValues_: function() {
+ calculateLayoutValues_() {
const grid = this.gridValues_;
const availableSpace = this.tileGrid_.clientWidth - 2 * MIN_WIDE_MARGIN;
const wide = availableSpace >= grid.minWideWidth;
@@ -850,7 +850,7 @@ cr.define('ntp', function() {
* Dispatches the custom pagelayout event.
* @private
*/
- firePageLayoutEvent_: function() {
+ firePageLayoutEvent_() {
cr.dispatchSimpleEvent(this, 'pagelayout', true, true);
},
@@ -858,7 +858,7 @@ cr.define('ntp', function() {
* @return {number} The amount of margin that should be animated (in pixels)
* for the current grid layout.
*/
- getAnimatedLeftMargin_: function() {
+ getAnimatedLeftMargin_() {
if (this.layoutValues_.wide) {
return 0;
}
@@ -875,7 +875,7 @@ cr.define('ntp', function() {
* positioned in a non-default location.
* @private
*/
- positionTile_: function(index, opt_indexOffset) {
+ positionTile_(index, opt_indexOffset) {
const grid = this.gridValues_;
const layout = this.layoutValues_;
@@ -935,7 +935,7 @@ cr.define('ntp', function() {
* @return {number}
* @private
*/
- getWouldBeIndexForPoint_: function(x, y) {
+ getWouldBeIndexForPoint_(x, y) {
const grid = this.gridValues_;
const layout = this.layoutValues_;
@@ -958,7 +958,7 @@ cr.define('ntp', function() {
* Window resize event handler. Window resizes may trigger re-layouts.
* @param {Object} e The resize event.
*/
- onResize_: function(e) {
+ onResize_(e) {
if (this.lastWidth_ == this.clientWidth &&
this.lastHeight_ == this.clientHeight) {
return;
@@ -980,7 +980,7 @@ cr.define('ntp', function() {
* as they enter or exit the grid.
* @private
*/
- updateMask_: function() {
+ updateMask_() {
if (!this.isCurrentDragTarget) {
this.tileGrid_.style.WebkitMaskBoxImage = '';
return;
@@ -1007,7 +1007,7 @@ cr.define('ntp', function() {
this.tileGrid_.style.WebkitMaskBoxImage = gradient;
},
- updateTopMargin_: function() {
+ updateTopMargin_() {
const layout = this.layoutValues_;
// The top margin is set so that the vertical midpoint of the grid will
@@ -1051,7 +1051,7 @@ cr.define('ntp', function() {
* the page.
* @private
*/
- onNodeInsertedIntoDocument_: function(e) {
+ onNodeInsertedIntoDocument_(e) {
this.calculateLayoutValues_();
this.heightChanged_();
},
@@ -1061,7 +1061,7 @@ cr.define('ntp', function() {
* tileGrid.
* @private
*/
- heightChanged_: function() {
+ heightChanged_() {
// The tile grid will expand to the bottom footer, or enough to hold all
// the tiles, whichever is greater. It would be nicer if tilePage were
// a flex box, and the tile grid could be box-flex: 1, but this exposes a
@@ -1080,7 +1080,7 @@ cr.define('ntp', function() {
* scroll delta.
* @param {Event} e The mousewheel event.
*/
- handleMouseWheel: function(e) {
+ handleMouseWheel(e) {
// The ctrl-wheel should triggle the zoom in/out actions in Chromium for
// all pages.
if (e.wheelDeltaY == 0 || e.ctrlKey) {
@@ -1096,7 +1096,7 @@ cr.define('ntp', function() {
* @param {Event} e The scroll event.
* @private
*/
- onScroll_: function(e) {
+ onScroll_(e) {
this.queueUpdateScrollbars_();
},
@@ -1113,7 +1113,7 @@ cr.define('ntp', function() {
* like clientHeight.
* @private
*/
- queueUpdateScrollbars_: function() {
+ queueUpdateScrollbars_() {
if (this.scrollbarUpdate_) {
return;
}
@@ -1127,7 +1127,7 @@ cr.define('ntp', function() {
* scrollbar thumb (there is no track or buttons).
* @private
*/
- doUpdateScrollbars_: function() {
+ doUpdateScrollbars_() {
this.scrollbarUpdate_ = 0;
const content = this.content_;
@@ -1158,7 +1158,7 @@ cr.define('ntp', function() {
* @param {number} width The pixel width of a tile.
* @return {number} The height for |width|.
*/
- heightForWidth: function(width) {
+ heightForWidth(width) {
return width;
},
@@ -1169,12 +1169,12 @@ cr.define('ntp', function() {
},
/** @override */
- doDragLeave: function(e) {
+ doDragLeave(e) {
this.cleanupDrag();
},
/** @override */
- doDragEnter: function(e) {
+ doDragEnter(e) {
// Applies the mask so doppleganger tiles disappear into the fog.
this.updateMask_();
@@ -1194,7 +1194,7 @@ cr.define('ntp', function() {
},
/** @override */
- doDragOver: function(e) {
+ doDragOver(e) {
e.preventDefault();
this.setDropEffect(e.dataTransfer);
@@ -1206,7 +1206,7 @@ cr.define('ntp', function() {
},
/** @override */
- doDrop: function(e) {
+ doDrop(e) {
e.stopPropagation();
e.preventDefault();
@@ -1242,7 +1242,7 @@ cr.define('ntp', function() {
* Appends the currently dragged tile to the end of the page. Called
* from outside the page, e.g. when dropping on a nav dot.
*/
- appendDraggingTile: function() {
+ appendDraggingTile() {
const originalPage = currentlyDraggingTile.tilePage;
if (originalPage == this) {
return;
@@ -1257,7 +1257,7 @@ cr.define('ntp', function() {
/**
* Makes sure all the tiles are in the right place after a drag is over.
*/
- cleanupDrag: function() {
+ cleanupDrag() {
this.repositionTiles_(currentlyDraggingTile);
// Remove the drag mask.
this.updateMask_();
@@ -1268,7 +1268,7 @@ cr.define('ntp', function() {
* @param {Node=} opt_ignoreNode An optional node to ignore.
* @private
*/
- repositionTiles_: function(opt_ignoreNode) {
+ repositionTiles_(opt_ignoreNode) {
for (let i = 0; i < this.tileElements_.length; i++) {
if (!opt_ignoreNode || opt_ignoreNode !== this.tileElements_[i]) {
this.positionTile_(i);
@@ -1281,7 +1281,7 @@ cr.define('ntp', function() {
* @param {number} newDragIndex
* @private
*/
- updateDropIndicator_: function(newDragIndex) {
+ updateDropIndicator_(newDragIndex) {
const oldDragIndex = this.currentDropIndex_;
if (newDragIndex == oldDragIndex) {
return;
@@ -1309,7 +1309,7 @@ cr.define('ntp', function() {
* likely want to check |e.dataTransfer|.
* @return {boolean} True if this page can handle the drag.
*/
- shouldAcceptDrag: function(e) {
+ shouldAcceptDrag(e) {
return false;
},
@@ -1319,7 +1319,7 @@ cr.define('ntp', function() {
* data. This should only be used if currentlyDraggingTile is null.
* @param {number} index The tile index at which the drop occurred.
*/
- addDragData: function(dataTransfer, index) {
+ addDragData(dataTransfer, index) {
assertNotReached();
},
@@ -1329,14 +1329,14 @@ cr.define('ntp', function() {
* @param {Node} draggedTile The tile that was dropped.
* @param {number} prevIndex The previous index of the tile.
*/
- tileMoved: function(draggedTile, prevIndex) {},
+ tileMoved(draggedTile, prevIndex) {},
/**
* Sets the drop effect on |dataTransfer| to the desired value (e.g.
* 'copy').
* @param {DataTransfer} dataTransfer The drag event dataTransfer object.
*/
- setDropEffect: function(dataTransfer) {
+ setDropEffect(dataTransfer) {
assertNotReached();
},
};
diff --git a/chromium/chrome/browser/resources/ntp4/trash.js b/chromium/chrome/browser/resources/ntp4/trash.js
index fef11165be8..b7ddd0ea1fa 100644
--- a/chromium/chrome/browser/resources/ntp4/trash.js
+++ b/chromium/chrome/browser/resources/ntp4/trash.js
@@ -24,7 +24,7 @@ cr.define('ntp', function() {
Trash.prototype = {
__proto__: HTMLDivElement.prototype,
- initialize: function(element) {
+ initialize(element) {
this.dragWrapper_ = new cr.ui.DragWrapper(this, this);
},
@@ -33,7 +33,7 @@ cr.define('ntp', function() {
* @param {Event} e The event from drag enter.
* @return {boolean} True if we are interested in the drag data for |e|.
*/
- shouldAcceptDrag: function(e) {
+ shouldAcceptDrag(e) {
const tile = ntp.getCurrentlyDraggingTile();
if (!tile) {
return false;
@@ -43,7 +43,7 @@ cr.define('ntp', function() {
},
/** @override */
- doDragOver: function(e) {
+ doDragOver(e) {
ntp.getCurrentlyDraggingTile().dragClone.classList.add(
'hovering-on-trash');
ntp.setCurrentDropEffect(e.dataTransfer, 'move');
@@ -51,12 +51,12 @@ cr.define('ntp', function() {
},
/** @override */
- doDragEnter: function(e) {
+ doDragEnter(e) {
this.doDragOver(e);
},
/** @override */
- doDrop: function(e) {
+ doDrop(e) {
e.preventDefault();
const tile = ntp.getCurrentlyDraggingTile();
@@ -65,7 +65,7 @@ cr.define('ntp', function() {
},
/** @override */
- doDragLeave: function(e) {
+ doDragLeave(e) {
ntp.getCurrentlyDraggingTile().dragClone.classList.remove(
'hovering-on-trash');
},
diff --git a/chromium/chrome/browser/resources/offline_pages/BUILD.gn b/chromium/chrome/browser/resources/offline_pages/BUILD.gn
index c008bad1595..4465cf5a066 100644
--- a/chromium/chrome/browser/resources/offline_pages/BUILD.gn
+++ b/chromium/chrome/browser/resources/offline_pages/BUILD.gn
@@ -21,7 +21,5 @@ js_library("offline_internals") {
}
js_library("offline_internals_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
}
diff --git a/chromium/chrome/browser/resources/omnibox/.eslintrc.js b/chromium/chrome/browser/resources/omnibox/.eslintrc.js
new file mode 100644
index 00000000000..18f6e9550ca
--- /dev/null
+++ b/chromium/chrome/browser/resources/omnibox/.eslintrc.js
@@ -0,0 +1,11 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/omnibox/BUILD.gn b/chromium/chrome/browser/resources/omnibox/BUILD.gn
index c3634a0f8f1..1e3b93208db 100644
--- a/chromium/chrome/browser/resources/omnibox/BUILD.gn
+++ b/chromium/chrome/browser/resources/omnibox/BUILD.gn
@@ -6,50 +6,62 @@ import("//third_party/closure_compiler/compile_js.gni")
import("//tools/grit/grit_rule.gni")
js_type_check("closure_compile") {
+ uses_js_modules = true
deps = [
":omnibox",
+ ":omnibox_element",
+ ":omnibox_input",
+ ":omnibox_output",
+ ":omnibox_popup",
]
}
js_library("omnibox") {
deps = [
- ":omnibox_element",
":omnibox_input",
":omnibox_output",
"//chrome/browser/ui/webui/omnibox:mojo_bindings_js_library_for_compile",
- "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:util.m",
]
}
js_library("omnibox_element") {
+ deps = [ "//ui/webui/resources/js:assert.m" ]
}
js_library("omnibox_input") {
+ deps = [ ":omnibox_element" ]
}
js_library("omnibox_output") {
deps = [
- "//ui/webui/resources/js:util",
+ ":omnibox_element",
+ ":omnibox_input",
+ "//chrome/browser/ui/webui/omnibox:mojo_bindings_js_library_for_compile",
]
externs_list = [ "$externs_path/pending.js" ]
}
+js_library("omnibox_popup") {
+ deps = [
+ "//chrome/browser/ui/webui/omnibox:mojo_bindings_js_library_for_compile",
+ "//ui/webui/resources/cr_components/omnibox:cr_autocomplete_match_list",
+ ]
+}
+
grit("resources") {
source = "resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
outputs = [
"grit/omnibox_resources.h",
"omnibox_resources.pak",
]
output_dir = "$root_gen_dir/chrome"
- depfile_dir = target_gen_dir
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
- deps = [
- "//chrome/browser/ui/webui/omnibox:mojo_bindings_js",
- ]
+ deps = [ "//chrome/browser/ui/webui/omnibox:mojo_bindings_js" ]
}
diff --git a/chromium/chrome/browser/resources/omnibox/omnibox.html b/chromium/chrome/browser/resources/omnibox/omnibox.html
index d5284f5df81..29c4fdaaf80 100644
--- a/chromium/chrome/browser/resources/omnibox/omnibox.html
+++ b/chromium/chrome/browser/resources/omnibox/omnibox.html
@@ -6,17 +6,7 @@
<title>Omnibox Debug Page</title>
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<link rel="stylesheet" href="omnibox.css">
- <script src="chrome://resources/js/promise_resolver.js"></script>
- <script src="chrome://resources/js/cr.js"></script>
- <script src="chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js"></script>
- <script src="chrome://resources/js/load_time_data.js"></script>
- <script src="chrome://resources/js/util.js"></script>
- <script src="chrome/browser/ui/webui/omnibox/omnibox.mojom-lite.js"></script>
- <script src="omnibox_element.js"></script>
- <script src="omnibox_input.js"></script>
- <script src="omnibox_output.js"></script>
- <script src="omnibox.js"></script>
- <script src="strings.js"></script>
+ <script type="module" src="omnibox.js"></script>
</head>
<body>
diff --git a/chromium/chrome/browser/resources/omnibox/omnibox.js b/chromium/chrome/browser/resources/omnibox/omnibox.js
index b27b8b8eb88..bd319cd6900 100644
--- a/chromium/chrome/browser/resources/omnibox/omnibox.js
+++ b/chromium/chrome/browser/resources/omnibox/omnibox.js
@@ -2,6 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import './chrome/browser/ui/webui/omnibox/omnibox.mojom-lite.js';
+import './strings.m.js';
+
+import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {$} from 'chrome://resources/js/util.m.js';
+
+import {DisplayInputs, OmniboxInput, QueryInputs} from './omnibox_input.js';
+import {OmniboxOutput} from './omnibox_output.js';
+
/**
* Javascript for omnibox.html, served from chrome://omnibox/
* This is used to debug omnibox ranking. The user enters some text
@@ -17,7 +28,6 @@
* are available, the Javascript formats them and displays them.
*/
-(function() {
/**
* @typedef {{
* inputText: string,
@@ -25,7 +35,7 @@
* display: boolean,
* }}
*/
-let Request;
+let OmniboxRequest;
/**
* @typedef {{
@@ -48,13 +58,13 @@ let OmniboxExport;
let browserProxy;
/** @type {!OmniboxInput} */
let omniboxInput;
-/** @type {!omnibox_output.OmniboxOutput} */
+/** @type {!OmniboxOutput} */
let omniboxOutput;
/** @type {!ExportDelegate} */
let exportDelegate;
class BrowserProxy {
- /** @param {!omnibox_output.OmniboxOutput} omniboxOutput */
+ /** @param {!OmniboxOutput} omniboxOutput */
constructor(omniboxOutput) {
/** @private {!mojom.OmniboxPageCallbackRouter} */
this.callbackRouter_ = new mojom.OmniboxPageCallbackRouter;
@@ -71,23 +81,17 @@ class BrowserProxy {
this.handler_.setClientPage(
this.callbackRouter_.$.bindNewPipeAndPassRemote());
- /** @private {?Request} */
+ /** @private {?OmniboxRequest} */
this.lastRequest;
}
-
/**
* @param {!mojom.OmniboxResponse} response
* @param {boolean} isPageController
*/
handleNewAutocompleteResponse(response, isPageController) {
- // Note: Using inputText is a sufficient fix for the way this is used today,
- // but in principle it would be better to associate requests with responses
- // using a unique session identifier, for example by rolling an integer each
- // time a request is made. Doing so would require extra bookkeeping on the
- // host side, so for now we keep it simple.
- const isForLastPageRequest = isPageController && this.lastRequest &&
- this.lastRequest.inputText === response.inputText;
+ const isForLastPageRequest =
+ this.isForLastPageRequest(response.inputText, isPageController);
// When unfocusing the browser omnibox, the autocomplete controller
// sends a response with no combined results. This response is ignored
@@ -116,8 +120,7 @@ class BrowserProxy {
handleNewAutocompleteQuery(isPageController, inputText) {
// If the request originated from the debug page and is not for display,
// then we don't want to clear the omniboxOutput.
- if (isPageController && this.lastRequest &&
- this.lastRequest.inputText === inputText &&
+ if (this.isForLastPageRequest(inputText, isPageController) &&
this.lastRequest.display ||
omniboxInput.connectWindowOmnibox && !isPageController) {
omniboxOutput.prepareNewQuery();
@@ -148,12 +151,27 @@ class BrowserProxy {
pageClassification);
});
}
+
+ /**
+ * @param {string} inputText
+ * @param {boolean} isPageController
+ * @return {boolean}
+ */
+ isForLastPageRequest(inputText, isPageController) {
+ // Note: Using inputText is a sufficient fix for the way this is used today,
+ // but in principle it would be better to associate requests with responses
+ // using a unique session identifier, for example by rolling an integer each
+ // time a request is made. Doing so would require extra bookkeeping on the
+ // host side, so for now we keep it simple.
+ return isPageController && this.lastRequest !== null &&
+ this.lastRequest.inputText.trimStart() === inputText;
+ }
}
document.addEventListener('DOMContentLoaded', () => {
omniboxInput = /** @type {!OmniboxInput} */ ($('omnibox-input'));
omniboxOutput =
- /** @type {!omnibox_output.OmniboxOutput} */ ($('omnibox-output'));
+ /** @type {!OmniboxOutput} */ ($('omnibox-output'));
browserProxy = new BrowserProxy(omniboxOutput);
exportDelegate = new ExportDelegate(omniboxOutput, omniboxInput);
@@ -182,17 +200,19 @@ document.addEventListener('DOMContentLoaded', () => {
omniboxOutput.addEventListener(
'responses-count-changed', e => omniboxInput.responsesCount = e.detail);
+
+ omniboxOutput.updateDisplayInputs(omniboxInput.displayInputs);
});
class ExportDelegate {
/**
- * @param {!omnibox_output.OmniboxOutput} omniboxOutput
+ * @param {!OmniboxOutput} omniboxOutput
* @param {!OmniboxInput} omniboxInput
*/
constructor(omniboxOutput, omniboxInput) {
/** @private {!OmniboxInput} */
this.omniboxInput_ = omniboxInput;
- /** @private {!omnibox_output.OmniboxOutput} */
+ /** @private {!OmniboxOutput} */
this.omniboxOutput_ = omniboxOutput;
}
@@ -241,13 +261,13 @@ class ExportDelegate {
batchExports.push(exportData);
}
const variationInfo =
- await cr.sendWithPromise('requestVariationInfo', true);
- const pathInfo = await cr.sendWithPromise('requestPathInfo');
+ await sendWithPromise('requestVariationInfo', true);
+ const pathInfo = await sendWithPromise('requestPathInfo');
const loadTimeDataKeys = ['cl', 'command_line', 'executable_path',
'language', 'official', 'os_type', 'profile_path', 'useragent',
'version', 'version_bitsize', 'version_modifier'];
const versionDetails = Object.fromEntries(
- loadTimeDataKeys.map(key => [key, window.loadTimeData.getValue(key)]));
+ loadTimeDataKeys.map(key => [key, loadTimeData.getValue(key)]));
const now = new Date();
const fileName = `omnibox_batch_${ExportDelegate.getTimeStamp(now)}.json`;
@@ -303,8 +323,8 @@ class ExportDelegate {
}
exportClipboard() {
- navigator.clipboard.writeText(JSON.stringify(this.exportData_)).catch(
- error => console.error('unable to export to clipboard:', error));
+ navigator.clipboard.writeText(JSON.stringify(this.exportData_, null, 2))
+ .catch(error => console.error('unable to export to clipboard:', error));
}
exportFile() {
@@ -406,4 +426,3 @@ function validateImportData_(importData) {
return true;
}
-})();
diff --git a/chromium/chrome/browser/resources/omnibox/omnibox_element.js b/chromium/chrome/browser/resources/omnibox/omnibox_element.js
index ab39bbc1b52..d85964ce480 100644
--- a/chromium/chrome/browser/resources/omnibox/omnibox_element.js
+++ b/chromium/chrome/browser/resources/omnibox/omnibox_element.js
@@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {assertInstanceof} from 'chrome://resources/js/assert.m.js';
+
/**
* Helper class to be used as the super class of all custom elements in
* chrome://omnibox.
* @abstract
*/
-class OmniboxElement extends HTMLElement {
+export class OmniboxElement extends HTMLElement {
/** @param {string} templateId */
constructor(templateId) {
super();
@@ -19,16 +21,25 @@ class OmniboxElement extends HTMLElement {
}
/**
- * Get an element that's known to exist within this OmniboxElement.
- * Searches local shadow root for element by query.
+ * Finds the 1st element matching the query within the local shadow root. At
+ * least 1 matching element should exist.
* @param {string} query
* @return {!Element}
*/
- $$(query) {
+ $(query) {
return OmniboxElement.getByQuery_(query, this.shadowRoot);
}
/**
+ * Finds all elements matching the query within the local shadow root.
+ * @param {string} query
+ * @return {!NodeList<!Element>}
+ */
+ $$(query) {
+ return (this.shadowRoot || document).querySelectorAll(query);
+ }
+
+ /**
* Get a template that's known to exist within the DOM document.
* @param {string} templateId
* @return {!Element}
diff --git a/chromium/chrome/browser/resources/omnibox/omnibox_input.js b/chromium/chrome/browser/resources/omnibox/omnibox_input.js
index 9d07a1a8003..5d02be28b9e 100644
--- a/chromium/chrome/browser/resources/omnibox/omnibox_input.js
+++ b/chromium/chrome/browser/resources/omnibox/omnibox_input.js
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {OmniboxElement} from './omnibox_element.js';
+
/**
* @typedef {{
* inputText: string,
@@ -15,7 +17,7 @@
* pageClassification: number,
* }}
*/
-let QueryInputs;
+export let QueryInputs;
/**
* @typedef {{
@@ -26,12 +28,12 @@ let QueryInputs;
* thinRows: boolean,
* }}
*/
-let DisplayInputs;
+export let DisplayInputs;
-class OmniboxInput extends OmniboxElement {
+export class OmniboxInput extends OmniboxElement {
constructor() {
super('omnibox-input-template');
- this.displayInputs = OmniboxInput.defaultDisplayInputs;
+ this.restoreInputs_();
}
/** @override */
@@ -40,6 +42,24 @@ class OmniboxInput extends OmniboxElement {
}
/** @private */
+ storeInputs_() {
+ const inputs = {
+ connectWindowOmnibox: this.connectWindowOmnibox,
+ displayInputs: this.displayInputs,
+ };
+ window.localStorage.setItem('preserved-inputs', JSON.stringify(inputs));
+ }
+
+ /** @private */
+ restoreInputs_() {
+ const inputsString = window.localStorage.getItem('preserved-inputs');
+ const inputs = inputsString && JSON.parse(inputsString) || {};
+ this.$('#connect-window-omnibox').checked = inputs.connectWindowOmnibox;
+ this.displayInputs =
+ inputs.displayInputs || OmniboxInput.defaultDisplayInputs;
+ }
+
+ /** @private */
setupElementListeners_() {
['#input-text',
'#reset-autocomplete-controller',
@@ -50,19 +70,22 @@ class OmniboxInput extends OmniboxElement {
'#current-url',
'#page-classification',
].forEach(query => {
- this.$$(query).addEventListener(
+ this.$(query).addEventListener(
'input', this.onQueryInputsChanged_.bind(this));
});
// Set text of .arrow-padding to substring of #input-text text, from
// beginning until cursor position, in order to correctly align .arrow-up.
- this.$$('#input-text')
+ this.$('#input-text')
.addEventListener(
'input', this.positionCursorPositionIndicators_.bind(this));
- this.$$('#response-selection')
+ this.$('#connect-window-omnibox')
+ .addEventListener('input', this.storeInputs_.bind(this));
+
+ this.$('#response-selection')
.addEventListener('input', this.onResponseSelectionChanged_.bind(this));
- this.$$('#response-selection')
+ this.$('#response-selection')
.addEventListener('blur', this.onResponseSelectionBlur_.bind(this));
['#show-incomplete-results',
@@ -71,30 +94,36 @@ class OmniboxInput extends OmniboxElement {
'#elide-cells',
'#thin-rows',
].forEach(query => {
- this.$$(query).addEventListener(
+ this.$(query).addEventListener(
'input', this.onDisplayInputsChanged_.bind(this));
});
- this.$$('#filter-text')
+ this.$('#filter-text')
.addEventListener('input', this.onFilterInputsChanged_.bind(this));
- this.$$('#export-clipboard')
+ this.$('#export-clipboard')
.addEventListener('click', this.onExportClipboard_.bind(this));
- this.$$('#export-file')
+ this.$('#export-file')
.addEventListener('click', this.onExportFile_.bind(this));
- this.$$('#import-clipboard')
+ this.$('#import-clipboard')
.addEventListener('click', this.onImportClipboard_.bind(this));
- this.$$('#import-file-input')
+ this.$('#import-file-input')
.addEventListener('input', this.onImportFile_.bind(this));
- this.$$('#process-batch-input')
+ this.$('#process-batch-input')
.addEventListener('input', this.onProcessBatchFile_.bind(this));
['#import-clipboard', '#import-file'].forEach(query => {
- this.setupDragListeners_(this.$$(query));
- this.$$(query).addEventListener('drop', this.onImportDropped_.bind(this));
+ this.setupDragListeners_(this.$(query));
+ this.$(query).addEventListener('drop', this.onImportDropped_.bind(this));
});
- this.setupDragListeners_(this.$$('#process-batch'));
- this.$$('#process-batch')
+ this.setupDragListeners_(this.$('#process-batch'));
+ this.$('#process-batch')
.addEventListener('drop', this.onProcessBatchDropped_.bind(this));
+
+ this.$$('.button').forEach(el => el.addEventListener('keypress', e => {
+ if (e.key === ' ' || e.key === 'Enter') {
+ el.click();
+ }
+ }));
}
/**
@@ -116,10 +145,10 @@ class OmniboxInput extends OmniboxElement {
/** @private */
onQueryInputsChanged_() {
- this.$$('#imported-warning').hidden = true;
- this.$$('#current-url').disabled = this.$$('#zero-suggest').checked;
- if (this.$$('#zero-suggest').checked) {
- this.$$('#current-url').value = this.$$('#input-text').value;
+ this.$('#imported-warning').hidden = true;
+ this.$('#current-url').disabled = this.$('#zero-suggest').checked;
+ if (this.$('#zero-suggest').checked) {
+ this.$('#current-url').value = this.$('#input-text').value;
}
this.dispatchEvent(
new CustomEvent('query-inputs-changed', {detail: this.queryInputs}));
@@ -128,87 +157,92 @@ class OmniboxInput extends OmniboxElement {
/** @return {QueryInputs} */
get queryInputs() {
return {
- inputText: this.$$('#input-text').value,
+ inputText: this.$('#input-text').value,
resetAutocompleteController:
- this.$$('#reset-autocomplete-controller').checked,
- cursorLock: this.$$('#lock-cursor-position').checked,
+ this.$('#reset-autocomplete-controller').checked,
+ cursorLock: this.$('#lock-cursor-position').checked,
cursorPosition: this.cursorPosition_,
- zeroSuggest: this.$$('#zero-suggest').checked,
- preventInlineAutocomplete:
- this.$$('#prevent-inline-autocomplete').checked,
- preferKeyword: this.$$('#prefer-keyword').checked,
- currentUrl: this.$$('#current-url').value,
- pageClassification: this.$$('#page-classification').value,
+ zeroSuggest: this.$('#zero-suggest').checked,
+ preventInlineAutocomplete: this.$('#prevent-inline-autocomplete').checked,
+ preferKeyword: this.$('#prefer-keyword').checked,
+ currentUrl: this.$('#current-url').value,
+ pageClassification: this.$('#page-classification').value,
};
}
/** @param {QueryInputs} queryInputs */
set queryInputs(queryInputs) {
- this.$$('#input-text').value = queryInputs.inputText;
- this.$$('#reset-autocomplete-controller').checked =
+ this.$('#input-text').value = queryInputs.inputText;
+ this.$('#reset-autocomplete-controller').checked =
queryInputs.resetAutocompleteController;
- this.$$('#lock-cursor-position').checked = queryInputs.cursorLock;
+ this.$('#lock-cursor-position').checked = queryInputs.cursorLock;
this.cursorPosition_ = queryInputs.cursorPosition;
- this.$$('#zero-suggest').checked = queryInputs.zeroSuggest;
- this.$$('#prevent-inline-autocomplete').checked =
+ this.$('#zero-suggest').checked = queryInputs.zeroSuggest;
+ this.$('#prevent-inline-autocomplete').checked =
queryInputs.preventInlineAutocomplete;
- this.$$('#prefer-keyword').checked = queryInputs.preferKeyword;
- this.$$('#current-url').value = queryInputs.currentUrl;
- this.$$('#page-classification').value = queryInputs.pageClassification;
+ this.$('#prefer-keyword').checked = queryInputs.preferKeyword;
+ this.$('#current-url').value = queryInputs.currentUrl;
+ this.$('#page-classification').value = queryInputs.pageClassification;
}
/** @private @return {number} */
get cursorPosition_() {
- return this.$$('#lock-cursor-position').checked ?
- this.$$('#input-text').value.length :
- this.$$('#input-text').selectionEnd;
+ return this.$('#lock-cursor-position').checked ?
+ this.$('#input-text').value.length :
+ this.$('#input-text').selectionEnd;
}
/** @private @param {number} value */
set cursorPosition_(value) {
- this.$$('#input-text').setSelectionRange(value, value);
+ this.$('#input-text').setSelectionRange(value, value);
this.positionCursorPositionIndicators_();
}
/** @private */
positionCursorPositionIndicators_() {
- this.$$('.arrow-padding').textContent =
- this.$$('#input-text').value.substring(0, this.cursorPosition_);
+ this.$('.arrow-padding').textContent =
+ this.$('#input-text').value.substring(0, this.cursorPosition_);
}
/** @return {boolean} */
get connectWindowOmnibox() {
- return this.$$('#connect-window-omnibox').checked;
+ return this.$('#connect-window-omnibox').checked;
+ }
+
+ /** @private @param {boolean} connectWindowOmnibox */
+ set connectWindowOmnibox_(connectWindowOmnibox) {
+ this.$('#connect-window-omnibox').checked = connectWindowOmnibox;
}
/** @private */
onResponseSelectionChanged_() {
- const {value, max} = this.$$('#response-selection');
- this.$$('#history-warning').hidden = value === '0' || value === max;
+ const {value, max} = this.$('#response-selection');
+ this.$('#history-warning').hidden = value === '0' || value === max;
this.dispatchEvent(new CustomEvent('response-select', {detail: value - 1}));
}
/** @private */
onResponseSelectionBlur_() {
- const {value, min, max} = this.$$('#response-selection');
- this.$$('#response-selection').value = Math.max(Math.min(value, max), min);
+ const {value, min, max} = this.$('#response-selection');
+ this.$('#response-selection').value = Math.max(Math.min(value, max), min);
this.onResponseSelectionChanged_();
}
/** @param {number} value */
set responsesCount(value) {
- if (this.$$('#response-selection').value ===
- this.$$('#response-selection').max) {
- this.$$('#response-selection').value = value;
+ if (this.$('#response-selection').value ===
+ this.$('#response-selection').max) {
+ this.$('#response-selection').value = value;
}
- this.$$('#response-selection').max = value;
- this.$$('#response-selection').min = value ? 1 : 0;
- this.$$('#responses-count').textContent = value;
+ this.$('#response-selection').max = value;
+ this.$('#response-selection').min = value ? 1 : 0;
+ this.$('#responses-count').textContent = value;
this.onResponseSelectionBlur_();
}
/** @private */
onDisplayInputsChanged_() {
+ this.storeInputs_();
this.dispatchEvent(new CustomEvent(
'display-inputs-changed', {detail: this.displayInputs}));
}
@@ -216,28 +250,28 @@ class OmniboxInput extends OmniboxElement {
/** @return {DisplayInputs} */
get displayInputs() {
return {
- showIncompleteResults: this.$$('#show-incomplete-results').checked,
- showDetails: this.$$('#show-details').checked,
- showAllProviders: this.$$('#show-all-providers').checked,
- elideCells: this.$$('#elide-cells').checked,
- thinRows: this.$$('#thin-rows').checked,
+ showIncompleteResults: this.$('#show-incomplete-results').checked,
+ showDetails: this.$('#show-details').checked,
+ showAllProviders: this.$('#show-all-providers').checked,
+ elideCells: this.$('#elide-cells').checked,
+ thinRows: this.$('#thin-rows').checked,
};
}
/** @param {DisplayInputs} displayInputs */
set displayInputs(displayInputs) {
- this.$$('#show-incomplete-results').checked =
+ this.$('#show-incomplete-results').checked =
displayInputs.showIncompleteResults;
- this.$$('#show-details').checked = displayInputs.showDetails;
- this.$$('#show-all-providers').checked = displayInputs.showAllProviders;
- this.$$('#elide-cells').checked = displayInputs.elideCells;
- this.$$('#thin-rows').checked = displayInputs.thinRows;
+ this.$('#show-details').checked = displayInputs.showDetails;
+ this.$('#show-all-providers').checked = displayInputs.showAllProviders;
+ this.$('#elide-cells').checked = displayInputs.elideCells;
+ this.$('#thin-rows').checked = displayInputs.thinRows;
}
/** @private */
onFilterInputsChanged_() {
this.dispatchEvent(new CustomEvent(
- 'filter-input-changed', {detail: this.$$('#filter-text').value}));
+ 'filter-input-changed', {detail: this.$('#filter-text').value}));
}
/** @private */
@@ -300,7 +334,7 @@ class OmniboxInput extends OmniboxElement {
try {
const importData = JSON.parse(importString);
// TODO(manukh): If import fails, this UI state change shouldn't happen.
- this.$$('#imported-warning').hidden = false;
+ this.$('#imported-warning').hidden = false;
this.dispatchEvent(new CustomEvent('import', {detail: importData}));
} catch (error) {
console.error('error during import, invalid json:', error);
@@ -318,7 +352,11 @@ class OmniboxInput extends OmniboxElement {
}
}
- /** @private @param {!File} file */
+ /**
+ * @private
+ * @param {!File} file
+ * @return {!Promise}
+ */
static readFile_(file) {
return new Promise(resolve => {
const reader = new FileReader();
diff --git a/chromium/chrome/browser/resources/omnibox/omnibox_output.js b/chromium/chrome/browser/resources/omnibox/omnibox_output.js
index 53815c5ff76..41118b01039 100644
--- a/chromium/chrome/browser/resources/omnibox/omnibox_output.js
+++ b/chromium/chrome/browser/resources/omnibox/omnibox_output.js
@@ -2,1154 +2,1157 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-cr.define('omnibox_output', function() {
- /**
- * @typedef {{
- * cursorPosition: number,
- * time: number,
- * done: boolean,
- * type: string,
- * host: string,
- * isTypedHost: boolean,
- * }}
- */
- let ResultsDetails;
-
- /** @param {!Element} element*/
- function clearChildren(element) {
- while (element.firstChild) {
- element.firstChild.remove();
- }
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import './chrome/browser/ui/webui/omnibox/omnibox.mojom-lite.js';
+
+import {OmniboxElement} from './omnibox_element.js';
+import {OmniboxInput, DisplayInputs} from './omnibox_input.js';
+
+/**
+ * @typedef {{
+ * cursorPosition: number,
+ * time: number,
+ * done: boolean,
+ * type: string,
+ * host: string,
+ * isTypedHost: boolean,
+ * }}
+ */
+let ResultsDetails;
+
+/** @param {!Element} element*/
+function clearChildren(element) {
+ while (element.firstChild) {
+ element.firstChild.remove();
+ }
+}
+
+export class OmniboxOutput extends OmniboxElement {
+ constructor() {
+ super('omnibox-output-template');
+
+ /** @private {number} */
+ this.selectedResponseIndex_ = 0;
+ /** @type {!Array<!Array<!mojom.OmniboxResponse>>} */
+ this.responsesHistory = [];
+ /** @private {!Array<!OutputResultsGroup>} */
+ this.resultsGroups_ = [];
+ /** @private {!DisplayInputs} */
+ this.displayInputs_ = OmniboxInput.defaultDisplayInputs;
+ /** @private {string} */
+ this.filterText_ = '';
}
- class OmniboxOutput extends OmniboxElement {
- constructor() {
- super('omnibox-output-template');
-
- /** @private {number} */
- this.selectedResponseIndex_ = 0;
- /** @type {!Array<!Array<!mojom.OmniboxResponse>>} */
- this.responsesHistory = [];
- /** @private {!Array<!OutputResultsGroup>} */
- this.resultsGroups_ = [];
- /** @private {!DisplayInputs} */
- this.displayInputs_ = OmniboxInput.defaultDisplayInputs;
- /** @private {string} */
- this.filterText_ = '';
- }
-
- /** @param {!DisplayInputs} displayInputs */
- updateDisplayInputs(displayInputs) {
- this.displayInputs_ = displayInputs;
- this.updateDisplay_();
- }
-
- /** @param {string} filterText */
- updateFilterText(filterText) {
- this.filterText_ = filterText;
- this.updateFilterHighlights_();
- }
-
- /** @param {!Array<!Array<!mojom.OmniboxResponse>>} responsesHistory */
- setResponsesHistory(responsesHistory) {
- this.responsesHistory = responsesHistory;
- this.dispatchEvent(new CustomEvent(
- 'responses-count-changed', {detail: responsesHistory.length}));
- this.updateSelectedResponseIndex(this.selectedResponseIndex_);
- }
-
- /** @param {number} selection */
- updateSelectedResponseIndex(selection) {
- if (selection >= 0 && selection < this.responsesHistory.length) {
- this.selectedResponseIndex_ = selection;
- this.clearResultsGroups_();
- this.responsesHistory[selection].forEach(
- this.createResultsGroup_.bind(this));
- }
- }
-
- prepareNewQuery() {
- this.responsesHistory.push([]);
- this.dispatchEvent(new CustomEvent(
- 'responses-count-changed', {detail: this.responsesHistory.length}));
- }
+ /** @param {!DisplayInputs} displayInputs */
+ updateDisplayInputs(displayInputs) {
+ this.displayInputs_ = displayInputs;
+ this.updateDisplay_();
+ }
- /** @param {!mojom.OmniboxResponse} response */
- addAutocompleteResponse(response) {
- const lastIndex = this.responsesHistory.length - 1;
- this.responsesHistory[lastIndex].push(response);
- if (lastIndex === this.selectedResponseIndex_) {
- this.createResultsGroup_(response);
- }
- }
+ /** @param {string} filterText */
+ updateFilterText(filterText) {
+ this.filterText_ = filterText;
+ this.updateFilterHighlights_();
+ }
- /**
- * Clears result groups from the UI.
- * @private
- */
- clearResultsGroups_() {
- this.resultsGroups_ = [];
- clearChildren(this.$$('#contents'));
- }
+ /** @param {!Array<!Array<!mojom.OmniboxResponse>>} responsesHistory */
+ setResponsesHistory(responsesHistory) {
+ this.responsesHistory = responsesHistory;
+ this.dispatchEvent(new CustomEvent(
+ 'responses-count-changed', {detail: responsesHistory.length}));
+ this.updateSelectedResponseIndex(this.selectedResponseIndex_);
+ }
- /**
- * Creates and adds a result group to the UI.
- * @private @param {!mojom.OmniboxResponse} response
- */
- createResultsGroup_(response) {
- const resultsGroup = OutputResultsGroup.create(response);
- this.resultsGroups_.push(resultsGroup);
- this.$$('#contents').appendChild(resultsGroup);
-
- this.updateDisplay_();
- this.updateFilterHighlights_();
+ /** @param {number} selection */
+ updateSelectedResponseIndex(selection) {
+ if (selection >= 0 && selection < this.responsesHistory.length) {
+ this.selectedResponseIndex_ = selection;
+ this.clearResultsGroups_();
+ this.responsesHistory[selection].forEach(
+ this.createResultsGroup_.bind(this));
}
+ }
- /**
- * @param {string} url
- * @param {string} data
- */
- updateAnswerImage(url, data) {
- this.autocompleteMatches.forEach(
- match => match.updateAnswerImage(url, data));
- }
+ prepareNewQuery() {
+ this.responsesHistory.push([]);
+ this.dispatchEvent(new CustomEvent(
+ 'responses-count-changed', {detail: this.responsesHistory.length}));
+ }
- /** @private */
- updateDisplay_() {
- this.updateVisibility_();
- this.updateEliding_();
- this.updateRowHeights_();
+ /** @param {!mojom.OmniboxResponse} response */
+ addAutocompleteResponse(response) {
+ const lastIndex = this.responsesHistory.length - 1;
+ this.responsesHistory[lastIndex].push(response);
+ if (lastIndex === this.selectedResponseIndex_) {
+ this.createResultsGroup_(response);
}
+ }
- /**
- * Show or hide various output elements depending on display inputs.
- * 1) Show non-last result groups only if showIncompleteResults is true.
- * 2) Show the details section above each table if showDetails or
- * showIncompleteResults are true.
- * 3) Show individual results when showAllProviders is true.
- * 4) Show certain columns and headers only if they showDetails is true.
- * @private
- */
- updateVisibility_() {
- // Show non-last result groups only if showIncompleteResults is true.
- this.resultsGroups_.forEach((resultsGroup, index) => {
- resultsGroup.hidden = !this.displayInputs_.showIncompleteResults &&
- index !== this.resultsGroups_.length - 1;
- });
-
- this.resultsGroups_.forEach(resultsGroup => {
- resultsGroup.updateVisibility(
- this.displayInputs_.showIncompleteResults,
- this.displayInputs_.showDetails,
- this.displayInputs_.showAllProviders);
- });
- }
+ /**
+ * Clears result groups from the UI.
+ * @private
+ */
+ clearResultsGroups_() {
+ this.resultsGroups_ = [];
+ clearChildren(this.$('#contents'));
+ }
- /** @private */
- updateEliding_() {
- this.resultsGroups_.forEach(
- resultsGroup =>
- resultsGroup.updateEliding(this.displayInputs_.elideCells));
- }
+ /**
+ * Creates and adds a result group to the UI.
+ * @private @param {!mojom.OmniboxResponse} response
+ */
+ createResultsGroup_(response) {
+ const resultsGroup = OutputResultsGroup.create(response);
+ this.resultsGroups_.push(resultsGroup);
+ this.$('#contents').appendChild(resultsGroup);
- /** @private */
- updateRowHeights_() {
- this.resultsGroups_.forEach(
- resultsGroup =>
- resultsGroup.updateRowHeights(this.displayInputs_.thinRows));
- }
+ this.updateDisplay_();
+ this.updateFilterHighlights_();
+ }
- /** @private */
- updateFilterHighlights_() {
- this.autocompleteMatches.forEach(match => match.filter(this.filterText_));
- }
+ /**
+ * @param {string} url
+ * @param {string} data
+ */
+ updateAnswerImage(url, data) {
+ this.autocompleteMatches.forEach(
+ match => match.updateAnswerImage(url, data));
+ }
- /** @return {!Array<!OutputMatch>} */
- get autocompleteMatches() {
- return this.resultsGroups_.flatMap(
- resultsGroup => resultsGroup.autocompleteMatches);
- }
+ /** @private */
+ updateDisplay_() {
+ this.updateVisibility_();
+ this.updateEliding_();
+ this.updateRowHeights_();
}
/**
- * Helps track and render a results group. C++ Autocomplete typically returns
- * 3 result groups per query. It may return less if the next query is
- * submitted before all 3 have been returned. Each result group contains
- * top level information (e.g., how long the result took to generate), as well
- * as a single list of combined results and multiple lists of individual
- * results. Each of these lists is tracked and rendered by OutputResultsTable
- * below.
+ * Show or hide various output elements depending on display inputs.
+ * 1) Show non-last result groups only if showIncompleteResults is true.
+ * 2) Show the details section above each table if showDetails or
+ * showIncompleteResults are true.
+ * 3) Show individual results when showAllProviders is true.
+ * 4) Show certain columns and headers only if they showDetails is true.
+ * @private
*/
- class OutputResultsGroup extends OmniboxElement {
- /**
- * @param {!mojom.OmniboxResponse} resultsGroup
- * @return {!OutputResultsGroup}
- */
- static create(resultsGroup) {
- const outputResultsGroup = new OutputResultsGroup();
- outputResultsGroup.setResultsGroup(resultsGroup);
- return outputResultsGroup;
- }
+ updateVisibility_() {
+ // Show non-last result groups only if showIncompleteResults is true.
+ this.resultsGroups_.forEach((resultsGroup, index) => {
+ resultsGroup.hidden = !this.displayInputs_.showIncompleteResults &&
+ index !== this.resultsGroups_.length - 1;
+ });
+
+ this.resultsGroups_.forEach(resultsGroup => {
+ resultsGroup.updateVisibility(
+ this.displayInputs_.showIncompleteResults,
+ this.displayInputs_.showDetails,
+ this.displayInputs_.showAllProviders);
+ });
+ }
- constructor() {
- super('output-results-group-template');
- }
+ /** @private */
+ updateEliding_() {
+ this.resultsGroups_.forEach(
+ resultsGroup =>
+ resultsGroup.updateEliding(this.displayInputs_.elideCells));
+ }
- /** @param {!mojom.OmniboxResponse} resultsGroup */
- setResultsGroup(resultsGroup) {
- /** @private {ResultsDetails} */
- this.details_ = {
- cursorPosition: resultsGroup.cursorPosition,
- time: resultsGroup.timeSinceOmniboxStartedMs,
- done: resultsGroup.done,
- type: resultsGroup.type,
- host: resultsGroup.host,
- isTypedHost: resultsGroup.isTypedHost,
- };
- /** @type {!Array<!OutputHeader>} */
- this.headers = COLUMNS.map(OutputHeader.create);
- /** @type {!OutputResultsTable} */
- this.combinedResults =
- OutputResultsTable.create(resultsGroup.combinedResults);
- /** @type {!Array<!OutputResultsTable>} */
- this.individualResultsList =
- resultsGroup.resultsByProvider
- .map(resultsWrapper => resultsWrapper.results)
- .filter(results => results.length > 0)
- .map(OutputResultsTable.create);
- if (this.hasAdditionalProperties) {
- this.headers.push(OutputHeader.create(ADDITIONAL_PROPERTIES_COLUMN));
- }
- this.render_();
- }
+ /** @private */
+ updateRowHeights_() {
+ this.resultsGroups_.forEach(
+ resultsGroup =>
+ resultsGroup.updateRowHeights(this.displayInputs_.thinRows));
+ }
- /**
- * Creates a HTML Node representing this data.
- * @private
- */
- render_() {
- clearChildren(this);
-
- /** @private {!Array<!Element>} */
- this.innerHeaders_ = [];
-
- customElements.whenDefined(this.$$('output-results-details').localName)
- .then(
- () =>
- this.$$('output-results-details').setDetails(this.details_));
-
- this.$$('#table').appendChild(this.renderHeader_());
- this.$$('#table').appendChild(this.combinedResults);
- this.individualResultsList.forEach(results => {
- const innerHeader = this.renderInnerHeader_(results);
- this.innerHeaders_.push(innerHeader);
- this.$$('#table').appendChild(innerHeader);
- this.$$('#table').appendChild(results);
- });
- }
+ /** @private */
+ updateFilterHighlights_() {
+ this.autocompleteMatches.forEach(match => match.filter(this.filterText_));
+ }
- /** @private @return {!Element} */
- renderHeader_() {
- const head = document.createElement('thead');
- head.classList.add('head');
- const row = document.createElement('tr');
- this.headers.forEach(cell => row.appendChild(cell));
- head.appendChild(row);
- return head;
- }
+ /** @return {!Array<!OutputMatch>} */
+ get autocompleteMatches() {
+ return this.resultsGroups_.flatMap(
+ resultsGroup => resultsGroup.autocompleteMatches);
+ }
+}
+
+/**
+ * Helps track and render a results group. C++ Autocomplete typically returns
+ * 3 result groups per query. It may return less if the next query is
+ * submitted before all 3 have been returned. Each result group contains
+ * top level information (e.g., how long the result took to generate), as well
+ * as a single list of combined results and multiple lists of individual
+ * results. Each of these lists is tracked and rendered by OutputResultsTable
+ * below.
+ */
+class OutputResultsGroup extends OmniboxElement {
+ /**
+ * @param {!mojom.OmniboxResponse} resultsGroup
+ * @return {!OutputResultsGroup}
+ */
+ static create(resultsGroup) {
+ const outputResultsGroup = new OutputResultsGroup();
+ outputResultsGroup.setResultsGroup(resultsGroup);
+ return outputResultsGroup;
+ }
- /**
- * @private
- * @param {!OutputResultsTable} results
- * @return {!Element}
- */
- renderInnerHeader_(results) {
- const head = document.createElement('tbody');
- head.classList.add('head');
- const row = document.createElement('tr');
- const cell = document.createElement('th');
- // Reserve 1 more column for showing the additional properties column.
- cell.colSpan = COLUMNS.length + 1;
- cell.textContent = results.innerHeaderText;
- row.appendChild(cell);
- head.appendChild(row);
- return head;
- }
+ constructor() {
+ super('output-results-group-template');
+ }
- /**
- * @param {boolean} showIncompleteResults
- * @param {boolean} showDetails
- * @param {boolean} showAllProviders
- */
- updateVisibility(showIncompleteResults, showDetails, showAllProviders) {
- // Show the details section above each table if showDetails or
- // showIncompleteResults are true.
- this.$$('output-results-details').hidden =
- !showDetails && !showIncompleteResults;
-
- // Show individual results when showAllProviders is true.
- this.individualResultsList.forEach(
- individualResults => individualResults.hidden = !showAllProviders);
- this.innerHeaders_.forEach(
- innerHeader => innerHeader.hidden = !showAllProviders);
-
- // Show certain column headers only if they showDetails is true.
- COLUMNS.forEach(({displayAlways}, index) => {
- this.headers[index].hidden = !showDetails && !displayAlways;
- });
-
- // Show certain columns only if they showDetails is true.
- this.autocompleteMatches.forEach(
- match => match.updateVisibility(showDetails));
- }
+ /** @param {!mojom.OmniboxResponse} resultsGroup */
+ setResultsGroup(resultsGroup) {
+ /** @private {ResultsDetails} */
+ this.details_ = {
+ cursorPosition: resultsGroup.cursorPosition,
+ time: resultsGroup.timeSinceOmniboxStartedMs,
+ done: resultsGroup.done,
+ type: resultsGroup.type,
+ host: resultsGroup.host,
+ isTypedHost: resultsGroup.isTypedHost,
+ };
+ /** @type {!Array<!OutputHeader>} */
+ this.headers = COLUMNS.map(OutputHeader.create);
+ /** @type {!OutputResultsTable} */
+ this.combinedResults =
+ OutputResultsTable.create(resultsGroup.combinedResults);
+ /** @type {!Array<!OutputResultsTable>} */
+ this.individualResultsList =
+ resultsGroup.resultsByProvider
+ .map(resultsWrapper => resultsWrapper.results)
+ .filter(results => results.length > 0)
+ .map(OutputResultsTable.create);
+ if (this.hasAdditionalProperties) {
+ this.headers.push(OutputHeader.create(ADDITIONAL_PROPERTIES_COLUMN));
+ }
+ this.render_();
+ }
- /** @param {boolean} elideCells */
- updateEliding(elideCells) {
- this.autocompleteMatches.forEach(
- match => match.updateEliding(elideCells));
- }
+ /**
+ * Creates a HTML Node representing this data.
+ * @private
+ */
+ render_() {
+ clearChildren(this);
+
+ /** @private {!Array<!Element>} */
+ this.innerHeaders_ = [];
+
+ customElements.whenDefined(this.$('output-results-details').localName)
+ .then(() => this.$('output-results-details').setDetails(this.details_));
+
+ this.$('#table').appendChild(this.renderHeader_());
+ this.$('#table').appendChild(this.combinedResults);
+ this.individualResultsList.forEach(results => {
+ const innerHeader = this.renderInnerHeader_(results);
+ this.innerHeaders_.push(innerHeader);
+ this.$('#table').appendChild(innerHeader);
+ this.$('#table').appendChild(results);
+ });
+ }
- /** @param {boolean} thinRows */
- updateRowHeights(thinRows) {
- this.autocompleteMatches.forEach(
- match => match.classList.toggle('thin', thinRows));
- }
+ /** @private @return {!Element} */
+ renderHeader_() {
+ const head = document.createElement('thead');
+ head.classList.add('head');
+ const row = document.createElement('tr');
+ this.headers.forEach(cell => row.appendChild(cell));
+ head.appendChild(row);
+ return head;
+ }
- /**
- * @private
- * @return {boolean}
- */
- get hasAdditionalProperties() {
- return this.combinedResults.hasAdditionalProperties ||
- this.individualResultsList.some(
- results => results.hasAdditionalProperties);
- }
+ /**
+ * @private
+ * @param {!OutputResultsTable} results
+ * @return {!Element}
+ */
+ renderInnerHeader_(results) {
+ const head = document.createElement('tbody');
+ head.classList.add('head');
+ const row = document.createElement('tr');
+ const cell = document.createElement('th');
+ // Reserve 1 more column for showing the additional properties column.
+ cell.colSpan = COLUMNS.length + 1;
+ cell.textContent = results.innerHeaderText;
+ row.appendChild(cell);
+ head.appendChild(row);
+ return head;
+ }
- /** @return {!Array<!OutputMatch>} */
- get autocompleteMatches() {
- return [this.combinedResults]
- .concat(this.individualResultsList)
- .flatMap(results => results.autocompleteMatches);
- }
+ /**
+ * @param {boolean} showIncompleteResults
+ * @param {boolean} showDetails
+ * @param {boolean} showAllProviders
+ */
+ updateVisibility(showIncompleteResults, showDetails, showAllProviders) {
+ // Show the details section above each table if showDetails or
+ // showIncompleteResults are true.
+ this.$('output-results-details').hidden =
+ !showDetails && !showIncompleteResults;
+
+ // Show individual results when showAllProviders is true.
+ this.individualResultsList.forEach(
+ individualResults => individualResults.hidden = !showAllProviders);
+ this.innerHeaders_.forEach(
+ innerHeader => innerHeader.hidden = !showAllProviders);
+
+ // Show certain column headers only if they showDetails is true.
+ COLUMNS.forEach(({displayAlways}, index) => {
+ this.headers[index].hidden = !showDetails && !displayAlways;
+ });
+
+ // Show certain columns only if they showDetails is true.
+ this.autocompleteMatches.forEach(
+ match => match.updateVisibility(showDetails));
}
- class OutputResultsDetails extends OmniboxElement {
- constructor() {
- super('output-results-details-template');
- }
+ /** @param {boolean} elideCells */
+ updateEliding(elideCells) {
+ this.autocompleteMatches.forEach(match => match.updateEliding(elideCells));
+ }
- /** @param {ResultsDetails} details */
- setDetails(details) {
- this.$$('#cursor-position').textContent = details.cursorPosition;
- this.$$('#time').textContent = details.time;
- this.$$('#done').textContent = details.done;
- this.$$('#type').textContent = details.type;
- this.$$('#host').textContent = details.host;
- this.$$('#is-typed-host').textContent = details.isTypedHost;
- }
+ /** @param {boolean} thinRows */
+ updateRowHeights(thinRows) {
+ this.autocompleteMatches.forEach(
+ match => match.classList.toggle('thin', thinRows));
}
/**
- * Helps track and render a list of results. Each result is tracked and
- * rendered by OutputMatch below.
+ * @private
+ * @return {boolean}
*/
- class OutputResultsTable extends HTMLTableSectionElement {
- /**
- * @param {!Array<!mojom.AutocompleteMatch>} results
- * @return {!OutputResultsTable}
- */
- static create(results) {
- const resultsTable = new OutputResultsTable();
- resultsTable.results = results;
- return resultsTable;
- }
-
- constructor() {
- super();
- this.classList.add('body');
- /** @type {!Array<!OutputMatch>} */
- this.autocompleteMatches = [];
- }
-
- /** @param {!Array<!mojom.AutocompleteMatch>} results */
- set results(results) {
- this.autocompleteMatches.forEach(match => match.remove());
- this.autocompleteMatches = results.map(OutputMatch.create);
- this.autocompleteMatches.forEach(this.appendChild.bind(this));
- }
+ get hasAdditionalProperties() {
+ return this.combinedResults.hasAdditionalProperties ||
+ this.individualResultsList.some(
+ results => results.hasAdditionalProperties);
+ }
- /** @return {?string} */
- get innerHeaderText() {
- return this.autocompleteMatches[0].providerName;
- }
+ /** @return {!Array<!OutputMatch>} */
+ get autocompleteMatches() {
+ return [this.combinedResults]
+ .concat(this.individualResultsList)
+ .flatMap(results => results.autocompleteMatches);
+ }
+}
- /** @return {boolean} */
- get hasAdditionalProperties() {
- return this.autocompleteMatches.some(
- match => match.hasAdditionalProperties);
- }
+class OutputResultsDetails extends OmniboxElement {
+ constructor() {
+ super('output-results-details-template');
}
- /** Helps track and render a single match. */
- class OutputMatch extends HTMLTableRowElement {
- /**
- * @param {!mojom.AutocompleteMatch} match
- * @return {!OutputMatch}
- */
- static create(match) {
- /** @suppress {checkTypes} */
- const outputMatch = new OutputMatch();
- outputMatch.match = match;
- return outputMatch;
- }
+ /** @param {ResultsDetails} details */
+ setDetails(details) {
+ this.$('#cursor-position').textContent = details.cursorPosition;
+ this.$('#time').textContent = details.time;
+ this.$('#done').textContent = details.done;
+ this.$('#type').textContent = details.type;
+ this.$('#host').textContent = details.host;
+ this.$('#is-typed-host').textContent = details.isTypedHost;
+ }
+}
- /** @param {!mojom.AutocompleteMatch} match */
- set match(match) {
- /** @type {!Object<string, !OutputProperty>} */
- this.properties = {};
- /** @type {!OutputProperty} */
- this.properties.contentsAndDescription;
- /** @type {?string} */
- this.providerName = match.providerName || null;
-
- COLUMNS.forEach(column => {
- const values = column.sourceProperties.map(
- propertyName => /** @type {Object} */ (match)[propertyName]);
- this.properties[column.matchKey] =
- OutputProperty.create(column, values);
- });
-
- const unconsumedProperties = {};
- Object.entries(match)
- .filter(([name]) => !CONSUMED_SOURCE_PROPERTIES.includes(name))
- .forEach(([name, value]) => unconsumedProperties[name] = value);
-
- /** @type {!OutputProperty} */
- this.additionalProperties = OutputProperty.create(
- ADDITIONAL_PROPERTIES_COLUMN, [unconsumedProperties]);
-
- this.render_();
- }
+/**
+ * Helps track and render a list of results. Each result is tracked and
+ * rendered by OutputMatch below.
+ */
+class OutputResultsTable extends HTMLTableSectionElement {
+ /**
+ * @param {!Array<!mojom.AutocompleteMatch>} results
+ * @return {!OutputResultsTable}
+ */
+ static create(results) {
+ const resultsTable = new OutputResultsTable();
+ resultsTable.results = results;
+ return resultsTable;
+ }
- /** @private */
- render_() {
- clearChildren(this);
- COLUMNS.map(column => this.properties[column.matchKey])
- .forEach(cell => this.appendChild(cell));
- if (this.hasAdditionalProperties) {
- this.appendChild(this.additionalProperties);
- }
- }
+ constructor() {
+ super();
+ this.classList.add('body');
+ /** @type {!Array<!OutputMatch>} */
+ this.autocompleteMatches = [];
+ }
- /**
- * @param {string} url
- * @param {string} data
- */
- updateAnswerImage(url, data) {
- if (this.properties.contentsAndDescription.value === url) {
- this.properties.contentsAndDescription.setAnswerImageData(data);
- }
- }
+ /** @param {!Array<!mojom.AutocompleteMatch>} results */
+ set results(results) {
+ this.autocompleteMatches.forEach(match => match.remove());
+ this.autocompleteMatches = results.map(OutputMatch.create);
+ this.autocompleteMatches.forEach(this.appendChild.bind(this));
+ }
- /** @param {boolean} showDetails */
- updateVisibility(showDetails) {
- // Show certain columns only if they showDetails is true.
- COLUMNS.forEach(({matchKey, displayAlways}) => {
- this.properties[matchKey].hidden = !showDetails && !displayAlways;
- });
- }
+ /** @return {?string} */
+ get innerHeaderText() {
+ return this.autocompleteMatches[0].providerName;
+ }
- /** @param {boolean} elideCells */
- updateEliding(elideCells) {
- Object.values(this.properties)
- .forEach(property => property.classList.toggle('elided', elideCells));
- }
+ /** @return {boolean} */
+ get hasAdditionalProperties() {
+ return this.autocompleteMatches.some(
+ match => match.hasAdditionalProperties);
+ }
+}
+
+/** Helps track and render a single match. */
+class OutputMatch extends HTMLTableRowElement {
+ constructor() {
+ super();
+ let mouseMoved;
+ this.addEventListener('mousedown', () => mouseMoved = false);
+ this.addEventListener('mousemove', () => mouseMoved = true);
+ this.addEventListener(
+ 'click', () => !mouseMoved && this.classList.toggle('expanded'));
+ }
- /** @param {string} filterText */
- filter(filterText) {
- this.classList.remove('filtered-highlighted');
- this.allProperties_.forEach(
- property => property.classList.remove('filtered-highlighted-nested'));
-
- if (!filterText) {
- return;
- }
-
- const matchedProperties = this.allProperties_.filter(
- property => FilterUtil.filterText(property.text, filterText));
- const isMatch = matchedProperties.length > 0;
- this.classList.toggle('filtered-highlighted', isMatch);
- matchedProperties.forEach(
- property => property.classList.add('filtered-highlighted-nested'));
- }
+ /**
+ * @param {!mojom.AutocompleteMatch} match
+ * @return {!OutputMatch}
+ */
+ static create(match) {
+ /** @suppress {checkTypes} */
+ const outputMatch = new OutputMatch();
+ outputMatch.match = match;
+ return outputMatch;
+ }
- /**
- * @return {boolean} Used to determine if the additional properties column
- * needs to be displayed for this match.
- */
- get hasAdditionalProperties() {
- return Object
- .keys(/** @type {!Object} */ (this.additionalProperties.value))
- .length > 0;
- }
+ /** @param {!mojom.AutocompleteMatch} match */
+ set match(match) {
+ /** @type {!Object<string, !OutputProperty>} */
+ this.properties = {};
+ /** @type {!OutputProperty} */
+ this.properties.contentsAndDescription;
+ /** @type {?string} */
+ this.providerName = match.providerName || null;
+
+ COLUMNS.forEach(column => {
+ const values = column.sourceProperties.map(
+ propertyName => /** @type {Object} */ (match)[propertyName]);
+ this.properties[column.matchKey] = OutputProperty.create(column, values);
+ });
+
+ const unconsumedProperties = {};
+ Object.entries(match)
+ .filter(([name]) => !CONSUMED_SOURCE_PROPERTIES.includes(name))
+ .forEach(([name, value]) => unconsumedProperties[name] = value);
+
+ /** @type {!OutputProperty} */
+ this.additionalProperties = OutputProperty.create(
+ ADDITIONAL_PROPERTIES_COLUMN, [unconsumedProperties]);
+
+ this.render_();
+ }
- /** @private @return {!Array<!OutputProperty>} */
- get allProperties_() {
- return Object.values(this.properties).concat(this.additionalProperties);
+ /** @private */
+ render_() {
+ clearChildren(this);
+ COLUMNS.map(column => this.properties[column.matchKey])
+ .forEach(cell => this.appendChild(cell));
+ if (this.hasAdditionalProperties) {
+ this.appendChild(this.additionalProperties);
}
}
- class OutputHeader extends HTMLTableCellElement {
- /**
- * @param {Column} column
- * @return {!OutputHeader}
- */
- static create(column) {
- const header = new OutputHeader();
- header.classList.add(column.headerClassName);
- header.setContents(column.headerText, column.url);
- header.title = column.tooltip;
- return header;
+ /**
+ * @param {string} url
+ * @param {string} data
+ */
+ updateAnswerImage(url, data) {
+ if (this.properties.contentsAndDescription.value === url) {
+ this.properties.contentsAndDescription.setAnswerImageData(data);
}
+ }
- /**
- * @param {!Array<string>} texts
- * @param {string=} url
- */
- setContents(texts, url) {
- clearChildren(this);
- let container;
- if (url) {
- container = document.createElement('a');
- container.href = url;
- } else {
- container = document.createElement('div');
- }
- container.classList.add('header-container');
- texts.forEach(text => {
- const part = document.createElement('span');
- part.textContent = text;
- container.appendChild(part);
- });
- this.appendChild(container);
- }
+ /** @param {boolean} showDetails */
+ updateVisibility(showDetails) {
+ // Show certain columns only if they showDetails is true.
+ COLUMNS.forEach(({matchKey, displayAlways}) => {
+ this.properties[matchKey].hidden = !showDetails && !displayAlways;
+ });
}
- class OutputProperty extends HTMLTableCellElement {
- constructor() {
- super();
- /** @type {string} */
- this.filterName;
- }
+ /** @param {boolean} elideCells */
+ updateEliding(elideCells) {
+ Object.values(this.properties)
+ .forEach(property => property.classList.toggle('elided', elideCells));
+ }
- /**
- * @param {Column} column
- * @param {!Array<*>} values
- * @return {!OutputProperty}
- */
- static create(column, values) {
- const outputProperty = new column.outputClass();
- outputProperty.classList.add(column.cellClassName);
- outputProperty.filterName = column.tooltip.split('\n', 1)[0];
- outputProperty.values = values;
- return outputProperty;
- }
+ /** @param {string} filterText */
+ filter(filterText) {
+ this.classList.remove('filtered-highlighted');
+ this.allProperties_.forEach(
+ property => property.classList.remove('filtered-highlighted-nested'));
- /** @param {!Array<*>} values */
- set values(values) {
- /** @type {*} */
- this.value = values[0];
- /** @private {!Array<*>} */
- this.values_ = values;
- /** @override */
- this.render_();
+ if (!filterText) {
+ return;
}
- /** @private */
- render_() {}
-
- /** @return {string} */
- get text() {
- return this.value + '';
- }
+ const matchedProperties = this.allProperties_.filter(
+ property => FilterUtil.filterText(property.text, filterText));
+ const isMatch = matchedProperties.length > 0;
+ this.classList.toggle('filtered-highlighted', isMatch);
+ matchedProperties.forEach(
+ property => property.classList.add('filtered-highlighted-nested'));
}
- class FlexWrappingOutputProperty extends OutputProperty {
- constructor() {
- super();
-
- // margin-right is used on .pair-item's to separate them. To compensate,
- // .pair-container has negative margin-right. This means .pair-container's
- // overflow their parent. Overflowing a table cell is problematic, as 1)
- // scroll bars overlay adjacent cell, and 2) the page receives a
- // horizontal scroll bar when the right most column overflows. To avoid
- // this, the parent of any element with negative margins (e.g.
- // .pair-container) must not be a table cell; hence, the use of
- // scrollContainer_.
- // Flex gutters may provide a cleaner alternative once implemented.
- // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Mastering_Wrapping_of_Flex_Items#Creating_gutters_between_items
- /** @private {!Element} */
- this.scrollContainer_ = document.createElement('div');
- this.appendChild(this.scrollContainer_);
-
- /** @private {!Element} */
- this.container_ = document.createElement('div');
- this.container_.classList.add('pair-container');
- this.scrollContainer_.appendChild(this.container_);
- }
+ /**
+ * @return {boolean} Used to determine if the additional properties column
+ * needs to be displayed for this match.
+ */
+ get hasAdditionalProperties() {
+ return Object.keys(/** @type {!Object} */ (this.additionalProperties.value))
+ .length > 0;
}
- class OutputPairProperty extends FlexWrappingOutputProperty {
- constructor() {
- super();
+ /** @private @return {!Array<!OutputProperty>} */
+ get allProperties_() {
+ return Object.values(this.properties).concat(this.additionalProperties);
+ }
+}
- /** @type {!Element} */
- this.first_ = document.createElement('div');
- this.first_.classList.add('pair-item');
- this.container_.appendChild(this.first_);
+class OutputHeader extends HTMLTableCellElement {
+ /**
+ * @param {Column} column
+ * @return {!OutputHeader}
+ */
+ static create(column) {
+ const header = new OutputHeader();
+ header.classList.add(column.headerClassName);
+ header.setContents(column.headerText, column.url);
+ header.title = column.tooltip;
+ return header;
+ }
- /** @type {!Element} */
- this.second_ = document.createElement('div');
- this.second_.classList.add('pair-item');
- this.container_.appendChild(this.second_);
- }
+ /**
+ * @param {!Array<string>} texts
+ * @param {string=} url
+ */
+ setContents(texts, url) {
+ clearChildren(this);
+ let container;
+ if (url) {
+ container = document.createElement('a');
+ container.href = url;
+ } else {
+ container = document.createElement('div');
+ }
+ container.classList.add('header-container');
+ texts.forEach(text => {
+ const part = document.createElement('span');
+ part.textContent = text;
+ container.appendChild(part);
+ });
+ this.appendChild(container);
+ }
+}
- /** @private @override */
- render_() {
- [this.first_.textContent, this.second_.textContent] = this.values_;
- }
+class OutputProperty extends HTMLTableCellElement {
+ constructor() {
+ super();
+ /** @type {string} */
+ this.filterName;
+ }
- /** @override @return {string} */
- get text() {
- return `${this.values_[0]}.${this.values_[1]}`;
- }
+ /**
+ * @param {Column} column
+ * @param {!Array<*>} values
+ * @return {!OutputProperty}
+ */
+ static create(column, values) {
+ const outputProperty = new column.outputClass();
+ outputProperty.classList.add(column.cellClassName);
+ outputProperty.filterName = column.tooltip.split('\n', 1)[0];
+ outputProperty.values = values;
+ return outputProperty;
}
- class OutputOverlappingPairProperty extends OutputPairProperty {
- constructor() {
- super();
+ /** @param {!Array<*>} values */
+ set values(values) {
+ /** @type {*} */
+ this.value = values[0];
+ /** @private {!Array<*>} */
+ this.values_ = values;
+ /** @override */
+ this.render_();
+ }
- this.notOverlapWarning_ = document.createElement('div');
- this.notOverlapWarning_.classList.add('overlap-warning');
- this.container_.appendChild(this.notOverlapWarning_);
- }
+ /** @private */
+ render_() {}
- /** @private @override */
- render_() {
- const overlap = this.values_[0].endsWith(this.values_[1]);
- const firstText = this.values_[1] && overlap ?
- this.values_[0].slice(0, -this.values_[1].length) :
- this.values_[0];
-
- this.first_.textContent = firstText;
- this.second_.textContent = this.values_[1];
- this.notOverlapWarning_.textContent = overlap ?
- '' :
- `btw, these texts do not overlap; '${
- this.values_[1]}' was expected to be a suffix of '${
- this.values_[0]}'`;
- }
+ /** @return {string} */
+ get text() {
+ return this.value + '';
+ }
+}
+
+class FlexWrappingOutputProperty extends OutputProperty {
+ constructor() {
+ super();
+
+ // margin-right is used on .pair-item's to separate them. To compensate,
+ // .pair-container has negative margin-right. This means .pair-container's
+ // overflow their parent. Overflowing a table cell is problematic, as 1)
+ // scroll bars overlay adjacent cell, and 2) the page receives a
+ // horizontal scroll bar when the right most column overflows. To avoid
+ // this, the parent of any element with negative margins (e.g.
+ // .pair-container) must not be a table cell; hence, the use of
+ // scrollContainer_.
+ // Flex gutters may provide a cleaner alternative once implemented.
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Mastering_Wrapping_of_Flex_Items#Creating_gutters_between_items
+ /** @private {!Element} */
+ this.scrollContainer_ = document.createElement('div');
+ this.appendChild(this.scrollContainer_);
+
+ /** @private {!Element} */
+ this.container_ = document.createElement('div');
+ this.container_.classList.add('pair-container');
+ this.scrollContainer_.appendChild(this.container_);
}
+}
- class OutputAnswerProperty extends FlexWrappingOutputProperty {
- constructor() {
- super();
+class OutputPairProperty extends FlexWrappingOutputProperty {
+ constructor() {
+ super();
- /** @type {!Element} */
- this.image_ = document.createElement('img');
- this.image_.classList.add('pair-item');
- this.container_.appendChild(this.image_);
+ /** @type {!Element} */
+ this.first_ = document.createElement('div');
+ this.first_.classList.add('pair-item');
+ this.container_.appendChild(this.first_);
- /** @type {!Element} */
- this.contents_ = document.createElement('div');
- this.contents_.classList.add('pair-item', 'contents');
- this.container_.appendChild(this.contents_);
+ /** @type {!Element} */
+ this.second_ = document.createElement('div');
+ this.second_.classList.add('pair-item');
+ this.container_.appendChild(this.second_);
+ }
- /** @type {!Element} */
- this.description_ = document.createElement('div');
- this.description_.classList.add('pair-item', 'description');
- this.container_.appendChild(this.description_);
+ /** @private @override */
+ render_() {
+ [this.first_.textContent, this.second_.textContent] = this.values_;
+ }
- /** @type {!Element} */
- this.answer_ = document.createElement('div');
- this.answer_.classList.add('pair-item', 'answer');
- this.container_.appendChild(this.answer_);
+ /** @override @return {string} */
+ get text() {
+ return `${this.values_[0]}.${this.values_[1]}`;
+ }
+}
- /** @type {!Element} */
- this.imageUrl_ = document.createElement('a');
- this.imageUrl_.classList.add('pair-item', 'image-url');
- this.container_.appendChild(this.imageUrl_);
- }
+class OutputOverlappingPairProperty extends OutputPairProperty {
+ constructor() {
+ super();
- /** @param {string} imageData */
- setAnswerImageData(imageData) {
- this.image_.src = imageData;
- }
+ this.notOverlapWarning_ = document.createElement('div');
+ this.notOverlapWarning_.classList.add('overlap-warning');
+ this.container_.appendChild(this.notOverlapWarning_);
+ }
- /** @private @override */
- render_() {
- // TODO (manukh) Wrap this line when Clang is updated,
- // https://b.corp.google.com/126708256 .
- const [image, contents, description, answer, contentsClassification, descriptionClassification] =
- this.values_;
- OutputAnswerProperty.renderClassifiedText_(
- this.contents_, /** @type {string} */ (contents),
- /** @type {!Array<!mojom.ACMatchClassification>} */
- (contentsClassification));
- OutputAnswerProperty.renderClassifiedText_(
- this.description_, /** @type {string} */ (description),
- /** @type {!Array<!mojom.ACMatchClassification>} */
- (descriptionClassification));
- this.answer_.textContent = answer;
- this.imageUrl_.textContent = image;
- this.imageUrl_.href = image;
- }
+ /** @private @override */
+ render_() {
+ const overlap = this.values_[0].endsWith(this.values_[1]);
+ const firstText = this.values_[1] && overlap ?
+ this.values_[0].slice(0, -this.values_[1].length) :
+ this.values_[0];
+
+ this.first_.textContent = firstText;
+ this.second_.textContent = this.values_[1];
+ this.notOverlapWarning_.textContent = overlap ?
+ '' :
+ `btw, these texts do not overlap; '${
+ this.values_[1]}' was expected to be a suffix of '${
+ this.values_[0]}'`;
+ }
+}
+
+class OutputAnswerProperty extends FlexWrappingOutputProperty {
+ constructor() {
+ super();
+
+ /** @type {!Element} */
+ this.image_ = document.createElement('img');
+ this.image_.classList.add('pair-item');
+ this.container_.appendChild(this.image_);
+
+ /** @type {!Element} */
+ this.contents_ = document.createElement('div');
+ this.contents_.classList.add('pair-item', 'contents');
+ this.container_.appendChild(this.contents_);
+
+ /** @type {!Element} */
+ this.description_ = document.createElement('div');
+ this.description_.classList.add('pair-item', 'description');
+ this.container_.appendChild(this.description_);
+
+ /** @type {!Element} */
+ this.answer_ = document.createElement('div');
+ this.answer_.classList.add('pair-item', 'answer');
+ this.container_.appendChild(this.answer_);
+
+ /** @type {!Element} */
+ this.imageUrl_ = document.createElement('a');
+ this.imageUrl_.classList.add('pair-item', 'image-url');
+ this.container_.appendChild(this.imageUrl_);
+ }
- /** @override @return {string} */
- get text() {
- return this.values_.join('.');
- }
+ /** @param {string} imageData */
+ setAnswerImageData(imageData) {
+ this.image_.src = imageData;
+ }
- /**
- * @private
- * @param {!Element} container
- * @param {string} string
- * @param {!Array<!mojom.ACMatchClassification>} classes
- */
- static renderClassifiedText_(container, string, classes) {
- clearChildren(container);
- OutputAnswerProperty.classify(string, classes)
- .map(
- ({string, style}) => OutputJsonProperty.renderJsonWord(
- string, OutputAnswerProperty.styleToClasses_(style)))
- .forEach(span => container.appendChild(span));
- }
+ /** @private @override */
+ render_() {
+ // TODO (manukh) Wrap this line when Clang is updated,
+ // https://b.corp.google.com/126708256 .
+ const [image, contents, description, answer, contentsClassification, descriptionClassification] =
+ this.values_;
+ OutputAnswerProperty.renderClassifiedText_(
+ this.contents_, /** @type {string} */ (contents),
+ /** @type {!Array<!mojom.ACMatchClassification>} */
+ (contentsClassification));
+ OutputAnswerProperty.renderClassifiedText_(
+ this.description_, /** @type {string} */ (description),
+ /** @type {!Array<!mojom.ACMatchClassification>} */
+ (descriptionClassification));
+ this.answer_.textContent = answer;
+ this.imageUrl_.textContent = image;
+ this.imageUrl_.href = image;
+ }
- /**
- * @param {string} string
- * @param {!Array<!mojom.ACMatchClassification>} classes
- * @return {!Array<{string: string, style: number}>}
- */
- static classify(string, classes) {
- return classes.map(({offset, style}, i) => {
- const end = classes[i + 1] ? classes[i + 1].offset : string.length;
- return {string: string.substring(offset, end), style};
- });
- }
+ /** @override @return {string} */
+ get text() {
+ return this.values_.join('.');
+ }
- /**
- * @private
- * @param {number} style
- * @return {!Array<string>}
- */
- static styleToClasses_(style) {
- // Maps the bitmask enum AutocompleteMatch::ACMatchClassification::Style
- // to strings. See autocomplete_match.h for more details.
- // E.g., maps the style 5 to classes ['style-url', 'style-dim'].
- return ['style-url', 'style-match', 'style-dim'].filter(
- (_, i) => (style >> i) % 2);
- }
+ /**
+ * @private
+ * @param {!Element} container
+ * @param {string} string
+ * @param {!Array<!mojom.ACMatchClassification>} classes
+ */
+ static renderClassifiedText_(container, string, classes) {
+ clearChildren(container);
+ OutputAnswerProperty.classify(string, classes)
+ .map(
+ ({string, style}) => OutputJsonProperty.renderJsonWord(
+ string, OutputAnswerProperty.styleToClasses_(style)))
+ .forEach(span => container.appendChild(span));
}
- class OutputBooleanProperty extends OutputProperty {
- constructor() {
- super();
- /** @private {!Element} */
- this.icon_ = document.createElement('div');
- this.appendChild(this.icon_);
- }
+ /**
+ * @param {string} string
+ * @param {!Array<!mojom.ACMatchClassification>} classes
+ * @return {!Array<{string: string, style: number}>}
+ */
+ static classify(string, classes) {
+ return classes.map(({offset, style}, i) => {
+ const end = classes[i + 1] ? classes[i + 1].offset : string.length;
+ return {string: string.substring(offset, end), style};
+ });
+ }
- /** @private @override */
- render_() {
- this.icon_.classList.toggle('check-mark', !!this.value);
- this.icon_.classList.toggle('x-mark', !this.value);
- }
+ /**
+ * @private
+ * @param {number} style
+ * @return {!Array<string>}
+ */
+ static styleToClasses_(style) {
+ // Maps the bitmask enum AutocompleteMatch::ACMatchClassification::Style
+ // to strings. See autocomplete_match.h for more details.
+ // E.g., maps the style 5 to classes ['style-url', 'style-dim'].
+ return ['style-url', 'style-match', 'style-dim'].filter(
+ (_, i) => (style >> i) % 2);
+ }
+}
+
+class OutputBooleanProperty extends OutputProperty {
+ constructor() {
+ super();
+ /** @private {!Element} */
+ this.icon_ = document.createElement('div');
+ this.appendChild(this.icon_);
+ }
- get text() {
- return (this.value ? 'is: ' : 'not: ') + this.filterName;
- }
+ /** @private @override */
+ render_() {
+ this.icon_.classList.toggle('check-mark', !!this.value);
+ this.icon_.classList.toggle('x-mark', !this.value);
}
- class OutputJsonProperty extends OutputProperty {
- constructor() {
- super();
- /** @private {!Element} */
- this.pre_ = document.createElement('pre');
- this.pre_.classList.add('json');
- this.appendChild(this.pre_);
- }
+ get text() {
+ return (this.value ? 'is: ' : 'not: ') + this.filterName;
+ }
+}
+
+class OutputJsonProperty extends OutputProperty {
+ constructor() {
+ super();
+ /** @private {!Element} */
+ this.pre_ = document.createElement('pre');
+ this.pre_.classList.add('json');
+ this.appendChild(this.pre_);
+ }
- /** @private @override */
- render_() {
- clearChildren(this.pre_);
- this.text.split(/("(?:[^"\\]|\\.)*":?|\w+)/)
- .map(word => {
- return OutputJsonProperty.renderJsonWord(
- word, [OutputJsonProperty.classifyJsonWord(word)]);
- })
- .forEach(jsonSpan => this.pre_.appendChild(jsonSpan));
- }
+ /** @private @override */
+ render_() {
+ clearChildren(this.pre_);
+ this.text.split(/("(?:[^"\\]|\\.)*":?|\w+)/)
+ .map(word => {
+ return OutputJsonProperty.renderJsonWord(
+ word, [OutputJsonProperty.classifyJsonWord(word)]);
+ })
+ .forEach(jsonSpan => this.pre_.appendChild(jsonSpan));
+ }
- /** @override @return {string} */
- get text() {
- return JSON.stringify(this.value, null, 2);
- }
+ /** @override @return {string} */
+ get text() {
+ return JSON.stringify(this.value, null, 2);
+ }
- /**
- * @param {string} word
- * @param {!Array<string>} classes
- * @return {!Element}
- */
- static renderJsonWord(word, classes) {
- const span = document.createElement('span');
- span.classList.add(...classes);
- span.textContent = word;
- return span;
- }
+ /**
+ * @param {string} word
+ * @param {!Array<string>} classes
+ * @return {!Element}
+ */
+ static renderJsonWord(word, classes) {
+ const span = document.createElement('span');
+ span.classList.add(...classes);
+ span.textContent = word;
+ return span;
+ }
- /**
- * @param {string} word
- * @return {string|undefined}
- */
- static classifyJsonWord(word) {
- // Statically creating the regexes only once.
- OutputJsonProperty.classifications =
- OutputJsonProperty.classifications || [
- {re: /^"[^]*":$/, clazz: 'key'},
- {re: /^"[^]*"$/, clazz: 'string'},
- {re: /true|false/, clazz: 'boolean'},
- {re: /null/, clazz: 'null'},
- ];
- OutputJsonProperty.spaceRegex = OutputJsonProperty.spaceRegex || /^\s*$/;
-
- // Using isNaN, because Number.isNaN checks explicitly for NaN whereas
- // isNaN coerces the param to a Number. I.e. isNaN('3') === false, while
- // Number.isNaN('3') === true.
- if (isNaN(word)) {
- const classification =
- OutputJsonProperty.classifications.find(({re}) => re.test(word));
- return classification && classification.clazz;
- } else if (!OutputJsonProperty.spaceRegex.test(word)) {
- return 'number';
- }
+ /**
+ * @param {string} word
+ * @return {string|undefined}
+ */
+ static classifyJsonWord(word) {
+ // Statically creating the regexes only once.
+ OutputJsonProperty.classifications = OutputJsonProperty.classifications || [
+ {re: /^"[^]*":$/, clazz: 'key'},
+ {re: /^"[^]*"$/, clazz: 'string'},
+ {re: /true|false/, clazz: 'boolean'},
+ {re: /null/, clazz: 'null'},
+ ];
+ OutputJsonProperty.spaceRegex = OutputJsonProperty.spaceRegex || /^\s*$/;
+
+ // Using isNaN, because Number.isNaN checks explicitly for NaN whereas
+ // isNaN coerces the param to a Number. I.e. isNaN('3') === false, while
+ // Number.isNaN('3') === true.
+ if (isNaN(word)) {
+ const classification =
+ OutputJsonProperty.classifications.find(({re}) => re.test(word));
+ return classification && classification.clazz;
+ } else if (!OutputJsonProperty.spaceRegex.test(word)) {
+ return 'number';
}
}
+}
- class OutputAdditionalInfoProperty extends OutputProperty {
- constructor() {
- super();
- const container = document.createElement('div');
-
- /** @private {!Element} */
- this.pre_ = document.createElement('pre');
- this.pre_.classList.add('json');
- container.appendChild(this.pre_);
+class OutputAdditionalInfoProperty extends OutputProperty {
+ constructor() {
+ super();
+ const container = document.createElement('div');
- /** @private {!Element} */
- this.link_ = document.createElement('a');
- this.link_.download = 'AdditionalInfo.json';
+ /** @private {!Element} */
+ this.pre_ = document.createElement('pre');
+ this.pre_.classList.add('json');
+ container.appendChild(this.pre_);
- container.appendChild(this.link_);
- this.appendChild(container);
- }
+ /** @private {!Element} */
+ this.link_ = document.createElement('a');
+ this.link_.download = 'AdditionalInfo.json';
- /** @private @override */
- render_() {
- clearChildren(this.pre_);
- this.value.forEach(({key, value}) => {
- this.pre_.appendChild(
- OutputJsonProperty.renderJsonWord(key + ': ', ['key']));
- this.pre_.appendChild(
- OutputJsonProperty.renderJsonWord(value + '\n', ['number']));
- });
- this.link_.href = this.createDownloadLink_();
- }
+ container.appendChild(this.link_);
+ this.appendChild(container);
+ }
- /** @override @return {string} */
- get text() {
- return this.value.reduce(
- (prev, {key, value}) => `${prev}${key}: ${value}\n`, '');
- }
+ /** @private @override */
+ render_() {
+ clearChildren(this.pre_);
+ this.value.forEach(({key, value}) => {
+ this.pre_.appendChild(
+ OutputJsonProperty.renderJsonWord(key + ': ', ['key']));
+ this.pre_.appendChild(
+ OutputJsonProperty.renderJsonWord(value + '\n', ['number']));
+ });
+ this.link_.href = this.createDownloadLink_();
+ }
- /** @private @return {string} */
- createDownloadLink_() {
- const obj = this.value.reduce((obj, {key, value}) => {
- obj[key] = value;
- return obj;
- }, {});
- const obj64 = btoa(unescape(encodeURIComponent(JSON.stringify(obj))));
- return `data:application/json;base64,${obj64}`;
- }
+ /** @override @return {string} */
+ get text() {
+ return this.value.reduce(
+ (prev, {key, value}) => `${prev}${key}: ${value}\n`, '');
}
- class OutputUrlProperty extends FlexWrappingOutputProperty {
- constructor() {
- super();
+ /** @private @return {string} */
+ createDownloadLink_() {
+ const obj = this.value.reduce((obj, {key, value}) => {
+ obj[key] = value;
+ return obj;
+ }, {});
+ const text = JSON.stringify(obj, null, 2);
+ const obj64 = btoa(unescape(encodeURIComponent(text)));
+ return `data:application/json;base64,${obj64}`;
+ }
+}
- /** @private {!Element} */
- this.iconAndUrlContainer_ = document.createElement('div');
- this.iconAndUrlContainer_.classList.add('pair-item');
- this.container_.appendChild(this.iconAndUrlContainer_);
+class OutputUrlProperty extends FlexWrappingOutputProperty {
+ constructor() {
+ super();
- /** @private {!Element} */
- this.icon_ = document.createElement('img');
- this.iconAndUrlContainer_.appendChild(this.icon_);
+ /** @private {!Element} */
+ this.iconAndUrlContainer_ = document.createElement('div');
+ this.iconAndUrlContainer_.classList.add('pair-item');
+ this.container_.appendChild(this.iconAndUrlContainer_);
- /** @private {!Element} */
- this.urlLink_ = document.createElement('a');
- this.iconAndUrlContainer_.appendChild(this.urlLink_);
+ /** @private {!Element} */
+ this.icon_ = document.createElement('img');
+ this.iconAndUrlContainer_.appendChild(this.icon_);
- /** @private {!Element} */
- this.strippedUrlLink_ = document.createElement('a');
- this.strippedUrlLink_.classList.add('pair-item');
- this.container_.appendChild(this.strippedUrlLink_);
- }
+ /** @private {!Element} */
+ this.urlLink_ = document.createElement('a');
+ this.iconAndUrlContainer_.appendChild(this.urlLink_);
- /** @private @override */
- render_() {
- const [destinationUrl, isSearchType, strippedDestinationUrl] =
- this.values_;
- if (isSearchType) {
- this.icon_.removeAttribute('src');
- } else {
- this.icon_.src = `chrome://favicon/${destinationUrl}`;
- }
- this.urlLink_.textContent = destinationUrl;
- this.urlLink_.href = destinationUrl;
- this.strippedUrlLink_.textContent = strippedDestinationUrl;
- this.strippedUrlLink_.href = strippedDestinationUrl;
- }
+ /** @private {!Element} */
+ this.strippedUrlLink_ = document.createElement('a');
+ this.strippedUrlLink_.classList.add('pair-item');
+ this.container_.appendChild(this.strippedUrlLink_);
}
- class OutputTextProperty extends OutputProperty {
- constructor() {
- super();
- /** @private {!Element} */
- this.div_ = document.createElement('div');
- this.appendChild(this.div_);
- }
-
- /** @private @override */
- render_() {
- this.div_.textContent = this.value;
- }
+ /** @private @override */
+ render_() {
+ const [destinationUrl, isSearchType, strippedDestinationUrl] = this.values_;
+ if (isSearchType) {
+ this.icon_.removeAttribute('src');
+ } else {
+ this.icon_.src = `chrome://favicon/${destinationUrl}`;
+ }
+ this.urlLink_.textContent = destinationUrl;
+ this.urlLink_.href = destinationUrl;
+ this.strippedUrlLink_.textContent = strippedDestinationUrl;
+ this.strippedUrlLink_.href = strippedDestinationUrl;
+ }
+}
+
+class OutputTextProperty extends OutputProperty {
+ constructor() {
+ super();
+ /** @private {!Element} */
+ this.div_ = document.createElement('div');
+ this.appendChild(this.div_);
}
- /** Responsible for highlighting and hiding rows using filter text. */
- class FilterUtil {
- /**
- * Checks if a string fuzzy-matches a filter string. Each character
- * of filterText must be present in the search text, either adjacent to the
- * previous matched character, or at the start of a new word (see
- * textToWords_).
- * E.g. `abc` matches `abc`, `a big cat`, `a-bigCat`, `a very big cat`, and
- * `an amBer cat`; but does not match `abigcat` or `an amber cat`.
- * `green rainbow` is matched by `gre rain`, but not by `gre bow`.
- * One exception is the first character, which may be matched mid-word.
- * E.g. `een rain` can also match `green rainbow`.
- * @param {string} searchText
- * @param {string} filterText
- * @return {boolean}
- */
- static filterText(searchText, filterText) {
- const regexFilter =
- Array.from(filterText)
- .map(word => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
- .join('(.*\\.)?');
- const words = FilterUtil.textToWords_(searchText).join('.');
- return words.match(new RegExp(regexFilter, 'i')) !== null;
- }
+ /** @private @override */
+ render_() {
+ this.div_.textContent = this.value;
+ }
+}
- /**
- * Splits a string into words, delimited by either capital letters, groups
- * of digits, or non alpha characters.
- * E.g., `https://google.com/the-dog-ate-134pies` will be split to:
- * https, :, /, /, google, ., com, /, the, -, dog, -, ate, -, 134, pies
- * This differs from `Array.split` in that this groups digits, e.g. 134.
- * @private
- * @param {string} text
- * @return {!Array<string>}
- */
- static textToWords_(text) {
- const MAX_TEXT_LENGTH = 200;
- if (text.length > MAX_TEXT_LENGTH) {
- text = text.slice(0, MAX_TEXT_LENGTH);
- console.warn(`text to be filtered too long, truncatd; max length: ${
- MAX_TEXT_LENGTH}, truncated text: ${text}`);
- }
- return text.match(/[a-z]+|[A-Z][a-z]*|\d+|./g) || [];
- }
+/** Responsible for highlighting and hiding rows using filter text. */
+class FilterUtil {
+ /**
+ * Checks if a string fuzzy-matches a filter string. Each character
+ * of filterText must be present in the search text, either adjacent to the
+ * previous matched character, or at the start of a new word (see
+ * textToWords_).
+ * E.g. `abc` matches `abc`, `a big cat`, `a-bigCat`, `a very big cat`, and
+ * `an amBer cat`; but does not match `abigcat` or `an amber cat`.
+ * `green rainbow` is matched by `gre rain`, but not by `gre bow`.
+ * One exception is the first character, which may be matched mid-word.
+ * E.g. `een rain` can also match `green rainbow`.
+ * @param {string} searchText
+ * @param {string} filterText
+ * @return {boolean}
+ */
+ static filterText(searchText, filterText) {
+ const regexFilter =
+ Array.from(filterText)
+ .map(word => word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
+ .join('(.*\\.)?');
+ const words = FilterUtil.textToWords_(searchText).join('.');
+ return words.match(new RegExp(regexFilter, 'i')) !== null;
}
- class Column {
- /**
- * @param {!Array<string>} headerText
- * @param {string} url
- * @param {string} matchKey
- * @param {boolean} displayAlways
- * @param {string} tooltip
- * @param {function(new:OutputProperty)} outputClass
- * @param {!Array<string>} sourceProperties
- */
- constructor(
- headerText, url, matchKey, displayAlways, tooltip, sourceProperties,
- outputClass) {
- /** @type {!Array<string>} split per span container to support styling. */
- this.headerText = headerText;
- /** @type {string} header link href or blank if non-hyperlink header. */
- this.url = url;
- /** @type {string} the field name used in the Match.properties object. */
- this.matchKey = matchKey;
- /** @type {boolean} if shown when showDetails option is false. */
- this.displayAlways = displayAlways;
- /** @type {string} header tooltip. */
- this.tooltip = tooltip;
- /** @type {!Array<string>} related mojo AutocompleteMatch properties. */
- this.sourceProperties = sourceProperties;
- /** @type {function(new:OutputProperty)} */
- this.outputClass = outputClass;
-
- const hyphenatedName =
- matchKey.replace(/[A-Z]/g, c => '-' + c.toLowerCase());
- /** @type {string} */
- this.cellClassName = 'cell-' + hyphenatedName;
- /** @type {string} */
- this.headerClassName = 'header-' + hyphenatedName;
- }
+ /**
+ * Splits a string into words, delimited by either capital letters, groups
+ * of digits, or non alpha characters.
+ * E.g., `https://google.com/the-dog-ate-134pies` will be split to:
+ * https, :, /, /, google, ., com, /, the, -, dog, -, ate, -, 134, pies
+ * This differs from `Array.split` in that this groups digits, e.g. 134.
+ * @private
+ * @param {string} text
+ * @return {!Array<string>}
+ */
+ static textToWords_(text) {
+ const MAX_TEXT_LENGTH = 200;
+ if (text.length > MAX_TEXT_LENGTH) {
+ text = text.slice(0, MAX_TEXT_LENGTH);
+ console.warn(`text to be filtered too long, truncatd; max length: ${
+ MAX_TEXT_LENGTH}, truncated text: ${text}`);
+ }
+ return text.match(/[a-z]+|[A-Z][a-z]*|\d+|./g) || [];
}
+}
+class Column {
/**
- * A constant that's used to decide what autocomplete result
- * properties to output in what order.
- * @type {!Array<!Column>}
+ * @param {!Array<string>} headerText
+ * @param {string} url
+ * @param {string} matchKey
+ * @param {boolean} displayAlways
+ * @param {string} tooltip
+ * @param {function(new:OutputProperty)} outputClass
+ * @param {!Array<string>} sourceProperties
*/
- const COLUMNS = [
- new Column(
- ['Provider', 'Type'], '', 'providerAndType', true,
- 'Provider & Type\nThe AutocompleteProvider suggesting this result. / ' +
- 'The type of the result.',
- ['providerName', 'type'], OutputPairProperty),
- new Column(
- ['Relevance'], '', 'relevance', true,
- 'Relevance\nThe result score. Higher is more relevant.', ['relevance'],
- OutputTextProperty),
- new Column(
- ['Contents', 'Description', 'Answer'], '', 'contentsAndDescription',
- true,
- 'Contents & Description & Answer\nURL classifications are styled ' +
- 'blue.\nMATCH classifications are styled bold.\nDIM ' +
- 'classifications are styled with a gray background.',
- [
- 'image', 'contents', 'description', 'answer', 'contentsClass',
- 'descriptionClass'
- ],
- OutputAnswerProperty),
- new Column(
- ['S'], '', 'swapContentsAndDescription', false,
- 'Swap Contents and Description', ['swapContentsAndDescription'],
- OutputBooleanProperty),
- new Column(
- ['D'], '', 'allowedToBeDefaultMatch', true,
- 'Can be Default\nA green checkmark indicates that the result can be ' +
- 'the default match (i.e., can be the match that pressing enter ' +
- 'in the omnibox navigates to).',
- ['allowedToBeDefaultMatch'], OutputBooleanProperty),
- new Column(
- ['S'], '', 'starred', false,
- 'Starred\nA green checkmark indicates that the result has been ' +
- 'bookmarked.',
- ['starred'], OutputBooleanProperty),
- new Column(
- ['T'], '', 'hasTabMatch', false,
- 'Has Tab Match\nA green checkmark indicates that the result URL ' +
- 'matches an open tab.',
- ['hasTabMatch'], OutputBooleanProperty),
- new Column(
- ['URL', 'Stripped URL'], '', 'destinationUrl', true,
- 'URL & Stripped URL\nThe URL for the result. / The stripped URL for ' +
- 'the result.',
- ['destinationUrl', 'isSearchType', 'strippedDestinationUrl'],
- OutputUrlProperty),
- new Column(
- ['Fill', 'Inline'], '', 'fillAndInline', false,
- 'Fill & Inline\nThe text shown in the omnibox when the result is ' +
- 'selected. / The text shown in the omnibox as a blue highlight ' +
- 'selection following the cursor, if this match is shown inline.',
- ['fillIntoEdit', 'inlineAutocompletion'],
- OutputOverlappingPairProperty),
- new Column(
- ['D'], '', 'deletable', false,
- 'Deletable\nA green checkmark indicates that the result can be ' +
- 'deleted from the visit history.',
- ['deletable'], OutputBooleanProperty),
- new Column(
- ['P'], '', 'fromPrevious', false,
- 'From Previous\nTrue if this match is from a previous result.',
- ['fromPrevious'], OutputBooleanProperty),
- new Column(
- ['Tran'],
- 'https://cs.chromium.org/chromium/src/ui/base/page_transition_types.h' +
- '?q=page_transition_types.h&sq=package:chromium&dr=CSs&l=14',
- 'transition', false, 'Transition\nHow the user got to the result.',
- ['transition'], OutputTextProperty),
- new Column(
- ['D'], '', 'providerDone', false,
- 'Done\nA green checkmark indicates that the provider is done looking ' +
- 'for more results.',
- ['providerDone'], OutputBooleanProperty),
- new Column(
- ['Associated Keyword'], '', 'associatedKeyword', false,
- 'Associated Keyword\nIf non-empty, a "press tab to search" hint will ' +
- 'be shown and will engage this keyword.',
- ['associatedKeyword'], OutputTextProperty),
- new Column(
- ['Keyword'], '', 'keyword', false,
- 'Keyword\nThe keyword of the search engine to be used.', ['keyword'],
- OutputTextProperty),
- new Column(
- ['D'], '', 'duplicates', false,
- 'Duplicates\nThe number of matches that have been marked as ' +
- 'duplicates of this match.',
- ['duplicates'], OutputTextProperty),
- new Column(
- ['Additional Info'], '', 'additionalInfo', false,
- 'Additional Info\nProvider-specific information about the result.',
- ['additionalInfo'], OutputAdditionalInfoProperty)
- ];
-
- /** @type {!Column} */
- const ADDITIONAL_PROPERTIES_COLUMN = new Column(
- ['Additional Properties'], '', 'additionalProperties', false,
- 'Properties not accounted for.', [], OutputJsonProperty);
-
- const CONSUMED_SOURCE_PROPERTIES =
- COLUMNS.flatMap(column => column.sourceProperties);
-
- customElements.define('omnibox-output', OmniboxOutput);
- customElements.define('output-results-group', OutputResultsGroup);
- customElements.define('output-results-details', OutputResultsDetails);
- customElements.define(
- 'output-results-table', OutputResultsTable, {extends: 'tbody'});
- customElements.define('output-match', OutputMatch, {extends: 'tr'});
- customElements.define('output-header', OutputHeader, {extends: 'th'});
- customElements.define(
- 'output-pair-property', OutputPairProperty, {extends: 'td'});
- customElements.define(
- 'output-overlapping-pair-property', OutputOverlappingPairProperty,
- {extends: 'td'});
- customElements.define(
- 'output-answer-property', OutputAnswerProperty, {extends: 'td'});
- customElements.define(
- 'output-boolean-property', OutputBooleanProperty, {extends: 'td'});
- customElements.define(
- 'output-json-property', OutputJsonProperty, {extends: 'td'});
- customElements.define(
- 'output-additional-info-property', OutputAdditionalInfoProperty,
- {extends: 'td'});
- customElements.define(
- 'output-url-property', OutputUrlProperty, {extends: 'td'});
- customElements.define(
- 'output-text-property', OutputTextProperty, {extends: 'td'});
-
- return {OmniboxOutput: OmniboxOutput};
-});
+ constructor(
+ headerText, url, matchKey, displayAlways, tooltip, sourceProperties,
+ outputClass) {
+ /** @type {!Array<string>} split per span container to support styling. */
+ this.headerText = headerText;
+ /** @type {string} header link href or blank if non-hyperlink header. */
+ this.url = url;
+ /** @type {string} the field name used in the Match.properties object. */
+ this.matchKey = matchKey;
+ /** @type {boolean} if shown when showDetails option is false. */
+ this.displayAlways = displayAlways;
+ /** @type {string} header tooltip. */
+ this.tooltip = tooltip;
+ /** @type {!Array<string>} related mojo AutocompleteMatch properties. */
+ this.sourceProperties = sourceProperties;
+ /** @type {function(new:OutputProperty)} */
+ this.outputClass = outputClass;
+
+ const hyphenatedName =
+ matchKey.replace(/[A-Z]/g, c => '-' + c.toLowerCase());
+ /** @type {string} */
+ this.cellClassName = 'cell-' + hyphenatedName;
+ /** @type {string} */
+ this.headerClassName = 'header-' + hyphenatedName;
+ }
+}
+
+/**
+ * A constant that's used to decide what autocomplete result
+ * properties to output in what order.
+ * @type {!Array<!Column>}
+ */
+const COLUMNS = [
+ new Column(
+ ['Provider', 'Type'], '', 'providerAndType', true,
+ 'Provider & Type\nThe AutocompleteProvider suggesting this result. / ' +
+ 'The type of the result.',
+ ['providerName', 'type'], OutputPairProperty),
+ new Column(
+ ['Relevance'], '', 'relevance', true,
+ 'Relevance\nThe result score. Higher is more relevant.', ['relevance'],
+ OutputTextProperty),
+ new Column(
+ ['Contents', 'Description', 'Answer'], '', 'contentsAndDescription', true,
+ 'Contents & Description & Answer\nURL classifications are styled ' +
+ 'blue.\nMATCH classifications are styled bold.\nDIM ' +
+ 'classifications are styled with a gray background.',
+ [
+ 'image', 'contents', 'description', 'answer', 'contentsClass',
+ 'descriptionClass'
+ ],
+ OutputAnswerProperty),
+ new Column(
+ ['S'], '', 'swapContentsAndDescription', false,
+ 'Swap Contents and Description', ['swapContentsAndDescription'],
+ OutputBooleanProperty),
+ new Column(
+ ['D'], '', 'allowedToBeDefaultMatch', true,
+ 'Can be Default\nA green checkmark indicates that the result can be ' +
+ 'the default match (i.e., can be the match that pressing enter ' +
+ 'in the omnibox navigates to).',
+ ['allowedToBeDefaultMatch'], OutputBooleanProperty),
+ new Column(
+ ['S'], '', 'starred', false,
+ 'Starred\nA green checkmark indicates that the result has been ' +
+ 'bookmarked.',
+ ['starred'], OutputBooleanProperty),
+ new Column(
+ ['T'], '', 'hasTabMatch', false,
+ 'Has Tab Match\nA green checkmark indicates that the result URL ' +
+ 'matches an open tab.',
+ ['hasTabMatch'], OutputBooleanProperty),
+ new Column(
+ ['URL', 'Stripped URL'], '', 'destinationUrl', true,
+ 'URL & Stripped URL\nThe URL for the result. / The stripped URL for ' +
+ 'the result.',
+ ['destinationUrl', 'isSearchType', 'strippedDestinationUrl'],
+ OutputUrlProperty),
+ new Column(
+ ['Fill', 'Inline'], '', 'fillAndInline', false,
+ 'Fill & Inline\nThe text shown in the omnibox when the result is ' +
+ 'selected. / The text shown in the omnibox as a blue highlight ' +
+ 'selection following the cursor, if this match is shown inline.',
+ ['fillIntoEdit', 'inlineAutocompletion'], OutputOverlappingPairProperty),
+ new Column(
+ ['D'], '', 'deletable', false,
+ 'Deletable\nA green checkmark indicates that the result can be ' +
+ 'deleted from the visit history.',
+ ['deletable'], OutputBooleanProperty),
+ new Column(
+ ['P'], '', 'fromPrevious', false,
+ 'From Previous\nTrue if this match is from a previous result.',
+ ['fromPrevious'], OutputBooleanProperty),
+ new Column(
+ ['Tran'],
+ 'https://cs.chromium.org/chromium/src/ui/base/page_transition_types.h' +
+ '?q=page_transition_types.h&sq=package:chromium&dr=CSs&l=14',
+ 'transition', false, 'Transition\nHow the user got to the result.',
+ ['transition'], OutputTextProperty),
+ new Column(
+ ['D'], '', 'providerDone', false,
+ 'Done\nA green checkmark indicates that the provider is done looking ' +
+ 'for more results.',
+ ['providerDone'], OutputBooleanProperty),
+ new Column(
+ ['Associated Keyword'], '', 'associatedKeyword', false,
+ 'Associated Keyword\nIf non-empty, a "press tab to search" hint will ' +
+ 'be shown and will engage this keyword.',
+ ['associatedKeyword'], OutputTextProperty),
+ new Column(
+ ['Keyword'], '', 'keyword', false,
+ 'Keyword\nThe keyword of the search engine to be used.', ['keyword'],
+ OutputTextProperty),
+ new Column(
+ ['D'], '', 'duplicates', false,
+ 'Duplicates\nThe number of matches that have been marked as ' +
+ 'duplicates of this match.',
+ ['duplicates'], OutputTextProperty),
+ new Column(
+ ['Additional Info'], '', 'additionalInfo', false,
+ 'Additional Info\nProvider-specific information about the result.',
+ ['additionalInfo'], OutputAdditionalInfoProperty)
+];
+
+/** @type {!Column} */
+const ADDITIONAL_PROPERTIES_COLUMN = new Column(
+ ['Additional Properties'], '', 'additionalProperties', false,
+ 'Properties not accounted for.', [], OutputJsonProperty);
+
+const CONSUMED_SOURCE_PROPERTIES =
+ COLUMNS.flatMap(column => column.sourceProperties);
+
+customElements.define('omnibox-output', OmniboxOutput);
+customElements.define('output-results-group', OutputResultsGroup);
+customElements.define('output-results-details', OutputResultsDetails);
+customElements.define(
+ 'output-results-table', OutputResultsTable, {extends: 'tbody'});
+customElements.define('output-match', OutputMatch, {extends: 'tr'});
+customElements.define('output-header', OutputHeader, {extends: 'th'});
+customElements.define(
+ 'output-pair-property', OutputPairProperty, {extends: 'td'});
+customElements.define(
+ 'output-overlapping-pair-property', OutputOverlappingPairProperty,
+ {extends: 'td'});
+customElements.define(
+ 'output-answer-property', OutputAnswerProperty, {extends: 'td'});
+customElements.define(
+ 'output-boolean-property', OutputBooleanProperty, {extends: 'td'});
+customElements.define(
+ 'output-json-property', OutputJsonProperty, {extends: 'td'});
+customElements.define(
+ 'output-additional-info-property', OutputAdditionalInfoProperty,
+ {extends: 'td'});
+customElements.define(
+ 'output-url-property', OutputUrlProperty, {extends: 'td'});
+customElements.define(
+ 'output-text-property', OutputTextProperty, {extends: 'td'});
diff --git a/chromium/chrome/browser/resources/omnibox/omnibox_popup.html b/chromium/chrome/browser/resources/omnibox/omnibox_popup.html
new file mode 100644
index 00000000000..9a6080e66e1
--- /dev/null
+++ b/chromium/chrome/browser/resources/omnibox/omnibox_popup.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Omnibox Popup</title>
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
+ <script type="module" src="omnibox_popup.js"></script>
+ <script type="module" src="chrome://resources/cr_components/omnibox/cr_autocomplete_match_list.js">
+ </script>
+</head>
+
+<body>
+ <cr-autocomplete-match-list></cr-autocomplete-match-list>
+</body>
+</html>
diff --git a/chromium/chrome/browser/resources/omnibox/omnibox_popup.js b/chromium/chrome/browser/resources/omnibox/omnibox_popup.js
new file mode 100644
index 00000000000..a6b55b23142
--- /dev/null
+++ b/chromium/chrome/browser/resources/omnibox/omnibox_popup.js
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import './chrome/browser/ui/webui/omnibox/omnibox.mojom-lite.js';
+
+import {AutocompleteMatchListElement} from 'chrome://resources/cr_components/omnibox/cr_autocomplete_match_list.js';
+
+/**
+ * Javascript proof-of-concept for omnibox_popup.html, served from
+ * chrome://omnibox/omnibox_popup.html. This is used for the experimental
+ * WebUI version of the omnibox popup.
+ */
+
+document.addEventListener('DOMContentLoaded', () => {
+ /** @private {!mojom.OmniboxPageCallbackRouter} */
+ const callbackRouter = new mojom.OmniboxPageCallbackRouter;
+
+ // Basically a Hello World proof of concept that writes the Autocomplete
+ // responses to the whole document.
+ callbackRouter.handleNewAutocompleteResponse.addListener(
+ (response, isPageController) => {
+ // Ignore debug controller and empty results.
+ if (!isPageController && response.combinedResults.length > 0) {
+ /** @private {!AutocompleteMatchListElement} */
+ const popup = /** @type {!AutocompleteMatchListElement} */ (
+ document.querySelector('cr-autocomplete-match-list'));
+
+ popup.updateMatches(response.combinedResults);
+ }
+ });
+
+ /** @private {!mojom.OmniboxPageHandlerRemote} */
+ const handler = mojom.OmniboxPageHandler.getRemote();
+ handler.setClientPage(callbackRouter.$.bindNewPipeAndPassRemote());
+});
diff --git a/chromium/chrome/browser/resources/omnibox/output_results_group.css b/chromium/chrome/browser/resources/omnibox/output_results_group.css
index c46e20e82aa..0f1ddcd618e 100644
--- a/chromium/chrome/browser/resources/omnibox/output_results_group.css
+++ b/chromium/chrome/browser/resources/omnibox/output_results_group.css
@@ -53,6 +53,14 @@ table {
max-height: 28px;
}
+.body tr.expanded {
+ height: 200px;
+}
+
+.body tr.expanded td > * {
+ max-height: 190px;
+}
+
.body td {
white-space: pre-wrap;
word-break: break-all;
diff --git a/chromium/chrome/browser/resources/omnibox/resources.grd b/chromium/chrome/browser/resources/omnibox/resources.grd
index d6011a893e8..349526f27ab 100644
--- a/chromium/chrome/browser/resources/omnibox/resources.grd
+++ b/chromium/chrome/browser/resources/omnibox/resources.grd
@@ -16,6 +16,10 @@
allowexternalscript="true"
type="BINDATA"
compress="gzip" />
+ <include name="IDR_OMNIBOX_POPUP_HTML"
+ file="omnibox_popup.html"
+ type="BINDATA"
+ compress="gzip" />
<include name="IDR_OMNIBOX_CSS"
file="omnibox.css"
type="BINDATA"
@@ -44,6 +48,10 @@
file="omnibox_output.js"
type="BINDATA"
compress="gzip" />
+ <include name="IDR_OMNIBOX_POPUP_JS"
+ file="omnibox_popup.js"
+ type="BINDATA"
+ compress="gzip" />
<include name="IDR_OMNIBOX_JS"
file="omnibox.js"
type="BINDATA"
diff --git a/chromium/chrome/browser/resources/optimize_webui.gni b/chromium/chrome/browser/resources/optimize_webui.gni
index 7292b2966db..bfc1f5a4121 100644
--- a/chromium/chrome/browser/resources/optimize_webui.gni
+++ b/chromium/chrome/browser/resources/optimize_webui.gni
@@ -29,9 +29,7 @@ template("optimize_webui") {
node(target_name) {
script = "//chrome/browser/resources/optimize_webui.py"
- inputs = [
- "//chrome/browser/resources/unpack_pak.py",
- ]
+ inputs = [ "//chrome/browser/resources/unpack_pak.py" ]
# This depfile is generated by optimize_webui.py
depfile = "${target_gen_dir}/${target_name}.d"
@@ -93,13 +91,9 @@ template("unpak") {
action(target_name) {
script = "//chrome/browser/resources/unpack_pak.py"
- inputs = [
- "$target_gen_dir/${invoker.pak_file}",
- ]
+ inputs = [ "$target_gen_dir/${invoker.pak_file}" ]
- outputs = [
- "$target_gen_dir/${invoker.out_folder}/unpack.stamp",
- ]
+ outputs = [ "$target_gen_dir/${invoker.out_folder}/unpack.stamp" ]
deps = invoker.deps
diff --git a/chromium/chrome/browser/resources/optimize_webui.py b/chromium/chrome/browser/resources/optimize_webui.py
index 3055403e032..388cb640460 100755
--- a/chromium/chrome/browser/resources/optimize_webui.py
+++ b/chromium/chrome/browser/resources/optimize_webui.py
@@ -7,6 +7,7 @@ import argparse
import itertools
import json
import os
+import glob
import platform
import re
import shutil
@@ -114,10 +115,10 @@ def _request_list_path(out_path, host):
def _update_dep_file(in_folder, args, manifest):
in_path = os.path.join(_CWD, in_folder)
- # Gather the dependencies of all bundled root HTML files.
+ # Gather the dependencies of all bundled root files.
request_list = []
- for html_file in manifest:
- request_list += manifest[html_file]
+ for out_file in manifest:
+ request_list += manifest[out_file]
# Add a slash in front of every dependency that is not a chrome:// URL, so
# that we can map it to the correct source file path below.
@@ -167,23 +168,31 @@ def _generate_rollup_config(tmp_out_dir, path_to_plugin, in_path, host,
f.close()
return rollup_config_file;
-# Create the manifest file from the sourcemap generated by rollup.
-def _generate_manifest_file(
- js_out_file, tmp_out_dir, in_path, manifest_out_path):
- sourcemap_file = js_out_file + '.map';
- with open(os.path.join(tmp_out_dir, sourcemap_file), 'r') as f:
- sourcemap = json.loads(f.read())
- if not 'sources' in sourcemap:
- raise Exception('rollup could not construct source map')
- sources = sourcemap['sources']
- replaced_sources = []
- for source in sources:
- replaced_sources.append(
- source.replace('../' + os.path.basename(in_path) + "/", ""))
- manifest = { 'sources': replaced_sources };
- with open(manifest_out_path, 'w') as f:
- f.write(json.dumps(manifest))
- f.close()
+# Create the manifest file from the sourcemap generated by rollup and return the
+# list of bundles.
+def _generate_manifest_file(tmp_out_dir, in_path, manifest_out_path):
+ generated_sourcemaps = glob.glob('%s/*.map' % tmp_out_dir)
+ manifest = {}
+ output_filenames = []
+ for sourcemap_file in generated_sourcemaps:
+ with open(sourcemap_file, 'r') as f:
+ sourcemap = json.loads(f.read())
+ if not 'sources' in sourcemap:
+ raise Exception('rollup could not construct source map')
+ sources = sourcemap['sources']
+ replaced_sources = []
+ for source in sources:
+ replaced_sources.append(
+ source.replace('../' + os.path.basename(in_path) + "/", ""))
+ filename = sourcemap_file[:-len('.map')]
+ manifest[os.path.basename(filename)] = replaced_sources
+ output_filenames.append(filename)
+
+ with open(manifest_out_path, 'w') as f:
+ f.write(json.dumps(manifest))
+ f.close()
+
+ return output_filenames
def _bundle_v3(tmp_out_dir, in_path, out_path, manifest_out_path, args,
excludes):
@@ -193,26 +202,48 @@ def _bundle_v3(tmp_out_dir, in_path, out_path, manifest_out_path, args,
os.path.abspath(_HERE_PATH), 'tools', 'rollup_plugin.js')
rollup_config_file = _generate_rollup_config(tmp_out_dir, path_to_plugin,
in_path, args.host, excludes)
+ rollup_args = [os.path.join(in_path, f) for f in args.js_module_in_files]
+
+ # Confirm names are as expected. This is necessary to avoid having to replace
+ # import statements in the generated output files.
+ # TODO(rbpotter): Is it worth adding import statement replacement to support
+ # arbitrary names?
bundled_paths = []
- for index, js_module_in_file in enumerate(args.js_module_in_files):
- js_out_file = args.js_out_files[index]
- rollup_js_out_file = '%s.rollup.js' % js_out_file[:-3]
- rollup_js_out_path = os.path.join(tmp_out_dir, rollup_js_out_file)
- node.RunNode(
- [node_modules.PathToRollup()] + [
- '--format', 'esm',
- '--input', os.path.join(in_path, js_module_in_file),
- '--file', rollup_js_out_path,
- '--sourcemap', '--sourcemapExcludeSources',
- '--config', rollup_config_file,
- '--silent',
- ])
-
- # Create the manifest file from the sourcemap generated by rollup.
- _generate_manifest_file(rollup_js_out_file, tmp_out_dir, in_path,
- manifest_out_path)
-
- bundled_paths.append(rollup_js_out_path)
+ for index, js_file in enumerate(args.js_module_in_files):
+ expected_name = '%s.rollup.js' % js_file[:-len('.js')]
+ assert args.js_out_files[index] == expected_name, \
+ 'Output file corresponding to %s should be named %s.rollup.js' % \
+ (js_file, expected_name)
+ bundled_paths.append(os.path.join(tmp_out_dir, expected_name))
+
+ # This indicates that rollup is expected to generate a shared chunk file as
+ # well as one file per module. Set its name using --chunkFileNames. Note:
+ # Currently, this only supports 2 entry points, which generate 2 corresponding
+ # outputs and 1 shared output.
+ if (len(args.js_out_files) == 3):
+ assert len(args.js_module_in_files) == 2, \
+ 'Expect 2 module entry points for generating 3 outputs'
+ shared_file_name = args.js_out_files[2]
+ rollup_args += [ '--chunkFileNames', shared_file_name ]
+ bundled_paths.append(os.path.join(tmp_out_dir, shared_file_name))
+
+ node.RunNode(
+ [node_modules.PathToRollup()] + rollup_args + [
+ '--format', 'esm',
+ '--dir', tmp_out_dir,
+ '--entryFileNames', '[name].rollup.js',
+ '--sourcemap', '--sourcemapExcludeSources',
+ '--config', rollup_config_file,
+ '--silent',
+ ])
+
+ # Create the manifest file from the sourcemaps generated by rollup.
+ generated_paths = _generate_manifest_file(tmp_out_dir, in_path,
+ manifest_out_path)
+ assert len(generated_paths) == len(bundled_paths), \
+ 'unexpected number of bundles - %s - generated by rollup' % \
+ (len(generated_paths))
+
return bundled_paths
def _bundle_v2(tmp_out_dir, in_path, out_path, manifest_out_path, args,
@@ -277,7 +308,7 @@ def _optimize(in_folder, args):
in_path = os.path.normpath(os.path.join(_CWD, in_folder)).replace('\\', '/')
out_path = os.path.join(_CWD, args.out_folder).replace('\\', '/')
manifest_out_path = _request_list_path(out_path, args.host)
- tmp_out_dir = os.path.join(out_path, 'bundled').replace('\\', '/')
+ tmp_out_dir = tempfile.mkdtemp(dir=out_path).replace('\\', '/')
excludes = _BASE_EXCLUDES + [
# This file is dynamically created by C++. Need to specify an exclusion
diff --git a/chromium/chrome/browser/resources/optimize_webui_test.py b/chromium/chrome/browser/resources/optimize_webui_test.py
index 86be89ab475..ed92727a210 100755
--- a/chromium/chrome/browser/resources/optimize_webui_test.py
+++ b/chromium/chrome/browser/resources/optimize_webui_test.py
@@ -44,24 +44,16 @@ class OptimizeWebUiTest(unittest.TestCase):
assert self._out_folder
return open(os.path.join(self._out_folder, file_name), 'r').read()
- def _run_optimize(self, depfile, html_in_file, html_out_file, js_out_file,
- js_module_in_file):
- # TODO(dbeam): make it possible to _run_optimize twice? Is that useful?
+ def _run_optimize(self, input_args):
assert not self._out_folder
self._out_folder = self._create_tmp_dir()
- args = [
- '--depfile', os.path.join(self._out_folder,'depfile.d'),
+ # TODO(dbeam): make it possible to _run_optimize twice? Is that useful?
+ args = input_args + [
+ '--depfile', os.path.join(self._out_folder, 'depfile.d'),
'--host', 'fake-host',
'--input', self._tmp_src_dir,
- '--js_out_files', js_out_file,
'--out_folder', self._out_folder,
]
- if (html_in_file):
- args += [ '--html_in_files', html_in_file ];
- if (html_out_file):
- args += [ '--html_out_files', html_out_file ];
- if (js_module_in_file):
- args += [ '--js_module_in_files', js_module_in_file ];
optimize_webui.main(args)
def _write_files_to_src_dir(self):
@@ -140,11 +132,12 @@ import './element_in_dir/element_in_dir.js';
def testSimpleOptimize(self):
self._write_files_to_src_dir()
- self._run_optimize(depfile='depfile.d',
- html_in_file='ui.html',
- html_out_file='fast.html',
- js_out_file='fast.js',
- js_module_in_file='')
+ args = [
+ '--html_in_files', 'ui.html',
+ '--html_out_files', 'fast.html',
+ '--js_out_files', 'fast.js',
+ ]
+ self._run_optimize(args)
fast_html = self._read_out_file('fast.html')
self._check_output_html(fast_html)
@@ -154,22 +147,22 @@ import './element_in_dir/element_in_dir.js';
def testV3SimpleOptimize(self):
self._write_v3_files_to_src_dir()
- self._run_optimize(depfile='depfile.d',
- html_in_file='',
- html_out_file='',
- js_out_file='ui.rollup.js',
- js_module_in_file='ui.js')
+ args = [
+ '--js_module_in_files', 'ui.js',
+ '--js_out_files', 'ui.rollup.js',
+ ]
+ self._run_optimize(args)
self._check_output_js('ui.rollup.js')
self._check_output_depfile(False)
def testV3OptimizeWithResources(self):
self._write_v3_files_with_resources_to_src_dir()
- self._run_optimize(depfile='depfile.d',
- html_in_file='',
- html_out_file='',
- js_out_file='ui.rollup.js',
- js_module_in_file='ui.js')
+ args = [
+ '--js_module_in_files', 'ui.js',
+ '--js_out_files', 'ui.rollup.js',
+ ]
+ self._run_optimize(args)
ui_rollup_js = self._read_out_file('ui.rollup.js')
self.assertIn('yay', ui_rollup_js)
@@ -187,5 +180,42 @@ import './element_in_dir/element_in_dir.js';
os.path.normpath('../gen/ui/webui/resources/js/fake_resource.m.js'),
depfile_d)
+ def testV3MultiBundleOptimize(self):
+ self._write_v3_files_to_src_dir()
+ self._write_file_to_src_dir('lazy_element.js',
+ "alert('hello from lazy_element');")
+ self._write_file_to_src_dir('lazy.js', '''
+import './lazy_element.js';
+import './element_in_dir/element_in_dir.js';
+''')
+
+ args = [
+ '--js_module_in_files', 'ui.js', 'lazy.js',
+ '--js_out_files', 'ui.rollup.js', 'lazy.rollup.js', 'shared.rollup.js',
+ ]
+ self._run_optimize(args)
+
+ # Check that the shared element is in the shared bundle and the non-shared
+ # elements are in the individual bundles.
+ ui_js = self._read_out_file('ui.rollup.js')
+ self.assertIn('yay', ui_js)
+ self.assertNotIn('hello from lazy_element', ui_js)
+ self.assertNotIn('hello from element_in_dir', ui_js)
+
+ lazy_js = self._read_out_file('lazy.rollup.js')
+ self.assertNotIn('yay', lazy_js)
+ self.assertIn('hello from lazy_element', lazy_js)
+ self.assertNotIn('hello from element_in_dir', lazy_js)
+
+ shared_js = self._read_out_file('shared.rollup.js')
+ self.assertNotIn('yay', shared_js)
+ self.assertNotIn('hello from lazy_element', shared_js)
+ self.assertIn('hello from element_in_dir', shared_js)
+
+ # All 3 JS files should be in the depfile.
+ self._check_output_depfile(False)
+ depfile_d = self._read_out_file('depfile.d')
+ self.assertIn('lazy_element.js', depfile_d)
+
if __name__ == '__main__':
unittest.main()
diff --git a/chromium/chrome/browser/resources/pdf/.eslintrc.js b/chromium/chrome/browser/resources/pdf/.eslintrc.js
new file mode 100644
index 00000000000..18f6e9550ca
--- /dev/null
+++ b/chromium/chrome/browser/resources/pdf/.eslintrc.js
@@ -0,0 +1,11 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/pdf/BUILD.gn b/chromium/chrome/browser/resources/pdf/BUILD.gn
index 0acf11807ff..f93045f59b9 100644
--- a/chromium/chrome/browser/resources/pdf/BUILD.gn
+++ b/chromium/chrome/browser/resources/pdf/BUILD.gn
@@ -18,25 +18,21 @@ js_library("annotation_tool") {
}
js_library("browser_api") {
- deps = [
- "//ui/webui/resources/js:assert.m",
- ]
+ deps = [ "//ui/webui/resources/js:assert.m" ]
externs_list = [
"$externs_path/chrome_extensions.js",
"$externs_path/mime_handler_private.js",
]
}
-js_library("pdf_fitting_type") {
+js_library("constants") {
}
js_library("gesture_detector") {
}
js_library("open_pdf_params_parser") {
- deps = [
- ":pdf_fitting_type",
- ]
+ deps = [ ":constants" ]
}
js_library("pdf_scripting_api") {
@@ -47,8 +43,8 @@ js_library("viewport_scroller") {
js_library("viewport") {
deps = [
+ ":constants",
":gesture_detector",
- ":pdf_fitting_type",
":zoom_manager",
"//ui/webui/resources/js:assert.m",
"//ui/webui/resources/js:event_tracker.m",
@@ -65,9 +61,7 @@ js_library("zoom_manager") {
}
js_library("metrics") {
- deps = [
- ":pdf_fitting_type",
- ]
+ deps = [ ":constants" ]
externs_list = [ "$externs_path/metrics_private.js" ]
}
@@ -101,6 +95,7 @@ js_library("controller") {
js_library("pdf_viewer") {
deps = [
+ ":constants",
":controller",
":metrics",
":navigator",
@@ -135,13 +130,13 @@ js_type_check("pdf_resources") {
deps = [
":annotation_tool",
":browser_api",
+ ":constants",
":controller",
":gesture_detector",
":main",
":metrics",
":navigator",
":open_pdf_params_parser",
- ":pdf_fitting_type",
":pdf_scripting_api",
":pdf_viewer",
":toolbar_manager",
diff --git a/chromium/chrome/browser/resources/pdf/browser_api.js b/chromium/chrome/browser/resources/pdf/browser_api.js
index 98b37391ed2..53ceeef1da9 100644
--- a/chromium/chrome/browser/resources/pdf/browser_api.js
+++ b/chromium/chrome/browser/resources/pdf/browser_api.js
@@ -97,7 +97,7 @@ export class BrowserApi {
*/
setZoom(zoom) {
assert(
- this.zoomBehavior_ == BrowserApi.ZoomBehavior.MANAGE,
+ this.zoomBehavior_ === BrowserApi.ZoomBehavior.MANAGE,
'Viewer does not manage browser zoom.');
return new Promise((resolve, reject) => {
chrome.tabs.setZoom(this.streamInfo_.tabId, zoom, resolve);
@@ -132,15 +132,15 @@ export class BrowserApi {
* factor.
*/
addZoomEventListener(listener) {
- if (!(this.zoomBehavior_ == BrowserApi.ZoomBehavior.MANAGE ||
- this.zoomBehavior_ == BrowserApi.ZoomBehavior.PROPAGATE_PARENT)) {
+ if (!(this.zoomBehavior_ === BrowserApi.ZoomBehavior.MANAGE ||
+ this.zoomBehavior_ === BrowserApi.ZoomBehavior.PROPAGATE_PARENT)) {
return;
}
chrome.tabs.onZoomChange.addListener(info => {
const zoomChangeInfo =
/** @type {{tabId: number, newZoomFactor: number}} */ (info);
- if (zoomChangeInfo.tabId != this.streamInfo_.tabId) {
+ if (zoomChangeInfo.tabId !== this.streamInfo_.tabId) {
return;
}
listener(zoomChangeInfo.newZoomFactor);
@@ -171,7 +171,7 @@ function createBrowserApiForMimeHandlerView() {
.then(function(streamInfo) {
const promises = [];
let zoomBehavior = BrowserApi.ZoomBehavior.NONE;
- if (streamInfo.tabId != -1) {
+ if (streamInfo.tabId !== -1) {
zoomBehavior = streamInfo.embedded ?
BrowserApi.ZoomBehavior.PROPAGATE_PARENT :
BrowserApi.ZoomBehavior.MANAGE;
@@ -183,7 +183,7 @@ function createBrowserApiForMimeHandlerView() {
}
}));
}
- if (zoomBehavior == BrowserApi.ZoomBehavior.MANAGE) {
+ if (zoomBehavior === BrowserApi.ZoomBehavior.MANAGE) {
promises.push(new Promise(function(resolve) {
chrome.tabs.setZoomSettings(
streamInfo.tabId, {mode: 'manual', scope: 'per-tab'}, resolve);
@@ -207,7 +207,7 @@ function createBrowserApiForPrintPreview() {
streamUrl: url,
originalUrl: url,
responseHeaders: {},
- embedded: window.parent != window,
+ embedded: window.parent !== window,
tabId: -1,
};
return new Promise(function(resolve, reject) {
diff --git a/chromium/chrome/browser/resources/pdf/pdf_fitting_type.js b/chromium/chrome/browser/resources/pdf/constants.js
index 7ff9bdb951b..70da3e827d7 100644
--- a/chromium/chrome/browser/resources/pdf/pdf_fitting_type.js
+++ b/chromium/chrome/browser/resources/pdf/constants.js
@@ -10,5 +10,14 @@ export const FittingType = {
NONE: 'none',
FIT_TO_PAGE: 'fit-to-page',
FIT_TO_WIDTH: 'fit-to-width',
- FIT_TO_HEIGHT: 'fit-to-height'
+ FIT_TO_HEIGHT: 'fit-to-height',
+};
+
+/**
+ * Enumeration of two up view actions.
+ * @enum {string}
+ */
+export const TwoUpViewAction = {
+ TWO_UP_VIEW_ENABLE: 'two-up-view-enable',
+ TWO_UP_VIEW_DISABLE: 'two-up-view-disable',
};
diff --git a/chromium/chrome/browser/resources/pdf/controller.js b/chromium/chrome/browser/resources/pdf/controller.js
index e607c688a85..9eccd835645 100644
--- a/chromium/chrome/browser/resources/pdf/controller.js
+++ b/chromium/chrome/browser/resources/pdf/controller.js
@@ -91,6 +91,9 @@ export class ContentController {
/** @abstract */
rotateCounterclockwise() {}
+ /** @abstract */
+ setTwoUpView(enableTwoUpView) {}
+
/** Triggers printing of the current document. */
print() {}
@@ -175,6 +178,11 @@ export class InkController extends ContentController {
}
/** @override */
+ setTwoUpView(enableTwoUpView) {
+ // TODO(dstockwell): Implement two up view.
+ }
+
+ /** @override */
viewportChanged() {
this.inkHost_.viewportChanged();
}
@@ -268,7 +276,7 @@ export class PluginController extends ContentController {
beforeZoom() {
this.postMessage_({type: 'stopScrolling'});
- if (this.viewport_.pinchPhase == Viewport.PinchPhase.PINCH_START) {
+ if (this.viewport_.pinchPhase === Viewport.PinchPhase.PINCH_START) {
const position = this.viewport_.position;
const zoom = this.viewport_.getZoom();
const pinchPhase = this.viewport_.pinchPhase;
@@ -334,6 +342,14 @@ export class PluginController extends ContentController {
}
/** @override */
+ setTwoUpView(enableTwoUpView) {
+ this.postMessage_({
+ type: 'setTwoUpView',
+ enableTwoUpView: enableTwoUpView,
+ });
+ }
+
+ /** @override */
print() {
this.postMessage_({type: 'print'});
}
@@ -492,7 +508,7 @@ export class PluginController extends ContentController {
`File too large to be saved: ${bufView.length} bytes.`);
assert(bufView.length >= MIN_FILE_SIZE);
assert(
- String.fromCharCode(bufView[0], bufView[1], bufView[2], bufView[3]) ==
+ String.fromCharCode(bufView[0], bufView[1], bufView[2], bufView[3]) ===
'%PDF');
resolver.resolve(messageData);
diff --git a/chromium/chrome/browser/resources/pdf/elements/BUILD.gn b/chromium/chrome/browser/resources/pdf/elements/BUILD.gn
index 1ffa8445e8e..923473079db 100644
--- a/chromium/chrome/browser/resources/pdf/elements/BUILD.gn
+++ b/chromium/chrome/browser/resources/pdf/elements/BUILD.gn
@@ -34,9 +34,7 @@ js_library("viewer-bookmark") {
}
js_library("viewer-error-screen") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
- ]
+ deps = [ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m" ]
}
if (is_chromeos) {
@@ -64,15 +62,11 @@ js_library("viewer-page-indicator") {
}
js_library("viewer-page-selector") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
- ]
+ deps = [ "//ui/webui/resources/cr_elements/cr_input:cr_input.m" ]
}
js_library("viewer-password-screen") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
- ]
+ deps = [ "//ui/webui/resources/cr_elements/cr_input:cr_input.m" ]
}
js_library("viewer-pdf-toolbar") {
@@ -95,7 +89,7 @@ js_library("viewer-toolbar-dropdown") {
js_library("viewer-zoom-toolbar") {
deps = [
":viewer-zoom-button",
- "..:pdf_fitting_type",
+ "..:constants",
"//ui/webui/resources/js:assert.m",
]
}
@@ -189,7 +183,7 @@ polymer_modulizer("icons") {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":icons_module",
":shared-vars_module",
":viewer-bookmark_module",
@@ -203,7 +197,7 @@ group("polymer3_elements") {
":viewer-zoom-toolbar_module",
]
if (is_chromeos) {
- deps += [
+ public_deps += [
":viewer-form-warning_module",
":viewer-ink-host_module",
":viewer-pen-options_module",
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.js b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.js
index fb9f73b7d1f..20363c71137 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-bookmark.js
@@ -74,25 +74,25 @@ Polymer({
keyBindings: {'enter': 'onEnter_', 'space': 'onSpace_'},
/** @override */
- attached: function() {
+ attached() {
this.keyEventTarget = this.$.item;
},
/** @private */
- bookmarkChanged_: function() {
+ bookmarkChanged_() {
this.$.expand.style.visibility =
this.bookmark.children.length > 0 ? 'visible' : 'hidden';
},
/** @private */
- depthChanged_: function() {
+ depthChanged_() {
this.childDepth_ = this.depth + 1;
this.$.item.style.paddingInlineStart =
(this.depth * BOOKMARK_INDENT) + 'px';
},
/** @private */
- onClick_: function() {
+ onClick_() {
if (this.bookmark.page != null) {
if (this.bookmark.zoom != null) {
this.fire('change-zoom', {zoom: this.bookmark.zoom});
@@ -118,10 +118,10 @@ Polymer({
* @param {!KeyboardEvent} e
* @private
*/
- onEnter_: function(e) {
+ onEnter_(e) {
// Don't allow events which have propagated up from the expand button to
// trigger a click.
- if (e.detail.keyboardEvent.target != this.$.expand) {
+ if (e.detail.keyboardEvent.target !== this.$.expand) {
this.onClick_();
}
},
@@ -130,7 +130,7 @@ Polymer({
* @param {!KeyboardEvent} e
* @private
*/
- onSpace_: function(e) {
+ onSpace_(e) {
// cr-icon-button stops propagation of space events, so there's no need
// to check the event source here.
this.onClick_();
@@ -142,7 +142,7 @@ Polymer({
* @param {!Event} e
* @private
*/
- toggleChildren_: function(e) {
+ toggleChildren_(e) {
this.childrenShown_ = !this.childrenShown_;
e.stopPropagation(); // Prevent the above onClick_ handler from firing.
}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js
index 7bb01225d8d..d3383b06e25 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-error-screen.js
@@ -19,11 +19,11 @@ Polymer({
strings: Object,
},
- show: function() {
+ show() {
/** @type {!CrDialogElement} */ (this.$.dialog).showModal();
},
- reload: function() {
+ reload() {
if (this.reloadFn) {
this.reloadFn();
}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js
index 5bd8f3c3692..d0cbd6d1de8 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-form-warning.js
@@ -21,18 +21,18 @@ Polymer({
/** @private {PromiseResolver} */
resolver_: null,
- show: function() {
+ show() {
this.resolver_ = new PromiseResolver();
/** @type {!CrDialogElement} */ (this.$.dialog).showModal();
return this.resolver_.promise;
},
- onCancel: function() {
+ onCancel() {
this.resolver_.reject();
this.$.dialog.cancel();
},
- onAction: function() {
+ onAction() {
this.resolver_.resolve();
this.$.dialog.close();
},
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js b/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js
index 1de273feb3e..fa208811e90 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-ink-host.js
@@ -84,14 +84,14 @@ Polymer({
/** @param {AnnotationTool} tool */
setAnnotationTool(tool) {
this.tool_ = tool;
- if (this.state_ == State.ACTIVE) {
+ if (this.state_ === State.ACTIVE) {
this.ink_.setAnnotationTool(tool);
}
},
/** @param {PointerEvent} e */
- isActivePointer_: function(e) {
- return this.activePointer_ && this.activePointer_.pointerId == e.pointerId;
+ isActivePointer_(e) {
+ return this.activePointer_ && this.activePointer_.pointerId === e.pointerId;
},
/**
@@ -99,7 +99,7 @@ Polymer({
*
* @param {PointerEvent} e
*/
- dispatchPointerEvent_: function(e) {
+ dispatchPointerEvent_(e) {
// TODO(dstockwell) come up with a solution to propagate e.timeStamp.
this.ink_.dispatchPointerEvent(e.type, {
pointerId: e.pointerId,
@@ -112,7 +112,7 @@ Polymer({
},
/** @param {TouchEvent} e */
- onTouchStart_: function(e) {
+ onTouchStart_(e) {
if (e.timeStamp !== this.allowTouchStartTimeStamp_) {
e.preventDefault();
}
@@ -120,18 +120,18 @@ Polymer({
},
/** @param {PointerEvent} e */
- onPointerDown_: function(e) {
- if (e.pointerType == 'mouse' && e.buttons != 1 || this.pointerGesture_) {
+ onPointerDown_(e) {
+ if (e.pointerType === 'mouse' && e.buttons !== 1 || this.pointerGesture_) {
return;
}
- if (e.pointerType == 'pen') {
+ if (e.pointerType === 'pen') {
this.penMode_ = true;
}
if (this.activePointer_) {
- if (this.activePointer_.pointerType == 'touch' &&
- e.pointerType == 'touch') {
+ if (this.activePointer_.pointerType === 'touch' &&
+ e.pointerType === 'touch') {
// A multi-touch gesture has started with the active pointer. Cancel
// the active pointer and suppress further events until it is released.
this.pointerGesture_ = true;
@@ -144,13 +144,13 @@ Polymer({
}
if (!this.viewport.isPointInsidePage({x: e.clientX, y: e.clientY}) &&
- (e.pointerType == 'touch' || e.pointerType == 'pen')) {
+ (e.pointerType === 'touch' || e.pointerType === 'pen')) {
// If a touch or pen is outside the page, we allow pan gestures to start.
this.allowTouchStartTimeStamp_ = e.timeStamp;
return;
}
- if (e.pointerType == 'touch' && this.penMode_) {
+ if (e.pointerType === 'touch' && this.penMode_) {
// If we see a touch after having seen a pen, we allow touches to start
// pan gestures anywhere and suppress all touches from drawing.
this.allowTouchStartTimeStamp_ = e.timeStamp;
@@ -162,37 +162,37 @@ Polymer({
},
/** @param {PointerEvent} e */
- onPointerLeave_: function(e) {
- if (e.pointerType != 'mouse' || !this.isActivePointer_(e)) {
+ onPointerLeave_(e) {
+ if (e.pointerType !== 'mouse' || !this.isActivePointer_(e)) {
return;
}
this.onPointerUpOrCancel_(new PointerEvent('pointerup', e));
},
/** @param {PointerEvent} e */
- onPointerUpOrCancel_: function(e) {
+ onPointerUpOrCancel_(e) {
if (!this.isActivePointer_(e)) {
return;
}
this.activePointer_ = null;
if (!this.pointerGesture_) {
this.dispatchPointerEvent_(e);
- // If the stroke was not cancelled (type == pointercanel),
+ // If the stroke was not cancelled (type === pointercanel),
// notify about mutation and record metrics.
- if (e.type == 'pointerup') {
+ if (e.type === 'pointerup') {
this.dispatchEvent(new CustomEvent('stroke-added'));
- if (e.pointerType == 'mouse') {
+ if (e.pointerType === 'mouse') {
PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_MOUSE);
- } else if (e.pointerType == 'pen') {
+ } else if (e.pointerType === 'pen') {
PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_PEN);
- } else if (e.pointerType == 'touch') {
+ } else if (e.pointerType === 'touch') {
PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_TOUCH);
}
- if (this.tool_.tool == 'eraser') {
+ if (this.tool_.tool === 'eraser') {
PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_ERASER);
- } else if (this.tool_.tool == 'pen') {
+ } else if (this.tool_.tool === 'pen') {
PDFMetrics.record(PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_PEN);
- } else if (this.tool_.tool == 'highlighter') {
+ } else if (this.tool_.tool === 'highlighter') {
PDFMetrics.record(
PDFMetrics.UserAction.ANNOTATE_STROKE_TOOL_HIGHLIGHTER);
}
@@ -202,13 +202,13 @@ Polymer({
},
/** @param {PointerEvent} e */
- onPointerMove_: function(e) {
+ onPointerMove_(e) {
if (!this.isActivePointer_(e) || this.pointerGesture_) {
return;
}
let events = e.getCoalescedEvents();
- if (events.length == 0) {
+ if (events.length === 0) {
events = [e];
}
for (const event of events) {
@@ -246,8 +246,8 @@ Polymer({
this.style.visibility = 'visible';
},
- viewportChanged: function() {
- if (this.state_ != State.ACTIVE) {
+ viewportChanged() {
+ if (this.state_ !== State.ACTIVE) {
return;
}
const viewport = this.viewport;
@@ -295,7 +295,7 @@ Polymer({
* The serialized PDF document including any annotations that were made.
*/
saveDocument: async function() {
- if (this.state_ == State.ACTIVE) {
+ if (this.state_ === State.ACTIVE) {
this.buffer_ = await this.ink_.getPDFDestructive().buffer;
this.state_ = State.IDLE;
}
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.js b/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.js
index 469ba84aeeb..5f901bb9db9 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-indicator.js
@@ -23,7 +23,7 @@ Polymer({
timerId: undefined,
/** @override */
- ready: function() {
+ ready() {
const callback = this.fadeIn_.bind(this);
window.addEventListener('scroll', function() {
requestAnimationFrame(callback);
@@ -31,7 +31,7 @@ Polymer({
},
/** @private */
- fadeIn_: function() {
+ fadeIn_() {
const percent = window.scrollY /
(document.scrollingElement.scrollHeight -
document.documentElement.clientHeight);
@@ -45,7 +45,7 @@ Polymer({
// those platforms, though.
assert(document.documentElement.dir);
const endEdge = isRTL() ? 'left' : 'right';
- if (window.innerWidth == document.scrollingElement.scrollWidth) {
+ if (window.innerWidth === document.scrollingElement.scrollWidth) {
this.style[endEdge] = '16px';
} else {
this.style[endEdge] = '0px';
@@ -60,11 +60,11 @@ Polymer({
}, 2000);
},
- pageLabelsChanged: function() {
+ pageLabelsChanged() {
this.indexChanged();
},
- indexChanged: function() {
+ indexChanged() {
if (this.pageLabels) {
this.label = this.pageLabels[this.index];
} else {
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js
index 035e5d8fa9b..5eda31ee514 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-page-selector.js
@@ -35,7 +35,7 @@ Polymer({
return /** @type {!CrInputElement} */ (this.$.pageselector);
},
- pageNoCommitted: function() {
+ pageNoCommitted() {
const page = parseInt(this.pageSelector.value, 10);
if (!isNaN(page) && page <= this.docLength && page > 0) {
@@ -47,27 +47,27 @@ Polymer({
},
/** @private */
- docLengthChanged_: function() {
+ docLengthChanged_() {
const numDigits = this.docLength.toString().length;
this.style.setProperty('--page-length-digits', `${numDigits}`);
},
- select: function() {
+ select() {
this.pageSelector.select();
},
/**
* @return {boolean} True if the selector input field is currently focused.
*/
- isActive: function() {
- return this.shadowRoot.activeElement == this.pageSelector;
+ isActive() {
+ return this.shadowRoot.activeElement === this.pageSelector;
},
/**
* Immediately remove any non-digit characters.
* @private
*/
- onInputValueChange_: function() {
+ onInputValueChange_() {
this.pageSelector.value = this.pageSelector.value.replace(/[^\d]/, '');
},
});
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js
index 96425280dac..79cd849c56b 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-password-screen.js
@@ -25,17 +25,17 @@ Polymer({
return this.$.dialog.open;
},
- show: function() {
+ show() {
this.$.dialog.showModal();
},
- close: function() {
+ close() {
if (this.active) {
this.$.dialog.close();
}
},
- deny: function() {
+ deny() {
const password = /** @type {!CrInputElement} */ (this.$.password);
password.disabled = false;
this.$.submit.disabled = false;
@@ -43,9 +43,9 @@ Polymer({
password.select();
},
- submit: function() {
+ submit() {
const password = /** @type {!CrInputElement} */ (this.$.password);
- if (password.value.length == 0) {
+ if (password.value.length === 0) {
return;
}
password.disabled = true;
@@ -60,7 +60,7 @@ Polymer({
* @param {string} message
* @return {string}
*/
- getErrorMessage_: function(message) {
+ getErrorMessage_(message) {
return this.invalid ? message : '';
}
});
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js
index 4f412de2b53..1a5af6551ab 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js
@@ -111,7 +111,7 @@ Polymer({
* @param {number} oldProgress
* @private
*/
- loadProgressChanged_: function(newProgress, oldProgress) {
+ loadProgressChanged_(newProgress, oldProgress) {
const loaded = newProgress >= 100;
const progressReset = newProgress < oldProgress;
if (progressReset || loaded) {
@@ -122,19 +122,19 @@ Polymer({
}
},
- hide: function() {
+ hide() {
if (this.opened && !this.shouldKeepOpen()) {
this.toggleVisibility();
}
},
- show: function() {
+ show() {
if (!this.opened) {
this.toggleVisibility();
}
},
- toggleVisibility: function() {
+ toggleVisibility() {
this.opened = !this.opened;
// We keep a handle on the animation in order to cancel the filling
@@ -160,18 +160,18 @@ Polymer({
}
},
- selectPageNumber: function() {
+ selectPageNumber() {
this.$.pageselector.select();
},
/** @return {boolean} Whether the toolbar should be kept open. */
- shouldKeepOpen: function() {
+ shouldKeepOpen() {
return this.$.bookmarks.dropdownOpen || this.loadProgress < 100 ||
this.$.pageselector.isActive() || this.annotationMode;
},
/** @return {boolean} Whether a dropdown was open and was hidden. */
- hideDropdowns: function() {
+ hideDropdowns() {
let result = false;
if (this.$.bookmarks.dropdownOpen) {
this.$.bookmarks.toggleDropdown();
@@ -189,31 +189,31 @@ Polymer({
},
/** @param {number} lowerBound */
- setDropdownLowerBound: function(lowerBound) {
+ setDropdownLowerBound(lowerBound) {
this.$.bookmarks.lowerBound = lowerBound;
},
- rotateRight: function() {
+ rotateRight() {
this.fire('rotate-right');
},
- download: function() {
+ download() {
this.fire('save');
},
- print: function() {
+ print() {
this.fire('print');
},
- undo: function() {
+ undo() {
this.fire('undo');
},
- redo: function() {
+ redo() {
this.fire('redo');
},
- toggleAnnotation: function() {
+ toggleAnnotation() {
this.annotationMode = !this.annotationMode;
if (this.annotationMode) {
// Select pen tool when entering annotation mode.
@@ -230,7 +230,7 @@ Polymer({
* @param {!Event} e
* @private
*/
- annotationToolClicked_: function(e) {
+ annotationToolClicked_(e) {
this.updateAnnotationTool_(/** @type {!HTMLElement} */ (e.currentTarget));
},
@@ -238,9 +238,9 @@ Polymer({
* @param {!Event} e
* @private
*/
- annotationToolOptionChanged_: function(e) {
+ annotationToolOptionChanged_(e) {
const element = e.currentTarget.parentElement;
- if (!this.annotationTool || element.id != this.annotationTool.tool) {
+ if (!this.annotationTool || element.id !== this.annotationTool.tool) {
return;
}
this.updateAnnotationTool_(e.currentTarget.parentElement);
@@ -250,7 +250,7 @@ Polymer({
* @param {!HTMLElement} element
* @private
*/
- updateAnnotationTool_: function(element) {
+ updateAnnotationTool_(element) {
const tool = element.id;
const options = element.querySelector('viewer-pen-options') || {
selectedSize: 1,
@@ -260,8 +260,8 @@ Polymer({
attributeStyleMap.set('--pen-tip-fill', options.selectedColor);
attributeStyleMap.set(
'--pen-tip-border',
- options.selectedColor == '#000000' ? 'currentcolor' :
- options.selectedColor);
+ options.selectedColor === '#000000' ? 'currentcolor' :
+ options.selectedColor);
this.annotationTool = {
tool: tool,
size: options.selectedSize,
@@ -274,7 +274,7 @@ Polymer({
* @return {boolean} Whether the annotation tool is using tool |toolName|.
* @private
*/
- isAnnotationTool_: function(toolName) {
+ isAnnotationTool_(toolName) {
return !!this.annotationTool && this.annotationTool.tool === toolName;
},
});
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js
index 134a0e8f771..0cc12c94384 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-pen-options.js
@@ -91,23 +91,23 @@ Polymer({
expandAnimations_: null,
/** @param {Event} e */
- sizeChanged_: function(e) {
+ sizeChanged_(e) {
this.selectedSize = Number(e.target.value);
},
/** @param {Event} e */
- colorChanged_: function(e) {
+ colorChanged_(e) {
this.selectedColor = e.target.value;
},
/** @private */
- toggleExpanded_: function() {
+ toggleExpanded_() {
this.expanded_ = !this.expanded_;
this.updateExpandedState_();
},
/** @private */
- updateExpandedStateAndFinishAnimations_: function() {
+ updateExpandedStateAndFinishAnimations_() {
this.updateExpandedState_();
for (const animation of /** @type {!Array<!Animation>} */ (
this.expandAnimations_)) {
@@ -116,7 +116,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
beforeNextRender(this, () => {
this.updateExpandedStateAndFinishAnimations_();
});
@@ -126,7 +126,7 @@ Polymer({
* Updates the state of the UI to reflect the current value of `expanded`.
* Starts or reverses animations and enables/disable controls.
*/
- updateExpandedState_: function() {
+ updateExpandedState_() {
const colors = this.$.colors;
if (!this.expandAnimations_) {
const separator = this.$.separator;
@@ -190,8 +190,8 @@ Polymer({
* @param {*} a
* @param {*} b
*/
- equal_: function(a, b) {
- return a == b;
+ equal_(a, b) {
+ return a === b;
},
/**
@@ -201,7 +201,7 @@ Polymer({
* @param {string} name
* @return {string}
*/
- lookup_: function(strings, name) {
+ lookup_(strings, name) {
return strings ? strings[name] : '';
},
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js
index 15c8b4e90af..d4ce32bd9b4 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-toolbar-dropdown.js
@@ -108,19 +108,19 @@ Polymer({
* @return {string} Current icon for the dropdown.
* @private
*/
- computeIcon_: function(dropdownOpen, closedIcon, openIcon) {
+ computeIcon_(dropdownOpen, closedIcon, openIcon) {
return dropdownOpen ? openIcon : closedIcon;
},
/** @private */
- lowerBoundChanged_: function() {
+ lowerBoundChanged_() {
this.maxHeightValid_ = false;
if (this.dropdownOpen) {
this.updateMaxHeight();
}
},
- toggleDropdown: function() {
+ toggleDropdown() {
if (!this.dropdownOpen && this.openAfterSelect && !this.selected) {
// The dropdown has `openAfterSelect` set, but is not yet selected.
return;
@@ -152,7 +152,7 @@ Polymer({
this.playAnimation_(this.dropdownOpen);
},
- updateMaxHeight: function() {
+ updateMaxHeight() {
const scrollContainer = this.$['scroll-container'];
let height = this.lowerBound - scrollContainer.getBoundingClientRect().top -
DROPDOWN_INNER_PADDING;
@@ -167,7 +167,7 @@ Polymer({
* exit.
* @private
*/
- playAnimation_: function(isEntry) {
+ playAnimation_(isEntry) {
this.animation_ = isEntry ? this.animateEntry_() : this.animateExit_();
this.animation_.onfinish = () => {
this.animation_ = null;
@@ -181,7 +181,7 @@ Polymer({
* @return {!Object} Animation
* @private
*/
- animateEntry_: function() {
+ animateEntry_() {
let maxHeight =
this.$.dropdown.getBoundingClientRect().height - DROPDOWN_OUTER_PADDING;
@@ -210,7 +210,7 @@ Polymer({
* @return {!Object} Animation
* @private
*/
- animateExit_: function() {
+ animateExit_() {
return this.$.dropdown.animate(
[
{transform: 'translateY(0)', opacity: 1},
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html
index 6eab6174020..f51075c5cab 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.html
@@ -77,6 +77,7 @@
</style>
<div id="wrapper">
<cr-icon-button iron-icon="[[visibleIcon_]]" on-click="fireClick_"
- aria-label$="[[visibleTooltip_]]" title="[[visibleTooltip_]]">
+ aria-label$="[[visibleTooltip_]]" title="[[visibleTooltip_]]"
+ disabled="[[disabled]]">
</cr-icon-button>
</div>
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.js b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.js
index 195bf25cc5a..3182b901947 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-button.js
@@ -25,6 +25,11 @@ Polymer({
observer: 'delayChanged_',
},
+ disabled: {
+ type: Boolean,
+ value: false,
+ },
+
/**
* Icons to be displayed on the FAB. Multiple icons should be separated with
* spaces, and will be cycled through every time the FAB is clicked.
@@ -83,7 +88,7 @@ Polymer({
* @return {!Array<string>} Array of icon name strings
* @private
*/
- computeIconsArray_: function(icons) {
+ computeIconsArray_(icons) {
return icons.split(' ');
},
@@ -93,7 +98,7 @@ Polymer({
* @return {string} Icon name for the currently visible icon.
* @private
*/
- computeVisibleIcon_: function(icons, activeIndex) {
+ computeVisibleIcon_(icons, activeIndex) {
return icons[activeIndex];
},
@@ -103,25 +108,25 @@ Polymer({
* @return {string} Tooltip for the currently visible icon.
* @private
*/
- computeVisibleTooltip_: function(tooltips, activeIndex) {
+ computeVisibleTooltip_(tooltips, activeIndex) {
return tooltips === undefined ? '' : tooltips[activeIndex];
},
/** @private */
- delayChanged_: function() {
+ delayChanged_() {
this.$.wrapper.style.transitionDelay = this.delay + 'ms';
},
- show: function() {
+ show() {
this.closed_ = false;
},
- hide: function() {
+ hide() {
this.closed_ = true;
},
/** @private */
- fireClick_: function() {
+ fireClick_() {
// We cannot attach an on-click to the entire viewer-zoom-button, as this
// will include clicks on the margins. Instead, proxy clicks on the FAB
// through.
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html
index 887999eaefa..ab6a4d461ca 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.html
@@ -1,4 +1,4 @@
- <style>
+ <style include="cr-hidden-style">
:host {
--button-position-offset: 48px;
bottom: 0;
@@ -44,21 +44,33 @@
display: block;
}
+ /*
+ * A larger gap between the fit button and the two-up view button
+ * and above the bottom two zoom buttons.
+ */
+ #two-up-view-button,
+ #zoom-in-button {
+ margin-top: 24px;
+ }
+
/* A small gap between the zoom in/zoom out buttons. */
#zoom-out-button {
margin-top: 10px;
}
-
- /* A larger gap between the fit button and bottom two buttons. */
- #zoom-in-button {
- margin-top: 24px;
- }
</style>
<div id="zoom-buttons">
- <viewer-zoom-button id="fit-button" on-fabclick="fitToggle" delay="100"
+ <viewer-zoom-button id="fit-button" on-fabclick="fitToggle"
+ delay="[[fitButtonDelay_]]"
keyboard-navigation-active="[[keyboardNavigationActive_]]"
icons="pdf:fullscreen-exit cr:fullscreen">
</viewer-zoom-button>
+ <!-- TODO(crbug.com/51472): Change icons for two-up-view-button -->
+ <!-- once they are finalized. -->
+ <viewer-zoom-button id="two-up-view-button" delay="100"
+ disabled="[[annotationMode]]" hidden$="[[!twoUpViewEnabled]]"
+ on-fabclick="twoUpViewToggle_"
+ keyboard-navigation-active="[[keyboardNavigationActive_]]"
+ icons="pdf:create pdf:eraser"></viewer-zoom-button>
<viewer-zoom-button id="zoom-in-button" icons="pdf:add"
keyboard-navigation-active="[[keyboardNavigationActive_]]"
on-fabclick="zoomIn" delay="50"></viewer-zoom-button>
diff --git a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js
index 03376cd29b4..ec5e991934f 100644
--- a/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js
+++ b/chromium/chrome/browser/resources/pdf/elements/viewer-zoom-toolbar.js
@@ -8,7 +8,7 @@ import './viewer-zoom-button.js';
import {assert} from 'chrome://resources/js/assert.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {FittingType} from '../pdf_fitting_type.js';
+import {FittingType, TwoUpViewAction} from '../constants.js';
/**
* @typedef {{
@@ -21,14 +21,31 @@ export let FitToChangedEvent;
const FIT_TO_PAGE_BUTTON_STATE = 0;
const FIT_TO_WIDTH_BUTTON_STATE = 1;
+const TWO_UP_VIEW_DISABLED_STATE = 0;
+const TWO_UP_VIEW_ENABLED_STATE = 1;
+
Polymer({
is: 'viewer-zoom-toolbar',
_template: html`{__html_template__}`,
properties: {
+ /** Whether the viewer is currently in annotation mode. */
+ annotationMode: {
+ type: Boolean,
+ value: false,
+ },
+
isPrintPreview: Boolean,
+ twoUpViewEnabled: Boolean,
+
+ /** @private */
+ fitButtonDelay_: {
+ type: Number,
+ computed: 'computeFitButtonDelay_(twoUpViewEnabled)',
+ },
+
/** @private */
keyboardNavigationActive_: {
type: Boolean,
@@ -36,6 +53,15 @@ Polymer({
},
},
+ /**
+ * @param {boolean} twoUpViewEnabled Whether two-up view button is enabled.
+ * @return {number} Delay for :qthe fit button.
+ * @private
+ */
+ computeFitButtonDelay_(twoUpViewEnabled) {
+ return twoUpViewEnabled ? 150 : 100;
+ },
+
listeners: {
'focus': 'onFocus_',
'keyup': 'onKeyUp_',
@@ -46,12 +72,12 @@ Polymer({
visible_: true,
/** @return {boolean} */
- isVisible: function() {
+ isVisible() {
return this.visible_;
},
/** @private */
- onFocus_: function() {
+ onFocus_() {
// This can only happen when the plugin is shown within Print Preview using
// keyboard navigation.
if (!this.visible_) {
@@ -62,7 +88,7 @@ Polymer({
},
/** @private */
- onKeyUp_: function() {
+ onKeyUp_() {
if (this.isPrintPreview) {
this.fire('keyboard-navigation-active', true);
}
@@ -70,7 +96,7 @@ Polymer({
},
/** @private */
- onPointerDown_: function() {
+ onPointerDown_() {
if (this.isPrintPreview) {
this.fire('keyboard-navigation-active', false);
}
@@ -81,33 +107,37 @@ Polymer({
* Change button tooltips to match any changes to localized strings.
* @param {!{tooltipFitToPage: string,
* tooltipFitToWidth: string,
+ * tooltipTwoUpViewEnable: string,
+ * tooltipTwoUpViewDisable: string,
* tooltipZoomIn: string,
* tooltipZoomOut: string}} strings
*/
- setStrings: function(strings) {
+ setStrings(strings) {
this.$['fit-button'].tooltips =
[strings.tooltipFitToPage, strings.tooltipFitToWidth];
+ this.$['two-up-view-button'].tooltips =
+ [strings.tooltipTwoUpViewEnable, strings.tooltipTwoUpViewDisable];
this.$['zoom-in-button'].tooltips = [strings.tooltipZoomIn];
this.$['zoom-out-button'].tooltips = [strings.tooltipZoomOut];
},
/** Handle clicks of the fit-button. */
- fitToggle: function() {
+ fitToggle() {
this.fireFitToChangedEvent_(
- this.$['fit-button'].activeIndex == FIT_TO_WIDTH_BUTTON_STATE ?
+ this.$['fit-button'].activeIndex === FIT_TO_WIDTH_BUTTON_STATE ?
FittingType.FIT_TO_WIDTH :
FittingType.FIT_TO_PAGE,
true);
},
/** Handle the keyboard shortcut equivalent of fit-button clicks. */
- fitToggleFromHotKey: function() {
+ fitToggleFromHotKey() {
this.fitToggle();
// Toggle the button state since there was no mouse click.
const button = this.$['fit-button'];
button.activeIndex =
- (button.activeIndex == FIT_TO_WIDTH_BUTTON_STATE ?
+ (button.activeIndex === FIT_TO_WIDTH_BUTTON_STATE ?
FIT_TO_PAGE_BUTTON_STATE :
FIT_TO_WIDTH_BUTTON_STATE);
},
@@ -116,13 +146,13 @@ Polymer({
* Handle forcing zoom via scripting to a fitting type.
* @param {!FittingType} fittingType Page fitting type to force.
*/
- forceFit: function(fittingType) {
+ forceFit(fittingType) {
this.fireFitToChangedEvent_(fittingType, false);
// Set the button state since there was no mouse click.
const nextButtonState =
- (fittingType == FittingType.FIT_TO_WIDTH ? FIT_TO_PAGE_BUTTON_STATE :
- FIT_TO_WIDTH_BUTTON_STATE);
+ (fittingType === FittingType.FIT_TO_WIDTH ? FIT_TO_PAGE_BUTTON_STATE :
+ FIT_TO_WIDTH_BUTTON_STATE);
this.$['fit-button'].activeIndex = nextButtonState;
},
@@ -133,39 +163,55 @@ Polymer({
* action.
* @private
*/
- fireFitToChangedEvent_: function(fittingType, userInitiated) {
+ fireFitToChangedEvent_(fittingType, userInitiated) {
this.fire(
'fit-to-changed',
{fittingType: fittingType, userInitiated: userInitiated});
},
/**
+ * Handle clicks of the two-up-view button.
+ * @private
+ */
+ twoUpViewToggle_: function() {
+ assert(this.twoUpViewEnabled);
+ const twoUpViewAction = this.$['two-up-view-button'].activeIndex ===
+ TWO_UP_VIEW_DISABLED_STATE ?
+ TwoUpViewAction.TWO_UP_VIEW_ENABLE :
+ TwoUpViewAction.TWO_UP_VIEW_DISABLE;
+
+ this.fire('two-up-view-changed', twoUpViewAction);
+ },
+
+ /**
* Handle clicks of the zoom-in-button.
*/
- zoomIn: function() {
+ zoomIn() {
this.fire('zoom-in');
},
/**
* Handle clicks of the zoom-out-button.
*/
- zoomOut: function() {
+ zoomOut() {
this.fire('zoom-out');
},
- show: function() {
+ show() {
if (!this.visible_) {
this.visible_ = true;
this.$['fit-button'].show();
+ this.$['two-up-view-button'].show();
this.$['zoom-in-button'].show();
this.$['zoom-out-button'].show();
}
},
- hide: function() {
+ hide() {
if (this.visible_) {
this.visible_ = false;
this.$['fit-button'].hide();
+ this.$['two-up-view-button'].hide();
this.$['zoom-in-button'].hide();
this.$['zoom-out-button'].hide();
}
diff --git a/chromium/chrome/browser/resources/pdf/gesture_detector.js b/chromium/chrome/browser/resources/pdf/gesture_detector.js
index f149d801910..e8a0db4e6a3 100644
--- a/chromium/chrome/browser/resources/pdf/gesture_detector.js
+++ b/chromium/chrome/browser/resources/pdf/gesture_detector.js
@@ -73,7 +73,7 @@ export class GestureDetector {
* @return {boolean} True if the last touch start was a two finger touch.
*/
wasTwoFingerTouch() {
- return this.lastTouchTouchesCount_ == 2;
+ return this.lastTouchTouchesCount_ === 2;
}
/**
diff --git a/chromium/chrome/browser/resources/pdf/index.html b/chromium/chrome/browser/resources/pdf/index.html
index 1af4cc2f119..59965552797 100644
--- a/chromium/chrome/browser/resources/pdf/index.html
+++ b/chromium/chrome/browser/resources/pdf/index.html
@@ -13,7 +13,7 @@
<div id="sizer"></div>
<viewer-password-screen id="password-screen"></viewer-password-screen>
-<viewer-zoom-toolbar id="zoom-toolbar"></viewer-zoom-toolbar>
+<viewer-zoom-toolbar id="zoom-toolbar" hidden></viewer-zoom-toolbar>
<viewer-page-indicator id="page-indicator"></viewer-page-indicator>
diff --git a/chromium/chrome/browser/resources/pdf/ink/BUILD.gn b/chromium/chrome/browser/resources/pdf/ink/BUILD.gn
index b1c2be215bd..ddf46dc4c31 100644
--- a/chromium/chrome/browser/resources/pdf/ink/BUILD.gn
+++ b/chromium/chrome/browser/resources/pdf/ink/BUILD.gn
@@ -5,15 +5,11 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":ink_api",
- ]
+ deps = [ ":ink_api" ]
}
js_library("ink_api") {
- deps = [
- "..:annotation_tool",
- ]
+ deps = [ "..:annotation_tool" ]
externs_list = [
"//third_party/ink/build/ink_lib_externs.js",
"$externs_path/pending.js",
diff --git a/chromium/chrome/browser/resources/pdf/ink/ink_api.js b/chromium/chrome/browser/resources/pdf/ink/ink_api.js
index 99eed15d900..c394b630077 100644
--- a/chromium/chrome/browser/resources/pdf/ink/ink_api.js
+++ b/chromium/chrome/browser/resources/pdf/ink/ink_api.js
@@ -78,7 +78,7 @@ class InkAPI {
highlighter: 'SMART_HIGHLIGHTER_TOOL',
}[tool.tool];
this.brush_.setShape(shape);
- if (tool.tool != 'eraser') {
+ if (tool.tool !== 'eraser') {
this.brush_.setColor(/** @type {string} */ (tool.color));
}
this.brush_.setStrokeWidth(tool.size);
diff --git a/chromium/chrome/browser/resources/pdf/metrics.js b/chromium/chrome/browser/resources/pdf/metrics.js
index dc7f62a6fb0..d1ca0a8270b 100644
--- a/chromium/chrome/browser/resources/pdf/metrics.js
+++ b/chromium/chrome/browser/resources/pdf/metrics.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import {FittingType} from './pdf_fitting_type.js';
+import {FittingType, TwoUpViewAction} from './constants.js';
/**
* Handles events specific to the PDF viewer and logs the corresponding metrics.
@@ -14,9 +14,9 @@ export class PDFMetrics {
* @param {FittingType} fittingType the new FittingType.
*/
static recordFitTo(fittingType) {
- if (fittingType == FittingType.FIT_TO_PAGE) {
+ if (fittingType === FittingType.FIT_TO_PAGE) {
PDFMetrics.record(PDFMetrics.UserAction.FIT_TO_PAGE);
- } else if (fittingType == FittingType.FIT_TO_WIDTH) {
+ } else if (fittingType === FittingType.FIT_TO_WIDTH) {
PDFMetrics.record(PDFMetrics.UserAction.FIT_TO_WIDTH);
}
// There is no user action to do a fit-to-height, this only happens with
@@ -24,6 +24,18 @@ export class PDFMetrics {
}
/**
+ * Records when the two up view mode is enabled or disabled.
+ *
+ * @param {TwoUpViewAction} twoUpViewAction the new TwoUpViewAction.
+ */
+ static recordTwoUpView(twoUpViewAction) {
+ PDFMetrics.record(
+ twoUpViewAction === TwoUpViewAction.TWO_UP_VIEW_ENABLE ?
+ PDFMetrics.UserAction.TWO_UP_VIEW_ENABLE :
+ PDFMetrics.UserAction.TWO_UP_VIEW_DISABLE);
+ }
+
+ /**
* Records the given action to chrome.metricsPrivate.
*
* @param {PDFMetrics.UserAction} action
@@ -149,7 +161,15 @@ PDFMetrics.UserAction = {
ANNOTATE_STROKE_DEVICE_PEN_FIRST: 33,
ANNOTATE_STROKE_DEVICE_PEN: 34,
- NUMBER_OF_ACTIONS: 35,
+ /** Recorded when two-up view mode is enabled. */
+ TWO_UP_VIEW_ENABLE_FIRST: 35,
+ TWO_UP_VIEW_ENABLE: 36,
+
+ /** Recorded when two-up view mode is disabled. */
+ TWO_UP_VIEW_DISABLE_FIRST: 37,
+ TWO_UP_VIEW_DISABLE: 38,
+
+ NUMBER_OF_ACTIONS: 39,
};
// Map from UserAction to the 'FIRST' action. These metrics are recorded
@@ -224,4 +244,12 @@ PDFMetrics.firstMap_ = new Map([
PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_PEN,
PDFMetrics.UserAction.ANNOTATE_STROKE_DEVICE_PEN_FIRST,
],
+ [
+ PDFMetrics.UserAction.TWO_UP_VIEW_ENABLE,
+ PDFMetrics.UserAction.TWO_UP_VIEW_ENABLE_FIRST,
+ ],
+ [
+ PDFMetrics.UserAction.TWO_UP_VIEW_DISABLE,
+ PDFMetrics.UserAction.TWO_UP_VIEW_DISABLE_FIRST,
+ ],
]);
diff --git a/chromium/chrome/browser/resources/pdf/navigator.js b/chromium/chrome/browser/resources/pdf/navigator.js
index df4762a46d0..e24d3e8ff02 100644
--- a/chromium/chrome/browser/resources/pdf/navigator.js
+++ b/chromium/chrome/browser/resources/pdf/navigator.js
@@ -26,7 +26,7 @@ export class NavigatorDelegate {
navigateInCurrentTab(url) {
// When the PDFviewer is inside a browser tab, prefer the tabs API because
// it can navigate from one file:// URL to another.
- if (chrome.tabs && this.tabId_ != -1) {
+ if (chrome.tabs && this.tabId_ !== -1) {
chrome.tabs.update(this.tabId_, {url: url});
} else {
window.location.href = url;
@@ -100,7 +100,7 @@ export class PdfNavigator {
* disposition when navigating to the new URL.
*/
navigate(urlString, disposition) {
- if (urlString.length == 0) {
+ if (urlString.length === 0) {
return;
}
@@ -169,7 +169,7 @@ export class PdfNavigator {
}
const pageNumber = viewportPosition.page;
- if (pageNumber != undefined && this.originalUrl_ && newUrl &&
+ if (pageNumber !== undefined && this.originalUrl_ && newUrl &&
this.originalUrl_.origin === newUrl.origin &&
this.originalUrl_.pathname === newUrl.pathname) {
this.viewport_.goToPage(pageNumber);
@@ -236,7 +236,7 @@ export class PdfNavigator {
}
if (!url.startsWith('.')) {
const domainSeparatorIndex = url.indexOf('/');
- const domainName = domainSeparatorIndex == -1 ?
+ const domainName = domainSeparatorIndex === -1 ?
url :
url.substr(0, domainSeparatorIndex);
const domainDotCount = (domainName.match(/\./g) || []).length;
diff --git a/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js b/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js
index 941d9a3fe4e..08ef73a94db 100644
--- a/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js
+++ b/chromium/chrome/browser/resources/pdf/open_pdf_params_parser.js
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-import {FittingType} from './pdf_fitting_type.js';
+import {FittingType} from './constants.js';
/**
* Parses the open pdf parameters passed in the url to set initial viewport
@@ -31,7 +31,7 @@ export class OpenPdfParamsParser {
*/
parseZoomParam_(paramValue) {
const paramValueSplit = paramValue.split(',');
- if (paramValueSplit.length != 1 && paramValueSplit.length != 3) {
+ if (paramValueSplit.length !== 1 && paramValueSplit.length !== 3) {
return {};
}
@@ -42,7 +42,7 @@ export class OpenPdfParamsParser {
}
// Handle #zoom=scale.
- if (paramValueSplit.length == 1) {
+ if (paramValueSplit.length === 1) {
return {'zoom': zoomFactor};
}
@@ -105,12 +105,12 @@ export class OpenPdfParamsParser {
const params = {};
const paramIndex = url.search('#');
- if (paramIndex == -1) {
+ if (paramIndex === -1) {
return params;
}
const paramTokens = url.substring(paramIndex + 1).split('&');
- if ((paramTokens.length == 1) && (paramTokens[0].search('=') == -1)) {
+ if ((paramTokens.length === 1) && (paramTokens[0].search('=') === -1)) {
// Handle the case of http://foo.com/bar#NAMEDDEST. This is not
// explicitly mentioned except by example in the Adobe
// "PDF Open Parameters" document.
@@ -120,7 +120,7 @@ export class OpenPdfParamsParser {
for (const paramToken of paramTokens) {
const keyValueSplit = paramToken.split('=');
- if (keyValueSplit.length != 2) {
+ if (keyValueSplit.length !== 2) {
continue;
}
params[keyValueSplit[0]] = keyValueSplit[1];
@@ -141,7 +141,7 @@ export class OpenPdfParamsParser {
const params = this.parseUrlParams_(url);
const uiParams = {toolbar: true};
- if ('toolbar' in params && params['toolbar'] == 0) {
+ if ('toolbar' in params && params['toolbar'] === '0') {
uiParams.toolbar = false;
}
@@ -196,7 +196,7 @@ export class OpenPdfParamsParser {
*/
onNamedDestinationReceived(pageNumber) {
const outstandingRequest = this.outstandingRequests_.shift();
- if (pageNumber != -1) {
+ if (pageNumber !== -1) {
outstandingRequest.params.page = pageNumber;
}
outstandingRequest.callback(outstandingRequest.params);
diff --git a/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js b/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js
index e69dd69ee17..8cae862e05d 100644
--- a/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js
+++ b/chromium/chrome/browser/resources/pdf/pdf_scripting_api.js
@@ -68,7 +68,7 @@ export class PDFScriptingAPI {
this.viewportChangedCallback_;
/** @private {Function} */
- this.loadCallback_;
+ this.loadCompleteCallback_;
/** @private {Function} */
this.selectedTextCallback_;
@@ -80,9 +80,9 @@ export class PDFScriptingAPI {
this.plugin_;
window.addEventListener('message', event => {
- if (event.origin !=
+ if (event.origin !==
'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai' &&
- event.origin != 'chrome://print') {
+ event.origin !== 'chrome://print') {
console.error(
'Received message that was not from the extension: ' + event);
return;
@@ -108,8 +108,8 @@ export class PDFScriptingAPI {
case 'documentLoaded': {
const data = /** @type {{load_state: LoadState}} */ (event.data);
this.loadState_ = data.load_state;
- if (this.loadCallback_) {
- this.loadCallback_(this.loadState_ == LoadState.SUCCESS);
+ if (this.loadCompleteCallback_) {
+ this.loadCompleteCallback_(this.loadState_ === LoadState.SUCCESS);
}
break;
}
@@ -181,10 +181,10 @@ export class PDFScriptingAPI {
*
* @param {Function} callback the callback to be called.
*/
- setLoadCallback(callback) {
- this.loadCallback_ = callback;
- if (this.loadState_ != LoadState.LOADING && this.loadCallback_) {
- this.loadCallback_(this.loadState_ == LoadState.SUCCESS);
+ setLoadCompleteCallback(callback) {
+ this.loadCompleteCallback_ = callback;
+ if (this.loadState_ !== LoadState.LOADING && this.loadCompleteCallback_) {
+ this.loadCompleteCallback_(this.loadState_ === LoadState.SUCCESS);
}
}
@@ -309,15 +309,15 @@ export function PDFCreateOutOfProcessPlugin(src, baseUrl) {
};
// Add the functions to the iframe so that they can be called directly.
- iframe.setViewportChangedCallback =
- client.setViewportChangedCallback.bind(client);
- iframe.setLoadCallback = client.setLoadCallback.bind(client);
- iframe.setKeyEventCallback = client.setKeyEventCallback.bind(client);
- iframe.resetPrintPreviewMode = client.resetPrintPreviewMode.bind(client);
+ iframe.darkModeChanged = client.darkModeChanged.bind(client);
+ iframe.hideToolbars = client.hideToolbars.bind(client);
iframe.loadPreviewPage = client.loadPreviewPage.bind(client);
- iframe.sendKeyEvent = client.sendKeyEvent.bind(client);
+ iframe.resetPrintPreviewMode = client.resetPrintPreviewMode.bind(client);
iframe.scrollPosition = client.scrollPosition.bind(client);
- iframe.hideToolbars = client.hideToolbars.bind(client);
- iframe.darkModeChanged = client.darkModeChanged.bind(client);
+ iframe.sendKeyEvent = client.sendKeyEvent.bind(client);
+ iframe.setKeyEventCallback = client.setKeyEventCallback.bind(client);
+ iframe.setLoadCompleteCallback = client.setLoadCompleteCallback.bind(client);
+ iframe.setViewportChangedCallback =
+ client.setViewportChangedCallback.bind(client);
return iframe;
}
diff --git a/chromium/chrome/browser/resources/pdf/pdf_viewer.js b/chromium/chrome/browser/resources/pdf/pdf_viewer.js
index d356d123d87..296c0fc0cce 100644
--- a/chromium/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chromium/chrome/browser/resources/pdf/pdf_viewer.js
@@ -9,6 +9,7 @@ import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
import {$, hasKeyModifiers, isRTL} from 'chrome://resources/js/util.m.js';
import {BrowserApi} from './browser_api.js';
+import {FittingType, TwoUpViewAction} from './constants.js';
import {ContentController, InkController, MessageData, PluginController, PrintPreviewParams} from './controller.js';
import {Bookmark} from './elements/viewer-bookmark.js';
import {FitToChangedEvent} from './elements/viewer-zoom-toolbar.js';
@@ -16,7 +17,6 @@ import {GestureDetector} from './gesture_detector.js';
import {PDFMetrics} from './metrics.js';
import {NavigatorDelegate, PdfNavigator} from './navigator.js';
import {OpenPdfParamsParser} from './open_pdf_params_parser.js';
-import {FittingType} from './pdf_fitting_type.js';
import {DeserializeKeyEvent, LoadState, SerializeKeyEvent} from './pdf_scripting_api.js';
import {ToolbarManager} from './toolbar_manager.js';
import {LayoutOptions, Point, Viewport} from './viewport.js';
@@ -130,8 +130,8 @@ export function shouldIgnoreKeyEvents(activeElement) {
return (
activeElement.isContentEditable ||
- (activeElement.tagName == 'INPUT' && activeElement.type != 'radio') ||
- activeElement.tagName == 'TEXTAREA');
+ (activeElement.tagName === 'INPUT' && activeElement.type !== 'radio') ||
+ activeElement.tagName === 'TEXTAREA');
}
/**
@@ -231,7 +231,7 @@ export class PDFViewer {
this.errorScreen_ =
/** @type {!ViewerErrorScreenElement} */ ($('error-screen'));
// Can only reload if we are in a normal tab.
- if (chrome.tabs && this.browserApi_.getStreamInfo().tabId != -1) {
+ if (chrome.tabs && this.browserApi_.getStreamInfo().tabId !== -1) {
this.errorScreen_.reloadFn = () => {
chrome.tabs.reload(this.browserApi_.getStreamInfo().tabId);
};
@@ -243,7 +243,7 @@ export class PDFViewer {
const topToolbarHeight =
(toolbarEnabled) ? PDFViewer.MATERIAL_TOOLBAR_HEIGHT : 0;
const defaultZoom =
- this.browserApi_.getZoomBehavior() == BrowserApi.ZoomBehavior.MANAGE ?
+ this.browserApi_.getZoomBehavior() === BrowserApi.ZoomBehavior.MANAGE ?
this.browserApi_.getDefaultZoom() :
1.0;
@@ -334,6 +334,10 @@ export class PDFViewer {
e => this.fitToChanged_(
/** @type {!CustomEvent<FitToChangedEvent>} */ (e)));
this.zoomToolbar_.addEventListener(
+ 'two-up-view-changed',
+ e => this.twoUpViewChanged_(
+ /** @type {!CustomEvent<!TwoUpViewAction>} */ (e)));
+ this.zoomToolbar_.addEventListener(
'zoom-in', () => this.viewport_.zoomIn());
this.zoomToolbar_.addEventListener(
'zoom-out', () => this.viewport_.zoomOut());
@@ -374,9 +378,9 @@ export class PDFViewer {
document.body.addEventListener('change-page', e => {
this.viewport_.goToPage(e.detail.page);
- if (e.detail.origin == 'bookmark') {
+ if (e.detail.origin === 'bookmark') {
PDFMetrics.record(PDFMetrics.UserAction.FOLLOW_BOOKMARK);
- } else if (e.detail.origin == 'pageselector') {
+ } else if (e.detail.origin === 'pageselector') {
PDFMetrics.record(PDFMetrics.UserAction.PAGE_SELECTOR_NAVIGATE);
}
});
@@ -398,7 +402,7 @@ export class PDFViewer {
});
document.body.addEventListener('dropdown-opened', e => {
- if (e.detail == 'bookmarks') {
+ if (e.detail === 'bookmarks') {
PDFMetrics.record(PDFMetrics.UserAction.OPEN_BOOKMARKS_PANEL);
}
});
@@ -610,9 +614,9 @@ export class PDFViewer {
}
handleMouseEvent_(e) {
- if (e.type == 'mousemove') {
+ if (e.type === 'mousemove') {
this.toolbarManager_.handleMouseMove(e);
- } else if (e.type == 'mouseout') {
+ } else if (e.type === 'mouseout') {
this.toolbarManager_.hideToolbarsForMouseOut();
}
}
@@ -641,9 +645,10 @@ export class PDFViewer {
*/
async annotationModeToggled_(e) {
const annotationMode = e.detail.value;
+ this.zoomToolbar_.annotationMode = annotationMode;
if (annotationMode) {
// Enter annotation mode.
- assert(this.currentController_ == this.pluginController_);
+ assert(this.currentController_ === this.pluginController_);
// TODO(dstockwell): set plugin read-only, begin transition
this.updateProgress_(0);
// TODO(dstockwell): handle save failure
@@ -657,6 +662,7 @@ export class PDFViewer {
} catch (e) {
// The user aborted entering annotation mode. Revert to the plugin.
this.toolbar_.annotationMode = false;
+ this.zoomToolbar_.annotationMode = false;
this.updateProgress_(100);
return;
}
@@ -674,7 +680,7 @@ export class PDFViewer {
} else {
// Exit annotation mode.
PDFMetrics.record(PDFMetrics.UserAction.EXIT_ANNOTATION_MODE);
- assert(this.currentController_ == this.inkController_);
+ assert(this.currentController_ === this.inkController_);
// TODO(dstockwell): set ink read-only, begin transition
this.updateProgress_(0);
// This runs separately to allow other consumers of `loaded` to queue
@@ -702,6 +708,7 @@ export class PDFViewer {
return;
}
this.toolbar_.toggleAnnotation();
+ this.zoomToolbar_.annotationMode = false;
await this.loaded;
}
@@ -711,12 +718,12 @@ export class PDFViewer {
* @private
*/
fitToChanged_(e) {
- if (e.detail.fittingType == FittingType.FIT_TO_PAGE) {
+ if (e.detail.fittingType === FittingType.FIT_TO_PAGE) {
this.viewport_.fitToPage();
this.toolbarManager_.forceHideTopToolbar();
- } else if (e.detail.fittingType == FittingType.FIT_TO_WIDTH) {
+ } else if (e.detail.fittingType === FittingType.FIT_TO_WIDTH) {
this.viewport_.fitToWidth();
- } else if (e.detail.fittingType == FittingType.FIT_TO_HEIGHT) {
+ } else if (e.detail.fittingType === FittingType.FIT_TO_HEIGHT) {
this.viewport_.fitToHeight();
this.toolbarManager_.forceHideTopToolbar();
}
@@ -727,12 +734,28 @@ export class PDFViewer {
}
/**
+ * Changes two up view mode for the controller. Controller will trigger
+ * layout update later, which will update the viewport accordingly.
+ * @param {!CustomEvent<!TwoUpViewAction>} e
+ * @private
+ */
+ twoUpViewChanged_(e) {
+ this.currentController_.setTwoUpView(
+ e.detail === TwoUpViewAction.TWO_UP_VIEW_ENABLE);
+ this.toolbarManager_.forceHideTopToolbar();
+ this.toolbar_.annotationAvailable =
+ (e.detail !== TwoUpViewAction.TWO_UP_VIEW_ENABLE);
+
+ PDFMetrics.recordTwoUpView(e.detail);
+ }
+
+ /**
* Sends a 'documentLoaded' message to the PDFScriptingAPI if the document has
* finished loading.
* @private
*/
sendDocumentLoadedMessage_() {
- if (this.loadState_ == LoadState.LOADING) {
+ if (this.loadState_ === LoadState.LOADING) {
return;
}
if (this.isPrintPreview_ && !this.isPrintPreviewLoadingFinished_) {
@@ -768,9 +791,9 @@ export class PDFViewer {
const zoomedPositionShift =
params.viewPosition * this.viewport_.getZoom();
const currentViewportPosition = this.viewport_.position;
- if (params.view == FittingType.FIT_TO_WIDTH) {
+ if (params.view === FittingType.FIT_TO_WIDTH) {
currentViewportPosition.y += zoomedPositionShift;
- } else if (params.view == FittingType.FIT_TO_HEIGHT) {
+ } else if (params.view === FittingType.FIT_TO_HEIGHT) {
currentViewportPosition.x += zoomedPositionShift;
}
this.viewport_.position = currentViewportPosition;
@@ -790,7 +813,7 @@ export class PDFViewer {
*/
goToPageAndXY_(origin, page, message) {
this.viewport_.goToPageAndXY(page, message.x, message.y);
- if (origin == 'bookmark') {
+ if (origin === 'bookmark') {
PDFMetrics.record(PDFMetrics.UserAction.FOLLOW_BOOKMARK);
}
}
@@ -821,19 +844,20 @@ export class PDFViewer {
* @private
*/
setLoadState_(loadState) {
- if (this.loadState_ == loadState) {
+ if (this.loadState_ === loadState) {
return;
}
assert(
- loadState == LoadState.LOADING || this.loadState_ == LoadState.LOADING);
+ loadState === LoadState.LOADING ||
+ this.loadState_ === LoadState.LOADING);
this.loadState_ = loadState;
if (!this.initialLoadComplete_) {
this.initialLoadComplete_ = true;
return;
}
- if (loadState == LoadState.SUCCESS) {
+ if (loadState === LoadState.SUCCESS) {
this.loaded_.resolve();
- } else if (loadState == LoadState.FAILED) {
+ } else if (loadState === LoadState.FAILED) {
this.loaded_.reject();
} else {
this.loaded_ = new PromiseResolver();
@@ -851,7 +875,7 @@ export class PDFViewer {
this.toolbar_.loadProgress = progress;
}
- if (progress == -1) {
+ if (progress === -1) {
// Document load failed.
this.errorScreen_.show();
this.sizer_.style.display = 'none';
@@ -862,7 +886,7 @@ export class PDFViewer {
this.setLoadState_(LoadState.FAILED);
this.isPrintPreviewLoadingFinished_ = true;
this.sendDocumentLoadedMessage_();
- } else if (progress == 100) {
+ } else if (progress === 100) {
// Document load complete.
if (this.lastViewportPosition_) {
this.viewport_.position = this.lastViewportPosition_;
@@ -901,6 +925,13 @@ export class PDFViewer {
document.documentElement.lang = stringsDictionary.language;
loadTimeData.data = strings;
+
+ // Predefined zoom factors to be used when zooming in/out. These are in
+ // ascending order.
+ const presetZoomFactors = /** @type {!Array<number>} */ (
+ JSON.parse(loadTimeData.getString('presetZoomFactors')));
+ this.viewport_.setZoomFactorRange(presetZoomFactors);
+
if (this.isPrintPreview_) {
this.sendBackgroundColorForPrintPreview_();
}
@@ -910,6 +941,11 @@ export class PDFViewer {
loadTimeData.getBoolean('pdfAnnotationsEnabled');
$('toolbar').printingEnabled = loadTimeData.getBoolean('printingEnabled');
$('zoom-toolbar').setStrings(strings);
+ $('zoom-toolbar').twoUpViewEnabled =
+ loadTimeData.getBoolean('pdfTwoUpViewEnabled') && !this.isPrintPreview_;
+ // Display the zoom toolbar after the UI text direction is set, to ensure it
+ // appears on the correct side of the PDF viewer.
+ $('zoom-toolbar').hidden = false;
$('password-screen').strings = strings;
$('error-screen').strings = strings;
if ($('form-warning')) {
@@ -933,7 +969,7 @@ export class PDFViewer {
* @private
*/
setUserInitiated_(userInitiated) {
- assert(this.isUserInitiatedEvent_ != userInitiated);
+ assert(this.isUserInitiatedEvent_ !== userInitiated);
this.isUserInitiatedEvent_ = userInitiated;
}
@@ -1053,11 +1089,11 @@ export class PDFViewer {
* @param {!MessageObject} message The message to handle.
*/
handleScriptingMessage(message) {
- if (this.parentWindow_ != message.source) {
+ if (this.parentWindow_ !== message.source) {
this.parentWindow_ = message.source;
this.parentOrigin_ = message.origin;
// Ensure that we notify the embedder if the document is loaded.
- if (this.loadState_ != LoadState.LOADING) {
+ if (this.loadState_ !== LoadState.LOADING) {
this.sendDocumentLoadedMessage_();
}
}
@@ -1068,7 +1104,7 @@ export class PDFViewer {
// Delay scripting messages from users of the scripting API until the
// document is loaded. This simplifies use of the APIs.
- if (this.loadState_ != LoadState.SUCCESS) {
+ if (this.loadState_ !== LoadState.SUCCESS) {
this.delayedScriptingMessages_.push(message);
return;
}
@@ -1171,9 +1207,9 @@ export class PDFViewer {
// unless we're sending it to ourselves (which could happen in the case
// of tests). We also allow documentLoaded messages through as this won't
// leak important information.
- if (this.parentOrigin_ == window.location.origin) {
+ if (this.parentOrigin_ === window.location.origin) {
targetOrigin = this.parentOrigin_;
- } else if (message.type == 'documentLoaded') {
+ } else if (message.type === 'documentLoaded') {
targetOrigin = '*';
} else {
targetOrigin = this.originalUrl_;
@@ -1390,7 +1426,7 @@ export class PDFViewer {
* @private
*/
async onSave_(streamUrl) {
- if (streamUrl != this.browserApi_.getStreamInfo().streamUrl) {
+ if (streamUrl !== this.browserApi_.getStreamInfo().streamUrl) {
return;
}
@@ -1426,7 +1462,7 @@ export class PDFViewer {
chrome.fileSystem.chooseEntry(
{type: 'saveFile', suggestedName: fileName}, entry => {
if (chrome.runtime.lastError) {
- if (chrome.runtime.lastError.message != 'User cancelled') {
+ if (chrome.runtime.lastError.message !== 'User cancelled') {
console.log(
'chrome.fileSystem.chooseEntry failed: ' +
chrome.runtime.lastError.message);
@@ -1463,7 +1499,7 @@ export class PDFViewer {
return;
}
let annotationAvailable = true;
- if (this.viewport_.getClockwiseRotations() != 0) {
+ if (this.viewport_.getClockwiseRotations() !== 0) {
annotationAvailable = false;
}
if (this.hadPassword_) {
diff --git a/chromium/chrome/browser/resources/pdf/toolbar_manager.js b/chromium/chrome/browser/resources/pdf/toolbar_manager.js
index f5ce74235d4..847b21172fc 100644
--- a/chromium/chrome/browser/resources/pdf/toolbar_manager.js
+++ b/chromium/chrome/browser/resources/pdf/toolbar_manager.js
@@ -144,7 +144,7 @@ export class ToolbarManager {
* @private
*/
isHighVelocityMouseMove_(e) {
- if (e.type == 'mousemove') {
+ if (e.type === 'mousemove') {
if (this.lastMovementTimestamp == null) {
this.lastMovementTimestamp = this.getCurrentTimestamp_();
} else {
@@ -154,7 +154,7 @@ export class ToolbarManager {
const interval = newTime - this.lastMovementTimestamp;
this.lastMovementTimestamp = newTime;
- if (interval != 0) {
+ if (interval !== 0) {
return movement / interval > SHOW_VELOCITY;
}
}
@@ -219,8 +219,8 @@ export class ToolbarManager {
// Remove focus to make any visible tooltips disappear -- otherwise they'll
// still be visible on screen when the toolbar is off screen.
- if ((this.toolbar_ && document.activeElement == this.toolbar_) ||
- document.activeElement == this.zoomToolbar_) {
+ if ((this.toolbar_ && document.activeElement === this.toolbar_) ||
+ document.activeElement === this.zoomToolbar_) {
document.activeElement.blur();
}
diff --git a/chromium/chrome/browser/resources/pdf/viewport.js b/chromium/chrome/browser/resources/pdf/viewport.js
index 3034d9eecab..37967176729 100644
--- a/chromium/chrome/browser/resources/pdf/viewport.js
+++ b/chromium/chrome/browser/resources/pdf/viewport.js
@@ -6,7 +6,7 @@ import {assert} from 'chrome://resources/js/assert.m.js';
import {EventTracker} from 'chrome://resources/js/event_tracker.m.js';
import {$} from 'chrome://resources/js/util.m.js';
-import {FittingType} from './pdf_fitting_type.js';
+import {FittingType} from './constants.js';
import {InactiveZoomManager, ZoomManager} from './zoom_manager.js';
/**
@@ -19,7 +19,12 @@ import {InactiveZoomManager, ZoomManager} from './zoom_manager.js';
*/
let DocumentDimensions;
-/** @typedef {{defaultPageOrientation: number}} */
+/**
+ * @typedef {{
+ * defaultPageOrientation: number,
+ * twoUpViewEnabled: boolean,
+ * }}
+ */
export let LayoutOptions;
/** @typedef {{x: number, y: number}} */
@@ -35,17 +40,6 @@ let Size;
let ViewportRect;
/**
- * Clamps the zoom factor (or page scale factor) to be within the limits.
- * @param {number} factor The zoom/scale factor.
- * @return {number} The factor clamped within the limits.
- */
-function clampZoom(factor) {
- return Math.max(
- Viewport.ZOOM_FACTOR_RANGE.min,
- Math.min(factor, Viewport.ZOOM_FACTOR_RANGE.max));
-}
-
-/**
* @param {!ViewportRect} rect1
* @param {!ViewportRect} rect2
* @return {number} The area of the intersection of the rects
@@ -128,6 +122,13 @@ export class Viewport {
/** @private {number} */
this.internalZoom_ = 1;
+ /**
+ * Predefined zoom factors to be used when zooming in/out. These are in
+ * ascending order.
+ * @private {!Array<number>}
+ */
+ this.presetZoomFactors_ = [];
+
/** @private {?ZoomManager} */
this.zoomManager_ = null;
@@ -140,12 +141,6 @@ export class Viewport {
/** @private {!FittingType} */
this.fittingType_ = FittingType.NONE;
- /**
- * |twoUpView_| should be in sync with |two_up_view_| in PDFiumEngine.
- * @private {boolean}
- */
- this.twoUpView_ = false;
-
/** @private {number} */
this.prevScale_ = 1;
@@ -224,9 +219,35 @@ export class Viewport {
return this.rotations_;
}
- /** @param {boolean} twoUpView The new two up view state to set. */
- setTwoUpView(twoUpView) {
- this.twoUpView_ = twoUpView;
+ /** @return {boolean} Whether viewport is in two-up view mode. */
+ twoUpViewEnabled() {
+ const options = this.getLayoutOptions();
+ if (options === undefined) {
+ return false;
+ }
+ return options.twoUpViewEnabled;
+ }
+
+ /**
+ * Clamps the zoom factor (or page scale factor) to be within the limits.
+ * @param {number} factor The zoom/scale factor.
+ * @return {number} The factor clamped within the limits.
+ * @private
+ */
+ clampZoom_(factor) {
+ return Math.max(
+ this.presetZoomFactors_[0],
+ Math.min(
+ factor,
+ this.presetZoomFactors_[this.presetZoomFactors_.length - 1]));
+ }
+
+ /**
+ * @param {!Array<number>} factors Array containing zoom/scale factors.
+ */
+ setZoomFactorRange(factors) {
+ assert(factors.length !== 0);
+ this.presetZoomFactors_ = factors;
}
/**
@@ -247,11 +268,11 @@ export class Viewport {
const rotation = this.rotations_ * 90;
// Set origin for rotation.
- if (rotation == 90) {
+ if (rotation === 90) {
matrix.translateSelf(width, 0);
- } else if (rotation == 180) {
+ } else if (rotation === 180) {
matrix.translateSelf(width, height);
- } else if (rotation == 270) {
+ } else if (rotation === 270) {
matrix.translateSelf(0, height);
}
matrix.rotateSelf(0, 0, rotation);
@@ -395,13 +416,13 @@ export class Viewport {
* @private
*/
resize_() {
- if (this.fittingType_ == FittingType.FIT_TO_PAGE) {
+ if (this.fittingType_ === FittingType.FIT_TO_PAGE) {
this.fitToPageInternal_(false);
- } else if (this.fittingType_ == FittingType.FIT_TO_WIDTH) {
+ } else if (this.fittingType_ === FittingType.FIT_TO_WIDTH) {
this.fitToWidth();
- } else if (this.fittingType_ == FittingType.FIT_TO_HEIGHT) {
+ } else if (this.fittingType_ === FittingType.FIT_TO_HEIGHT) {
this.fitToHeightInternal_(false);
- } else if (this.internalZoom_ == 0) {
+ } else if (this.internalZoom_ === 0) {
this.fitToNone();
} else {
this.updateViewport_();
@@ -532,7 +553,7 @@ export class Viewport {
this.allowedToChangeZoom_,
'Called Viewport.setPinchZoomInternal_ without calling ' +
'Viewport.mightZoom_.');
- this.internalZoom_ = clampZoom(this.internalZoom_ * scaleDelta);
+ this.internalZoom_ = this.clampZoom_(this.internalZoom_ * scaleDelta);
const newCenterInContent = this.frameToContent_(center);
const delta = {
@@ -574,7 +595,7 @@ export class Viewport {
setZoom(newZoom) {
this.fittingType_ = FittingType.NONE;
this.mightZoom_(() => {
- this.setZoomInternal_(clampZoom(newZoom));
+ this.setZoomInternal_(this.clampZoom_(newZoom));
this.updateViewport_();
});
}
@@ -659,7 +680,7 @@ export class Viewport {
getLastPageInViewport_(viewportRect) {
const pageAtY = this.getPageAtY_(viewportRect.y + viewportRect.height);
- if (!this.twoUpView_ || pageAtY % 2 == 1 ||
+ if (!this.twoUpViewEnabled() || pageAtY % 2 === 1 ||
pageAtY + 1 >= this.pageDimensions_.length) {
return pageAtY;
}
@@ -943,10 +964,10 @@ export class Viewport {
zoomOut() {
this.mightZoom_(() => {
this.fittingType_ = FittingType.NONE;
- let nextZoom = Viewport.ZOOM_FACTORS[0];
- for (let i = 0; i < Viewport.ZOOM_FACTORS.length; i++) {
- if (Viewport.ZOOM_FACTORS[i] < this.internalZoom_) {
- nextZoom = Viewport.ZOOM_FACTORS[i];
+ let nextZoom = this.presetZoomFactors_[0];
+ for (let i = 0; i < this.presetZoomFactors_.length; i++) {
+ if (this.presetZoomFactors_[i] < this.internalZoom_) {
+ nextZoom = this.presetZoomFactors_[i];
}
}
this.setZoomInternal_(nextZoom);
@@ -958,10 +979,11 @@ export class Viewport {
zoomIn() {
this.mightZoom_(() => {
this.fittingType_ = FittingType.NONE;
- let nextZoom = Viewport.ZOOM_FACTORS[Viewport.ZOOM_FACTORS.length - 1];
- for (let i = Viewport.ZOOM_FACTORS.length - 1; i >= 0; i--) {
- if (Viewport.ZOOM_FACTORS[i] > this.internalZoom_) {
- nextZoom = Viewport.ZOOM_FACTORS[i];
+ const maxZoomIndex = this.presetZoomFactors_.length - 1;
+ let nextZoom = this.presetZoomFactors_[maxZoomIndex];
+ for (let i = maxZoomIndex; i >= 0; i--) {
+ if (this.presetZoomFactors_[i] > this.internalZoom_) {
+ nextZoom = this.presetZoomFactors_[i];
}
}
this.setZoomInternal_(nextZoom);
@@ -975,7 +997,7 @@ export class Viewport {
*/
pinchZoom(e) {
this.mightZoom_(() => {
- this.pinchPhase_ = e.direction == 'out' ?
+ this.pinchPhase_ = e.direction === 'out' ?
Viewport.PinchPhase.PINCH_UPDATE_ZOOM_OUT :
Viewport.PinchPhase.PINCH_UPDATE_ZOOM_IN;
@@ -987,7 +1009,7 @@ export class Viewport {
const needsScrollbars =
this.documentNeedsScrollbars_(this.zoomManager_.applyBrowserZoom(
- clampZoom(this.internalZoom_ * scaleDelta)));
+ this.clampZoom_(this.internalZoom_ * scaleDelta)));
this.pinchCenter_ = e.center;
@@ -1051,7 +1073,8 @@ export class Viewport {
*/
goToNextPage() {
const currentPage = this.getMostVisiblePage();
- const nextPageOffset = (this.twoUpView_ && currentPage % 2 == 0) ? 2 : 1;
+ const nextPageOffset =
+ (this.twoUpViewEnabled() && currentPage % 2 === 0) ? 2 : 1;
this.goToPage(currentPage + nextPageOffset);
}
@@ -1063,8 +1086,8 @@ export class Viewport {
const currentPage = this.getMostVisiblePage();
let previousPageOffset = -1;
- if (this.twoUpView_) {
- previousPageOffset = (currentPage % 2 == 0) ? -2 : -3;
+ if (this.twoUpViewEnabled()) {
+ previousPageOffset = (currentPage % 2 === 0) ? -2 : -3;
}
this.goToPage(currentPage + previousPageOffset);
@@ -1193,8 +1216,8 @@ export class Viewport {
*/
isPagedMode() {
return (
- this.fittingType_ == FittingType.FIT_TO_PAGE ||
- this.fittingType_ == FittingType.FIT_TO_HEIGHT);
+ this.fittingType_ === FittingType.FIT_TO_PAGE ||
+ this.fittingType_ === FittingType.FIT_TO_HEIGHT);
}
/**
@@ -1203,11 +1226,11 @@ export class Viewport {
scrollTo(point) {
let changed = false;
const newPosition = this.position;
- if (point.x !== undefined && point.x != newPosition.x) {
+ if (point.x !== undefined && point.x !== newPosition.x) {
newPosition.x = point.x;
changed = true;
}
- if (point.y !== undefined && point.y != newPosition.y) {
+ if (point.y !== undefined && point.y !== newPosition.y) {
newPosition.y = point.y;
changed = true;
}
@@ -1254,23 +1277,6 @@ Viewport.PinchPhase = {
*/
Viewport.SCROLL_INCREMENT = 40;
-/**
- * Predefined zoom factors to be used when zooming in/out. These are in
- * ascending order. This should match the lists in
- * components/zoom/page_zoom_constants.h and
- * chrome/browser/resources/settings/appearance_page/appearance_page.js
- */
-Viewport.ZOOM_FACTORS = [
- 0.25, 1 / 3, 0.5, 2 / 3, 0.75, 0.8, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3,
- 4, 5
-];
-
-/** The minimum and maximum range to be used to clip zoom factor. */
-Viewport.ZOOM_FACTOR_RANGE = {
- min: Viewport.ZOOM_FACTORS[0],
- max: Viewport.ZOOM_FACTORS[Viewport.ZOOM_FACTORS.length - 1]
-};
-
/** The width of the page shadow around pages in pixels. */
Viewport.PAGE_SHADOW = {
top: 3,
diff --git a/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json b/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json
index 079eca1a6bb..e4ebe1274d3 100644
--- a/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json
+++ b/chromium/chrome/browser/resources/plugin_metadata/plugins_linux.json
@@ -1,5 +1,5 @@
{
- "x-version": 42,
+ "x-version": 43,
"adobe-flash-player": {
"mime_types": [
"application/futuresplash",
@@ -10,9 +10,9 @@
],
"versions": [
{
- "version": "32.0.0.255",
+ "version": "32.0.0.330",
"status": "up_to_date",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-46.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb20-06.html"
}
],
"lang": "en-US",
diff --git a/chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json b/chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json
index 0351e901fab..f26dc10cce3 100644
--- a/chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json
+++ b/chromium/chrome/browser/resources/plugin_metadata/plugins_mac.json
@@ -1,5 +1,5 @@
{
- "x-version": 48,
+ "x-version": 49,
"adobe-flash-player": {
"mime_types": [
"application/futuresplash",
@@ -7,9 +7,9 @@
],
"versions": [
{
- "version": "32.0.0.255",
+ "version": "32.0.0.330",
"status": "requires_authorization",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-46.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb20-06.html"
}
],
"lang": "en-US",
diff --git a/chromium/chrome/browser/resources/plugin_metadata/plugins_win.json b/chromium/chrome/browser/resources/plugin_metadata/plugins_win.json
index 5df5cacdb68..68dbb851351 100644
--- a/chromium/chrome/browser/resources/plugin_metadata/plugins_win.json
+++ b/chromium/chrome/browser/resources/plugin_metadata/plugins_win.json
@@ -1,5 +1,5 @@
{
- "x-version": 57,
+ "x-version": 58,
"adobe-flash-player": {
"mime_types": [
"application/futuresplash",
@@ -7,9 +7,9 @@
],
"versions": [
{
- "version": "32.0.0.255",
+ "version": "32.0.0.330",
"status": "requires_authorization",
- "reference": "https://helpx.adobe.com/security/products/flash-player/apsb19-46.html"
+ "reference": "https://helpx.adobe.com/security/products/flash-player/apsb20-06.html"
}
],
"lang": "en-US",
diff --git a/chromium/chrome/browser/resources/print_preview/.eslintrc.js b/chromium/chrome/browser/resources/print_preview/.eslintrc.js
new file mode 100644
index 00000000000..9c84e103640
--- /dev/null
+++ b/chromium/chrome/browser/resources/print_preview/.eslintrc.js
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/print_preview/BUILD.gn b/chromium/chrome/browser/resources/print_preview/BUILD.gn
index f0acff7fd89..eac678d2bba 100644
--- a/chromium/chrome/browser/resources/print_preview/BUILD.gn
+++ b/chromium/chrome/browser/resources/print_preview/BUILD.gn
@@ -32,24 +32,18 @@ if (optimize_webui) {
pak_file = print_preview_pak_file
out_folder = unpak_folder
- deps = [
- ":flattened_resources",
- ]
+ deps = [ ":flattened_resources" ]
}
grit("flattened_resources") {
source = "print_preview_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
- deps = [
- "ui:polymer3_elements",
- ]
+ deps = [ "ui:polymer3_elements" ]
defines = chrome_grit_defines
outputs = [
"grit/print_preview_resources.h",
@@ -92,9 +86,7 @@ js_library("print_preview_utils") {
}
js_library("metrics") {
- deps = [
- ":native_layer",
- ]
+ deps = [ ":native_layer" ]
}
js_library("cloud_print_interface") {
@@ -128,9 +120,7 @@ js_library("cloud_print_interface_js") {
}
js_library("cloud_print_interface_native") {
- deps = [
- ":cloud_print_interface",
- ]
+ deps = [ ":cloud_print_interface" ]
}
js_library("native_layer") {
@@ -145,7 +135,5 @@ js_library("native_layer") {
}
js_library("dark_mode_behavior") {
- deps = [
- "//ui/webui/resources/js:assert.m",
- ]
+ deps = [ "//ui/webui/resources/js:assert.m" ]
}
diff --git a/chromium/chrome/browser/resources/print_preview/cloud_print_interface.js b/chromium/chrome/browser/resources/print_preview/cloud_print_interface.js
index f3f3b1a578c..de2a7ba09a4 100644
--- a/chromium/chrome/browser/resources/print_preview/cloud_print_interface.js
+++ b/chromium/chrome/browser/resources/print_preview/cloud_print_interface.js
@@ -29,6 +29,7 @@ export const CloudPrintInterfaceEventType = {
* errorCode: number,
* message: string,
* origin: !DestinationOrigin,
+ * account: ?string,
* }}
*/
export let CloudPrintInterfaceErrorEventDetail;
diff --git a/chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js b/chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js
index 0c1f9658674..16af9283310 100644
--- a/chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js
+++ b/chromium/chrome/browser/resources/print_preview/cloud_print_interface_js.js
@@ -107,7 +107,7 @@ export class CloudPrintInterfaceJS {
let origins = opt_origin ? [opt_origin] : CloudOrigins;
if (this.isInAppKioskMode_) {
origins = origins.filter(function(origin) {
- return origin != DestinationOrigin.COOKIES;
+ return origin !== DestinationOrigin.COOKIES;
});
}
this.abortSearchRequests_(origins);
@@ -171,7 +171,7 @@ export class CloudPrintInterfaceJS {
submit(destination, printTicket, documentTitle, data) {
const result = VERSION_REGEXP_.exec(navigator.userAgent);
let chromeVersion = 'unknown';
- if (result && result.length == 2) {
+ if (result && result.length === 2) {
chromeVersion = result[1];
}
const params = [
@@ -218,7 +218,7 @@ export class CloudPrintInterfaceJS {
buildRequest_(method, action, params, origin, account, callback) {
const url = new URL(this.baseUrl_ + '/' + action);
const searchParams = url.searchParams;
- if (origin == DestinationOrigin.COOKIES) {
+ if (origin === DestinationOrigin.COOKIES) {
const xsrfToken = this.xsrfTokens_[account];
if (!xsrfToken) {
searchParams.append('xsrf', '');
@@ -241,11 +241,11 @@ export class CloudPrintInterfaceJS {
searchParams.append('hl', this.uiLocale_);
let body = null;
if (params) {
- if (method == 'GET') {
+ if (method === 'GET') {
params.forEach(param => {
searchParams.append(param.name, encodeURIComponent(param.value));
});
- } else if (method == 'POST') {
+ } else if (method === 'POST') {
body = params.reduce(function(partialBody, param) {
return partialBody + 'Content-Disposition: form-data; name=\"' +
param.name + '\"\r\n\r\n' + param.value + '\r\n--' +
@@ -256,15 +256,15 @@ export class CloudPrintInterfaceJS {
const headers = {};
headers['X-CloudPrint-Proxy'] = 'ChromePrintPreview';
- if (method == 'GET') {
+ if (method === 'GET') {
headers['Content-Type'] = URL_ENCODED_CONTENT_TYPE_;
- } else if (method == 'POST') {
+ } else if (method === 'POST') {
headers['Content-Type'] = MULTIPART_CONTENT_TYPE_;
}
const xhr = new XMLHttpRequest();
xhr.open(method, url.toString(), true);
- xhr.withCredentials = (origin == DestinationOrigin.COOKIES);
+ xhr.withCredentials = (origin === DestinationOrigin.COOKIES);
for (const header in headers) {
xhr.setRequestHeader(header, headers[header]);
}
@@ -279,14 +279,14 @@ export class CloudPrintInterfaceJS {
* @private
*/
sendOrQueueRequest_(request) {
- if (request.origin == DestinationOrigin.COOKIES) {
+ if (request.origin === DestinationOrigin.COOKIES) {
this.sendRequest_(request);
return;
}
// <if expr="chromeos">
- assert(request.origin == DestinationOrigin.DEVICE);
- if (this.accessTokenRequestPromise_ == null) {
+ assert(request.origin === DestinationOrigin.DEVICE);
+ if (this.accessTokenRequestPromise_ === null) {
this.accessTokenRequestPromise_ = this.nativeLayer_.getAccessToken();
}
@@ -322,6 +322,7 @@ export class CloudPrintInterfaceJS {
errorCode: status200 ? request.result['errorCode'] : 0,
message: status200 ? request.result['message'] : '',
origin: request.origin,
+ account: request.account,
};
}
@@ -346,7 +347,7 @@ export class CloudPrintInterfaceJS {
* @private
*/
setUsers_(request) {
- if (request.origin == DestinationOrigin.COOKIES) {
+ if (request.origin === DestinationOrigin.COOKIES) {
const users = request.result['request']['users'] || [];
this.setUsers(users);
}
@@ -387,7 +388,7 @@ export class CloudPrintInterfaceJS {
* @private
*/
onAccessTokenReady_(request, accessToken) {
- assert(request.origin == DestinationOrigin.DEVICE);
+ assert(request.origin === DestinationOrigin.DEVICE);
if (accessToken) {
request.xhr.setRequestHeader('Authorization', 'Bearer ' + accessToken);
this.sendRequest_(request);
@@ -407,11 +408,11 @@ export class CloudPrintInterfaceJS {
* @private
*/
onReadyStateChange_(request) {
- if (request.xhr.readyState == 4) {
- if (request.xhr.status == 200) {
+ if (request.xhr.readyState === 4) {
+ if (request.xhr.status === 200) {
request.result =
/** @type {Object} */ (JSON.parse(request.xhr.responseText));
- if (request.origin == DestinationOrigin.COOKIES &&
+ if (request.origin === DestinationOrigin.COOKIES &&
request.result['success']) {
this.xsrfTokens_[request.result['request']['user']] =
request.result['xsrf_token'];
@@ -433,17 +434,17 @@ export class CloudPrintInterfaceJS {
let lastRequestForThisOrigin = true;
this.outstandingCloudSearchRequests_ =
this.outstandingCloudSearchRequests_.filter(function(item) {
- if (item != request && item.origin == request.origin) {
+ if (item !== request && item.origin === request.origin) {
lastRequestForThisOrigin = false;
}
- return item != request;
+ return item !== request;
});
let activeUser = '';
- if (request.origin == DestinationOrigin.COOKIES) {
+ if (request.origin === DestinationOrigin.COOKIES) {
activeUser = request.result && request.result['request'] &&
request.result['request']['user'];
}
- if (request.xhr.status == 200 && request.result['success']) {
+ if (request.xhr.status === 200 && request.result['success']) {
// Extract printers.
const printerListJson = request.result['printers'] || [];
const printerList = [];
@@ -490,7 +491,7 @@ export class CloudPrintInterfaceJS {
const activeUser = (request.result && request.result['request'] &&
request.result['request']['user']) ||
'';
- if (request.xhr.status == 200 && request.result['success']) {
+ if (request.xhr.status === 200 && request.result['success']) {
// Extract invitations.
const invitationListJson = request.result['invites'] || [];
const invitationList = [];
@@ -528,7 +529,7 @@ export class CloudPrintInterfaceJS {
request.result['request']['user']) ||
'';
let printer = null;
- if (request.xhr.status == 200 && request.result['success'] && accept) {
+ if (request.xhr.status === 200 && request.result['success'] && accept) {
try {
printer = parseCloudDestination(
request.result['printer'], request.origin, activeUser);
@@ -554,7 +555,7 @@ export class CloudPrintInterfaceJS {
* @private
*/
onSubmitDone_(request) {
- if (request.xhr.status == 200 && request.result['success']) {
+ if (request.xhr.status === 200 && request.result['success']) {
this.eventTarget_.dispatchEvent(new CustomEvent(
CloudPrintInterfaceEventType.SUBMIT_DONE,
{detail: request.result['job']['id']}));
@@ -576,14 +577,14 @@ export class CloudPrintInterfaceJS {
onPrinterDone_(destinationId, request) {
// Special handling of the first printer request. It does not matter at
// this point, whether printer was found or not.
- if (request.origin == DestinationOrigin.COOKIES && request.result &&
+ if (request.origin === DestinationOrigin.COOKIES && request.result &&
request.result['request']['user'] &&
request.result['request']['users']) {
const users = request.result['request']['users'];
this.setUsers_(request);
// In case the user account is known, but not the primary one,
// activate it.
- if (request.account != request.result['request']['user'] &&
+ if (request.account !== request.result['request']['user'] &&
this.userSessionIndex_[request.account] > 0 && request.account) {
this.dispatchUserUpdateEvent_(request.account, users);
// Repeat the request for the newly activated account.
@@ -596,9 +597,9 @@ export class CloudPrintInterfaceJS {
this.dispatchUserUpdateEvent_(request.result['request']['user'], users);
}
// Process response.
- if (request.xhr.status == 200 && request.result['success']) {
+ if (request.xhr.status === 200 && request.result['success']) {
let activeUser = '';
- if (request.origin == DestinationOrigin.COOKIES) {
+ if (request.origin === DestinationOrigin.COOKIES) {
activeUser = request.result['request']['user'];
}
const printerJson = request.result['printers'][0];
diff --git a/chromium/chrome/browser/resources/print_preview/data/BUILD.gn b/chromium/chrome/browser/resources/print_preview/data/BUILD.gn
index 4720df3dec6..030f5a2088f 100644
--- a/chromium/chrome/browser/resources/print_preview/data/BUILD.gn
+++ b/chromium/chrome/browser/resources/print_preview/data/BUILD.gn
@@ -82,9 +82,7 @@ js_library("cloud_parsers") {
}
js_library("invitation") {
- deps = [
- ":destination",
- ]
+ deps = [ ":destination" ]
}
js_library("destination") {
@@ -114,9 +112,7 @@ js_library("margins") {
}
js_library("measurement_system") {
- deps = [
- "//ui/webui/resources/js:assert.m",
- ]
+ deps = [ "//ui/webui/resources/js:assert.m" ]
}
js_library("model") {
diff --git a/chromium/chrome/browser/resources/print_preview/data/cloud_parsers.js b/chromium/chrome/browser/resources/print_preview/data/cloud_parsers.js
index 0650b0dfabf..0c6fca53289 100644
--- a/chromium/chrome/browser/resources/print_preview/data/cloud_parsers.js
+++ b/chromium/chrome/browser/resources/print_preview/data/cloud_parsers.js
@@ -57,11 +57,11 @@ const DestinationCloudType = {
* @private
*/
function parseType(typeStr) {
- if (typeStr == DestinationCloudType.ANDROID ||
- typeStr == DestinationCloudType.IOS) {
+ if (typeStr === DestinationCloudType.ANDROID ||
+ typeStr === DestinationCloudType.IOS) {
return DestinationType.MOBILE;
}
- if (typeStr == DestinationCloudType.DOCS) {
+ if (typeStr === DestinationCloudType.DOCS) {
return DestinationType.GOOGLE_PROMOTED;
}
return DestinationType.GOOGLE;
@@ -82,9 +82,9 @@ function extractCertificateStatus(tags) {
certTag.substring(CERT_TAG.length));
// Only 2 valid values sent by GCP server.
assert(
- value == DestinationCertificateStatus.UNKNOWN ||
- value == DestinationCertificateStatus.YES ||
- value == DestinationCertificateStatus.NO);
+ value === DestinationCertificateStatus.UNKNOWN ||
+ value === DestinationCertificateStatus.YES ||
+ value === DestinationCertificateStatus.NO);
return value;
}
@@ -96,7 +96,7 @@ function extractCertificateStatus(tags) {
* @param {!DestinationOrigin} origin The origin of the
* response.
* @param {string} account The account this destination is registered for or
- * empty string, if origin != COOKIES.
+ * empty string, if origin !== COOKIES.
* @return {!Destination} Parsed destination.
*/
export function parseCloudDestination(json, origin, account) {
@@ -174,11 +174,11 @@ export function parseInvitation(json, account) {
const receiver = json[InvitationField.RECEIVER];
let receiverName = '';
const receiverType = receiver['type'];
- if (receiverType == InvitationAclType.USER) {
+ if (receiverType === InvitationAclType.USER) {
// It's a personal invitation, empty name indicates just that.
} else if (
- receiverType == InvitationAclType.GROUP ||
- receiverType == InvitationAclType.DOMAIN) {
+ receiverType === InvitationAclType.GROUP ||
+ receiverType === InvitationAclType.DOMAIN) {
receiverName = nameFormatter(receiver['name'], receiver['scope']);
} else {
throw Error('Invitation of unsupported receiver type');
diff --git a/chromium/chrome/browser/resources/print_preview/data/coordinate2d.js b/chromium/chrome/browser/resources/print_preview/data/coordinate2d.js
index e106e409cfb..cb3a8ba1210 100644
--- a/chromium/chrome/browser/resources/print_preview/data/coordinate2d.js
+++ b/chromium/chrome/browser/resources/print_preview/data/coordinate2d.js
@@ -40,6 +40,6 @@ export class Coordinate2d {
* @return {boolean} Whether another point is equal to this one.
*/
equals(other) {
- return other != null && this.x_ == other.x_ && this.y_ == other.y_;
+ return other !== null && this.x_ === other.x_ && this.y_ === other.y_;
}
}
diff --git a/chromium/chrome/browser/resources/print_preview/data/destination.js b/chromium/chrome/browser/resources/print_preview/data/destination.js
index a15773bce4d..80124d68cbc 100644
--- a/chromium/chrome/browser/resources/print_preview/data/destination.js
+++ b/chromium/chrome/browser/resources/print_preview/data/destination.js
@@ -277,7 +277,6 @@ export class Destination {
* certificateStatus:
* (DestinationCertificateStatus|undefined),
* policies: (DestinationPolicies|undefined),
- * eulaUrl: (string|undefined),
* }=} opt_params Optional
* parameters for the destination.
*/
@@ -416,7 +415,7 @@ export class Destination {
// </if>
assert(
- this.provisionalType_ !=
+ this.provisionalType_ !==
DestinationProvisionalType.NEEDS_USB_PERMISSION ||
this.isExtension,
'Provisional USB destination only supprted with extension origin.');
@@ -474,16 +473,16 @@ export class Destination {
/** @return {boolean} Whether the destination is local or cloud-based. */
get isLocal() {
- return this.origin_ == DestinationOrigin.LOCAL ||
- this.origin_ == DestinationOrigin.EXTENSION ||
- this.origin_ == DestinationOrigin.CROS ||
- (this.origin_ == DestinationOrigin.PRIVET &&
- this.connectionStatus_ != DestinationConnectionStatus.UNREGISTERED);
+ return this.origin_ === DestinationOrigin.LOCAL ||
+ this.origin_ === DestinationOrigin.EXTENSION ||
+ this.origin_ === DestinationOrigin.CROS ||
+ (this.origin_ === DestinationOrigin.PRIVET &&
+ this.connectionStatus_ !== DestinationConnectionStatus.UNREGISTERED);
}
/** @return {boolean} Whether the destination is a Privet local printer */
get isPrivet() {
- return this.origin_ == DestinationOrigin.PRIVET;
+ return this.origin_ === DestinationOrigin.PRIVET;
}
/**
@@ -491,7 +490,7 @@ export class Destination {
* printer.
*/
get isExtension() {
- return this.origin_ == DestinationOrigin.EXTENSION;
+ return this.origin_ === DestinationOrigin.EXTENSION;
}
/**
@@ -499,7 +498,7 @@ export class Destination {
* the location is unknown.
*/
get location() {
- if (this.location_ == null) {
+ if (this.location_ === null) {
this.location_ = '';
this.tags_.some(tag => {
return Destination.LOCATION_TAG_PREFIXES.some(prefix => {
@@ -526,7 +525,7 @@ export class Destination {
* destination.
*/
get hint() {
- if (this.id_ == Destination.GooglePromotedId.DOCS) {
+ if (this.id_ === Destination.GooglePromotedId.DOCS) {
return this.account_;
}
return this.location || this.extensionName || this.description;
@@ -621,7 +620,7 @@ export class Destination {
* certificate.
*/
get hasInvalidCertificate() {
- return this.certificateStatus_ == DestinationCertificateStatus.NO;
+ return this.certificateStatus_ === DestinationCertificateStatus.NO;
}
/**
@@ -630,7 +629,7 @@ export class Destination {
* warning to appear in the preview area when selected.
*/
get shouldShowInvalidCertificateError() {
- return this.certificateStatus_ == DestinationCertificateStatus.NO &&
+ return this.certificateStatus_ === DestinationCertificateStatus.NO &&
!loadTimeData.getBoolean('isEnterpriseManaged');
}
@@ -651,8 +650,8 @@ export class Destination {
/** @return {boolean} Whether the destination is ready to be selected. */
get readyForSelection() {
- return (!isChromeOS || this.origin_ != DestinationOrigin.CROS ||
- this.capabilities_ != null) &&
+ return (!isChromeOS || this.origin_ !== DestinationOrigin.CROS ||
+ this.capabilities_ !== null) &&
!this.isProvisional;
}
@@ -690,10 +689,10 @@ export class Destination {
/** @return {string} Path to the SVG for the destination's icon. */
get icon() {
- if (this.id_ == Destination.GooglePromotedId.DOCS) {
+ if (this.id_ === Destination.GooglePromotedId.DOCS) {
return 'print-preview:save-to-drive';
}
- if (this.id_ == Destination.GooglePromotedId.SAVE_AS_PDF) {
+ if (this.id_ === Destination.GooglePromotedId.SAVE_AS_PDF) {
return 'cr:insert-drive-file';
}
if (this.isEnterprisePrinter) {
@@ -702,10 +701,10 @@ export class Destination {
if (this.isLocal) {
return 'print-preview:print';
}
- if (this.type_ == DestinationType.MOBILE && this.isOwned_) {
+ if (this.type_ === DestinationType.MOBILE && this.isOwned_) {
return 'print-preview:smartphone';
}
- if (this.type_ == DestinationType.MOBILE) {
+ if (this.type_ === DestinationType.MOBILE) {
return 'print-preview:smartphone';
}
if (this.isOwned_) {
@@ -755,7 +754,7 @@ export class Destination {
* @return {boolean}
*/
get isProvisional() {
- return this.provisionalType_ != DestinationProvisionalType.NONE;
+ return this.provisionalType_ !== DestinationProvisionalType.NONE;
}
/**
@@ -767,6 +766,17 @@ export class Destination {
}
/**
+ * @return (Object} Copies capability of this destination.
+ * @private
+ */
+ copiesCapability_() {
+ return this.capabilities && this.capabilities.printer &&
+ this.capabilities.printer.copies ?
+ this.capabilities.printer.copies :
+ null;
+ }
+
+ /**
* @return {Object} Color capability of this destination.
* @private
*/
@@ -808,6 +818,15 @@ export class Destination {
// </if>
+ /** @return {boolean} Whether the printer supports copies. */
+ get hasCopiesCapability() {
+ const capability = this.copiesCapability_();
+ if (!capability) {
+ return false;
+ }
+ return capability.max ? capability.max > 1 : true;
+ }
+
/**
* @return {boolean} Whether the printer supports both black and white and
* color printing.
@@ -866,7 +885,7 @@ export class Destination {
}
for (let i = 0; i < typesToLookFor.length; i++) {
const matchingOptions = capability.option.filter(option => {
- return option.type == typesToLookFor[i];
+ return option.type === typesToLookFor[i];
});
if (matchingOptions.length > 0) {
return matchingOptions[0];
@@ -905,7 +924,7 @@ export class Destination {
const defaultOptions = capability.option.filter(option => {
return option.is_default;
});
- return defaultOptions.length != 0 ? defaultOptions[0] : null;
+ return defaultOptions.length !== 0 ? defaultOptions[0] : null;
}
/** @return {string} A unique identifier for this destination. */
diff --git a/chromium/chrome/browser/resources/print_preview/data/destination_match.js b/chromium/chrome/browser/resources/print_preview/data/destination_match.js
index f4da5541e6f..30a00c8f8ea 100644
--- a/chromium/chrome/browser/resources/print_preview/data/destination_match.js
+++ b/chromium/chrome/browser/resources/print_preview/data/destination_match.js
@@ -43,7 +43,7 @@ export const originToType = function(origin) {
* @return {!PrinterType} Map the destination to a PrinterType.
*/
export function getPrinterTypeForDestination(destination) {
- if (destination.id == Destination.GooglePromotedId.SAVE_AS_PDF) {
+ if (destination.id === Destination.GooglePromotedId.SAVE_AS_PDF) {
return PrinterType.PDF_PRINTER;
}
return originToType(destination.origin);
diff --git a/chromium/chrome/browser/resources/print_preview/data/destination_store.js b/chromium/chrome/browser/resources/print_preview/data/destination_store.js
index 816788d662a..fab9b6385db 100644
--- a/chromium/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chromium/chrome/browser/resources/print_preview/data/destination_store.js
@@ -66,12 +66,12 @@ const localizeCapabilities = function(capabilities) {
* Compare two media sizes by their names.
* @param {!Object} a Media to compare.
* @param {!Object} b Media to compare.
- * @return {number} 1 if a > b, -1 if a < b, or 0 if a == b.
+ * @return {number} 1 if a > b, -1 if a < b, or 0 if a === b.
*/
const compareMediaNames = function(a, b) {
const nameA = a.custom_display_name_localized || a.custom_display_name;
const nameB = b.custom_display_name_localized || b.custom_display_name;
- return nameA == nameB ? 0 : (nameA > nameB ? 1 : -1);
+ return nameA === nameB ? 0 : (nameA > nameB ? 1 : -1);
};
/**
@@ -112,8 +112,8 @@ const sortMediaSizes = function(capabilities) {
category = categoryStandardNA;
} else if (
name.startsWith('PRC_') || name.startsWith('ROC_') ||
- name == 'OM_DAI_PA_KAI' || name == 'OM_JUURO_KU_KAI' ||
- name == 'OM_PA_KAI') {
+ name === 'OM_DAI_PA_KAI' || name === 'OM_JUURO_KU_KAI' ||
+ name === 'OM_PA_KAI') {
category = categoryStandardCN;
} else if (name.startsWith('ISO_')) {
category = categoryStandardISO;
@@ -122,7 +122,7 @@ const sortMediaSizes = function(capabilities) {
} else if (name.startsWith('OM_')) {
category = categoryStandardMisc;
} else {
- assert(name == 'CUSTOM', 'Unknown media size. Assuming custom');
+ assert(name === 'CUSTOM', 'Unknown media size. Assuming custom');
category = categoryCustom;
}
category.push(media);
@@ -291,7 +291,7 @@ export class DestinationStore extends EventTarget {
destinations(opt_account) {
return this.destinations_.filter(function(destination) {
return !destination.account ||
- (!!opt_account && destination.account == opt_account);
+ (!!opt_account && destination.account === opt_account);
});
}
@@ -349,26 +349,31 @@ export class DestinationStore extends EventTarget {
this.systemDefaultDestinationId_ = systemDefaultDestinationId;
this.createLocalPdfPrintDestination_();
+ let destinationSelected = false;
// System default printer policy takes priority.
- if (this.useSystemDefaultAsDefault_ &&
- this.selectSystemDefaultDestination_()) {
- return;
+ if (this.useSystemDefaultAsDefault_) {
+ destinationSelected = this.selectSystemDefaultDestination_();
}
- // Run through the destinations forward. As soon as we find a destination,
- // select or try to fetch it and return.
+ // Run through the destinations forward and try to fetch them. Autoselect
+ // the first one we find.
for (const destination of recentDestinations) {
const candidate =
this.destinationMap_.get(createRecentDestinationKey(destination));
- if (candidate) {
+ if (candidate && !destinationSelected) {
this.selectDestination(candidate);
- return;
- }
- if (this.fetchPreselectedDestination_(destination)) {
- return;
+ destinationSelected = true;
+ } else if (!candidate) {
+ const fetchStarted = this.fetchPreselectedDestination_(
+ destination, !destinationSelected);
+ destinationSelected = destinationSelected || fetchStarted;
}
}
+ if (destinationSelected) {
+ return;
+ }
+
// Try the default destination rules, if they exist.
const destinationMatch = this.convertToDestinationMatch_(
serializedDefaultDestinationSelectionRulesStr);
@@ -393,13 +398,13 @@ export class DestinationStore extends EventTarget {
* the store or fetch was started successfully.
*/
selectSystemDefaultDestination_() {
- if (this.systemDefaultDestinationId_ == '') {
+ if (this.systemDefaultDestinationId_ === '') {
return false;
}
const serializedSystemDefault = {
id: this.systemDefaultDestinationId_,
- origin: this.systemDefaultDestinationId_ ==
+ origin: this.systemDefaultDestinationId_ ===
Destination.GooglePromotedId.SAVE_AS_PDF ?
DestinationOrigin.LOCAL :
this.platformOrigin_,
@@ -417,7 +422,8 @@ export class DestinationStore extends EventTarget {
return true;
}
- return this.fetchPreselectedDestination_(serializedSystemDefault);
+ return this.fetchPreselectedDestination_(
+ serializedSystemDefault, /*autoselect=*/ true);
}
/** Removes all events being tracked from the tracker. */
@@ -427,12 +433,22 @@ export class DestinationStore extends EventTarget {
/**
* Attempts to fetch capabilities of the destination identified by
- * |serializedDestination|.
+ * |serializedDestination|. Will autoselect the destination when capabilities
+ * are returned if |autoselect| is true.
* @param {!RecentDestination} serializedDestination
+ * @param {boolean} autoselect Whether to select the destination if its
+ * capabilities are retrieved successfully.
* @return {boolean} Whether capabilities fetch was successfully started.
* @private
*/
- fetchPreselectedDestination_(serializedDestination) {
+ fetchPreselectedDestination_(serializedDestination, autoselect) {
+ const id = serializedDestination.id;
+ const origin = serializedDestination.origin;
+ if (autoselect) {
+ this.autoSelectMatchingDestination_ =
+ this.createExactDestinationMatch_(origin, id);
+ }
+
const key = createRecentDestinationKey(serializedDestination);
if (this.inFlightCloudPrintRequests_.has(key)) {
// Don't send another request if we are already fetching this
@@ -440,11 +456,6 @@ export class DestinationStore extends EventTarget {
return true;
}
- const id = serializedDestination.id;
- const origin = serializedDestination.origin;
- this.autoSelectMatchingDestination_ =
- this.createExactDestinationMatch_(origin, id);
-
let error = false;
const type = originToType(origin);
switch (type) {
@@ -459,26 +470,28 @@ export class DestinationStore extends EventTarget {
// privet or extension printers in this case.
this.startLoadDestinations_(type);
- // Create a fake selectedDestination_ that is not actually in the
- // destination store. When the real destination is created, this
- // destination will be overwritten.
- const params = (origin === DestinationOrigin.PRIVET) ? {} : {
- description: '',
- extensionId: serializedDestination.extensionId,
- extensionName: serializedDestination.extensionName,
- provisionalType: DestinationProvisionalType.NONE
- };
- this.selectedDestination_ = new Destination(
- id, DestinationType.LOCAL, origin,
- serializedDestination.displayName,
- DestinationConnectionStatus.ONLINE, params);
-
- if (serializedDestination.capabilities) {
- this.selectedDestination_.capabilities =
- serializedDestination.capabilities;
- this.dispatchEvent(
- new CustomEvent(DestinationStore.EventType
- .SELECTED_DESTINATION_CAPABILITIES_READY));
+ if (autoselect) {
+ // Create a fake selectedDestination_ that is not actually in the
+ // destination store. When the real destination is created, this
+ // destination will be overwritten.
+ const params = (origin === DestinationOrigin.PRIVET) ? {} : {
+ description: '',
+ extensionId: serializedDestination.extensionId,
+ extensionName: serializedDestination.extensionName,
+ provisionalType: DestinationProvisionalType.NONE
+ };
+ this.selectedDestination_ = new Destination(
+ id, DestinationType.LOCAL, origin,
+ serializedDestination.displayName,
+ DestinationConnectionStatus.ONLINE, params);
+
+ if (serializedDestination.capabilities) {
+ this.selectedDestination_.capabilities =
+ serializedDestination.capabilities;
+ this.dispatchEvent(
+ new CustomEvent(DestinationStore.EventType
+ .SELECTED_DESTINATION_CAPABILITIES_READY));
+ }
}
break;
case PrinterType.CLOUD_PRINTER:
@@ -496,7 +509,7 @@ export class DestinationStore extends EventTarget {
error = true;
}
- if (!error) {
+ if (!error && autoselect) {
this.startAutoSelectTimeout_();
}
return !error;
@@ -511,7 +524,7 @@ export class DestinationStore extends EventTarget {
this.autoSelectMatchingDestination_ = destinationMatch;
const types = destinationMatch.getTypes();
types.forEach(type => {
- if (type != PrinterType.CLOUD_PRINTER) {
+ if (type !== PrinterType.CLOUD_PRINTER) {
// Local, extension, or privet printer
this.startLoadDestinations_(type);
} else if (CloudOrigins.some(origin => {
@@ -531,7 +544,8 @@ export class DestinationStore extends EventTarget {
this.nativeLayer_.getEulaUrl(destinationId).then(response => {
// Check that the currently selected destination ID still matches the
// destination ID we used to fetch the EULA URL.
- if (destinationId === this.selectedDestination_.id) {
+ if (this.selectedDestination_ &&
+ destinationId === this.selectedDestination_.id) {
this.dispatchEvent(new CustomEvent(
DestinationStore.EventType.DESTINATION_EULA_READY,
{detail: response}));
@@ -560,8 +574,8 @@ export class DestinationStore extends EventTarget {
return null;
}
- const isLocal = !matchRules.kind || matchRules.kind == 'local';
- const isCloud = !matchRules.kind || matchRules.kind == 'cloud';
+ const isLocal = !matchRules.kind || matchRules.kind === 'local';
+ const isCloud = !matchRules.kind || matchRules.kind === 'cloud';
if (!isLocal && !isCloud) {
console.error('Unsupported type: "' + matchRules.kind + '"');
return null;
@@ -646,7 +660,7 @@ export class DestinationStore extends EventTarget {
* to set.
*/
setCloudPrintInterface(cloudPrintInterface) {
- assert(this.cloudPrintInterface_ == null);
+ assert(this.cloudPrintInterface_ === null);
this.cloudPrintInterface_ = cloudPrintInterface;
[CloudPrintInterfaceEventType.SEARCH_DONE,
CloudPrintInterfaceEventType.SEARCH_FAILED,
@@ -669,6 +683,11 @@ export class DestinationStore extends EventTarget {
this.onCloudPrintProcessInviteDone_.bind(this));
}
+ /** @param {string} key Key identifying the destination to select */
+ selectDestinationByKey(key) {
+ this.selectDestination(this.destinationMap_.get(key));
+ }
+
/**
* @param {Destination} destination Destination to select.
*/
@@ -679,10 +698,10 @@ export class DestinationStore extends EventTarget {
if (this.autoSelectTimeout_) {
clearTimeout(this.autoSelectTimeout_);
this.autoSelectTimeout_ = null;
- } else if (destination == this.selectedDestination_) {
+ } else if (destination === this.selectedDestination_) {
return;
}
- if (destination == null) {
+ if (destination === null) {
this.selectedDestination_ = null;
this.dispatchEvent(
new CustomEvent(DestinationStore.EventType.DESTINATION_SELECT));
@@ -697,8 +716,8 @@ export class DestinationStore extends EventTarget {
// Adjust metrics.
if (destination.cloudID &&
this.destinations_.some(function(otherDestination) {
- return otherDestination.cloudID == destination.cloudID &&
- otherDestination != destination;
+ return otherDestination.cloudID === destination.cloudID &&
+ otherDestination !== destination;
})) {
this.metrics_.record(
destination.isPrivet ?
@@ -710,7 +729,7 @@ export class DestinationStore extends EventTarget {
new CustomEvent(DestinationStore.EventType.DESTINATION_SELECT));
// Request destination capabilities from backend, since they are not
// known yet.
- if (destination.capabilities == null) {
+ if (destination.capabilities === null) {
const type = originToType(destination.origin);
if (type !== PrinterType.CLOUD_PRINTER) {
this.nativeLayer_.getPrinterCapabilities(destination.id, type)
@@ -721,7 +740,7 @@ export class DestinationStore extends EventTarget {
destination.origin, destination.id));
} else {
assert(
- this.cloudPrintInterface_ != null,
+ this.cloudPrintInterface_ !== null,
'Cloud destination selected, but GCP is not enabled');
this.cloudPrintInterface_.printer(
destination.id, destination.origin, destination.account);
@@ -739,7 +758,7 @@ export class DestinationStore extends EventTarget {
* @return {!Promise<!PrinterSetupResponse>}
*/
resolveCrosDestination(destination) {
- assert(destination.origin == DestinationOrigin.CROS);
+ assert(destination.origin === DestinationOrigin.CROS);
return this.nativeLayer_.setupPrinter(destination.id);
}
@@ -751,7 +770,7 @@ export class DestinationStore extends EventTarget {
*/
resolveProvisionalDestination(destination) {
assert(
- destination.provisionalType ==
+ destination.provisionalType ===
DestinationProvisionalType.NEEDS_USB_PERMISSION,
'Provisional type cannot be resolved.');
return this.nativeLayer_.grantExtensionPrinterAccess(destination.id)
@@ -894,59 +913,48 @@ export class DestinationStore extends EventTarget {
* for the specified origin only.
*/
startLoadCloudDestinations(opt_origin) {
- if (this.cloudPrintInterface_ == null) {
+ if (this.cloudPrintInterface_ === null) {
return;
}
const origins = this.loadedCloudOrigins_.get(this.activeUser_) || [];
- if (origins.length == 0 || (opt_origin && origins.includes(opt_origin))) {
+ if (origins.length === 0 || (opt_origin && origins.includes(opt_origin))) {
this.cloudPrintInterface_.search(this.activeUser_, opt_origin);
}
}
/**
- * If a destination with key |key| is already in the store, selects it.
- * Otherwise, fetches the recent destination with key matching |key|.
- * @param {string} key
- * @param {!Array<!RecentDestination>} recentDestinations
- * @return {boolean} Whether the destination was selected or fetch was
- * started successfully.
+ * @param {string} key Key identifying the destination
+ * @return {?Destination} The destination matching the key, if it exists.
*/
- selectRecentDestinationByKey(key, recentDestinations) {
- const destination = this.destinationMap_.get(key);
- if (destination) {
- this.selectDestination(destination);
- return true;
- }
-
- const recent = recentDestinations.find(d => {
- return createRecentDestinationKey(d) === key;
- });
- if (recent) {
- return this.fetchPreselectedDestination_(recent);
- }
-
- // Should be fetching the Google Drive destination.
- return this.startLoadGoogleDrive();
+ getDestinationByKey(key) {
+ return this.destinationMap_.get(key);
}
/**
- * Tries to load the Google Drive destination for the active user.
+ * Tries to load the cookie based destination for the active user.
+ * @param {string} id
* @return {boolean}
*/
- startLoadGoogleDrive() {
- const driveKey = createDestinationKey(
- Destination.GooglePromotedId.DOCS, DestinationOrigin.COOKIES,
- this.activeUser_);
- return this.fetchPreselectedDestination_({
- id: Destination.GooglePromotedId.DOCS,
- origin: DestinationOrigin.COOKIES,
- account: this.activeUser_,
- capabilities: null,
- displayName: '',
- extensionId: '',
- extensionName: '',
- });
+ startLoadCookieDestination(id) {
+ const key =
+ createDestinationKey(id, DestinationOrigin.COOKIES, this.activeUser_);
+ if (this.destinationMap_.get(key) ||
+ this.inFlightCloudPrintRequests_.has(key)) {
+ return true;
+ }
+
+ return this.fetchPreselectedDestination_(
+ {
+ id: id,
+ origin: DestinationOrigin.COOKIES,
+ account: this.activeUser_,
+ capabilities: null,
+ displayName: '',
+ extensionId: '',
+ extensionName: '',
+ },
+ false /* autoSelect */);
}
// <if expr="chromeos">
@@ -958,7 +966,7 @@ export class DestinationStore extends EventTarget {
*/
removeProvisionalDestination_(provisionalId) {
this.destinations_ = this.destinations_.filter(function(el) {
- if (el.id == provisionalId) {
+ if (el.id === provisionalId) {
this.destinationMap_.delete(el.key);
return false;
}
@@ -1059,15 +1067,15 @@ export class DestinationStore extends EventTarget {
destination.capabilities = sortMediaSizes(destination.capabilities);
}
const existingDestination = this.destinationMap_.get(destination.key);
- if (existingDestination != undefined) {
+ if (existingDestination !== undefined) {
existingDestination.capabilities = destination.capabilities;
} else {
this.insertDestination_(destination);
}
if (this.selectedDestination_ &&
- (existingDestination == this.selectedDestination_ ||
- destination == this.selectedDestination_)) {
+ (existingDestination === this.selectedDestination_ ||
+ destination === this.selectedDestination_)) {
this.sendSelectedDestinationUpdateEvent_();
}
}
@@ -1098,14 +1106,14 @@ export class DestinationStore extends EventTarget {
insertIntoStore_(destination) {
const key = destination.key;
const existingDestination = this.destinationMap_.get(key);
- if (existingDestination == undefined) {
+ if (existingDestination === undefined) {
this.destinations_.push(destination);
this.destinationMap_.set(key, destination);
return true;
}
- if (existingDestination.connectionStatus ==
+ if (existingDestination.connectionStatus ===
DestinationConnectionStatus.UNKNOWN &&
- destination.connectionStatus != DestinationConnectionStatus.UNKNOWN) {
+ destination.connectionStatus !== DestinationConnectionStatus.UNKNOWN) {
existingDestination.connectionStatus = destination.connectionStatus;
return true;
}
@@ -1198,7 +1206,7 @@ export class DestinationStore extends EventTarget {
this.updateDestination_(dest);
// <if expr="chromeos">
// Start the fetch for the PPD EULA URL.
- this.fetchEulaUrl(this.selectedDestination_.id);
+ this.fetchEulaUrl(dest.id);
// </if>
}
}
@@ -1216,7 +1224,7 @@ export class DestinationStore extends EventTarget {
console.warn(
'Failed to get print capabilities for printer ' + destinationId);
if (this.selectedDestination_ &&
- this.selectedDestination_.id == destinationId) {
+ this.selectedDestination_.id === destinationId) {
this.dispatchEvent(new CustomEvent(
DestinationStore.EventType.ERROR,
{detail: DestinationErrorType.INVALID}));
@@ -1298,7 +1306,8 @@ export class DestinationStore extends EventTarget {
*/
onCloudPrintPrinterFailed_(event) {
const key = createDestinationKey(
- event.detail.destinationId, event.detail.origin, this.activeUser_);
+ event.detail.destinationId, event.detail.origin,
+ event.detail.account || '');
this.inFlightCloudPrintRequests_.delete(key);
if (this.autoSelectMatchingDestination_ &&
this.autoSelectMatchingDestination_.matchIdAndOrigin(
diff --git a/chromium/chrome/browser/resources/print_preview/data/document_info.js b/chromium/chrome/browser/resources/print_preview/data/document_info.js
index a7fec264935..1747cd9ded8 100644
--- a/chromium/chrome/browser/resources/print_preview/data/document_info.js
+++ b/chromium/chrome/browser/resources/print_preview/data/document_info.js
@@ -51,7 +51,7 @@ Polymer({
documentSettings: {
type: Object,
notify: true,
- value: function() {
+ value() {
return {
hasCssMediaStyles: false,
hasSelection: false,
@@ -86,7 +86,7 @@ Polymer({
pageSize: {
type: Object,
notify: true,
- value: function() {
+ value() {
return new Size(612, 792);
},
},
@@ -98,7 +98,7 @@ Polymer({
printableArea: {
type: Object,
notify: true,
- value: function() {
+ value() {
return new PrintableArea(new Coordinate2d(0, 0), new Size(612, 792));
},
},
@@ -111,7 +111,7 @@ Polymer({
isInitialized_: false,
/** @override */
- attached: function() {
+ attached() {
this.addWebUIListener(
'page-count-ready', this.onPageCountReady_.bind(this));
this.addWebUIListener(
@@ -127,7 +127,7 @@ Polymer({
* @param {boolean} hasSelection Whether the document has user-selected
* content.
*/
- init: function(isModifiable, isFromArc, isPdf, title, hasSelection) {
+ init(isModifiable, isFromArc, isPdf, title, hasSelection) {
this.isInitialized_ = true;
this.set('documentSettings.isModifiable', isModifiable);
this.set('documentSettings.isFromArc', isFromArc);
@@ -142,7 +142,7 @@ Polymer({
* @param {boolean} isScalingDisabled Whether scaling of the document is
* prohibited.
*/
- updateIsScalingDisabled: function(isScalingDisabled) {
+ updateIsScalingDisabled(isScalingDisabled) {
if (this.isInitialized_) {
this.set('documentSettings.isScalingDisabled', isScalingDisabled);
}
@@ -157,7 +157,7 @@ Polymer({
* custom page size or style to use.
* @private
*/
- onPageLayoutReady_: function(pageLayout, hasCustomPageSizeStyle) {
+ onPageLayoutReady_(pageLayout, hasCustomPageSizeStyle) {
const origin =
new Coordinate2d(pageLayout.printableAreaX, pageLayout.printableAreaY);
const size =
@@ -189,8 +189,8 @@ Polymer({
* to page.
* @private
*/
- onPageCountReady_: function(pageCount, previewResponseId, fitToPageScaling) {
- if (this.inFlightRequestId != previewResponseId || !this.isInitialized_) {
+ onPageCountReady_(pageCount, previewResponseId, fitToPageScaling) {
+ if (this.inFlightRequestId !== previewResponseId || !this.isInitialized_) {
return;
}
this.set('documentSettings.pageCount', pageCount);
diff --git a/chromium/chrome/browser/resources/print_preview/data/invitation_store.js b/chromium/chrome/browser/resources/print_preview/data/invitation_store.js
index 42a5f8d05a6..fc2a58d687a 100644
--- a/chromium/chrome/browser/resources/print_preview/data/invitation_store.js
+++ b/chromium/chrome/browser/resources/print_preview/data/invitation_store.js
@@ -81,7 +81,7 @@ export class InvitationStore extends EventTarget {
* to set.
*/
setCloudPrintInterface(cloudPrintInterface) {
- assert(this.cloudPrintInterface_ == null);
+ assert(this.cloudPrintInterface_ === null);
this.cloudPrintInterface_ = cloudPrintInterface;
this.tracker_.add(
this.cloudPrintInterface_.getEventTarget(),
@@ -112,7 +112,7 @@ export class InvitationStore extends EventTarget {
return;
}
if (this.loadStatus_.hasOwnProperty(user)) {
- if (this.loadStatus_[user] == InvitationStoreLoadStatus.DONE) {
+ if (this.loadStatus_[user] === InvitationStoreLoadStatus.DONE) {
this.dispatchEvent(
new CustomEvent(InvitationStore.EventType.INVITATION_SEARCH_DONE));
}
@@ -145,10 +145,10 @@ export class InvitationStore extends EventTarget {
if (this.invitations_.hasOwnProperty(invitation.account)) {
this.invitations_[invitation.account] =
this.invitations_[invitation.account].filter(function(i) {
- return i != invitation;
+ return i !== invitation;
});
}
- if (this.invitationInProgress_ == invitation) {
+ if (this.invitationInProgress_ === invitation) {
this.invitationInProgress_ = null;
}
}
diff --git a/chromium/chrome/browser/resources/print_preview/data/margins.js b/chromium/chrome/browser/resources/print_preview/data/margins.js
index ce37c7733b7..f213e4d6d8a 100644
--- a/chromium/chrome/browser/resources/print_preview/data/margins.js
+++ b/chromium/chrome/browser/resources/print_preview/data/margins.js
@@ -105,11 +105,11 @@ export class Margins {
* @return {boolean} Whether this margins object is equal to another.
*/
equals(other) {
- if (other == null) {
+ if (other === null) {
return false;
}
for (const orientation in this.value_) {
- if (this.value_[orientation] != other.value_[orientation]) {
+ if (this.value_[orientation] !== other.value_[orientation]) {
return false;
}
}
diff --git a/chromium/chrome/browser/resources/print_preview/data/model.js b/chromium/chrome/browser/resources/print_preview/data/model.js
index 15e712dc8cd..24f2b0c5cac 100644
--- a/chromium/chrome/browser/resources/print_preview/data/model.js
+++ b/chromium/chrome/browser/resources/print_preview/data/model.js
@@ -6,7 +6,7 @@ import {assert} from 'chrome://resources/js/assert.m.js';
import {isMac, isWindows} from 'chrome://resources/js/cr.m.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
-import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {BackgroundGraphicsModeRestriction, Policies} from '../native_layer.js';
@@ -68,7 +68,7 @@ export let Settings;
/**
* @typedef {{
- * version: string,
+ * version: number,
* recentDestinations: (!Array<!RecentDestination> |
* undefined),
* dpi: ({horizontal_dpi: number,
@@ -200,7 +200,7 @@ Polymer({
settings: {
type: Object,
notify: true,
- value: function() {
+ value() {
return {
pages: {
value: [1],
@@ -491,8 +491,7 @@ Polymer({
'documentSettings.isPdf, documentSettings.hasCssMediaStyles, ' +
'documentSettings.hasSelection)',
'updateHeaderFooterAvailable_(' +
- 'margins, settings.margins.value, ' +
- 'settings.customMargins.value, settings.mediaSize.value)',
+ 'margins, settings.margins.value, settings.mediaSize.value)',
],
/** @private {boolean} */
@@ -508,14 +507,14 @@ Polymer({
lastDestinationCapabilities_: null,
/** @override */
- attached: function() {
+ attached() {
assert(!instance);
instance = this;
whenReadyResolver.resolve();
},
/** @override */
- detached: function() {
+ detached() {
instance = null;
whenReadyResolver = new PromiseResolver();
},
@@ -524,7 +523,7 @@ Polymer({
* @param {string} settingName Name of the setting to get.
* @return {Setting} The setting object.
*/
- getSetting: function(settingName) {
+ getSetting(settingName) {
const setting =
/** @type {Setting} */ (this.get(settingName, this.settings));
assert(setting, 'Setting is missing: ' + settingName);
@@ -535,7 +534,7 @@ Polymer({
* @param {string} settingName Name of the setting to get the value for.
* @return {*} The value of the setting, accounting for availability.
*/
- getSettingValue: function(settingName) {
+ getSettingValue(settingName) {
const setting = this.getSetting(settingName);
return setting.available ? setting.value : setting.unavailableValue;
},
@@ -548,7 +547,7 @@ Polymer({
* @param {*} value value to set.
* @private
*/
- setSettingPath_: function(settingPath, value) {
+ setSettingPath_(settingPath, value) {
const settingName = settingPath.split('.')[0];
const setting = this.getSetting(settingName);
const oldValue = this.getSettingValue(settingName);
@@ -569,7 +568,7 @@ Polymer({
* @param {boolean=} noSticky Whether to avoid stickying the setting. Defaults
* to false.
*/
- setSetting: function(settingName, value, noSticky) {
+ setSetting(settingName, value, noSticky) {
const setting = this.getSetting(settingName);
if (setting.setByPolicy) {
return;
@@ -592,7 +591,7 @@ Polymer({
* @param {boolean=} noSticky Whether to avoid stickying the setting. Defaults
* to false.
*/
- setSettingSplice: function(settingName, start, end, newValue, noSticky) {
+ setSettingSplice(settingName, start, end, newValue, noSticky) {
const setting = this.getSetting(settingName);
if (setting.setByPolicy) {
return;
@@ -616,14 +615,14 @@ Polymer({
* @param {string} settingName Name of the setting to set
* @param {boolean} valid Whether the setting value is currently valid.
*/
- setSettingValid: function(settingName, valid) {
+ setSettingValid(settingName, valid) {
const setting = this.getSetting(settingName);
// Should not set the setting to invalid if it is not available, as there
// is no way for the user to change the value in this case.
if (!valid) {
assert(setting.available, 'Setting is not available: ' + settingName);
}
- const shouldFireEvent = valid != setting.valid;
+ const shouldFireEvent = valid !== setting.valid;
this.set(`settings.${settingName}.valid`, valid);
if (shouldFireEvent) {
this.fire('setting-valid-changed', valid);
@@ -635,12 +634,12 @@ Polymer({
* media size settings based on the destination capabilities.
* @private
*/
- updateSettingsFromDestination_: function() {
+ updateSettingsFromDestination_() {
if (!this.destination || !this.settings) {
return;
}
- if (this.destination.capabilities == this.lastDestinationCapabilities_) {
+ if (this.destination.capabilities === this.lastDestinationCapabilities_) {
return;
}
@@ -662,23 +661,24 @@ Polymer({
* @param {?CddCapabilities} caps The printer capabilities.
* @private
*/
- updateSettingsAvailabilityFromDestination_: function(caps) {
- this.setSettingPath_('copies.available', !!caps && !!caps.copies);
+ updateSettingsAvailabilityFromDestination_(caps) {
+ this.setSettingPath_(
+ 'copies.available', this.destination.hasCopiesCapability);
this.setSettingPath_('collate.available', !!caps && !!caps.collate);
this.setSettingPath_(
'color.available', this.destination.hasColorCapability);
const capsHasDuplex = !!caps && !!caps.duplex && !!caps.duplex.option;
const capsHasLongEdge = capsHasDuplex &&
- caps.duplex.option.some(o => o.type == DuplexType.LONG_EDGE);
+ caps.duplex.option.some(o => o.type === DuplexType.LONG_EDGE);
const capsHasShortEdge = capsHasDuplex &&
- caps.duplex.option.some(o => o.type == DuplexType.SHORT_EDGE);
+ caps.duplex.option.some(o => o.type === DuplexType.SHORT_EDGE);
this.setSettingPath_(
'duplexShortEdge.available', capsHasLongEdge && capsHasShortEdge);
this.setSettingPath_(
'duplex.available',
(capsHasLongEdge || capsHasShortEdge) &&
- caps.duplex.option.some(o => o.type == DuplexType.NO_DUPLEX));
+ caps.duplex.option.some(o => o.type === DuplexType.NO_DUPLEX));
this.setSettingPath_(
'vendorItems.available', !!caps && !!caps.vendor_capability);
@@ -696,9 +696,9 @@ Polymer({
},
/** @private */
- updateSettingsAvailabilityFromDestinationAndDocumentSettings_: function() {
+ updateSettingsAvailabilityFromDestinationAndDocumentSettings_() {
const isSaveAsPDF =
- this.destination.id == Destination.GooglePromotedId.SAVE_AS_PDF;
+ this.destination.id === Destination.GooglePromotedId.SAVE_AS_PDF;
const knownSizeToSaveAsPdf = isSaveAsPDF &&
(!this.documentSettings.isModifiable ||
this.documentSettings.hasCssMediaStyles);
@@ -726,7 +726,7 @@ Polymer({
},
/** @private */
- updateSettingsAvailabilityFromDocumentSettings_: function() {
+ updateSettingsAvailabilityFromDocumentSettings_() {
if (!this.settings) {
return;
}
@@ -770,7 +770,7 @@ Polymer({
},
/** @private */
- updateHeaderFooterAvailable_: function() {
+ updateHeaderFooterAvailable_() {
if (this.documentSettings === undefined) {
return;
}
@@ -783,7 +783,7 @@ Polymer({
* @return {boolean} Whether the header/footer setting should be available.
* @private
*/
- isHeaderFooterAvailable_: function() {
+ isHeaderFooterAvailable_() {
// Always unavailable for PDFs.
if (!this.documentSettings.isModifiable) {
return false;
@@ -798,35 +798,26 @@ Polymer({
}
// Otherwise, availability depends on the margins.
- let available = false;
const marginsType =
/** @type {!MarginsType} */ (this.getSettingValue('margins'));
- switch (marginsType) {
- case MarginsType.DEFAULT:
- available = !this.margins ||
- this.margins.get(CustomMarginsOrientation.TOP) > 0 ||
- this.margins.get(CustomMarginsOrientation.BOTTOM) > 0;
- break;
- case MarginsType.NO_MARGINS:
- break;
- case MarginsType.MINIMUM:
- available = true;
- break;
- case MarginsType.CUSTOM:
- const margins = this.getSettingValue('customMargins');
- available = margins.marginTop > 0 || margins.marginBottom > 0;
- break;
- default:
- break;
+ if (marginsType === MarginsType.NO_MARGINS) {
+ return false;
+ }
+
+ if (marginsType === MarginsType.MINIMUM) {
+ return true;
}
- return available;
+
+ return !this.margins ||
+ this.margins.get(CustomMarginsOrientation.TOP) > 0 ||
+ this.margins.get(CustomMarginsOrientation.BOTTOM) > 0;
},
/**
* @param {?CddCapabilities} caps The printer capabilities.
* @private
*/
- isLayoutAvailable_: function(caps) {
+ isLayoutAvailable_(caps) {
if (!caps || !caps.page_orientation || !caps.page_orientation.option ||
(!this.documentSettings.isModifiable &&
!this.documentSettings.isFromArc) ||
@@ -837,8 +828,8 @@ Polymer({
let hasLandscapeOption = false;
caps.page_orientation.option.forEach(option => {
hasAutoOrPortraitOption = hasAutoOrPortraitOption ||
- option.type == 'AUTO' || option.type == 'PORTRAIT';
- hasLandscapeOption = hasLandscapeOption || option.type == 'LANDSCAPE';
+ option.type === 'AUTO' || option.type === 'PORTRAIT';
+ hasLandscapeOption = hasLandscapeOption || option.type === 'LANDSCAPE';
});
return hasLandscapeOption && hasAutoOrPortraitOption;
},
@@ -847,7 +838,7 @@ Polymer({
* @param {?CddCapabilities} caps The printer capabilities.
* @private
*/
- updateSettingsValues_: function(caps) {
+ updateSettingsValues_(caps) {
if (this.settings.mediaSize.available) {
const defaultOption = caps.media_size.option.find(o => !!o.is_default) ||
caps.media_size.option[0];
@@ -912,13 +903,13 @@ Polymer({
const defaultOption = caps.duplex.option.find(o => !!o.is_default);
this.setSetting(
'duplex',
- defaultOption ? (defaultOption.type == DuplexType.LONG_EDGE ||
- defaultOption.type == DuplexType.SHORT_EDGE) :
+ defaultOption ? (defaultOption.type === DuplexType.LONG_EDGE ||
+ defaultOption.type === DuplexType.SHORT_EDGE) :
false,
true);
this.setSetting(
'duplexShortEdge',
- defaultOption ? defaultOption.type == DuplexType.SHORT_EDGE : false,
+ defaultOption ? defaultOption.type === DuplexType.SHORT_EDGE : false,
true);
if (!this.settings.duplexShortEdge.available) {
@@ -926,16 +917,16 @@ Polymer({
// Set duplexShortEdge's unavailable value based on the printer.
this.setSettingPath_(
'duplexShortEdge.unavailableValue',
- caps.duplex.option.some(o => o.type == DuplexType.SHORT_EDGE));
+ caps.duplex.option.some(o => o.type === DuplexType.SHORT_EDGE));
}
} else if (
!this.settings.duplex.available && caps && caps.duplex &&
caps.duplex.option) {
// In this case, there must only be one option.
const hasLongEdge =
- caps.duplex.option.some(o => o.type == DuplexType.LONG_EDGE);
+ caps.duplex.option.some(o => o.type === DuplexType.LONG_EDGE);
const hasShortEdge =
- caps.duplex.option.some(o => o.type == DuplexType.SHORT_EDGE);
+ caps.duplex.option.some(o => o.type === DuplexType.SHORT_EDGE);
// If the only option available is long edge, the value should always be
// true.
this.setSettingPath_(
@@ -951,21 +942,21 @@ Polymer({
const vendorSettings = {};
for (const item of caps.vendor_capability) {
let defaultValue = null;
- if (item.type == 'SELECT' && item.select_cap &&
+ if (item.type === 'SELECT' && item.select_cap &&
item.select_cap.option) {
const defaultOption =
item.select_cap.option.find(o => !!o.is_default);
defaultValue = defaultOption ? defaultOption.value : null;
- } else if (item.type == 'RANGE') {
+ } else if (item.type === 'RANGE') {
if (item.range_cap) {
defaultValue = item.range_cap.default || null;
}
- } else if (item.type == 'TYPED_VALUE') {
+ } else if (item.type === 'TYPED_VALUE') {
if (item.typed_value_cap) {
defaultValue = item.typed_value_cap.default || null;
}
}
- if (defaultValue != null) {
+ if (defaultValue !== null) {
vendorSettings[item.id] = defaultValue;
}
}
@@ -978,7 +969,7 @@ Polymer({
* settings will be applied when destinaton capabilities have been retrieved.
* @param {?string} savedSettingsStr The sticky settings from native layer
*/
- setStickySettings: function(savedSettingsStr) {
+ setStickySettings(savedSettingsStr) {
assert(!this.stickySettings_);
if (!savedSettingsStr) {
@@ -993,7 +984,7 @@ Polymer({
console.error('Unable to parse state ' + e);
return; // use default values rather than updating.
}
- if (savedSettings.version != 2) {
+ if (savedSettings.version !== 2) {
return;
}
@@ -1016,7 +1007,7 @@ Polymer({
* @param {boolean} managed Flag showing whether value of setting is managed.
* @private
*/
- setPolicySetting_: function(settingName, value, managed) {
+ setPolicySetting_(settingName, value, managed) {
if (!this.policySettings_) {
this.policySettings_ = {};
}
@@ -1034,7 +1025,7 @@ Polymer({
* @param {*} defaultMode Policy value of default mode.
* @private
*/
- configurePolicySetting_: function(settingName, allowedMode, defaultMode) {
+ configurePolicySetting_(settingName, allowedMode, defaultMode) {
switch (settingName) {
case 'headerFooter': {
const value = allowedMode !== undefined ? allowedMode : defaultMode;
@@ -1062,7 +1053,7 @@ Polymer({
* those settings from being changed via other means.
* @param {Policies} policies Value of policies.
*/
- setPolicySettings: function(policies) {
+ setPolicySettings(policies) {
if (policies === undefined) {
return;
}
@@ -1076,12 +1067,12 @@ Polymer({
});
},
- applyStickySettings: function() {
+ applyStickySettings() {
if (this.stickySettings_) {
STICKY_SETTING_NAMES.forEach(settingName => {
const setting = this.get(settingName, this.settings);
const value = this.stickySettings_[setting.key];
- if (value != undefined) {
+ if (value !== undefined) {
this.setSetting(settingName, value);
} else {
this.applyScalingStickySettings_(settingName);
@@ -1102,7 +1093,7 @@ Polymer({
* @param {string} settingName Name of the setting being applied.
* @private
*/
- applyScalingStickySettings_: function(settingName) {
+ applyScalingStickySettings_(settingName) {
// TODO(dhoss): Remove checks for 'customScaling' and 'fitToPage'
if (settingName === 'scalingType' &&
'customScaling' in this.stickySettings_) {
@@ -1126,7 +1117,7 @@ Polymer({
},
/** @private */
- applyPolicySettings_: function() {
+ applyPolicySettings_() {
if (this.policySettings_) {
for (const [settingName, policy] of Object.entries(
this.policySettings_)) {
@@ -1145,7 +1136,7 @@ Polymer({
* Restricts settings and applies defaults as defined by policy applicable to
* current destination.
*/
- applyDestinationSpecificPolicies: function() {
+ applyDestinationSpecificPolicies() {
const colorPolicy = this.destination.colorPolicy;
const colorValue =
colorPolicy ? colorPolicy : this.destination.defaultColorPolicy;
@@ -1164,7 +1155,7 @@ Polymer({
if (duplexValue) {
this.set(
'settings.duplex.value',
- duplexValue != DuplexModeRestriction.SIMPLEX);
+ duplexValue !== DuplexModeRestriction.SIMPLEX);
if (duplexValue === DuplexModeRestriction.SHORT_EDGE) {
this.set('settings.duplexShortEdge.value', true);
setDuplexTypeByPolicy = true;
@@ -1194,7 +1185,7 @@ Polymer({
// </if>
/** @private */
- updateManaged_: function() {
+ updateManaged_() {
let managedSettings = ['cssBackground', 'headerFooter'];
// <if expr="chromeos">
managedSettings =
@@ -1207,7 +1198,7 @@ Polymer({
},
/** @return {boolean} Whether the model has been initialized. */
- initialized: function() {
+ initialized() {
return this.initialized_;
},
@@ -1215,7 +1206,7 @@ Polymer({
* @return {string} The current serialized settings.
* @private
*/
- getStickySettings_: function() {
+ getStickySettings_() {
const serialization = {
version: 2,
};
@@ -1234,7 +1225,7 @@ Polymer({
* @return {!DuplexMode} The duplex mode selected.
* @private
*/
- getDuplexMode_: function() {
+ getDuplexMode_() {
if (!this.getSettingValue('duplex')) {
return DuplexMode.SIMPLEX;
}
@@ -1247,7 +1238,7 @@ Polymer({
* @return {!DuplexType} The duplex type selected.
* @private
*/
- getCddDuplexType_: function() {
+ getCddDuplexType_() {
if (!this.getSettingValue('duplex')) {
return DuplexType.NO_DUPLEX;
}
@@ -1265,7 +1256,7 @@ Polymer({
* the system dialog.
* @return {string} Serialized print ticket.
*/
- createPrintTicket: function(destination, openPdfInPreview, showSystemDialog) {
+ createPrintTicket(destination, openPdfInPreview, showSystemDialog) {
const dpi =
/**
@type {{horizontal_dpi: (number | undefined),
@@ -1290,7 +1281,7 @@ Polymer({
shouldPrintBackgrounds: this.getSettingValue('cssBackground'),
shouldPrintSelectionOnly: false, // only used in print preview
previewModifiable: this.documentSettings.isModifiable,
- printToGoogleDrive: destination.id == Destination.GooglePromotedId.DOCS,
+ printToGoogleDrive: destination.id === Destination.GooglePromotedId.DOCS,
printerType: getPrinterTypeForDestination(destination),
rasterizePDF: this.getSettingValue('rasterize'),
scaleFactor:
@@ -1313,7 +1304,7 @@ Polymer({
ticket.cloudPrintID = destination.id;
}
- if (this.getSettingValue('margins') == MarginsType.CUSTOM) {
+ if (this.getSettingValue('margins') === MarginsType.CUSTOM) {
ticket.marginsCustom = this.getSettingValue('customMargins');
}
@@ -1332,7 +1323,7 @@ Polymer({
if (this.getSettingValue('pin')) {
ticket.pinValue = this.getSettingValue('pinValue');
}
- if (destination.origin == DestinationOrigin.CROS) {
+ if (destination.origin === DestinationOrigin.CROS) {
ticket.advancedSettings = this.getSettingValue('vendorItems');
}
// </if>
@@ -1345,7 +1336,7 @@ Polymer({
* @param {!Destination} destination Destination to print to.
* @return {string} Google Cloud Print print ticket.
*/
- createCloudJobTicket: function(destination) {
+ createCloudJobTicket(destination) {
assert(
!destination.isLocal || destination.isPrivet || destination.isExtension,
'Trying to create a Google Cloud Print print ticket for a local ' +
@@ -1409,7 +1400,7 @@ Polymer({
destination.capabilities.printer.page_orientation :
null;
if (capability && capability.option &&
- capability.option.some(option => option.type == 'AUTO')) {
+ capability.option.some(option => option.type === 'AUTO')) {
cjt.print.page_orientation = {type: 'AUTO'};
}
} else {
diff --git a/chromium/chrome/browser/resources/print_preview/data/printable_area.js b/chromium/chrome/browser/resources/print_preview/data/printable_area.js
index 80b1bfbc85b..202527e3610 100644
--- a/chromium/chrome/browser/resources/print_preview/data/printable_area.js
+++ b/chromium/chrome/browser/resources/print_preview/data/printable_area.js
@@ -50,7 +50,7 @@ export class PrintableArea {
* @return {boolean} Whether another printable area is equal to this one.
*/
equals(other) {
- return other != null && this.origin_.equals(other.origin_) &&
+ return other !== null && this.origin_.equals(other.origin_) &&
this.size_.equals(other.size_);
}
}
diff --git a/chromium/chrome/browser/resources/print_preview/data/size.js b/chromium/chrome/browser/resources/print_preview/data/size.js
index 166108656d1..4a22057c0db 100644
--- a/chromium/chrome/browser/resources/print_preview/data/size.js
+++ b/chromium/chrome/browser/resources/print_preview/data/size.js
@@ -39,7 +39,7 @@ export class Size {
* @return {boolean} Whether this size object is equal to another.
*/
equals(other) {
- return other != null && this.width_ == other.width_ &&
- this.height_ == other.height_;
+ return other !== null && this.width_ === other.width_ &&
+ this.height_ === other.height_;
}
}
diff --git a/chromium/chrome/browser/resources/print_preview/data/state.js b/chromium/chrome/browser/resources/print_preview/data/state.js
index 4e40ea1f579..cbf683558ff 100644
--- a/chromium/chrome/browser/resources/print_preview/data/state.js
+++ b/chromium/chrome/browser/resources/print_preview/data/state.js
@@ -52,36 +52,36 @@ Polymer({
},
/** @param {State} newState The state to transition to. */
- transitTo: function(newState) {
+ transitTo(newState) {
switch (newState) {
case (State.NOT_READY):
assert(
- this.state == State.NOT_READY || this.state == State.READY ||
- this.state == State.ERROR);
+ this.state === State.NOT_READY || this.state === State.READY ||
+ this.state === State.ERROR);
break;
case (State.READY):
assert(
- this.state == State.ERROR || this.state == State.NOT_READY ||
- this.state == State.PRINTING);
+ this.state === State.ERROR || this.state === State.NOT_READY ||
+ this.state === State.PRINTING);
break;
case (State.HIDDEN):
- assert(this.state == State.READY);
+ assert(this.state === State.READY);
break;
case (State.PRINTING):
- assert(this.state == State.READY || this.state == State.HIDDEN);
+ assert(this.state === State.READY || this.state === State.HIDDEN);
break;
case (State.SYSTEM_DIALOG):
assert(
- this.state != State.HIDDEN && this.state != State.PRINTING &&
- this.state != State.CLOSING);
+ this.state !== State.HIDDEN && this.state !== State.PRINTING &&
+ this.state !== State.CLOSING);
break;
case (State.ERROR):
assert(
- this.state == State.ERROR || this.state == State.NOT_READY ||
- this.state == State.READY);
+ this.state === State.ERROR || this.state === State.NOT_READY ||
+ this.state === State.READY);
break;
case (State.CLOSING):
- assert(this.state != State.HIDDEN);
+ assert(this.state !== State.HIDDEN);
break;
}
this.state = newState;
diff --git a/chromium/chrome/browser/resources/print_preview/data/user_manager.js b/chromium/chrome/browser/resources/print_preview/data/user_manager.js
index cc0c839ca9e..fb96c98cfbc 100644
--- a/chromium/chrome/browser/resources/print_preview/data/user_manager.js
+++ b/chromium/chrome/browser/resources/print_preview/data/user_manager.js
@@ -9,7 +9,7 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bun
import {CloudPrintInterface, CloudPrintInterfaceErrorEventDetail, CloudPrintInterfaceEventType} from '../cloud_print_interface.js';
-import {DestinationOrigin} from './destination.js';
+import {Destination, DestinationOrigin} from './destination.js';
import {DestinationStore} from './destination_store.js';
import {InvitationStore} from './invitation_store.js';
@@ -56,7 +56,7 @@ Polymer({
users: {
type: Array,
notify: true,
- value: function() {
+ value() {
return [];
},
},
@@ -69,7 +69,7 @@ Polymer({
tracker_: new EventTracker(),
/** @override */
- detached: function() {
+ detached() {
this.tracker_.removeAll();
this.initialized_ = false;
},
@@ -78,7 +78,7 @@ Polymer({
* @param {?Array<string>} userAccounts
* @param {boolean} syncAvailable
*/
- initUserAccounts: function(userAccounts, syncAvailable) {
+ initUserAccounts(userAccounts, syncAvailable) {
assert(!this.initialized_);
this.initialized_ = true;
@@ -98,7 +98,8 @@ Polymer({
// Request the Google Docs destination from the Google Cloud Print server
// directly. We have to do this in incognito mode in order to get the
// user's login state.
- this.destinationStore.startLoadGoogleDrive();
+ this.destinationStore.startLoadCookieDestination(
+ Destination.GooglePromotedId.DOCS);
this.addWebUIListener('check-for-account-update', () => {
this.destinationStore.startLoadCloudDestinations(
DestinationOrigin.COOKIES);
@@ -107,7 +108,7 @@ Polymer({
},
/** @private */
- onCloudPrintInterfaceSet_: function() {
+ onCloudPrintInterfaceSet_() {
this.tracker_.add(
this.cloudPrintInterface.getEventTarget(),
CloudPrintInterfaceEventType.UPDATE_USERS,
@@ -133,8 +134,8 @@ Polymer({
* event Contains the error status
* @private
*/
- checkCloudPrintStatus_: function(event) {
- if (event.detail.status != 403 ||
+ checkCloudPrintStatus_(event) {
+ if (event.detail.status !== 403 ||
this.cloudPrintInterface.areCookieDestinationsDisabled()) {
return;
}
@@ -151,7 +152,7 @@ Polymer({
* active user and users.
* @private
*/
- onCloudPrintUpdateUsers_: function(e) {
+ onCloudPrintUpdateUsers_(e) {
this.updateActiveUser(e.detail.activeUser);
if (e.detail.users) {
this.updateUsers_(e.detail.users);
@@ -162,7 +163,7 @@ Polymer({
* @param {!Array<string>} users The full list of signed in users.
* @private
*/
- updateUsers_: function(users) {
+ updateUsers_(users) {
const updateActiveUser = (users.length > 0 && this.users.length === 0) ||
!users.includes(this.activeUser);
this.users = users;
@@ -175,7 +176,7 @@ Polymer({
},
/** @param {string} user The new active user. */
- updateActiveUser: function(user) {
+ updateActiveUser(user) {
if (user === this.activeUser) {
return;
}
diff --git a/chromium/chrome/browser/resources/print_preview/native_layer.js b/chromium/chrome/browser/resources/print_preview/native_layer.js
index bbddeda0bf6..7e4ae9a91e3 100644
--- a/chromium/chrome/browser/resources/print_preview/native_layer.js
+++ b/chromium/chrome/browser/resources/print_preview/native_layer.js
@@ -144,7 +144,7 @@ export class NativeLayer {
* @return {!NativeLayer} The singleton instance.
*/
static getInstance() {
- if (currentInstance == null) {
+ if (currentInstance === null) {
currentInstance = new NativeLayer();
}
return assert(currentInstance);
@@ -198,7 +198,7 @@ export class NativeLayer {
getPrinterCapabilities(destinationId, type) {
return sendWithPromise(
'getPrinterCapabilities', destinationId,
- destinationId == Destination.GooglePromotedId.SAVE_AS_PDF ?
+ destinationId === Destination.GooglePromotedId.SAVE_AS_PDF ?
PrinterType.PDF_PRINTER :
type);
}
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.html b/chromium/chrome/browser/resources/print_preview/print_preview.html
index 80cdb5afc44..4aa26d79dbd 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview.html
+++ b/chromium/chrome/browser/resources/print_preview/print_preview.html
@@ -2,6 +2,7 @@
<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{a11yenhanced}
class="loading">
<head>
+ <title>$i18n{title}</title>
<meta charset="utf-8">
<if expr="not optimize_webui">
<base href="chrome://print">
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview.js b/chromium/chrome/browser/resources/print_preview/print_preview.js
index 5237bc238d2..80aa82a4711 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview.js
+++ b/chromium/chrome/browser/resources/print_preview/print_preview.js
@@ -21,6 +21,7 @@ export {Size} from './data/size.js';
export {Error, State} from './data/state.js';
export {BackgroundGraphicsModeRestriction, NativeLayer} from './native_layer.js';
export {getSelectDropdownBackground} from './print_preview_utils.js';
+export {DEFAULT_MAX_COPIES} from './ui/copies_settings.js';
export {DestinationState} from './ui/destination_settings.js';
export {PluginProxy} from './ui/plugin_proxy.js';
export {PreviewAreaState} from './ui/preview_area.js';
diff --git a/chromium/chrome/browser/resources/print_preview/print_preview_utils.js b/chromium/chrome/browser/resources/print_preview/print_preview_utils.js
index 1f9c2ab7996..2af9c619623 100644
--- a/chromium/chrome/browser/resources/print_preview/print_preview_utils.js
+++ b/chromium/chrome/browser/resources/print_preview/print_preview_utils.js
@@ -14,11 +14,11 @@ import {DarkModeBehavior} from './dark_mode_behavior.js';
* @return {boolean} true if the arrays are equal.
*/
export function areRangesEqual(array1, array2) {
- if (array1.length != array2.length) {
+ if (array1.length !== array2.length) {
return false;
}
for (let i = 0; i < array1.length; i++) {
- if (array1[i].from != array2[i].from || array1[i].to != array2[i].to) {
+ if (array1[i].from !== array2[i].from || array1[i].to !== array2[i].to) {
return false;
}
}
@@ -35,7 +35,7 @@ export function areRangesEqual(array1, array2) {
export function getStringForLocale(localizedStrings, locale) {
locale = locale.toLowerCase();
for (let i = 0; i < localizedStrings.length; i++) {
- if (localizedStrings[i].locale.toLowerCase() == locale) {
+ if (localizedStrings[i].locale.toLowerCase() === locale) {
return localizedStrings[i].value;
}
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/BUILD.gn b/chromium/chrome/browser/resources/print_preview/ui/BUILD.gn
index fb2567297cd..b33e1f7e245 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/BUILD.gn
+++ b/chromium/chrome/browser/resources/print_preview/ui/BUILD.gn
@@ -318,9 +318,7 @@ js_library("settings_behavior") {
}
js_library("input_behavior") {
- deps = [
- "//ui/webui/resources/js:assert.m",
- ]
+ deps = [ "//ui/webui/resources/js:assert.m" ]
}
js_library("select_behavior") {
@@ -485,7 +483,7 @@ js_library("highlight_utils") {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":advanced_options_settings_module",
":advanced_settings_dialog_module",
":advanced_settings_item_module",
diff --git a/chromium/chrome/browser/resources/print_preview/ui/advanced_options_settings.js b/chromium/chrome/browser/resources/print_preview/ui/advanced_options_settings.js
index 2b197cada75..b2712c604d8 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/advanced_options_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/advanced_options_settings.js
@@ -34,12 +34,12 @@ Polymer({
},
/** @private */
- onButtonClick_: function() {
+ onButtonClick_() {
this.showAdvancedDialog_ = true;
},
/** @private */
- onDialogClose_: function() {
+ onDialogClose_() {
this.showAdvancedDialog_ = false;
this.$.button.focus();
},
diff --git a/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html b/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html
index 5351a4959e0..df22693f2a3 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.html
@@ -5,29 +5,55 @@
max-width: calc(100vw - 2 * var(--print-preview-dialog-margin));
}
+ #dialog::part(wrapper) {
+ height: calc(100vh - 2 * var(--print-preview-dialog-margin));
+ }
+
+ #dialog::part(body-container) {
+ flex: 1;
+ }
+
print-preview-search-box {
margin-bottom: 8px;
- margin-top: 24px;
+ margin-top: 16px;
+ }
+
+ cr-dialog [slot=body] {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ }
+
+ #itemList {
+ flex: 1;
+ overflow-x: hidden;
+ overflow-y: overlay;
+ }
+
+ #itemList.searching {
+ padding-bottom: 20px;
+ padding-top: 20px;
}
</style>
<cr-dialog id="dialog" on-close="onCloseOrCancel_">
<div slot="title">
- <div>[[i18n('advancedSettingsDialogTitle', destination.displayName)]]
- </div>
+ [[i18n('advancedSettingsDialogTitle', destination.displayName)]]
+ </div>
+ <div slot="body">
<print-preview-search-box id="searchBox"
hidden$="[[!hasMultipleItems_(
destination.capabilities.printer.vendor_capability)]]"
label="$i18n{advancedSettingsSearchBoxPlaceholder}"
search-query="{{searchQuery_}}" autofocus>
</print-preview-search-box>
- </div>
- <div slot="body">
- <template is="dom-repeat"
- items="[[destination.capabilities.printer.vendor_capability]]">
- <print-preview-advanced-settings-item capability="[[item]]"
- settings="[[settings]]">
- </print-preview-advanced-settings-item>
- </template>
+ <div id="itemList" class$="[[isSearching_(searchQuery_)]]">
+ <template is="dom-repeat"
+ items="[[destination.capabilities.printer.vendor_capability]]">
+ <print-preview-advanced-settings-item capability="[[item]]"
+ settings="[[settings]]">
+ </print-preview-advanced-settings-item>
+ </template>
+ </div>
<div class="no-settings-match-hint"
hidden$="[[!shouldShowHint_(hasMatching_)]]">
$i18n{noAdvancedSettingsMatchSearchHint}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.js b/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.js
index c74d6bf08b0..4036512b361 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.js
@@ -49,17 +49,17 @@ Polymer({
'keydown': 'onKeydown_',
},
- /** @private {!Array<Node>} */
+ /** @private {!Array<!Node>} */
highlights_: [],
- /** @private {!Array<Node>} */
- bubbles_: [],
+ /** @private {!Map<!Node, number>} */
+ bubbles_: new Map,
/** @private {!MetricsContext} */
metrics_: MetricsContext.printSettingsUi(),
/** @override */
- attached: function() {
+ attached() {
this.metrics_.record(
Metrics.PrintSettingsUiBucket.ADVANCED_SETTINGS_DIALOG_SHOWN);
this.$.dialog.showModal();
@@ -69,17 +69,18 @@ Polymer({
* @param {!KeyboardEvent} e Event containing the key
* @private
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
e.stopPropagation();
const searchInput = this.$.searchBox.getSearchInput();
const eventInSearchBox = e.composedPath().includes(searchInput);
- if (e.key == 'Escape' && (!eventInSearchBox || !searchInput.value.trim())) {
+ if (e.key === 'Escape' &&
+ (!eventInSearchBox || !searchInput.value.trim())) {
this.$.dialog.cancel();
e.preventDefault();
return;
}
- if (e.key == 'Enter' && !eventInSearchBox) {
+ if (e.key === 'Enter' && !eventInSearchBox) {
const activeElementTag = e.composedPath()[0].tagName;
if (['CR-BUTTON', 'SELECT'].includes(activeElementTag)) {
return;
@@ -94,7 +95,7 @@ Polymer({
* @return {boolean} Whether there is more than one vendor item to display.
* @private
*/
- hasMultipleItems_: function() {
+ hasMultipleItems_() {
return this.destination.capabilities.printer.vendor_capability.length > 1;
},
@@ -102,17 +103,15 @@ Polymer({
* @return {boolean} Whether there is a setting matching the query.
* @private
*/
- computeHasMatching_: function() {
+ computeHasMatching_() {
if (!this.shadowRoot) {
return true;
}
removeHighlights(this.highlights_);
- for (const bubble of this.bubbles_) {
- bubble.remove();
- }
+ this.bubbles_.forEach((number, bubble) => bubble.remove());
this.highlights_ = [];
- this.bubbles_ = [];
+ this.bubbles_.clear();
const listItems = this.shadowRoot.querySelectorAll(
'print-preview-advanced-settings-item');
@@ -121,9 +120,8 @@ Polymer({
const matches = item.hasMatch(this.searchQuery_);
item.hidden = !matches;
hasMatch = hasMatch || matches;
- const result = item.updateHighlighting(this.searchQuery_);
- this.highlights_.push(...result.highlights);
- this.bubbles_.push(...result.bubbles);
+ this.highlights_.push(
+ ...item.updateHighlighting(this.searchQuery_, this.bubbles_));
});
return hasMatch;
},
@@ -132,28 +130,28 @@ Polymer({
* @return {boolean} Whether the no matching settings hint should be shown.
* @private
*/
- shouldShowHint_: function() {
+ shouldShowHint_() {
return !!this.searchQuery_ && !this.hasMatching_;
},
/** @private */
- onCloseOrCancel_: function() {
+ onCloseOrCancel_() {
if (this.searchQuery_) {
this.$.searchBox.setValue('');
}
- if (this.$.dialog.getNative().returnValue == 'success') {
+ if (this.$.dialog.getNative().returnValue === 'success') {
this.metrics_.record(
Metrics.PrintSettingsUiBucket.ADVANCED_SETTINGS_DIALOG_CANCELED);
}
},
/** @private */
- onCancelButtonClick_: function() {
+ onCancelButtonClick_() {
this.$.dialog.cancel();
},
/** @private */
- onApplyButtonClick_: function() {
+ onApplyButtonClick_() {
const settingsValues = {};
this.shadowRoot.querySelectorAll('print-preview-advanced-settings-item')
.forEach(item => {
@@ -163,7 +161,15 @@ Polymer({
this.$.dialog.close();
},
- close: function() {
+ close() {
this.$.dialog.close();
},
+
+ /**
+ * @return {string}
+ * @private
+ */
+ isSearching_() {
+ return this.searchQuery_ ? 'searching' : '';
+ },
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_item.js b/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_item.js
index e70f0b0e7e6..84ca21aaea5 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_item.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/advanced_settings_item.js
@@ -15,7 +15,7 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bun
import {Destination, VendorCapability, VendorCapabilitySelectOption} from '../data/destination.js';
import {getStringForCurrentLocale} from '../print_preview_utils.js';
-import {HighlightResults, updateHighlights} from './highlight_utils.js';
+import {updateHighlights} from './highlight_utils.js';
import {SettingsBehavior} from './settings_behavior.js';
Polymer({
@@ -38,7 +38,7 @@ Polymer({
],
/** @private */
- updateFromSettings_: function() {
+ updateFromSettings_() {
const settings = this.getSetting('vendorItems').value;
// The settings may not have a property with the id if they were populated
@@ -67,7 +67,7 @@ Polymer({
* @return {string} The display name for the setting.
* @private
*/
- getDisplayName_: function(item) {
+ getDisplayName_(item) {
let displayName = item.display_name;
if (!displayName && item.display_name_localized) {
displayName = getStringForCurrentLocale(item.display_name_localized);
@@ -80,8 +80,8 @@ Polymer({
* of type select.
* @private
*/
- isCapabilityTypeSelect_: function() {
- return this.capability.type == 'SELECT';
+ isCapabilityTypeSelect_() {
+ return this.capability.type === 'SELECT';
},
/**
@@ -89,9 +89,9 @@ Polymer({
* of type checkbox.
* @private
*/
- isCapabilityTypeCheckbox_: function() {
- return this.capability.type == 'TYPED_VALUE' &&
- this.capability.typed_value_cap.value_type == 'BOOLEAN';
+ isCapabilityTypeCheckbox_() {
+ return this.capability.type === 'TYPED_VALUE' &&
+ this.capability.typed_value_cap.value_type === 'BOOLEAN';
},
/**
@@ -99,7 +99,7 @@ Polymer({
* of type input.
* @private
*/
- isCapabilityTypeInput_: function() {
+ isCapabilityTypeInput_() {
return !this.isCapabilityTypeSelect_() && !this.isCapabilityTypeCheckbox_();
},
@@ -107,8 +107,8 @@ Polymer({
* @return {boolean} Whether the checkbox setting is checked.
* @private
*/
- isChecked_: function() {
- return this.currentValue_ == 'true';
+ isChecked_() {
+ return this.currentValue_ === 'true';
},
/**
@@ -117,7 +117,7 @@ Polymer({
* @return {boolean} Whether the option is selected.
* @private
*/
- isOptionSelected_: function(option) {
+ isOptionSelected_(option) {
return this.currentValue_ === undefined ?
!!option.is_default :
option.value === this.currentValue_;
@@ -127,14 +127,14 @@ Polymer({
* @return {string} The placeholder value for the capability's text input.
* @private
*/
- getCapabilityPlaceholder_: function() {
- if (this.capability.type == 'TYPED_VALUE' &&
+ getCapabilityPlaceholder_() {
+ if (this.capability.type === 'TYPED_VALUE' &&
this.capability.typed_value_cap &&
- this.capability.typed_value_cap.default != undefined) {
+ this.capability.typed_value_cap.default !== undefined) {
return this.capability.typed_value_cap.default.toString() || '';
}
- if (this.capability.type == 'RANGE' && this.capability.range_cap &&
- this.capability.range_cap.default != undefined) {
+ if (this.capability.type === 'RANGE' && this.capability.range_cap &&
+ this.capability.range_cap.default !== undefined) {
return this.capability.range_cap.default.toString() || '';
}
return '';
@@ -144,17 +144,18 @@ Polymer({
* @return {boolean}
* @private
*/
- hasOptionWithValue_: function(value) {
+ hasOptionWithValue_(value) {
return !!this.capability.select_cap &&
!!this.capability.select_cap.option &&
- this.capability.select_cap.option.some(option => option.value == value);
+ this.capability.select_cap.option.some(
+ option => option.value === value);
},
/**
* @param {?RegExp} query The current search query.
* @return {boolean} Whether the item has a match for the query.
*/
- hasMatch: function(query) {
+ hasMatch(query) {
if (!query || this.getDisplayName_(this.capability).match(query)) {
return true;
}
@@ -177,7 +178,7 @@ Polymer({
* @param {!Event} e Event containing the new value.
* @private
*/
- onUserInput_: function(e) {
+ onUserInput_(e) {
this.currentValue_ = e.target.value;
},
@@ -185,7 +186,7 @@ Polymer({
* @param {!Event} e Event containing the new value.
* @private
*/
- onCheckboxInput_: function(e) {
+ onCheckboxInput_(e) {
this.currentValue_ = e.target.checked ? 'true' : 'false';
},
@@ -193,7 +194,7 @@ Polymer({
* @return {string} The current value of the setting, or the empty string if
* it is not set.
*/
- getCurrentValue: function() {
+ getCurrentValue() {
return this.currentValue_ || '';
},
@@ -201,16 +202,16 @@ Polymer({
* Only used in tests.
* @param {string} value A value to set the setting to.
*/
- setCurrentValueForTest: function(value) {
+ setCurrentValueForTest(value) {
this.currentValue_ = value;
},
/**
* @param {?RegExp} query The current search query.
- * @return {!HighlightResults} The highlight wrappers and
- * search bubbles that were created.
+ * @param {!Map<!Node, number>} bubbles
+ * @return {!Array<!Node>} The highlight wrappers and that were created.
*/
- updateHighlighting: function(query) {
- return updateHighlights(this, query);
+ updateHighlighting(query, bubbles) {
+ return updateHighlights(this, query, bubbles);
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/app.js b/chromium/chrome/browser/resources/print_preview/ui/app.js
index fe5c9bce7f6..7e8e246f32d 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/app.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/app.js
@@ -147,7 +147,7 @@ Polymer({
openDialogs_: [],
/** @override */
- created: function() {
+ created() {
// Regular expression that captures the leading slash, the content and the
// trailing slash in three different groups.
const CANONICAL_PATH_REGEX = /(^\/)([\/-\w]+)(\/$)/;
@@ -158,12 +158,12 @@ Polymer({
},
/** @override */
- ready: function() {
+ ready() {
FocusOutlineManager.forDocument(document);
},
/** @override */
- attached: function() {
+ attached() {
document.documentElement.classList.remove('loading');
this.nativeLayer_ = NativeLayer.getInstance();
this.addWebUIListener('print-failed', this.onPrintFailed_.bind(this));
@@ -177,13 +177,13 @@ Polymer({
},
/** @override */
- detached: function() {
+ detached() {
this.tracker_.removeAll();
this.whenReady_ = null;
},
/** @private */
- onSidebarFocus_: function() {
+ onSidebarFocus_() {
this.$.previewArea.hideToolbars();
},
@@ -193,13 +193,13 @@ Polymer({
* @param {!KeyboardEvent} e The keyboard event.
* @private
*/
- onKeyDown_: function(e) {
+ onKeyDown_(e) {
// Escape key closes the topmost dialog that is currently open within
// Print Preview. If no such dialog exists, then the Print Preview dialog
// itself is closed.
- if (e.code == 'Escape' && !hasKeyModifiers(e)) {
+ if (e.code === 'Escape' && !hasKeyModifiers(e)) {
// Don't close the Print Preview dialog if there is a child dialog open.
- if (this.openDialogs_.length != 0) {
+ if (this.openDialogs_.length !== 0) {
// Manually cancel the dialog, since we call preventDefault() to prevent
// views from closing the Print Preview dialog.
const dialogToClose = this.openDialogs_[this.openDialogs_.length - 1];
@@ -218,14 +218,14 @@ Polymer({
}
// On Mac, Cmd+Period should close the print dialog.
- if (isMac && e.code == 'Period' && e.metaKey) {
+ if (isMac && e.code === 'Period' && e.metaKey) {
this.close_();
e.preventDefault();
return;
}
// Ctrl + Shift + p / Mac equivalent.
- if (e.code == 'KeyP') {
+ if (e.code === 'KeyP') {
if ((isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
(!isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
// Don't use system dialog if the link isn't available.
@@ -236,7 +236,7 @@ Polymer({
// Don't try to print with system dialog on Windows if the document is
// not ready, because we send the preview document to the printer on
// Windows.
- if (!isWindows || this.state == State.READY) {
+ if (!isWindows || this.state === State.READY) {
this.onPrintWithSystemDialog_();
}
e.preventDefault();
@@ -265,7 +265,7 @@ Polymer({
* @param {!Event} e The cr-dialog-open event.
* @private
*/
- onCrDialogOpen_: function(e) {
+ onCrDialogOpen_(e) {
this.openDialogs_.push(
/** @type {!CrDialogElement} */ (e.composedPath()[0]));
},
@@ -274,13 +274,13 @@ Polymer({
* @param {!Event} e The close event.
* @private
*/
- onCrDialogClose_: function(e) {
+ onCrDialogClose_(e) {
// Note: due to event re-firing in cr_dialog.js, this event will always
// appear to be coming from the outermost child dialog.
// TODO(rbpotter): Fix event re-firing so that the event comes from the
// dialog that has been closed, and add an assertion that the removed
// dialog matches e.composedPath()[0].
- if (e.composedPath()[0].nodeName == 'CR-DIALOG') {
+ if (e.composedPath()[0].nodeName === 'CR-DIALOG') {
this.openDialogs_.pop();
}
},
@@ -289,7 +289,7 @@ Polymer({
* @param {!NativeInitialSettings} settings
* @private
*/
- onInitialSettingsSet_: function(settings) {
+ onInitialSettingsSet_(settings) {
if (!this.whenReady_) {
// This element and its corresponding model were detached while waiting
// for the callback. This can happen in tests; return early.
@@ -338,7 +338,7 @@ Polymer({
* @param {string} uiLocale The UI locale.
* @private
*/
- initializeCloudPrint_: function(cloudPrintUrl, appKioskMode, uiLocale) {
+ initializeCloudPrint_(cloudPrintUrl, appKioskMode, uiLocale) {
assert(!this.cloudPrintInterface_);
this.cloudPrintInterface_ = getCloudPrintInterface(
cloudPrintUrl, assert(this.nativeLayer_), appKioskMode, uiLocale);
@@ -356,12 +356,12 @@ Polymer({
* are managed.
* @private
*/
- computeControlsManaged_: function() {
+ computeControlsManaged_() {
return this.destinationsManaged_ || this.settingsManaged_;
},
/** @private */
- onDestinationStateChange_: function() {
+ onDestinationStateChange_() {
switch (this.destinationState_) {
case DestinationState.SELECTED:
case DestinationState.SET:
@@ -399,12 +399,12 @@ Polymer({
* @param {!CustomEvent<string>} e Event containing the new sticky settings.
* @private
*/
- onStickySettingChanged_: function(e) {
+ onStickySettingChanged_(e) {
this.nativeLayer_.saveAppState(e.detail);
},
/** @private */
- onPreviewSettingChanged_: function() {
+ onPreviewSettingChanged_() {
if (this.state === State.READY) {
this.$.previewArea.startPreview(false);
this.startPreviewWhenReady_ = false;
@@ -414,8 +414,8 @@ Polymer({
},
/** @private */
- onStateChanged_: function() {
- if (this.state == State.READY) {
+ onStateChanged_() {
+ if (this.state === State.READY) {
if (this.startPreviewWhenReady_) {
this.$.previewArea.startPreview(false);
this.startPreviewWhenReady_ = false;
@@ -425,16 +425,16 @@ Polymer({
// Reset in case printing fails.
this.printRequested_ = false;
}
- } else if (this.state == State.CLOSING) {
+ } else if (this.state === State.CLOSING) {
this.remove();
this.nativeLayer_.dialogClose(this.cancelled_);
- } else if (this.state == State.HIDDEN) {
+ } else if (this.state === State.HIDDEN) {
if (this.destination_.isLocal &&
this.destination_.id !== Destination.GooglePromotedId.SAVE_AS_PDF) {
// Only hide the preview for local, non PDF destinations.
this.nativeLayer_.hidePreview();
}
- } else if (this.state == State.PRINTING) {
+ } else if (this.state === State.PRINTING) {
const destination = assert(this.destination_);
const whenPrintDone =
this.nativeLayer_.print(this.$.model.createPrintTicket(
@@ -442,7 +442,7 @@ Polymer({
this.showSystemDialogBeforePrint_));
if (destination.isLocal) {
const onError =
- destination.id == Destination.GooglePromotedId.SAVE_AS_PDF ?
+ destination.id === Destination.GooglePromotedId.SAVE_AS_PDF ?
this.onFileSelectionCancel_.bind(this) :
this.onPrintFailed_.bind(this);
whenPrintDone.then(this.close_.bind(this), onError);
@@ -457,7 +457,7 @@ Polymer({
},
/** @private */
- onPrintRequested_: function() {
+ onPrintRequested_() {
if (this.state === State.NOT_READY) {
this.printRequested_ = true;
return;
@@ -467,7 +467,7 @@ Polymer({
},
/** @private */
- onCancelRequested_: function() {
+ onCancelRequested_() {
this.cancelled_ = true;
this.$.state.transitTo(State.CLOSING);
},
@@ -476,7 +476,7 @@ Polymer({
* @param {!CustomEvent<boolean>} e The event containing the new validity.
* @private
*/
- onSettingValidChanged_: function(e) {
+ onSettingValidChanged_(e) {
if (e.detail) {
this.$.state.transitTo(State.READY);
} else {
@@ -486,7 +486,7 @@ Polymer({
},
/** @private */
- onFileSelectionCancel_: function() {
+ onFileSelectionCancel_() {
this.$.state.transitTo(State.READY);
},
@@ -496,9 +496,10 @@ Polymer({
* @param {string} data The body to send in the HTTP request.
* @private
*/
- onPrintToCloud_: function(data) {
+ onPrintToCloud_(data) {
assert(
- this.cloudPrintInterface_ != null, 'Google Cloud Print is not enabled');
+ this.cloudPrintInterface_ !== null,
+ 'Google Cloud Print is not enabled');
const destination = assert(this.destination_);
this.cloudPrintInterface_.submit(
destination, this.$.model.createCloudJobTicket(destination),
@@ -507,7 +508,7 @@ Polymer({
// <if expr="not chromeos">
/** @private */
- onPrintWithSystemDialog_: function() {
+ onPrintWithSystemDialog_() {
// <if expr="is_win">
this.showSystemDialogBeforePrint_ = true;
this.onPrintRequested_();
@@ -521,7 +522,7 @@ Polymer({
// <if expr="is_macosx">
/** @private */
- onOpenPdfInPreview_: function() {
+ onOpenPdfInPreview_() {
this.openPdfInPreview_ = true;
this.$.previewArea.setOpeningPdfInPreview();
this.onPrintRequested_();
@@ -534,14 +535,14 @@ Polymer({
* the error, if not an HTTP error.
* @private
*/
- onPrintFailed_: function(httpError) {
+ onPrintFailed_(httpError) {
console.error('Printing failed with error code ' + httpError);
this.error_ = Error.PRINT_FAILED;
this.$.state.transitTo(State.FATAL_ERROR);
},
/** @private */
- onPreviewStateChange_: function() {
+ onPreviewStateChange_() {
switch (this.previewState_) {
case PreviewAreaState.DISPLAY_PREVIEW:
case PreviewAreaState.OPEN_IN_PREVIEW_LOADED:
@@ -569,15 +570,15 @@ Polymer({
* event Contains the error message.
* @private
*/
- onCloudPrintError_: function(appKioskMode, event) {
- if (event.detail.status == 0 ||
- (event.detail.status == 403 && !appKioskMode)) {
+ onCloudPrintError_(appKioskMode, event) {
+ if (event.detail.status === 0 ||
+ (event.detail.status === 403 && !appKioskMode)) {
return; // No internet connectivity or not signed in.
}
this.cloudPrintErrorMessage_ = event.detail.message;
this.error_ = Error.CLOUD_PRINT_ERROR;
this.$.state.transitTo(State.FATAL_ERROR);
- if (event.detail.status == 200) {
+ if (event.detail.status === 200) {
console.error(
'Google Cloud Print Error: ' +
`(${event.detail.errorCode}) ${event.detail.message}`);
@@ -596,7 +597,7 @@ Polymer({
* from the document.
* @private
*/
- onPrintPresetOptions_: function(disableScaling, copies, duplex) {
+ onPrintPresetOptions_(disableScaling, copies, duplex) {
if (disableScaling) {
this.$.documentInfo.updateIsScalingDisabled(true);
}
@@ -627,12 +628,12 @@ Polymer({
* @param {!CustomEvent<number>} e Contains the new preview request ID.
* @private
*/
- onPreviewStart_: function(e) {
+ onPreviewStart_(e) {
this.$.documentInfo.inFlightRequestId = e.detail;
},
/** @private */
- close_: function() {
+ close_() {
this.$.state.transitTo(State.CLOSING);
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/button_strip.js b/chromium/chrome/browser/resources/print_preview/ui/button_strip.js
index ae801713a47..6629a3cb3c2 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/button_strip.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/button_strip.js
@@ -38,7 +38,7 @@ Polymer({
/** @private */
printButtonLabel_: {
type: String,
- value: function() {
+ value() {
return loadTimeData.getString('printButton');
},
},
@@ -50,12 +50,12 @@ Polymer({
lastState_: State.NOT_READY,
/** @private */
- onPrintClick_: function() {
+ onPrintClick_() {
this.fire('print-requested');
},
/** @private */
- onCancelClick_: function() {
+ onCancelClick_() {
this.fire('cancel-requested');
},
@@ -63,20 +63,20 @@ Polymer({
* @return {boolean}
* @private
*/
- isPdfOrDrive_: function() {
+ isPdfOrDrive_() {
return this.destination &&
- (this.destination.id == Destination.GooglePromotedId.SAVE_AS_PDF ||
- this.destination.id == Destination.GooglePromotedId.DOCS);
+ (this.destination.id === Destination.GooglePromotedId.SAVE_AS_PDF ||
+ this.destination.id === Destination.GooglePromotedId.DOCS);
},
/** @private */
- updatePrintButtonLabel_: function() {
+ updatePrintButtonLabel_() {
this.printButtonLabel_ = loadTimeData.getString(
this.isPdfOrDrive_() ? 'saveButton' : 'printButton');
},
/** @private */
- updatePrintButtonEnabled_: function() {
+ updatePrintButtonEnabled_() {
switch (this.state) {
case (State.PRINTING):
this.printButtonEnabled_ = false;
diff --git a/chromium/chrome/browser/resources/print_preview/ui/color_settings.js b/chromium/chrome/browser/resources/print_preview/ui/color_settings.js
index df5bdf11935..5ef123fd04d 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/color_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/color_settings.js
@@ -34,7 +34,7 @@ Polymer({
* @param {*} newValue The new value of the color setting.
* @private
*/
- onColorSettingChange_: function(newValue) {
+ onColorSettingChange_(newValue) {
this.selectedValue = /** @type {boolean} */ (newValue) ? 'color' : 'bw';
},
@@ -44,12 +44,12 @@ Polymer({
* @return {boolean} Whether drop-down should be disabled.
* @private
*/
- computeDisabled_: function(disabled, managed) {
+ computeDisabled_(disabled, managed) {
return !!(disabled || managed);
},
/** @param {string} value The new select value. */
- onProcessSelectChange: function(value) {
- this.setSetting('color', value == 'color');
+ onProcessSelectChange(value) {
+ this.setSetting('color', value === 'color');
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/copies_settings.html b/chromium/chrome/browser/resources/print_preview/ui/copies_settings.html
index 75b632433e7..db5c19e362a 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/copies_settings.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/copies_settings.html
@@ -3,13 +3,15 @@
margin-inline-start: 16px;
}
</style>
-<print-preview-number-settings-section max-value="999" min-value="1"
+<print-preview-number-settings-section max-value="[[copiesMax_]]" min-value="1"
default-value="1" input-label="$i18n{copiesLabel}"
input-aria-label="$i18n{copiesLabel}"
disabled="[[disabled]]" current-value="{{currentValue_}}"
- input-valid="{{inputValid_}}" hint-message="$i18n{copiesInstruction}">
+ input-valid="{{inputValid_}}"
+ hint-message="[[getHintMessage_(copiesMax_)]]">
<div slot="opt-inside-content" class="checkbox" aria-live="polite"
- hidden$="[[collateHidden_(currentValue_, inputValid_)]]">
+ hidden$="[[collateHidden_(
+ currentValue_, settings.collate.available, inputValid_)]]">
<cr-checkbox id="collate" on-change="onCollateChange_"
disabled="[[disabled]]" aria-labelledby="copies-collate-label">
<span id="copies-collate-label">$i18n{optionCollate}</span>
diff --git a/chromium/chrome/browser/resources/print_preview/ui/copies_settings.js b/chromium/chrome/browser/resources/print_preview/ui/copies_settings.js
index 69fce4831df..25195c01da6 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/copies_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/copies_settings.js
@@ -6,10 +6,18 @@ import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
import './number_settings_section.js';
import './print_preview_shared_css.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {SettingsBehavior} from './settings_behavior.js';
+/**
+ * Maximum number of copies supported by the printer if not explicitly
+ * specified.
+ * @type {number}
+ */
+export const DEFAULT_MAX_COPIES = 999;
+
Polymer({
is: 'print-preview-copies-settings',
@@ -18,6 +26,14 @@ Polymer({
behaviors: [SettingsBehavior],
properties: {
+ capability: Object,
+
+ /** @private {number} */
+ copiesMax_: {
+ type: Number,
+ computed: 'computeCopiesMax_(capability)',
+ },
+
/** @private {string} */
currentValue_: {
type: String,
@@ -30,14 +46,30 @@ Polymer({
disabled: Boolean,
},
- observers:
- ['onSettingsChanged_(settings.copies.value, settings.collate.value)'],
+ observers: ['onSettingsChanged_(settings.copies.value, settings.collate.*)'],
+
+ /**
+ * @return {number} The maximum number of copies this printer supports.
+ * @private
+ */
+ computeCopiesMax_() {
+ return (this.capability && this.capability.max) ? this.capability.max :
+ DEFAULT_MAX_COPIES;
+ },
+
+ /**
+ * @return {string} The message to show as hint.
+ * @private
+ */
+ getHintMessage_() {
+ return loadTimeData.getStringF('copiesInstruction', this.copiesMax_);
+ },
/**
* Updates the input string when the setting has been initialized.
* @private
*/
- onSettingsChanged_: function() {
+ onSettingsChanged_() {
const copies = this.getSetting('copies');
if (this.inputValid_) {
this.currentValue_ = /** @type {string} */ (copies.value.toString());
@@ -51,7 +83,7 @@ Polymer({
* and current value of the copies input.
* @private
*/
- onInputChanged_: function() {
+ onInputChanged_() {
if (this.currentValue_ !== '' &&
this.currentValue_ !== this.getSettingValue('copies').toString()) {
this.setSetting(
@@ -64,13 +96,13 @@ Polymer({
* @return {boolean} Whether collate checkbox should be hidden.
* @private
*/
- collateHidden_: function() {
- return !this.inputValid_ || this.currentValue_ === '' ||
- parseInt(this.currentValue_, 10) == 1;
+ collateHidden_() {
+ return !this.getSetting('collate').available || !this.inputValid_ ||
+ this.currentValue_ === '' || parseInt(this.currentValue_, 10) === 1;
},
/** @private */
- onCollateChange_: function() {
+ onCollateChange_() {
this.setSetting('collate', this.$.collate.checked);
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.html b/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.html
index a9873cd3c0e..56a6a8d8ee6 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.html
@@ -16,25 +16,26 @@
print-preview-search-box {
margin-bottom: 16px;
- margin-top: 14px;
+ margin-top: 6px;
}
.user-info {
- font-size: calc(13 / 15 * 1em);
line-height: calc(20 / 15 * 1em);
margin-bottom: 14px;
- margin-top: 8px;
}
- .user-info .account-select-label {
- padding-inline-end: 18px;
+ .user-info .md-select {
+ width: auto;
}
- .user-info .account-select {
- width: auto
+ #accountSelectLabel {
+ color: var(--cr-primary-text-color);
+ padding-inline-end: 18px;
}
cr-dialog [slot=body] {
+ display: flex;
+ flex-direction: column;
height: 100%;
}
@@ -113,18 +114,14 @@
}
</style>
<cr-dialog id="dialog" on-close="onCloseOrCancel_">
- <div slot="title" id="header">
- <div>$i18n{destinationSearchTitle}</div>
+ <div slot="title" id="header">$i18n{destinationSearchTitle}</div>
+ <div slot="body">
<div class="user-info" hidden$="[[!activeUser]]" hidden>
- <label class="account-select-label" id="accountSelectLabel">
- $i18n{accountSelectTitle}
- </label>
- <select class="md-select account-select"
+ <label id="accountSelectLabel">$i18n{accountSelectTitle}</label>
+ <select class="md-select"
aria-labelledby="accountSelectLabel" on-change="onUserChange_">
<template is="dom-repeat" items="[[users]]">
- <option value="[[item]]">
- [[item]]
- </option>
+ <option value="[[item]]">[[item]]</option>
</template>
<option value="">$i18n{addAccountTitle}</option>
</select>
@@ -133,13 +130,10 @@
label="$i18n{searchBoxPlaceholder}" search-query="{{searchQuery_}}"
autofocus>
</print-preview-search-box>
- </div>
- <div slot="body">
<print-preview-destination-list id="printList"
destinations="[[destinations_]]"
loading-destinations="[[loadingDestinations_]]"
search-query="[[searchQuery_]]"
- list-name="$i18n{printDestinationsTitle}"
on-destination-selected="onDestinationSelected_">
</print-preview-destination-list>
<print-preview-provisional-destination-resolver id="provisionalResolver"
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.js b/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.js
index 2f24d98b292..e0532e60acf 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_dialog.js
@@ -125,27 +125,27 @@ Polymer({
initialized_: false,
/** @override */
- ready: function() {
+ ready() {
this.$$('.promo-text').innerHTML =
this.i18nAdvanced('cloudPrintPromotion', {
substitutions: ['<a is="action-link" class="sign-in">', '</a>'],
attrs: {
- 'is': (node, v) => v == 'action-link',
- 'class': (node, v) => v == 'sign-in',
- 'tabindex': (node, v) => v == '0',
- 'role': (node, v) => v == 'link',
+ 'is': (node, v) => v === 'action-link',
+ 'class': (node, v) => v === 'sign-in',
+ 'tabindex': (node, v) => v === '0',
+ 'role': (node, v) => v === 'link',
},
});
},
/** @override */
- attached: function() {
+ attached() {
this.tracker_.add(
assert(this.$$('.sign-in')), 'click', this.onSignInClick_.bind(this));
},
/** @override */
- detached: function() {
+ detached() {
this.tracker_.removeAll();
},
@@ -153,10 +153,10 @@ Polymer({
* @param {!KeyboardEvent} e Event containing the key
* @private
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
e.stopPropagation();
const searchInput = this.$.searchBox.getSearchInput();
- if (e.key == 'Escape' &&
+ if (e.key === 'Escape' &&
(e.composedPath()[0] !== searchInput || !searchInput.value.trim())) {
this.$.dialog.cancel();
e.preventDefault();
@@ -164,8 +164,8 @@ Polymer({
},
/** @private */
- onDestinationStoreSet_: function() {
- assert(this.destinations_.length == 0);
+ onDestinationStoreSet_() {
+ assert(this.destinations_.length === 0);
const destinationStore = assert(this.destinationStore);
this.tracker_.add(
destinationStore, DestinationStore.EventType.DESTINATIONS_INSERTED,
@@ -177,7 +177,7 @@ Polymer({
},
/** @private */
- onInvitationStoreSet_: function() {
+ onInvitationStoreSet_() {
const invitationStore = assert(this.invitationStore);
this.tracker_.add(
invitationStore, InvitationStore.EventType.INVITATION_SEARCH_DONE,
@@ -188,7 +188,7 @@ Polymer({
},
/** @private */
- onActiveUserChange_: function() {
+ onActiveUserChange_() {
if (this.activeUser) {
this.$$('select').value = this.activeUser;
}
@@ -197,7 +197,7 @@ Polymer({
},
/** @private */
- updateDestinationsAndInvitations_: function() {
+ updateDestinationsAndInvitations_() {
if (!this.initialized_) {
return;
}
@@ -209,7 +209,7 @@ Polymer({
},
/** @private */
- updateDestinations_: function() {
+ updateDestinations_() {
if (this.destinationStore === undefined) {
return;
}
@@ -223,7 +223,7 @@ Polymer({
},
/** @private */
- onCloseOrCancel_: function() {
+ onCloseOrCancel_() {
if (this.searchQuery_) {
this.$.searchBox.setValue('');
}
@@ -239,7 +239,7 @@ Polymer({
},
/** @private */
- onCancelButtonClick_: function() {
+ onCancelButtonClick_() {
this.$.dialog.cancel();
},
@@ -248,7 +248,7 @@ Polymer({
* containing the selected destination list item element.
* @private
*/
- onDestinationSelected_: function(e) {
+ onDestinationSelected_(e) {
const listItem = e.detail;
const destination = listItem.destination;
@@ -315,12 +315,12 @@ Polymer({
* @param {!Destination} destination The destination to select.
* @private
*/
- selectDestination_: function(destination) {
+ selectDestination_(destination) {
this.destinationStore.selectDestination(destination);
this.$.dialog.close();
},
- show: function() {
+ show() {
this.$.dialog.showModal();
this.loadingDestinations_ = this.destinationStore === undefined ||
this.destinationStore.isPrintDestinationSearchInProgress;
@@ -330,22 +330,21 @@ Polymer({
this.$$('select').value = this.activeUser;
});
}
- this.$.printList.forceIronResize();
},
/** @return {boolean} Whether the dialog is open. */
- isOpen: function() {
+ isOpen() {
return this.$.dialog.hasAttribute('open');
},
/** @private */
- onSignInClick_: function() {
+ onSignInClick_() {
this.metrics_.record(Metrics.DestinationSearchBucket.SIGNIN_TRIGGERED);
NativeLayer.getInstance().signIn(false);
},
/** @private */
- onCloudPrintPromoDismissed_: function() {
+ onCloudPrintPromoDismissed_() {
this.cloudPrintPromoDismissed_ = true;
},
@@ -353,11 +352,11 @@ Polymer({
* Updates printer sharing invitations UI.
* @private
*/
- updateInvitations_: function() {
+ updateInvitations_() {
const invitations = this.activeUser ?
this.invitationStore.invitations(this.activeUser) :
[];
- if (this.invitation_ != invitations[0]) {
+ if (this.invitation_ !== invitations[0]) {
this.metrics_.record(
Metrics.DestinationSearchBucket.INVITATION_AVAILABLE);
}
@@ -370,7 +369,7 @@ Polymer({
* invitation.
* @private
*/
- getAcceptButtonText_: function() {
+ getAcceptButtonText_() {
if (!this.invitation_) {
return '';
}
@@ -383,7 +382,7 @@ Polymer({
* @return {string} The formatted text to show for the invitation promo.
* @private
*/
- getInvitationText_: function() {
+ getInvitationText_() {
if (!this.invitation_) {
return '';
}
@@ -404,21 +403,21 @@ Polymer({
},
/** @private */
- onInvitationAcceptClick_: function() {
+ onInvitationAcceptClick_() {
this.metrics_.record(Metrics.DestinationSearchBucket.INVITATION_ACCEPTED);
this.invitationStore.processInvitation(assert(this.invitation_), true);
this.updateInvitations_();
},
/** @private */
- onInvitationRejectClick_: function() {
+ onInvitationRejectClick_() {
this.metrics_.record(Metrics.DestinationSearchBucket.INVITATION_REJECTED);
this.invitationStore.processInvitation(assert(this.invitation_), false);
this.updateInvitations_();
},
/** @private */
- onUserChange_: function() {
+ onUserChange_() {
const select = this.$$('select');
const account = select.value;
if (account) {
@@ -437,13 +436,13 @@ Polymer({
* @return {boolean} Whether to show the cloud print promo.
* @private
*/
- computeShouldShowCloudPrintPromo_: function() {
+ computeShouldShowCloudPrintPromo_() {
return !this.activeUser && !this.cloudPrintDisabled &&
!this.cloudPrintPromoDismissed_;
},
/** @private */
- onShouldShowCloudPrintPromoChanged_: function() {
+ onShouldShowCloudPrintPromoChanged_() {
if (this.shouldShowCloudPrintPromo_) {
this.metrics_.record(Metrics.DestinationSearchBucket.SIGNIN_PROMPT);
} else {
@@ -457,12 +456,12 @@ Polymer({
* @return {boolean} Whether to show the footer.
* @private
*/
- shouldShowFooter_: function() {
+ shouldShowFooter_() {
return this.shouldShowCloudPrintPromo_ || !!this.invitation_;
},
/** @private */
- onOpenSettingsPrintPage_: function() {
+ onOpenSettingsPrintPage_() {
this.metrics_.record(Metrics.DestinationSearchBucket.MANAGE_BUTTON_CLICKED);
NativeLayer.getInstance().openSettingsPrintPage();
},
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_list.html b/chromium/chrome/browser/resources/print_preview/ui/destination_list.html
index d0aae98140a..82031d4ca32 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_list.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_list.html
@@ -8,7 +8,7 @@
}
#list {
- max-height: 100%;
+ min-height: var(--destination-item-height);
}
.throbber-container {
@@ -24,7 +24,6 @@
}
.no-destinations-message {
- color: #999;
padding-bottom: 8px;
padding-inline-start: 18px;
padding-top: 8px;
@@ -52,13 +51,19 @@
<div class="no-destinations-message" hidden$="[[hasDestinations_]]">
$i18n{noDestinationsMessage}
</div>
-<iron-list id="list" items="[[matchingDestinations_]]">
+<iron-list id="list" items="[[matchingDestinations_]]" role="grid"
+ aria-rowcount$="[[matchingDestinations_.length]]"
+ aria-label="$i18n{printDestinationsTitle}" hidden$="[[hideList_]]">
<template>
- <print-preview-destination-list-item class="list-item"
- search-query="[[searchQuery]]" destination="[[item]]"
- on-click="onDestinationSelected_" on-keydown="onKeydown_"
- tabindex$="[[tabIndex]]">
- </print-preview-destination-list-item>
+ <div role="row" id$="destination_[[index]]"
+ aria-rowindex$="[[getAriaRowindex_(index)]]">
+ <print-preview-destination-list-item class="list-item"
+ search-query="[[searchQuery]]" destination="[[item]]"
+ on-click="onDestinationSelected_" on-keydown="onKeydown_"
+ role="gridcell" tabindex$="[[tabIndex]]"
+ iron-list-tab-index="[[tabIndex]]">
+ </print-preview-destination-list-item>
+ </div>
</template>
</iron-list>
<div class="throbber-container" hidden$="[[throbberHidden_]]">
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_list.js b/chromium/chrome/browser/resources/print_preview/ui/destination_list.js
index 9cf81ca6ec8..9d12a9a976f 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_list.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_list.js
@@ -15,6 +15,8 @@ import {afterNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/po
import {Destination} from '../data/destination.js';
+const DESTINATION_ITEM_HEIGHT = 32;
+
Polymer({
is: 'print-preview-destination-list',
@@ -35,8 +37,6 @@ Polymer({
value: false,
},
- listName: String,
-
/** @private {!Array<!Destination>} */
matchingDestinations_: {
type: Array,
@@ -54,50 +54,101 @@ Polymer({
type: Boolean,
value: false,
},
+
+ /** @private */
+ hideList_: {
+ type: Boolean,
+ value: false,
+ },
},
observers: [
- 'updateMatchingDestinations_(destinations.*, searchQuery)',
- 'matchingDestinationsChanged_(' +
- 'matchingDestinations_.*, loadingDestinations)',
- 'updateThrobberHidden_(matchingDestinations_.*, loadingDestinations)',
+ 'updateMatchingDestinations_(' +
+ 'destinations.*, searchQuery, loadingDestinations)',
],
- // This is a workaround to ensure that the iron-list correctly updates the
- // displayed destination information when the elements in the
- // |matchingDestinations_| array change, instead of using stale information
- // (a known iron-list issue). The event needs to be fired while the list is
- // visible, so firing it immediately when the change occurs does not always
- // work.
- forceIronResize: function() {
+ /** @private {?function(Event)} */
+ boundUpdateHeight_: null,
+
+ /** @override */
+ attached() {
+ this.boundUpdateHeight_ = () => this.updateHeight_();
+ window.addEventListener('resize', this.boundUpdateHeight_);
+ },
+
+ /** @override */
+ detached() {
+ window.removeEventListener('resize', this.boundUpdateHeight_);
+ this.boundUpdateHeight_ = null;
+ },
+
+ /**
+ * This is a workaround to ensure that the iron-list correctly updates the
+ * displayed destination information when the elements in the
+ * |matchingDestinations_| array change, instead of using stale information
+ * (a known iron-list issue). The event needs to be fired while the list is
+ * visible, so firing it immediately when the change occurs does not always
+ * work.
+ * @private
+ */
+ forceIronResize_() {
this.$.list.fire('iron-resize');
},
+ /**
+ * @param {number=} numDestinations
+ * @private
+ */
+ updateHeight_(numDestinations) {
+ const count = numDestinations === undefined ?
+ this.matchingDestinations_.length :
+ numDestinations;
+
+ const maxDisplayedItems = this.offsetHeight / DESTINATION_ITEM_HEIGHT;
+ const isListFullHeight = maxDisplayedItems <= count;
+
+ // Update the throbber and "No destinations" message.
+ this.hasDestinations_ = count > 0 || this.loadingDestinations;
+ this.throbberHidden_ =
+ !this.loadingDestinations || isListFullHeight || !this.hasDestinations_;
+
+ this.hideList_ = count === 0;
+ if (this.hideList_) {
+ return;
+ }
+
+ const listHeight =
+ isListFullHeight ? this.offsetHeight : count * DESTINATION_ITEM_HEIGHT;
+ this.$.list.style.height = listHeight > DESTINATION_ITEM_HEIGHT ?
+ `${listHeight}px` :
+ `${DESTINATION_ITEM_HEIGHT}px`;
+ },
+
/** @private */
- updateMatchingDestinations_: function() {
+ updateMatchingDestinations_() {
if (this.destinations === undefined) {
return;
}
+ const matchingDestinations = this.searchQuery ?
+ this.destinations.filter(
+ d => d.matches(/** @type {!RegExp} */ (this.searchQuery))) :
+ this.destinations.slice();
+
+ // Update the height before updating the list.
+ this.updateHeight_(matchingDestinations.length);
this.updateList(
'matchingDestinations_', destination => destination.key,
- this.searchQuery ?
- this.destinations.filter(
- d => d.matches(/** @type {!RegExp} */ (this.searchQuery))) :
- this.destinations.slice());
- },
+ matchingDestinations);
- /** @private */
- matchingDestinationsChanged_: function() {
- const count = this.matchingDestinations_.length;
- this.hasDestinations_ = count > 0 || this.loadingDestinations;
+ this.forceIronResize_();
},
/**
* @param {!KeyboardEvent} e Event containing the destination and key.
* @private
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
if (e.key === 'Enter') {
this.onDestinationSelected_(e);
e.stopPropagation();
@@ -108,7 +159,7 @@ Polymer({
* @param {!Event} e Event containing the destination that was selected.
* @private
*/
- onDestinationSelected_: function(e) {
+ onDestinationSelected_(e) {
if (e.composedPath()[0].tagName === 'A') {
return;
}
@@ -116,19 +167,13 @@ Polymer({
this.fire('destination-selected', e.target);
},
- /** @private */
- updateThrobberHidden_: function() {
- if (!this.loadingDestinations) {
- this.throbberHidden_ = true;
- } else if (!this.matchingDestinations_) {
- this.throbberHidden_ = false;
- } else {
- const maxDisplayedItems = this.offsetHeight / 32;
- this.throbberHidden_ =
- maxDisplayedItems <= this.matchingDestinations_.length;
- }
- afterNextRender(this, () => {
- this.forceIronResize();
- });
- }
+ /**
+ * Returns a 1-based index for aria-rowindex.
+ * @param {number} index
+ * @return {number}
+ * @private
+ */
+ getAriaRowindex_(index) {
+ return index + 1;
+ },
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_list_item.html b/chromium/chrome/browser/resources/print_preview/ui/destination_list_item.html
index 93e347dd168..86d31e21f64 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_list_item.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_list_item.html
@@ -7,10 +7,8 @@
font-size: calc(12/13 * 1em);
min-height: var(--destination-item-height);
opacity: .87;
- padding-bottom: 2px;
padding-inline-end: 2px;
padding-inline-start: 14px;
- padding-top: 2px;
vertical-align: middle;
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_list_item.js b/chromium/chrome/browser/resources/print_preview/ui/destination_list_item.js
index 207aeb895cd..f05328f5b38 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_list_item.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_list_item.js
@@ -17,7 +17,7 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bun
import {Destination, DestinationOrigin} from '../data/destination.js';
-import {HighlightResults, updateHighlights} from './highlight_utils.js';
+import {updateHighlights} from './highlight_utils.js';
// <if expr="chromeos">
@@ -79,7 +79,7 @@ Polymer({
highlights_: [],
/** @private */
- onDestinationPropertiesChange_: function() {
+ onDestinationPropertiesChange_() {
this.title = this.destination.displayName;
this.stale_ = this.destination.isOfflineOrInvalid;
if (this.destination.isExtension) {
@@ -97,10 +97,10 @@ Polymer({
* Called if the printer configuration request is accepted. Show the waiting
* message to the user as the configuration might take longer than expected.
*/
- onConfigureRequestAccepted: function() {
+ onConfigureRequestAccepted() {
// It must be a Chrome OS CUPS printer which hasn't been set up before.
assert(
- this.destination.origin == DestinationOrigin.CROS &&
+ this.destination.origin === DestinationOrigin.CROS &&
!this.destination.capabilities);
this.configurationStatus_ = DestinationConfigStatus.IN_PROGRESS;
},
@@ -109,7 +109,7 @@ Polymer({
* Called when the printer configuration request completes.
* @param {boolean} success Whether configuration was successful.
*/
- onConfigureComplete: function(success) {
+ onConfigureComplete(success) {
this.configurationStatus_ =
success ? DestinationConfigStatus.IDLE : DestinationConfigStatus.FAILED;
},
@@ -119,20 +119,20 @@ Polymer({
* @return {boolean} Whether the current configuration status is |status|.
* @private
*/
- checkConfigurationStatus_: function(status) {
- return this.configurationStatus_ == status;
+ checkConfigurationStatus_(status) {
+ return this.configurationStatus_ === status;
},
// </if>
/** @private */
- updateHighlightsAndHint_: function() {
+ updateHighlightsAndHint_() {
this.updateSearchHint_();
removeHighlights(this.highlights_);
- this.highlights_ = this.updateHighlighting_().highlights;
+ this.highlights_ = updateHighlights(this, this.searchQuery, new Map);
},
/** @private */
- updateSearchHint_: function() {
+ updateSearchHint_() {
const matches = !this.searchQuery ?
[] :
this.destination.extraPropertiesToMatch.filter(
@@ -143,19 +143,10 @@ Polymer({
},
/**
- * @return {!HighlightResults} The highlight wrappers and
- * search bubbles that were created.
- * @private
- */
- updateHighlighting_: function() {
- return updateHighlights(this, this.searchQuery);
- },
-
- /**
* @return {string} A tooltip for the extension printer icon.
* @private
*/
- getExtensionPrinterTooltip_: function() {
+ getExtensionPrinterTooltip_() {
if (!this.destination.isExtension) {
return '';
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_select.html b/chromium/chrome/browser/resources/print_preview/ui/destination_select.html
index 92127e580c6..c93947a7634 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_select.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_select.html
@@ -25,14 +25,14 @@
disabled$="[[disabled]]"
value="{{selectedValue::change}}">
<template is="dom-repeat" items="[[recentDestinationList]]">
- <option value="[[getKey_(item)]]">[[item.displayName]]</option>
+ <option value="[[item.key]]">[[item.displayName]]</option>
</template>
<option value="[[getPdfDestinationKey_()]]"
hidden$="[[pdfPrinterDisabled]]">
$i18n{printToPDF}
</option>
<option value="[[getGoogleDriveDestinationKey_(activeUser)]]"
- hidden$="[[!activeUser]]">
+ hidden$="[[!driveDestinationReady]]">
$i18n{printToGoogleDrive}
</option>
<option value="noDestinations"
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_select.js b/chromium/chrome/browser/resources/print_preview/ui/destination_select.js
index cf90a5f7b97..4798ea2bcfb 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_select.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_select.js
@@ -15,7 +15,7 @@ import '../strings.m.js';
import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
import {Base, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {createDestinationKey, createRecentDestinationKey, Destination, DestinationOrigin, RecentDestination} from '../data/destination.js';
+import {createDestinationKey, Destination, DestinationOrigin, RecentDestination} from '../data/destination.js';
import {getSelectDropdownBackground} from '../print_preview_utils.js';
import {SelectBehavior} from './select_behavior.js';
@@ -37,11 +37,13 @@ Polymer({
disabled: Boolean,
+ driveDestinationReady: Boolean,
+
noDestinations: Boolean,
pdfPrinterDisabled: Boolean,
- /** @type {!Array<!RecentDestination>} */
+ /** @type {!Array<!Destination>} */
recentDestinationList: Array,
},
@@ -49,12 +51,12 @@ Polymer({
meta_: /** @type {!IronMetaElement} */ (
Base.create('iron-meta', {type: 'iconset'})),
- focus: function() {
+ focus() {
this.$$('.md-select').focus();
},
/** Sets the select to the current value of |destination|. */
- updateDestination: function() {
+ updateDestination() {
this.selectedValue = this.destination.key;
},
@@ -62,7 +64,7 @@ Polymer({
* @return {string} Unique identifier for the Save as PDF destination
* @private
*/
- getPdfDestinationKey_: function() {
+ getPdfDestinationKey_() {
return createDestinationKey(
Destination.GooglePromotedId.SAVE_AS_PDF, DestinationOrigin.LOCAL, '');
},
@@ -71,7 +73,7 @@ Polymer({
* @return {string} Unique identifier for the Save to Google Drive destination
* @private
*/
- getGoogleDriveDestinationKey_: function() {
+ getGoogleDriveDestinationKey_() {
return createDestinationKey(
Destination.GooglePromotedId.DOCS, DestinationOrigin.COOKIES,
this.activeUser);
@@ -84,7 +86,7 @@ Polymer({
* @return {string} The iconset and icon for the current selection.
* @private
*/
- getDestinationIcon_: function() {
+ getDestinationIcon_() {
if (!this.selectedValue) {
return '';
}
@@ -106,7 +108,7 @@ Polymer({
// Otherwise, must be in the recent list.
const recent = this.recentDestinationList.find(d => {
- return createRecentDestinationKey(d) === this.selectedValue;
+ return d.key === this.selectedValue;
});
if (recent && recent.icon) {
return recent.icon;
@@ -123,7 +125,7 @@ Polymer({
* destination and the image for the dropdown arrow.
* @private
*/
- getBackgroundImages_: function() {
+ getBackgroundImages_() {
const icon = this.getDestinationIcon_();
if (!icon) {
return '';
@@ -139,16 +141,7 @@ Polymer({
return getSelectDropdownBackground(iconset, iconSetAndIcon[1], this);
},
- onProcessSelectChange: function(value) {
+ onProcessSelectChange(value) {
this.fire('selected-option-change', value);
},
-
- /**
- * @param {!RecentDestination} recentDestination
- * @return {string} Key for the recent destination
- * @private
- */
- getKey_: function(recentDestination) {
- return createRecentDestinationKey(recentDestination);
- },
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_settings.html b/chromium/chrome/browser/resources/print_preview/ui/destination_settings.html
index 9e3b4c556ac..9c6d5c8b1f8 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_settings.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_settings.html
@@ -51,6 +51,7 @@
destination="[[destination]]"
disabled="[[shouldDisableDropdown_(
destinationState, state, disabled)]]"
+ drive-destination-ready="[[driveDestinationReady_]]"
no-destinations="[[noDestinations_]]"
pdf-printer-disabled="[[pdfPrinterDisabled_]]"
recent-destination-list="[[displayedDestinations_]]"
diff --git a/chromium/chrome/browser/resources/print_preview/ui/destination_settings.js b/chromium/chrome/browser/resources/print_preview/ui/destination_settings.js
index 5ddc5a1ff32..6d1d029ebcb 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/destination_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/destination_settings.js
@@ -21,7 +21,7 @@ import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behav
import {beforeNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {CloudPrintInterface} from '../cloud_print_interface.js';
-import {createRecentDestinationKey, Destination, DestinationOrigin, makeRecentDestination, RecentDestination} from '../data/destination.js';
+import {createDestinationKey, createRecentDestinationKey, Destination, DestinationOrigin, makeRecentDestination, RecentDestination} from '../data/destination.js';
import {DestinationErrorType, DestinationStore} from '../data/destination_store.js';
import {InvitationStore} from '../data/invitation_store.js';
import {Error, State} from '../data/state.js';
@@ -104,9 +104,15 @@ Polymer({
value: null,
},
- /** @private {!Array<!RecentDestination>} */
+ /** @private {!Array<!Destination>} */
displayedDestinations_: Array,
+ /** @private */
+ driveDestinationReady_: {
+ type: Boolean,
+ value: false,
+ },
+
// <if expr="chromeos">
hasPinSetting_: {
type: Boolean,
@@ -159,7 +165,7 @@ Polymer({
tracker_: new EventTracker(),
/** @override */
- attached: function() {
+ attached() {
this.destinationStore_ =
new DestinationStore(this.addWebUIListener.bind(this));
this.invitationStore_ = new InvitationStore();
@@ -192,21 +198,42 @@ Polymer({
},
/** @override */
- detached: function() {
+ detached() {
this.invitationStore_.resetTracker();
this.destinationStore_.resetTracker();
this.tracker_.removeAll();
},
/** @private */
- onCloudPrintInterfaceSet_: function() {
+ onCloudPrintInterfaceSet_() {
const cloudPrintInterface = assert(this.cloudPrintInterface);
this.destinationStore_.setCloudPrintInterface(cloudPrintInterface);
this.invitationStore_.setCloudPrintInterface(cloudPrintInterface);
},
/** @private */
- onActiveUserChanged_: function() {
+ updateDriveDestinationReady_() {
+ const key = createDestinationKey(
+ Destination.GooglePromotedId.DOCS, DestinationOrigin.COOKIES,
+ this.activeUser_);
+ this.driveDestinationReady_ =
+ !!this.destinationStore_.getDestinationByKey(key);
+ },
+
+ /** @private */
+ onActiveUserChanged_() {
+ this.destinationStore_.startLoadCookieDestination(
+ Destination.GooglePromotedId.DOCS);
+ this.updateDriveDestinationReady_();
+ const recentDestinations = this.getSettingValue('recentDestinations');
+ recentDestinations.forEach(destination => {
+ if (destination.origin === DestinationOrigin.COOKIES &&
+ (destination.account === this.activeUser_ ||
+ destination.account === '')) {
+ this.destinationStore_.startLoadCookieDestination(destination.id);
+ }
+ });
+
// Re-filter the dropdown destinations for the new account.
if (!this.isDialogOpen_) {
// Don't update the destination settings UI while the dialog is open in
@@ -247,11 +274,8 @@ Polymer({
d.account === this.activeUser_;
});
if (recent) {
- const success = this.destinationStore_.selectRecentDestinationByKey(
- createRecentDestinationKey(recent), this.displayedDestinations_);
- if (success) {
- return;
- }
+ this.destinationStore_.selectDestination(recent);
+ return;
}
this.destinationStore_.selectDefaultDestination();
},
@@ -266,7 +290,7 @@ Polymer({
* determine whether to wait for user info updates from the handler, or
* to always send requests to the Google Cloud Print server.
*/
- init: function(
+ init(
defaultPrinter, pdfPrinterDisabled, serializedDefaultDestinationRulesStr,
userAccounts, syncAvailable) {
this.pdfPrinterDisabled_ = pdfPrinterDisabled;
@@ -279,7 +303,7 @@ Polymer({
},
/** @private */
- onDestinationSelect_: function() {
+ onDestinationSelect_() {
// If the user selected a destination in the dialog after changing the
// active user, do the UI updates that were previously deferred.
if (this.isDialogOpen_ && this.lastUser_ !== this.activeUser_) {
@@ -298,6 +322,7 @@ Polymer({
} else {
this.destinationState = DestinationState.SELECTED;
}
+
// Notify observers that the destination is set only after updating the
// destinationState.
this.destination = destination;
@@ -305,7 +330,7 @@ Polymer({
},
/** @private */
- onDestinationCapabilitiesReady_: function() {
+ onDestinationCapabilitiesReady_() {
this.notifyPath('destination.capabilities');
this.updateRecentDestinations_();
if (this.destinationState === DestinationState.SET) {
@@ -317,7 +342,7 @@ Polymer({
* @param {!CustomEvent<!DestinationErrorType>} e
* @private
*/
- onDestinationError_: function(e) {
+ onDestinationError_(e) {
let errorType = Error.NONE;
switch (e.detail) {
case DestinationErrorType.INVALID:
@@ -337,10 +362,10 @@ Polymer({
},
/** @private */
- onErrorChanged_: function() {
- if (this.error == Error.INVALID_PRINTER ||
- this.error == Error.UNSUPPORTED_PRINTER ||
- this.error == Error.NO_DESTINATIONS) {
+ onErrorChanged_() {
+ if (this.error === Error.INVALID_PRINTER ||
+ this.error === Error.UNSUPPORTED_PRINTER ||
+ this.error === Error.NO_DESTINATIONS) {
this.destinationState = DestinationState.ERROR;
}
},
@@ -350,13 +375,13 @@ Polymer({
* @return {boolean} Whether the destination is Save as PDF or Save to
* Drive.
*/
- destinationIsDriveOrPdf_: function(destination) {
+ destinationIsDriveOrPdf_(destination) {
return destination.id === Destination.GooglePromotedId.SAVE_AS_PDF ||
destination.id === Destination.GooglePromotedId.DOCS;
},
/** @private */
- updateRecentDestinations_: function() {
+ updateRecentDestinations_() {
if (!this.destination) {
return;
}
@@ -369,23 +394,23 @@ Polymer({
this.getSettingValue('recentDestinations'));
let indexFound = recentDestinations.findIndex(function(recent) {
return (
- newDestination.id == recent.id &&
- newDestination.origin == recent.origin);
+ newDestination.id === recent.id &&
+ newDestination.origin === recent.origin);
});
// No change
- if (indexFound == 0 &&
- recentDestinations[0].capabilities == newDestination.capabilities) {
+ if (indexFound === 0 &&
+ recentDestinations[0].capabilities === newDestination.capabilities) {
return;
}
- const isNew = indexFound == -1;
+ const isNew = indexFound === -1;
// Shift the array so that the nth most recent destination is located at
// index n.
- if (isNew && recentDestinations.length == NUM_PERSISTED_DESTINATIONS) {
+ if (isNew && recentDestinations.length === NUM_PERSISTED_DESTINATIONS) {
indexFound = NUM_PERSISTED_DESTINATIONS - 1;
}
- if (indexFound != -1) {
+ if (indexFound !== -1) {
this.setSettingSplice('recentDestinations', indexFound, 1, null);
}
@@ -397,29 +422,36 @@ Polymer({
},
/** @private */
- updateDropdownDestinations_: function() {
- this.displayedDestinations_ =
- /** @type {!Array<!RecentDestination>} */ (
- this.getSettingValue('recentDestinations'))
- .filter(d => {
- return !this.destinationIsDriveOrPdf_(d) &&
- (d.origin !== DestinationOrigin.COOKIES ||
- d.account === this.activeUser_);
- });
+ updateDropdownDestinations_() {
+ const recentDestinations = /** @type {!Array<!RecentDestination>} */ (
+ this.getSettingValue('recentDestinations'));
+
+ const updatedDestinations = [];
+ recentDestinations.forEach(recent => {
+ const key = createRecentDestinationKey(recent);
+ const destination = this.destinationStore_.getDestinationByKey(key);
+ if (destination && !this.destinationIsDriveOrPdf_(recent) &&
+ (!destination.account || destination.account === this.activeUser_)) {
+ updatedDestinations.push(destination);
+ }
+ });
+
+ this.displayedDestinations_ = updatedDestinations;
+ this.updateDriveDestinationReady_();
},
/**
* @return {boolean} Whether the destinations dropdown should be disabled.
* @private
*/
- shouldDisableDropdown_: function() {
+ shouldDisableDropdown_() {
return this.state === State.FATAL_ERROR ||
(this.destinationState === DestinationState.UPDATED && this.disabled &&
this.state !== State.NOT_READY);
},
/** @private */
- computeShouldHideSpinner_: function() {
+ computeShouldHideSpinner_() {
return this.destinationState === DestinationState.ERROR ||
this.destinationState === DestinationState.UPDATED ||
(this.destinationState === DestinationState.SET && !!this.destination &&
@@ -431,7 +463,7 @@ Polymer({
* @return {string} The connection status text to display.
* @private
*/
- computeStatusText_: function() {
+ computeStatusText_() {
// |destination| can be either undefined, or null here.
if (!this.destination) {
return '';
@@ -447,7 +479,7 @@ Polymer({
* @return {boolean}
* @private
*/
- computeHasPinSetting_: function() {
+ computeHasPinSetting_() {
return this.getSetting('pin').available;
},
// </if>
@@ -457,7 +489,7 @@ Polymer({
* destination that was selected, or "seeMore".
* @private
*/
- onSelectedDestinationOptionChange_: function(e) {
+ onSelectedDestinationOptionChange_(e) {
const value = e.detail;
if (value === 'seeMore') {
this.destinationStore_.startLoadAllDestinations();
@@ -468,11 +500,7 @@ Polymer({
this.lastUser_ = this.activeUser_;
this.isDialogOpen_ = true;
} else {
- const success = this.destinationStore_.selectRecentDestinationByKey(
- value, this.displayedDestinations_);
- if (!success) {
- this.error = Error.INVALID_PRINTER;
- }
+ this.destinationStore_.selectDestinationByKey(value);
}
},
@@ -481,23 +509,25 @@ Polymer({
* account.
* @private
*/
- onAccountChange_: function(e) {
+ onAccountChange_(e) {
this.$.userManager.updateActiveUser(e.detail, true);
+ this.updateDriveDestinationReady_();
},
/** @private */
- onDialogClose_: function() {
- // Reset the select value if the user dismissed the dialog without
- // selecting a new destination.
- if (this.lastUser_ != this.activeUser_) {
+ onDialogClose_() {
+ if (this.lastUser_ !== this.activeUser_) {
this.updateDropdownDestinations_();
}
+
+ // Reset the select value if the user dismissed the dialog without
+ // selecting a new destination.
this.updateDestinationSelect_();
this.isDialogOpen_ = false;
},
/** @private */
- updateDestinationSelect_: function() {
+ updateDestinationSelect_() {
if (this.destinationState === DestinationState.ERROR && !this.destination) {
return;
}
@@ -522,7 +552,7 @@ Polymer({
* @param {!CustomEvent<string>} e Event containing the current destination's
* EULA URL.
*/
- updateDestinationEulaUrl_: function(e) {
+ updateDestinationEulaUrl_(e) {
if (!this.destination) {
return;
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/dpi_settings.js b/chromium/chrome/browser/resources/print_preview/ui/dpi_settings.js
index 696b23ecab3..3b0e2380346 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/dpi_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/dpi_settings.js
@@ -59,7 +59,7 @@ Polymer({
* @return {?{option: Array<!SelectOption>}}
* @private
*/
- computeCapabilityWithLabels_: function() {
+ computeCapabilityWithLabels_() {
if (this.capability === undefined) {
return null;
}
@@ -71,7 +71,7 @@ Polymer({
const dpiOption = /** @type {DpiOption} */ (option);
const hDpi = dpiOption.horizontal_dpi || 0;
const vDpi = dpiOption.vertical_dpi || 0;
- if (hDpi > 0 && vDpi > 0 && hDpi != vDpi) {
+ if (hDpi > 0 && vDpi > 0 && hDpi !== vDpi) {
result.option[index].name = loadTimeData.getStringF(
'nonIsotropicDpiItemLabel', hDpi.toLocaleString(),
vDpi.toLocaleString());
@@ -84,7 +84,7 @@ Polymer({
},
/** @private */
- onDpiSettingChange_: function() {
+ onDpiSettingChange_() {
if (this.capabilityWithLabels_ === null ||
this.capabilityWithLabels_ === undefined) {
return;
@@ -95,9 +95,9 @@ Polymer({
for (const option of assert(this.capabilityWithLabels_.option)) {
const dpiOption =
/** @type {LabelledDpiOption} */ (option);
- if (dpiValue.horizontal_dpi == dpiOption.horizontal_dpi &&
- dpiValue.vertical_dpi == dpiOption.vertical_dpi &&
- dpiValue.vendor_id == dpiOption.vendor_id) {
+ if (dpiValue.horizontal_dpi === dpiOption.horizontal_dpi &&
+ dpiValue.vertical_dpi === dpiOption.vertical_dpi &&
+ dpiValue.vendor_id === dpiOption.vendor_id) {
this.$$('print-preview-settings-select')
.selectValue(JSON.stringify(option));
return;
diff --git a/chromium/chrome/browser/resources/print_preview/ui/duplex_settings.js b/chromium/chrome/browser/resources/print_preview/ui/duplex_settings.js
index 31a990c8b50..996ff03ed3b 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/duplex_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/duplex_settings.js
@@ -51,23 +51,23 @@ Polymer({
Base.create('iron-meta', {type: 'iconset'})),
/** @private */
- onDuplexSettingChange_: function() {
+ onDuplexSettingChange_() {
this.$.duplex.checked = this.getSettingValue('duplex');
},
/** @private */
- onDuplexTypeChange_: function() {
+ onDuplexTypeChange_() {
this.selectedValue = this.getSettingValue('duplexShortEdge') ?
this.duplexValueEnum_.SHORT_EDGE.toString() :
this.duplexValueEnum_.LONG_EDGE.toString();
},
/** @private */
- onCheckboxChange_: function() {
+ onCheckboxChange_() {
this.setSetting('duplex', this.$.duplex.checked);
},
- onProcessSelectChange: function(value) {
+ onProcessSelectChange(value) {
this.setSetting(
'duplexShortEdge',
value === this.duplexValueEnum_.SHORT_EDGE.toString());
@@ -77,7 +77,7 @@ Polymer({
* @return {boolean} Whether to expand the collapse for the dropdown.
* @private
*/
- getOpenCollapse_: function() {
+ getOpenCollapse_() {
return this.getSetting('duplexShortEdge').available &&
/** @type {boolean} */ (this.getSettingValue('duplex'));
},
@@ -88,7 +88,7 @@ Polymer({
* @return {boolean} Whether the controls should be disabled.
* @private
*/
- getDisabled_: function(managed, disabled) {
+ getDisabled_(managed, disabled) {
return managed || disabled;
},
@@ -97,7 +97,7 @@ Polymer({
* the dropdown arrow.
* @private
*/
- getBackgroundImages_: function() {
+ getBackgroundImages_() {
const icon =
this.getSettingValue('duplexShortEdge') ? 'short-edge' : 'long-edge';
const iconset = /** @type {!IronIconsetSvgElement} */ (
diff --git a/chromium/chrome/browser/resources/print_preview/ui/header.js b/chromium/chrome/browser/resources/print_preview/ui/header.js
index 9d8ab16b35b..3848934ecb3 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/header.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/header.js
@@ -13,17 +13,8 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bun
import {Destination} from '../data/destination.js';
import {Error, State} from '../data/state.js';
-
import {SettingsBehavior} from './settings_behavior.js';
-/**
- * @typedef {{numPages: number,
- * numSheets: number,
- * pagesLabel: string,
- * summaryLabel: string}}
- */
-let LabelInfo;
-
Polymer({
is: 'print-preview-header',
@@ -45,80 +36,41 @@ Polymer({
managed: Boolean,
+ /** @private {number} */
+ sheetCount: Number,
+
/** @private {?string} */
summary_: {
type: String,
- value: null,
+ computed: 'computeSummary_(sheetCount, state, destination.id)',
},
},
- observers: [
- 'update_(settings.copies.value, settings.duplex.value, ' +
- 'settings.pages.value, state, destination.id)',
- ],
-
/**
* @return {boolean}
* @private
*/
- isPdfOrDrive_: function() {
+ isPdfOrDrive_() {
return this.destination &&
- (this.destination.id == Destination.GooglePromotedId.SAVE_AS_PDF ||
- this.destination.id == Destination.GooglePromotedId.DOCS);
+ (this.destination.id === Destination.GooglePromotedId.SAVE_AS_PDF ||
+ this.destination.id === Destination.GooglePromotedId.DOCS);
},
/**
- * @return {!LabelInfo}
+ * @return {?string}
* @private
*/
- computeLabelInfo_: function() {
- const saveToPdfOrDrive = this.isPdfOrDrive_();
- let numPages = this.getSettingValue('pages').length;
- let numSheets = numPages;
- if (!saveToPdfOrDrive && this.getSettingValue('duplex')) {
- numSheets = Math.ceil(numPages / 2);
- }
-
- const copies = parseInt(this.getSettingValue('copies'), 10);
- numSheets *= copies;
- numPages *= copies;
-
- const pagesLabel = loadTimeData.getString('printPreviewPageLabelPlural');
- let summaryLabel;
- if (numSheets > 1) {
- summaryLabel = saveToPdfOrDrive ?
- pagesLabel :
- loadTimeData.getString('printPreviewSheetsLabelPlural');
- } else {
- summaryLabel = loadTimeData.getString(
- saveToPdfOrDrive ? 'printPreviewPageLabelSingular' :
- 'printPreviewSheetsLabelSingular');
- }
- return {
- numPages: numPages,
- numSheets: numSheets,
- pagesLabel: pagesLabel,
- summaryLabel: summaryLabel
- };
- },
-
- /** @private */
- update_: function() {
+ computeSummary_() {
switch (this.state) {
case (State.PRINTING):
- this.summary_ = loadTimeData.getString(
+ return loadTimeData.getString(
this.isPdfOrDrive_() ? 'saving' : 'printing');
- break;
case (State.READY):
- const labelInfo = this.computeLabelInfo_();
- this.summary_ = this.getSummary_(labelInfo);
- break;
+ return this.getSheetsSummary_();
case (State.FATAL_ERROR):
- this.summary_ = this.getErrorMessage_();
- break;
+ return this.getErrorMessage_();
default:
- this.summary_ = null;
- break;
+ return null;
}
},
@@ -126,7 +78,7 @@ Polymer({
* @return {string} The error message to display.
* @private
*/
- getErrorMessage_: function() {
+ getErrorMessage_() {
switch (this.error) {
case Error.PRINT_FAILED:
return loadTimeData.getString('couldNotPrint');
@@ -138,15 +90,20 @@ Polymer({
},
/**
- * @param {!LabelInfo} labelInfo
* @return {string}
* @private
*/
- getSummary_: function(labelInfo) {
- return labelInfo.numSheets === 0 ?
- '' :
- loadTimeData.getStringF(
- 'printPreviewNewSummaryFormatShort',
- labelInfo.numSheets.toLocaleString(), labelInfo.summaryLabel);
+ getSheetsSummary_() {
+ if (this.sheetCount === 0) {
+ return '';
+ }
+
+ const pageOrSheets = this.isPdfOrDrive_() ? 'Page' : 'Sheets';
+ const singularOrPlural = this.sheetCount > 1 ? 'Plural' : 'Singular';
+ const label = loadTimeData.getString(
+ `printPreview${pageOrSheets}Label${singularOrPlural}`);
+ return loadTimeData.getStringF(
+ 'printPreviewSummaryFormatShort', this.sheetCount.toLocaleString(),
+ label);
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/highlight_utils.js b/chromium/chrome/browser/resources/print_preview/ui/highlight_utils.js
index 77982f3e165..7a568dc0136 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/highlight_utils.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/highlight_utils.js
@@ -3,60 +3,69 @@
// found in the LICENSE file.
import {assert} from 'chrome://resources/js/assert.m.js';
-import {highlight, highlightControlWithBubble} from 'chrome://resources/js/search_highlight_utils.m.js';
-
-/**
- * @typedef {{
- * highlights: !Array<!Node>,
- * bubbles: !Array<!Node>
- * }}
- */
-export let HighlightResults;
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {createEmptySearchBubble, highlight, Range, stripDiacritics} from 'chrome://resources/js/search_highlight_utils.m.js';
/**
* @param {!HTMLElement} element The element to update. Element should have a
* shadow root.
* @param {?RegExp} query The current search query
- * @return {!HighlightResults} The highlight wrappers and
- * search bubbles that were created.
+ * @param {!Map<!Node, number>} bubbles A map of bubbles created / results found
+ * so far.
+ * @return {!Array<!Node>} The highlight wrappers that were created.
*/
-export function updateHighlights(element, query) {
- const result = {highlights: [], bubbles: []};
+export function updateHighlights(element, query, bubbles) {
+ const highlights = [];
if (!query) {
- return result;
+ return highlights;
}
+ assert(query.global);
+
element.shadowRoot.querySelectorAll('.searchable').forEach(childElement => {
childElement.childNodes.forEach(node => {
- if (node.nodeType != Node.TEXT_NODE) {
+ if (node.nodeType !== Node.TEXT_NODE) {
return;
}
- const textContent = node.nodeValue.trim();
- if (textContent.length == 0) {
+ const textContent = node.nodeValue;
+ if (textContent.trim().length === 0) {
return;
}
- if (query.test(textContent)) {
+ const strippedText = stripDiacritics(textContent);
+ /** @type {!Array<!Range>} */
+ const ranges = [];
+ for (let match; match = query.exec(strippedText);) {
+ ranges.push({start: match.index, length: match[0].length});
+ }
+
+ if (ranges.length > 0) {
// Don't highlight <select> nodes, yellow rectangles can't be
// displayed within an <option>.
- if (node.parentNode.nodeName != 'OPTION') {
- result.highlights.push(highlight(node, textContent.split(query)));
- } else {
- const selectNode = node.parentNode.parentNode;
+ if (node.parentNode.nodeName === 'OPTION') {
// The bubble should be parented by the select node's parent.
// Note: The bubble's ::after element, a yellow arrow, will not
// appear correctly in print preview without SPv175 enabled. See
// https://crbug.com/817058.
- const bubble = highlightControlWithBubble(
- /** @type {!HTMLElement} */ (assert(selectNode.parentNode)),
- textContent.match(query)[0]);
- if (bubble) {
- result.bubbles.push(bubble);
- }
+ // TODO(crbug.com/1038464): turn on horizontallyCenter when we fix
+ // incorrect positioning caused by scrollbar width changing after
+ // search finishes.
+ const bubble = createEmptySearchBubble(
+ /** @type {!Node} */ (assert(node.parentNode.parentNode)),
+ /* horizontallyCenter= */ false);
+ const numHits = ranges.length + (bubbles.get(bubble) || 0);
+ bubbles.set(bubble, numHits);
+ const msgName = numHits === 1 ? 'searchResultBubbleText' :
+ 'searchResultsBubbleText';
+ bubble.firstChild.textContent =
+ loadTimeData.getStringF(msgName, numHits);
+ } else {
+ highlights.push(highlight(node, ranges));
}
}
});
});
- return result;
+
+ return highlights;
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/input_behavior.js b/chromium/chrome/browser/resources/print_preview/ui/input_behavior.js
index 7bb3c4cef3b..25e3c9379ea 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/input_behavior.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/input_behavior.js
@@ -27,7 +27,7 @@ export const InputBehavior = {
timeout_: null,
/** @override */
- ready: function() {
+ ready() {
this.getInput().addEventListener('input', this.resetTimeout_.bind(this));
this.getInput().addEventListener('keydown', this.onKeyDown_.bind(this));
},
@@ -37,7 +37,7 @@ export const InputBehavior = {
* element the behavior should use. Should be overridden by elements
* using this behavior.
*/
- getInput: function() {},
+ getInput() {},
/**
* @return {number} The delay to use for the timeout, in ms. Elements using
@@ -45,7 +45,7 @@ export const InputBehavior = {
* element returned by getInput().
* @private
*/
- getTimeoutDelayMs_: function() {
+ getTimeoutDelayMs_() {
const delay = parseInt(
/** @type {{timeoutDelay: number}} */ (this.getInput().dataset)
.timeoutDelay,
@@ -59,8 +59,8 @@ export const InputBehavior = {
* @param {!KeyboardEvent} event Contains the key that was pressed.
* @private
*/
- onKeyDown_: function(event) {
- if (event.code != 'Enter' && event.code != 'Tab') {
+ onKeyDown_(event) {
+ if (event.code !== 'Enter' && event.code !== 'Tab') {
return;
}
@@ -72,7 +72,7 @@ export const InputBehavior = {
* timeout.
* @private
*/
- resetTimeout_: function() {
+ resetTimeout_() {
if (this.timeout_) {
clearTimeout(this.timeout_);
}
@@ -84,22 +84,22 @@ export const InputBehavior = {
* Called after a timeout after user input into the textfield.
* @private
*/
- onTimeout_: function() {
+ onTimeout_() {
this.timeout_ = null;
const value = this.getInput().value;
- if (this.lastValue_ != value) {
+ if (this.lastValue_ !== value) {
this.lastValue_ = value;
this.fire('input-change', value);
}
},
// Resets the lastValue_ so that future inputs trigger a change event.
- resetString: function() {
+ resetString() {
this.lastValue_ = null;
},
// Called to clear the timeout and update the value.
- resetAndUpdate: function() {
+ resetAndUpdate() {
if (this.timeout_) {
clearTimeout(this.timeout_);
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/layout_settings.js b/chromium/chrome/browser/resources/print_preview/ui/layout_settings.js
index e0c0e569206..a27bf9e0bcc 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/layout_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/layout_settings.js
@@ -28,13 +28,13 @@ Polymer({
* @param {*} newValue The new value of the layout setting.
* @private
*/
- onLayoutSettingChange_: function(newValue) {
+ onLayoutSettingChange_(newValue) {
this.selectedValue =
/** @type {boolean} */ (newValue) ? 'landscape' : 'portrait';
},
/** @param {string} value The new select value. */
- onProcessSelectChange: function(value) {
- this.setSetting('layout', value == 'landscape');
+ onProcessSelectChange(value) {
+ this.setSetting('layout', value === 'landscape');
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/link_container.js b/chromium/chrome/browser/resources/print_preview/ui/link_container.js
index bd93d679183..beb61d226c8 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/link_container.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/link_container.js
@@ -56,7 +56,7 @@ Polymer({
* @return {boolean} Whether the system dialog link should be visible.
* @private
*/
- computeShouldShowSystemDialogLink_: function() {
+ computeShouldShowSystemDialogLink_() {
if (this.appKioskMode) {
return false;
}
@@ -64,20 +64,20 @@ Polymer({
return true;
}
return !!this.destination &&
- this.destination.origin == DestinationOrigin.LOCAL &&
- this.destination.id != Destination.GooglePromotedId.SAVE_AS_PDF;
+ this.destination.origin === DestinationOrigin.LOCAL &&
+ this.destination.id !== Destination.GooglePromotedId.SAVE_AS_PDF;
},
/**
* @return {boolean} Whether the system dialog link should be disabled
* @private
*/
- computeSystemDialogLinkDisabled_: function() {
+ computeSystemDialogLinkDisabled_() {
return isWindows && this.disabled;
},
/** @private */
- onSystemDialogClick_: function() {
+ onSystemDialogClick_() {
if (!this.shouldShowSystemDialogLink_) {
return;
}
@@ -90,14 +90,14 @@ Polymer({
// <if expr="is_macosx">
/** @private */
- onOpenInPreviewClick_: function() {
+ onOpenInPreviewClick_() {
this.openingInPreview_ = true;
this.fire('open-pdf-in-preview');
},
// </if>
/** @return {boolean} Whether the system dialog link is available. */
- systemDialogLinkAvailable: function() {
+ systemDialogLinkAvailable() {
return this.shouldShowSystemDialogLink_ && !this.systemDialogLinkDisabled_;
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/margin_control.js b/chromium/chrome/browser/resources/print_preview/ui/margin_control.js
index bbef1dff393..883e7eaa6a5 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/margin_control.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/margin_control.js
@@ -106,7 +106,7 @@ Polymer({
},
/** @return {!HTMLInputElement} The input element for InputBehavior. */
- getInput: function() {
+ getInput() {
return /** @type {!HTMLInputElement} */ (this.$.input);
},
@@ -114,10 +114,10 @@ Polymer({
* @param {number} valueInPts New value of the margin control's textbox in
* pts.
*/
- setTextboxValue: function(valueInPts) {
+ setTextboxValue(valueInPts) {
const textbox = this.$.input;
const pts = textbox.value ? this.parseValueToPts_(textbox.value) : null;
- if (!!pts && valueInPts === Math.round(pts)) {
+ if (pts !== null && valueInPts === Math.round(pts)) {
// If the textbox's value represents the same value in pts as the new one,
// don't reset. This allows the "undo" command to work as expected, see
// https://crbug.com/452844.
@@ -125,15 +125,16 @@ Polymer({
}
textbox.value = this.serializeValueFromPts_(valueInPts);
+ this.resetString();
},
/** @return {number} The current position of the margin control. */
- getPositionInPts: function() {
+ getPositionInPts() {
return this.positionInPts_;
},
/** @param {number} position The new position for the margin control. */
- setPositionInPts: function(position) {
+ setPositionInPts(position) {
this.positionInPts_ = position;
},
@@ -142,7 +143,7 @@ Polymer({
* aria-hidden.
* @private
*/
- getAriaHidden_: function() {
+ getAriaHidden_() {
return this.invisible.toString();
},
@@ -151,22 +152,22 @@ Polymer({
* @param {number} pixels Pixel value to convert.
* @return {number} Given value expressed in points.
*/
- convertPixelsToPts: function(pixels) {
+ convertPixelsToPts(pixels) {
let pts;
const Orientation = CustomMarginsOrientation;
- if (this.side == Orientation.TOP) {
+ if (this.side === Orientation.TOP) {
pts = pixels - this.translateTransform.y + RADIUS_PX;
pts /= this.scaleTransform;
- } else if (this.side == Orientation.RIGHT) {
+ } else if (this.side === Orientation.RIGHT) {
pts = pixels - this.translateTransform.x + RADIUS_PX;
pts /= this.scaleTransform;
pts = this.pageSize.width - pts;
- } else if (this.side == Orientation.BOTTOM) {
+ } else if (this.side === Orientation.BOTTOM) {
pts = pixels - this.translateTransform.y + RADIUS_PX;
pts /= this.scaleTransform;
pts = this.pageSize.height - pts;
} else {
- assert(this.side == Orientation.LEFT);
+ assert(this.side === Orientation.LEFT);
pts = pixels - this.translateTransform.x + RADIUS_PX;
pts /= this.scaleTransform;
}
@@ -177,13 +178,14 @@ Polymer({
* @param {!PointerEvent} event A pointerdown event triggered by this element.
* @return {boolean} Whether the margin should start being dragged.
*/
- shouldDrag: function(event) {
- return !this.disabled && event.button == 0 &&
- (event.path[0] == this.$.lineContainer || event.path[0] == this.$.line);
+ shouldDrag(event) {
+ return !this.disabled && event.button === 0 &&
+ (event.path[0] === this.$.lineContainer ||
+ event.path[0] === this.$.line);
},
/** @private */
- onDisabledChange_: function() {
+ onDisabledChange_() {
if (this.disabled) {
this.focused_ = false;
}
@@ -194,9 +196,9 @@ Polymer({
* @return {?number} Value in points represented by the input value.
* @private
*/
- parseValueToPts_: function(value) {
+ parseValueToPts_(value) {
value = value.trim();
- if (value.length == 0) {
+ if (value.length === 0) {
return null;
}
assert(this.measurementSystem);
@@ -222,7 +224,7 @@ Polymer({
* units.
* @private
*/
- serializeValueFromPts_: function(value) {
+ serializeValueFromPts_(value) {
assert(this.measurementSystem);
value = this.measurementSystem.convertFromPoints(value);
value = this.measurementSystem.roundValue(value);
@@ -232,11 +234,12 @@ Polymer({
},
/**
- * @param {!CustomEvent<string>} e Contains the new value of the input.
+ * @param {!CustomEvent<string|undefined>} e Contains the new value of the
+ * input.
* @private
*/
- onInputChange_: function(e) {
- if (!e.detail) {
+ onInputChange_(e) {
+ if (e.detail === '' || e.detail === undefined) {
return;
}
@@ -250,20 +253,20 @@ Polymer({
},
/** @private */
- onBlur_: function() {
+ onBlur_() {
this.focused_ = false;
this.resetAndUpdate();
this.fire('text-blur', this.invalid || !this.$.input.value);
},
/** @private */
- onFocus_: function() {
+ onFocus_() {
this.focused_ = true;
this.fire('text-focus');
},
/** @private */
- updatePosition_: function() {
+ updatePosition_() {
if (!observerDepsDefined(Array.from(arguments))) {
return;
}
@@ -273,15 +276,15 @@ Polymer({
let y = this.translateTransform.y;
let width = null;
let height = null;
- if (this.side == Orientation.TOP) {
+ if (this.side === Orientation.TOP) {
y = this.scaleTransform * this.positionInPts_ +
this.translateTransform.y - RADIUS_PX;
width = this.scaleTransform * this.pageSize.width;
- } else if (this.side == Orientation.RIGHT) {
+ } else if (this.side === Orientation.RIGHT) {
x = this.scaleTransform * (this.pageSize.width - this.positionInPts_) +
this.translateTransform.x - RADIUS_PX;
height = this.scaleTransform * this.pageSize.height;
- } else if (this.side == Orientation.BOTTOM) {
+ } else if (this.side === Orientation.BOTTOM) {
y = this.scaleTransform * (this.pageSize.height - this.positionInPts_) +
this.translateTransform.y - RADIUS_PX;
width = this.scaleTransform * this.pageSize.width;
@@ -293,10 +296,10 @@ Polymer({
window.requestAnimationFrame(() => {
this.style.left = Math.round(x) + 'px';
this.style.top = Math.round(y) + 'px';
- if (width != null) {
+ if (width !== null) {
this.style.width = Math.round(width) + 'px';
}
- if (height != null) {
+ if (height !== null) {
this.style.height = Math.round(height) + 'px';
}
});
@@ -304,7 +307,7 @@ Polymer({
},
/** @private */
- onClipSizeChange_: function() {
+ onClipSizeChange_() {
if (!this.clipSize) {
return;
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/margin_control_container.html b/chromium/chrome/browser/resources/print_preview/ui/margin_control_container.html
index 032540cb441..09f1d496521 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/margin_control_container.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/margin_control_container.html
@@ -1,6 +1,9 @@
<style>
:host {
display: block;
+ left: 0;
+ position: absolute;
+ top: 0;
}
:host([dragging_=dragging-vertical]) {
diff --git a/chromium/chrome/browser/resources/print_preview/ui/margin_control_container.js b/chromium/chrome/browser/resources/print_preview/ui/margin_control_container.js
index f9c05c5be63..43199a559b8 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/margin_control_container.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/margin_control_container.js
@@ -146,14 +146,14 @@ Polymer({
* @return {boolean}
* @private
*/
- computeAvailable_: function() {
+ computeAvailable_() {
return this.previewLoaded && !!this.clipSize_ &&
- this.getSettingValue('margins') == MarginsType.CUSTOM &&
+ this.getSettingValue('margins') === MarginsType.CUSTOM &&
!!this.pageSize;
},
/** @private */
- onAvailableChange_: function() {
+ onAvailableChange_() {
if (this.available_ && this.resetMargins_) {
// Set the custom margins values to the current document margins if the
// custom margins were reset.
@@ -169,9 +169,9 @@ Polymer({
},
/** @private */
- onMarginSettingsChange_: function() {
+ onMarginSettingsChange_() {
const margins = this.getSettingValue('customMargins');
- if (margins.marginTop === undefined) {
+ if (!margins || margins.marginTop === undefined) {
// This may be called when print preview model initially sets the
// settings. It sets custom margins empty by default.
return;
@@ -186,7 +186,7 @@ Polymer({
},
/** @private */
- onMediaSizeOrLayoutChange_: function() {
+ onMediaSizeOrLayoutChange_() {
// Reset the custom margins when the paper size changes. Don't do this if
// it is the first preview.
if (this.resetMargins_ === null) {
@@ -194,23 +194,18 @@ Polymer({
}
this.resetMargins_ = true;
- const marginsSetting = this.getSetting('margins');
- if (marginsSetting.value == MarginsType.CUSTOM) {
- // Set the margins value to default first.
- this.setSetting('margins', MarginsType.DEFAULT);
- }
- // Reset custom margins so that the sticky value is not restored for the
- // new paper size.
+ // Reset custom margins so that the sticky value is not restored for the new
+ // paper size.
this.setSetting('customMargins', {});
},
/** @private */
- onStateChanged_: function() {
- if (this.state == State.READY && this.resetMargins_ === null) {
+ onStateChanged_() {
+ if (this.state === State.READY && this.resetMargins_ === null) {
// Don't reset margins if there are sticky values. Otherwise, set them
// to the document margins when the user selects custom margins.
- this.resetMargins_ =
- this.getSettingValue('customMargins').marginTop === undefined;
+ const margins = this.getSettingValue('customMargins');
+ this.resetMargins_ = !margins || margins.marginTop === undefined;
}
},
@@ -218,7 +213,7 @@ Polymer({
* @return {boolean} Whether the controls should be disabled.
* @private
*/
- controlsDisabled_: function() {
+ controlsDisabled_() {
return this.state !== State.READY || this.invisible_;
},
@@ -228,9 +223,9 @@ Polymer({
* @return {boolean} Whether the given orientation is TOP or BOTTOM.
* @private
*/
- isTopOrBottom_: function(orientation) {
- return orientation == CustomMarginsOrientation.TOP ||
- orientation == CustomMarginsOrientation.BOTTOM;
+ isTopOrBottom_(orientation) {
+ return orientation === CustomMarginsOrientation.TOP ||
+ orientation === CustomMarginsOrientation.BOTTOM;
},
/**
@@ -242,7 +237,7 @@ Polymer({
* x direction for the left/right controls, y direction otherwise.
* @private
*/
- posInPixelsToPts_: function(control, posInPixels) {
+ posInPixelsToPts_(control, posInPixels) {
const side =
/** @type {CustomMarginsOrientation} */ (control.side);
return this.clipAndRoundValue_(
@@ -260,7 +255,7 @@ Polymer({
* is for the left or right margin, and the y direction otherwise.
* @private
*/
- moveControlWithConstraints_: function(control, posInPts) {
+ moveControlWithConstraints_(control, posInPts) {
control.setPositionInPts(posInPts);
control.setTextboxValue(posInPts);
},
@@ -272,7 +267,7 @@ Polymer({
* the pointer.
* @return {!Coordinate2d} New position of the margin control.
*/
- translatePointerToPositionInPixels: function(pointerPosition) {
+ translatePointerToPositionInPixels(pointerPosition) {
return new Coordinate2d(
pointerPosition.x - this.pointerStartPositionInPixels_.x +
this.marginStartPositionInPixels_.x,
@@ -286,7 +281,7 @@ Polymer({
* @param {!PointerEvent} event Contains the position of the pointer.
* @private
*/
- onPointerMove_: function(event) {
+ onPointerMove_(event) {
const control =
/** @type {!PrintPreviewMarginControlElement} */ (event.target);
const posInPts = this.posInPixelsToPts_(
@@ -302,7 +297,7 @@ Polymer({
* @param {!PointerEvent} event Contains the position of the pointer.
* @private
*/
- onPointerUp_: function(event) {
+ onPointerUp_(event) {
const control =
/** @type {!PrintPreviewMarginControlElement} */ (event.target);
this.dragging_ = '';
@@ -323,7 +318,7 @@ Polymer({
* @param {boolean} invisible Whether the margin controls should be
* invisible.
*/
- setInvisible: function(invisible) {
+ setInvisible(invisible) {
// Ignore changes if the margin controls are not available.
if (!this.available_) {
return;
@@ -331,7 +326,7 @@ Polymer({
// Do not set the controls invisible if the user is dragging or focusing
// the textbox for one of them.
- if (invisible && (this.dragging_ != '' || this.textboxFocused_)) {
+ if (invisible && (this.dragging_ !== '' || this.textboxFocused_)) {
return;
}
@@ -343,7 +338,7 @@ Polymer({
* event.
* @private
*/
- onTextFocus_: function(e) {
+ onTextFocus_(e) {
this.textboxFocused_ = true;
const control =
/** @type {!PrintPreviewMarginControlElement} */ (e.target);
@@ -394,13 +389,13 @@ Polymer({
* @param {number} marginValue New value for the margin in points.
* @private
*/
- setMargin_: function(side, marginValue) {
+ setMargin_(side, marginValue) {
const marginSide =
/** @type {!CustomMarginsOrientation} */ (side);
const oldMargins =
/** @type {MarginsSetting} */ (this.getSettingValue('customMargins'));
const key = MARGIN_KEY_MAP.get(marginSide);
- if (oldMargins[key] == marginValue) {
+ if (oldMargins[key] === marginValue) {
return;
}
const newMargins = Object.assign({}, oldMargins);
@@ -414,7 +409,7 @@ Polymer({
* @return {number} The clipped margin value in points.
* @private
*/
- clipAndRoundValue_: function(side, value) {
+ clipAndRoundValue_(side, value) {
const marginSide =
/** @type {!CustomMarginsOrientation} */ (side);
if (value < 0) {
@@ -423,14 +418,14 @@ Polymer({
const Orientation = CustomMarginsOrientation;
let limit = 0;
const margins = this.getSettingValue('customMargins');
- if (marginSide == Orientation.TOP) {
+ if (marginSide === Orientation.TOP) {
limit = this.pageSize.height - margins.marginBottom - MINIMUM_DISTANCE;
- } else if (marginSide == Orientation.RIGHT) {
+ } else if (marginSide === Orientation.RIGHT) {
limit = this.pageSize.width - margins.marginLeft - MINIMUM_DISTANCE;
- } else if (marginSide == Orientation.BOTTOM) {
+ } else if (marginSide === Orientation.BOTTOM) {
limit = this.pageSize.height - margins.marginTop - MINIMUM_DISTANCE;
} else {
- assert(marginSide == Orientation.LEFT);
+ assert(marginSide === Orientation.LEFT);
limit = this.pageSize.width - margins.marginRight - MINIMUM_DISTANCE;
}
return Math.round(Math.min(value, limit));
@@ -440,7 +435,7 @@ Polymer({
* @param {!CustomEvent<number>} e Event containing the new textbox value.
* @private
*/
- onTextChange_: function(e) {
+ onTextChange_(e) {
const control =
/** @type {!PrintPreviewMarginControlElement} */ (e.target);
control.invalid = false;
@@ -455,7 +450,7 @@ Polymer({
* invalid state.
* @private
*/
- onTextBlur_: function(e) {
+ onTextBlur_(e) {
const control =
/** @type {!PrintPreviewMarginControlElement} */ (e.target);
control.setTextboxValue(control.getPositionInPts());
@@ -470,7 +465,7 @@ Polymer({
* control.
* @private
*/
- onPointerDown_: function(e) {
+ onPointerDown_(e) {
const control =
/** @type {!PrintPreviewMarginControlElement} */ (e.target);
if (!control.shouldDrag(e)) {
@@ -497,7 +492,7 @@ Polymer({
* Set display:none after the opacity transition for the controls is done.
* @private
*/
- onTransitionEnd_: function() {
+ onTransitionEnd_() {
if (this.invisible_) {
this.style.display = 'none';
}
@@ -509,7 +504,7 @@ Polymer({
* @param {Coordinate2d} translateTransform Updated value of
* the translation transformation.
*/
- updateTranslationTransform: function(translateTransform) {
+ updateTranslationTransform(translateTransform) {
if (!translateTransform.equals(this.translateTransform_)) {
this.translateTransform_ = translateTransform;
}
@@ -519,8 +514,8 @@ Polymer({
* Updates the scaling transform that scales pixels values to point values.
* @param {number} scaleTransform Updated value of the scale transform.
*/
- updateScaleTransform: function(scaleTransform) {
- if (scaleTransform != this.scaleTransform_) {
+ updateScaleTransform(scaleTransform) {
+ if (scaleTransform !== this.scaleTransform_) {
this.scaleTransform_ = scaleTransform;
}
},
@@ -529,7 +524,7 @@ Polymer({
* Clips margin controls to the given clip size in pixels.
* @param {Size} clipSize Size to clip the margin controls to.
*/
- updateClippingMask: function(clipSize) {
+ updateClippingMask(clipSize) {
if (!clipSize) {
return;
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/margins_settings.html b/chromium/chrome/browser/resources/print_preview/ui/margins_settings.html
index a5841a4d3e7..f06afa2bd95 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/margins_settings.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/margins_settings.html
@@ -4,8 +4,7 @@
<span id="margins-label" slot="title">$i18n{marginsLabel}</span>
<div slot="controls">
<select class="md-select" aria-labelledby="margins-label"
- disabled$="[[getMarginsSettingsDisabled_(disabled,
- settings.pagesPerSheet.value)]]"
+ disabled$="[[marginsDisabled_]]"
value="{{selectedValue::change}}">
<!-- The order of these options must match the natural order of their
values, which come from MarginsType. -->
diff --git a/chromium/chrome/browser/resources/print_preview/ui/margins_settings.js b/chromium/chrome/browser/resources/print_preview/ui/margins_settings.js
index f35959a0baf..baf5f690881 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/margins_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/margins_settings.js
@@ -9,6 +9,7 @@ import './settings_section.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {MarginsType} from '../data/margins.js';
+import {State} from '../data/state.js';
import {SelectBehavior} from './select_behavior.js';
import {SettingsBehavior} from './settings_behavior.js';
@@ -21,40 +22,80 @@ Polymer({
behaviors: [SettingsBehavior, SelectBehavior],
properties: {
- disabled: Boolean,
+ disabled: {
+ type: Boolean,
+ observer: 'updateMarginsDisabled_',
+ },
+
+ /** @type {!State} */
+ state: {
+ type: Number,
+ observer: 'onStateChange_',
+ },
+
+ /** @private */
+ marginsDisabled_: Boolean,
/** Mirroring the enum so that it can be used from HTML bindings. */
MarginsTypeEnum: Object,
},
- observers: ['onMarginsSettingChange_(settings.margins.value)'],
+ observers: [
+ 'onMarginsSettingChange_(settings.margins.value)',
+ 'onMediaSizeOrLayoutChange_(' +
+ 'settings.mediaSize.value, settings.layout.value)',
+ 'onPagesPerSheetSettingChange_(settings.pagesPerSheet.value)'
+ ],
+
+ /** @private {boolean} */
+ loaded_: false,
/** @override */
- ready: function() {
+ ready() {
this.MarginsTypeEnum = MarginsType;
},
+ /** @private */
+ onStateChange_() {
+ if (this.state === State.READY) {
+ this.loaded_ = true;
+ }
+ },
+
+ /** @private */
+ onMediaSizeOrLayoutChange_() {
+ if (this.loaded_ &&
+ this.getSetting('margins').value === MarginsType.CUSTOM) {
+ this.setSetting('margins', MarginsType.DEFAULT);
+ }
+ },
+
/**
- * @param {*} newValue The new value of the margins setting.
+ * @param {number} newValue The new value of the pages per sheet setting.
* @private
*/
- onMarginsSettingChange_: function(newValue) {
+ onPagesPerSheetSettingChange_(newValue) {
+ if (newValue > 1) {
+ this.setSetting('margins', MarginsType.DEFAULT);
+ }
+ this.updateMarginsDisabled_();
+ },
+
+ /** @param {*} newValue The new value of the margins setting. */
+ onMarginsSettingChange_(newValue) {
this.selectedValue =
/** @type {!MarginsType} */ (newValue).toString();
},
/** @param {string} value The new select value. */
- onProcessSelectChange: function(value) {
+ onProcessSelectChange(value) {
this.setSetting('margins', parseInt(value, 10));
},
- /**
- * @param {boolean} globallyDisabled Value of the |disabled| property.
- * @param {number} pagesPerSheet Number of pages per sheet.
- * @return {boolean} Whether the margins settings button should be disabled.
- * @private
- */
- getMarginsSettingsDisabled_: function(globallyDisabled, pagesPerSheet) {
- return globallyDisabled || pagesPerSheet > 1;
+ /** @private */
+ updateMarginsDisabled_() {
+ this.marginsDisabled_ =
+ /** @type {number} */ (this.getSettingValue('pagesPerSheet')) > 1 ||
+ this.disabled;
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/media_size_settings.js b/chromium/chrome/browser/resources/print_preview/ui/media_size_settings.js
index 234792d869e..5b432c2755e 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/media_size_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/media_size_settings.js
@@ -27,7 +27,7 @@ Polymer({
['onMediaSizeSettingChange_(settings.mediaSize.*, capability.option)'],
/** @private */
- onMediaSizeSettingChange_: function() {
+ onMediaSizeSettingChange_() {
if (!this.capability) {
return;
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/more_settings.js b/chromium/chrome/browser/resources/print_preview/ui/more_settings.js
index 0d852cc99d0..b8bf9a2a6a7 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/more_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/more_settings.js
@@ -40,10 +40,10 @@ Polymer({
* @param {!Event} e
* @private
*/
- toggleExpandButton_: function(e) {
+ toggleExpandButton_(e) {
// The expand button handles toggling itself.
const expandButtonTag = 'CR-EXPAND-BUTTON';
- if (e.target.tagName == expandButtonTag) {
+ if (e.target.tagName === expandButtonTag) {
return;
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/number_settings_section.html b/chromium/chrome/browser/resources/print_preview/ui/number_settings_section.html
index ef311426eb8..a24a7655f49 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/number_settings_section.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/number_settings_section.html
@@ -38,7 +38,7 @@
max="[[maxValue]]" min="[[minValue]]" data-timeout-delay="250"
disabled$="[[getDisabled_(disabled)]]" on-keydown="onKeydown_"
on-blur="onBlur_" aria-label="[[inputAriaLabel]]"
- error-message="[[hintMessage]]" auto-validate>
+ error-message="[[errorMessage_]]" auto-validate>
<span slot="suffix">
<slot name="opt-inside-content"></slot>
</span>
diff --git a/chromium/chrome/browser/resources/print_preview/ui/number_settings_section.js b/chromium/chrome/browser/resources/print_preview/ui/number_settings_section.js
index 47821083598..889c755ab3d 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/number_settings_section.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/number_settings_section.js
@@ -54,6 +54,12 @@ Polymer({
hintMessage: String,
disabled: Boolean,
+
+ /** @private */
+ errorMessage_: {
+ type: String,
+ computed: 'computeErrorMessage_(hintMessage, inputValid)',
+ },
},
listeners: {
@@ -61,7 +67,7 @@ Polymer({
},
/** @return {!CrInputElement} The cr-input field element for InputBehavior. */
- getInput: function() {
+ getInput() {
return /** @type {!CrInputElement} */ (this.$.userValue);
},
@@ -69,7 +75,7 @@ Polymer({
* @param {!CustomEvent<string>} e Contains the new input value.
* @private
*/
- onInputChange_: function(e) {
+ onInputChange_(e) {
this.inputString_ = e.detail;
},
@@ -77,42 +83,42 @@ Polymer({
* @return {boolean} Whether the input should be disabled.
* @private
*/
- getDisabled_: function() {
+ getDisabled_() {
return this.disabled && this.inputValid;
},
/**
* @param {!KeyboardEvent} e The keyboard event
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
if (['.', 'e', 'E', '-', '+'].includes(e.key)) {
e.preventDefault();
return;
}
- if (e.key == 'Enter') {
+ if (e.key === 'Enter') {
this.onBlur_();
}
},
/** @private */
- onBlur_: function() {
- if (this.inputString_ == '') {
+ onBlur_() {
+ if (this.inputString_ === '') {
this.set('inputString_', this.defaultValue);
}
- if (this.$.userValue.value == '') {
+ if (this.$.userValue.value === '') {
this.$.userValue.value = this.defaultValue;
}
},
/** @private */
- onInputChanged_: function() {
+ onInputChanged_() {
this.inputValid = this.computeValid_();
this.currentValue = this.inputString_;
},
/** @private */
- onCurrentValueChanged_: function() {
+ onCurrentValueChanged_() {
this.inputString_ = this.currentValue;
this.resetString();
},
@@ -122,9 +128,17 @@ Polymer({
* valid and non-empty, so that it can be used to update the setting.
* @private
*/
- computeValid_: function() {
+ computeValid_() {
// Make sure value updates first, in case inputString_ was updated by JS.
this.$.userValue.value = this.inputString_;
return !this.$.userValue.invalid;
},
+
+ /**
+ * @return {string}
+ * @private
+ */
+ computeErrorMessage_() {
+ return this.inputValid ? '' : this.hintMessage;
+ },
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/other_options_settings.js b/chromium/chrome/browser/resources/print_preview/ui/other_options_settings.js
index 9ccb4825b39..153c763d9c7 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/other_options_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/other_options_settings.js
@@ -32,7 +32,7 @@ Polymer({
*/
options_: {
type: Array,
- value: function() {
+ value() {
return [
{name: 'headerFooter', label: 'optionHeaderFooter'},
{name: 'cssBackground', label: 'optionBackgroundColorsAndImages'},
@@ -69,16 +69,16 @@ Polymer({
* @param {string} settingName The name of the setting to updated.
* @param {boolean} newValue The new value for the setting.
*/
- updateSettingWithTimeout_: function(settingName, newValue) {
+ updateSettingWithTimeout_(settingName, newValue) {
const timeout = this.timeouts_.get(settingName);
- if (timeout != null) {
+ if (timeout !== null) {
clearTimeout(timeout);
}
this.timeouts_.set(
settingName, setTimeout(() => {
this.timeouts_.delete(settingName);
- if (this.previousValues_.get(settingName) == newValue) {
+ if (this.previousValues_.get(settingName) === newValue) {
return;
}
this.previousValues_.set(settingName, newValue);
@@ -93,7 +93,7 @@ Polymer({
* @param {number} index The index of the option to update.
* @private
*/
- updateOptionFromSetting_: function(index) {
+ updateOptionFromSetting_(index) {
const setting = this.getSetting(this.options_[index].name);
this.set(`options_.${index}.available`, setting.available);
this.set(`options_.${index}.value`, setting.value);
@@ -112,27 +112,27 @@ Polymer({
* @return {boolean} Whether the checkbox should be disabled.
* @private
*/
- getDisabled_: function(managed, disabled) {
+ getDisabled_(managed, disabled) {
return managed || disabled;
},
/** @private */
- onHeaderFooterSettingChange_: function() {
+ onHeaderFooterSettingChange_() {
this.updateOptionFromSetting_(0);
},
/** @private */
- onCssBackgroundSettingChange_: function() {
+ onCssBackgroundSettingChange_() {
this.updateOptionFromSetting_(1);
},
/** @private */
- onRasterizeSettingChange_: function() {
+ onRasterizeSettingChange_() {
this.updateOptionFromSetting_(2);
},
/** @private */
- onSelectionOnlySettingChange_: function() {
+ onSelectionOnlySettingChange_() {
this.updateOptionFromSetting_(3);
},
@@ -140,7 +140,7 @@ Polymer({
* @param {!Event} e Contains the checkbox item that was checked.
* @private
*/
- onChange_: function(e) {
+ onChange_(e) {
const name = e.model.item.name;
this.updateSettingWithTimeout_(name, this.$$(`#${name}`).checked);
},
@@ -151,7 +151,7 @@ Polymer({
* section is the first visible.
* @private
*/
- getClass_: function(index) {
+ getClass_(index) {
return index === this.firstIndex_ ? 'first-visible' : '';
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js b/chromium/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js
index 8bdd7e157e0..9c5d6929c4b 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js
@@ -30,13 +30,12 @@ Polymer({
* @param {*} newValue The new value of the pages per sheet setting.
* @private
*/
- onPagesPerSheetSettingChange_: function(newValue) {
+ onPagesPerSheetSettingChange_(newValue) {
this.selectedValue = /** @type {number} */ (newValue).toString();
- this.setSetting('margins', MarginsType.DEFAULT);
},
/** @param {string} value The new select value. */
- onProcessSelectChange: function(value) {
+ onProcessSelectChange(value) {
this.setSetting('pagesPerSheet', parseInt(value, 10));
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/pages_settings.js b/chromium/chrome/browser/resources/print_preview/ui/pages_settings.js
index d03231cd05b..cb1ed21726d 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/pages_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/pages_settings.js
@@ -91,7 +91,7 @@ Polymer({
/** @private {!Array<number>} */
pagesToPrint_: {
type: Array,
- value: function() {
+ value() {
return [];
},
},
@@ -135,12 +135,12 @@ Polymer({
* settings.pages, because settings.pages is not sticky.
* @override
*/
- attached: function() {
+ attached() {
this.selectedValue = PagesValue.ALL.toString();
},
/** @return {!CrInputElement} The cr-input field element for InputBehavior. */
- getInput: function() {
+ getInput() {
return /** @type {!CrInputElement} */ (this.$.pageSettingsCustomInput);
},
@@ -148,19 +148,19 @@ Polymer({
* @param {!CustomEvent<string>} e Contains the new input value.
* @private
*/
- onInputChange_: function(e) {
+ onInputChange_(e) {
if (this.inputString_ !== e.detail) {
this.restoreLastInput_ = true;
}
this.inputString_ = e.detail;
},
- onProcessSelectChange: function(value) {
+ onProcessSelectChange(value) {
this.customSelected_ = value === PagesValue.CUSTOM.toString();
},
/** @private */
- onCollapseChanged_: function() {
+ onCollapseChanged_() {
if (this.customSelected_) {
/** @type {!CrInputElement} */ (this.$.pageSettingsCustomInput)
.inputElement.focus();
@@ -171,7 +171,7 @@ Polymer({
* @return {boolean} Whether the controls should be disabled.
* @private
*/
- computeControlsDisabled_: function() {
+ computeControlsDisabled_() {
// Disable the input if other settings are responsible for the error state.
return !this.hasError_ && this.disabled;
},
@@ -181,7 +181,7 @@ Polymer({
* current value of the input.
* @private
*/
- updatePagesToPrint_: function() {
+ updatePagesToPrint_() {
if (!this.customSelected_) {
this.errorState_ = PagesInputErrorState.NO_ERROR;
this.pagesToPrint_ = this.pageCount ?
@@ -198,7 +198,7 @@ Polymer({
const ranges = this.inputString_.split(/,|\u3001/);
const maxPage = this.pageCount;
for (const range of ranges) {
- if (range == '') {
+ if (range === '') {
this.errorState_ = PagesInputErrorState.INVALID_SYNTAX;
this.onRangeChange_();
return;
@@ -217,7 +217,7 @@ Polymer({
this.onRangeChange_();
return;
}
- if (limits.length == 1) {
+ if (limits.length === 1) {
if (min > maxPage) {
this.errorState_ = PagesInputErrorState.OUT_OF_BOUNDS;
this.onRangeChange_();
@@ -273,10 +273,10 @@ Polymer({
* @return {!Array<{to: number, from: number}>}
* @private
*/
- computeRangesToPrint_: function() {
- if (!this.pagesToPrint_ || this.pagesToPrint_.length == 0 ||
- this.pagesToPrint_[0] == -1 ||
- this.pagesToPrint_.length == this.pageCount) {
+ computeRangesToPrint_() {
+ if (!this.pagesToPrint_ || this.pagesToPrint_.length === 0 ||
+ this.pagesToPrint_[0] === -1 ||
+ this.pagesToPrint_.length === this.pageCount) {
return [];
}
@@ -284,7 +284,7 @@ Polymer({
let to = this.pagesToPrint_[0];
const ranges = [];
for (const page of this.pagesToPrint_.slice(1)) {
- if (page == to + 1) {
+ if (page === to + 1) {
to = page;
continue;
}
@@ -302,10 +302,10 @@ Polymer({
* user.
* @private
*/
- getNupPages_: function() {
+ getNupPages_() {
const pagesPerSheet =
/** @type {number} */ (this.getSettingValue('pagesPerSheet'));
- if (pagesPerSheet <= 1 || this.pagesToPrint_.length == 0) {
+ if (pagesPerSheet <= 1 || this.pagesToPrint_.length === 0) {
return this.pagesToPrint_;
}
@@ -322,7 +322,7 @@ Polymer({
* needed.
* @private
*/
- onRangeChange_: function() {
+ onRangeChange_() {
if (this.settings === undefined || this.pagesToPrint_ === undefined) {
return;
}
@@ -344,7 +344,7 @@ Polymer({
this.rangesToPrint_,
/** @type {!Array} */ (this.getSettingValue('ranges')));
if (rangesChanged ||
- nupPages.length != this.getSettingValue('pages').length) {
+ nupPages.length !== this.getSettingValue('pages').length) {
this.setSetting('pages', nupPages);
}
if (rangesChanged) {
@@ -355,7 +355,7 @@ Polymer({
},
/** @private */
- onSelectBlur_: function(event) {
+ onSelectBlur_(event) {
if (!this.customSelected_ ||
event.relatedTarget === this.$.pageSettingsCustomInput) {
return;
@@ -365,7 +365,7 @@ Polymer({
},
/** @private */
- onCustomInputBlur_: function() {
+ onCustomInputBlur_() {
this.resetAndUpdate();
if (this.errorState_ === PagesInputErrorState.EMPTY) {
// Update with all pages.
@@ -380,14 +380,14 @@ Polymer({
* @return {string} Gets message to show as hint.
* @private
*/
- getHintMessage_: function() {
- if (this.errorState_ == PagesInputErrorState.NO_ERROR ||
- this.errorState_ == PagesInputErrorState.EMPTY) {
+ getHintMessage_() {
+ if (this.errorState_ === PagesInputErrorState.NO_ERROR ||
+ this.errorState_ === PagesInputErrorState.EMPTY) {
return '';
}
let formattedMessage = '';
- if (this.errorState_ == PagesInputErrorState.INVALID_SYNTAX) {
+ if (this.errorState_ === PagesInputErrorState.INVALID_SYNTAX) {
formattedMessage = loadTimeData.getStringF(
'pageRangeSyntaxInstruction',
loadTimeData.getString('examplePageRangeText'));
@@ -402,16 +402,16 @@ Polymer({
* @return {boolean} Whether to hide the hint.
* @private
*/
- hintHidden_: function() {
- return this.errorState_ == PagesInputErrorState.NO_ERROR ||
- this.errorState_ == PagesInputErrorState.EMPTY;
+ hintHidden_() {
+ return this.errorState_ === PagesInputErrorState.NO_ERROR ||
+ this.errorState_ === PagesInputErrorState.EMPTY;
},
/**
* @return {boolean} Whether to disable the custom input.
* @private
*/
- inputDisabled_: function() {
+ inputDisabled_() {
return !this.customSelected_ || this.controlsDisabled_;
},
@@ -419,7 +419,7 @@ Polymer({
* @return {string} A string representing the full page range.
* @private
*/
- getAllPagesString_: function() {
+ getAllPagesString_() {
if (this.pageCount === 0) {
return '';
}
@@ -428,7 +428,7 @@ Polymer({
},
/** @private */
- onCustomSelectedChange_: function() {
+ onCustomSelectedChange_() {
if ((this.customSelected_ && !this.restoreLastInput_) ||
this.errorState_ !== PagesInputErrorState.NO_ERROR) {
this.restoreLastInput_ = true;
@@ -444,7 +444,7 @@ Polymer({
* @param {number} previous
* @private
*/
- onPageCountChange_: function(current, previous) {
+ onPageCountChange_(current, previous) {
// Reset the custom input to the new "all pages" value if it is equal to the
// full page range and was either set automatically, or would become invalid
// due to the page count change.
diff --git a/chromium/chrome/browser/resources/print_preview/ui/pin_settings.html b/chromium/chrome/browser/resources/print_preview/ui/pin_settings.html
index bd83d18acd0..965f41a53e4 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/pin_settings.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/pin_settings.html
@@ -39,7 +39,8 @@
maxlength="4" data-timeout-delay="250" aria-labelledby="pin"
placeholder="$i18n{pinPlaceholder}" spellcheck="false"
disabled$="[[inputDisabled_(pinEnabled_, inputValid_, disabled)]]"
- error-message="$i18n{pinErrorMessage}" required auto-validate>
+ error-message="[[getPinErrorMessage_(inputValid_)]]" required
+ auto-validate>
</cr-input>
</div>
</print-preview-settings-section>
diff --git a/chromium/chrome/browser/resources/print_preview/ui/pin_settings.js b/chromium/chrome/browser/resources/print_preview/ui/pin_settings.js
index dd0d7742700..40a944e4ba3 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/pin_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/pin_settings.js
@@ -8,6 +8,7 @@ import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
import './print_preview_shared_css.js';
import './settings_section.js';
+import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
import {State} from '../data/state.js';
@@ -20,7 +21,7 @@ Polymer({
_template: html`{__html_template__}`,
- behaviors: [SettingsBehavior, InputBehavior],
+ behaviors: [SettingsBehavior, InputBehavior, I18nBehavior],
properties: {
/** @type {!State} */
@@ -66,7 +67,7 @@ Polymer({
},
/** @return {!CrInputElement} The cr-input field element for InputBehavior. */
- getInput: function() {
+ getInput() {
return /** @type {!CrInputElement} */ (this.$.pinValue);
},
@@ -74,12 +75,12 @@ Polymer({
* @param {!CustomEvent<string>} e Contains the new input value.
* @private
*/
- onInputChange_: function(e) {
+ onInputChange_(e) {
this.inputString_ = e.detail;
},
/** @private */
- onCollapseChanged_: function() {
+ onCollapseChanged_() {
if (this.pinEnabled_) {
/** @type {!CrInputElement} */ (this.$.pinValue).focusInput();
}
@@ -92,7 +93,7 @@ Polymer({
* @return {boolean} Whether pin checkbox should be disabled.
* @private
*/
- computeCheckboxDisabled_: function(inputValid, disabled, managed) {
+ computeCheckboxDisabled_(inputValid, disabled, managed) {
return managed || (inputValid && disabled);
},
@@ -100,7 +101,7 @@ Polymer({
* @return {boolean} Whether to disable the pin value input.
* @private
*/
- inputDisabled_: function() {
+ inputDisabled_() {
return !this.pinEnabled_ || (this.inputValid_ && this.disabled);
},
@@ -108,7 +109,7 @@ Polymer({
* Updates the checkbox state when the setting has been initialized.
* @private
*/
- onSettingsChanged_: function() {
+ onSettingsChanged_() {
const pinEnabled = /** @type {boolean} */ (this.getSetting('pin').value);
this.$.pin.checked = pinEnabled;
this.pinEnabled_ = pinEnabled;
@@ -118,7 +119,7 @@ Polymer({
},
/** @private */
- onPinChange_: function() {
+ onPinChange_() {
this.setSetting('pin', this.$.pin.checked);
// We need to set validity of pinValue to true to return to READY state
// after unchecking the pin and to check the validity again after checking
@@ -133,7 +134,7 @@ Polymer({
/**
* @private
*/
- onInputChanged_: function() {
+ onInputChanged_() {
this.changePinValueSetting_();
},
@@ -142,7 +143,7 @@ Polymer({
* input.
* @private
*/
- changePinValueSetting_: function() {
+ changePinValueSetting_() {
if (this.settings === undefined) {
return;
}
@@ -151,7 +152,7 @@ Polymer({
// It's done because we don't permit multiple simultaneous validation errors
// in Print Preview and we also don't want to set the value when sticky
// settings may not yet have been set.
- if (this.state != State.READY && this.settings.pinValue.valid) {
+ if (this.state !== State.READY && this.settings.pinValue.valid) {
return;
}
this.inputValid_ = this.computeValid_();
@@ -159,7 +160,7 @@ Polymer({
// We allow to save the empty string as sticky setting value to give users
// the opportunity to unset their PIN in sticky settings.
- if ((this.inputValid_ || this.inputString_ == '') &&
+ if ((this.inputValid_ || this.inputString_ === '') &&
this.inputString_ !== this.getSettingValue('pinValue')) {
this.setSetting('pinValue', this.inputString_);
}
@@ -170,10 +171,18 @@ Polymer({
* valid, so that it can be used to update the setting.
* @private
*/
- computeValid_: function() {
+ computeValid_() {
// Make sure value updates first, in case inputString_ was updated by JS.
this.$.pinValue.value = this.inputString_;
this.$.pinValue.validate();
return !this.$.pinValue.invalid;
},
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getPinErrorMessage_() {
+ return this.inputValid_ ? '' : this.i18n('pinErrorMessage');
+ },
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/plugin_proxy.js b/chromium/chrome/browser/resources/print_preview/ui/plugin_proxy.js
index f87b3cf9f2b..c145fccf79f 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/plugin_proxy.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/plugin_proxy.js
@@ -6,33 +6,15 @@ import {assert} from 'chrome://resources/js/assert.m.js';
import {PDFCreateOutOfProcessPlugin} from '../pdf/pdf_scripting_api.js';
/**
- * @typedef {{accessibility: Function,
- * documentLoadComplete: Function,
- * getHeight: Function,
- * getHorizontalScrollbarThickness: Function,
- * getPageLocationNormalized: Function,
- * getVerticalScrollbarThickness: Function,
- * getWidth: Function,
- * getZoomLevel: Function,
- * goToPage: Function,
- * grayscale: Function,
+ * @typedef {{darkModeChanged: Function,
+ * hideToolbars: Function,
* loadPreviewPage: Function,
- * onload: Function,
- * onPluginSizeChanged: Function,
- * onScroll: Function,
- * pageXOffset: Function,
- * pageYOffset: Function,
- * reload: Function,
* resetPrintPreviewMode: Function,
+ * scrollPosition: Function,
* sendKeyEvent: Function,
- * setPageNumbers: Function,
- * setPageXOffset: Function,
- * setPageYOffset: Function,
- * setZoomLevel: Function,
- * fitToHeight: Function,
- * fitToWidth: Function,
- * zoomIn: Function,
- * zoomOut: Function}}
+ * setKeyEventCallback: Function,
+ * setLoadCompleteCallback: Function,
+ * setViewportChangedCallback: Function}}
*/
export let PDFPlugin;
@@ -45,7 +27,7 @@ export class PluginProxy {
* @return {!PluginProxy} The singleton instance.
*/
static getInstance() {
- if (instance == null) {
+ if (instance === null) {
instance = new PluginProxy();
}
return assert(instance);
@@ -164,9 +146,9 @@ export class PluginProxy {
this.plugin_.setKeyEventCallback(keyEventCallback);
}
- /** @param {?Function} loadCallback */
- setLoadCallback(loadCallback) {
- this.plugin_.setLoadCallback(loadCallback);
+ /** @param {?Function} loadCompleteCallback */
+ setLoadCompleteCallback(loadCompleteCallback) {
+ this.plugin_.setLoadCompleteCallback(loadCompleteCallback);
}
/** @param {?Function} viewportChangedCallback */
diff --git a/chromium/chrome/browser/resources/print_preview/ui/preview_area.js b/chromium/chrome/browser/resources/print_preview/ui/preview_area.js
index 9b0e8b1f3e8..e75d9bffbf7 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/preview_area.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/preview_area.js
@@ -42,7 +42,6 @@ let MediaSizeValue;
/** @enum {string} */
export const PreviewAreaState = {
- NO_PLUGIN: 'no-plugin',
LOADING: 'loading',
DISPLAY_PREVIEW: 'display-preview',
OPEN_IN_PREVIEW_LOADING: 'open-in-preview-loading',
@@ -93,8 +92,8 @@ Polymer({
/** @type {!State} */
state: Number,
- /** @private {boolean} Whether the plugin is loaded */
- pluginLoaded_: {
+ /** @private {boolean} Whether the plugin completely loaded the preview */
+ pluginLoadComplete_: {
type: Boolean,
value: false,
},
@@ -109,7 +108,7 @@ Polymer({
previewLoaded_: {
type: Boolean,
notify: true,
- computed: 'computePreviewLoaded_(documentReady_, pluginLoaded_)',
+ computed: 'computePreviewLoaded_(documentReady_, pluginLoadComplete_)',
},
},
@@ -120,7 +119,7 @@ Polymer({
observers: [
'onDarkModeChanged_(inDarkMode)',
- 'pluginOrDocumentStatusChanged_(pluginLoaded_, documentReady_)',
+ 'pluginOrDocumentStatusChanged_(pluginLoadComplete_, documentReady_)',
'onStateOrErrorChange_(state, error)',
],
@@ -140,7 +139,7 @@ Polymer({
keyEventCallback_: null,
/** @override */
- attached: function() {
+ attached() {
this.nativeLayer_ = NativeLayer.getInstance();
this.addWebUIListener(
'page-preview-ready', this.onPagePreviewReady_.bind(this));
@@ -153,7 +152,7 @@ Polymer({
},
/** @override */
- created: function() {
+ created() {
this.pluginProxy_ = PluginProxy.getInstance();
},
@@ -161,12 +160,12 @@ Polymer({
* @return {boolean} Whether the preview is loaded.
* @private
*/
- computePreviewLoaded_: function() {
- return this.documentReady_ && this.pluginLoaded_;
+ computePreviewLoaded_() {
+ return this.documentReady_ && this.pluginLoadComplete_;
},
/** @return {boolean} Whether the preview is loaded. */
- previewLoaded: function() {
+ previewLoaded() {
return this.previewLoaded_;
},
@@ -176,11 +175,11 @@ Polymer({
* @param {!Event} event Contains element pointer moved from.
* @private
*/
- onPointerOver_: function(event) {
+ onPointerOver_(event) {
const marginControlContainer = this.$.marginControlContainer;
let fromElement = event.fromElement;
- while (fromElement != null) {
- if (fromElement == marginControlContainer) {
+ while (fromElement !== null) {
+ if (fromElement === marginControlContainer) {
return;
}
@@ -195,11 +194,11 @@ Polymer({
* @param {!Event} event Contains element pointer moved to.
* @private
*/
- onPointerOut_: function(event) {
+ onPointerOut_(event) {
const marginControlContainer = this.$.marginControlContainer;
let toElement = event.toElement;
- while (toElement != null) {
- if (toElement == marginControlContainer) {
+ while (toElement !== null) {
+ if (toElement === marginControlContainer) {
return;
}
@@ -209,14 +208,14 @@ Polymer({
},
/** @private */
- pluginOrDocumentStatusChanged_: function() {
- if (!this.pluginLoaded_ || !this.documentReady_ ||
+ pluginOrDocumentStatusChanged_() {
+ if (!this.pluginLoadComplete_ || !this.documentReady_ ||
this.previewState === PreviewAreaState.ERROR) {
return;
}
this.previewState =
- this.previewState == PreviewAreaState.OPEN_IN_PREVIEW_LOADING ?
+ this.previewState === PreviewAreaState.OPEN_IN_PREVIEW_LOADING ?
PreviewAreaState.OPEN_IN_PREVIEW_LOADED :
PreviewAreaState.DISPLAY_PREVIEW;
},
@@ -225,7 +224,7 @@ Polymer({
* @return {string} 'invisible' if overlay is invisible, '' otherwise.
* @private
*/
- getInvisible_: function() {
+ getInvisible_() {
return this.isInDisplayPreviewState_() ? 'invisible' : '';
},
@@ -233,7 +232,7 @@ Polymer({
* @return {string} 'true' if overlay is aria-hidden, 'false' otherwise.
* @private
*/
- getAriaHidden_: function() {
+ getAriaHidden_() {
return this.isInDisplayPreviewState_().toString();
},
@@ -241,23 +240,23 @@ Polymer({
* @return {boolean} Whether the preview area is in DISPLAY_PREVIEW state.
* @private
*/
- isInDisplayPreviewState_: function() {
- return this.previewState == PreviewAreaState.DISPLAY_PREVIEW;
+ isInDisplayPreviewState_() {
+ return this.previewState === PreviewAreaState.DISPLAY_PREVIEW;
},
/**
* @return {boolean} Whether the preview is currently loading.
* @private
*/
- isPreviewLoading_: function() {
- return this.previewState == PreviewAreaState.LOADING;
+ isPreviewLoading_() {
+ return this.previewState === PreviewAreaState.LOADING;
},
/**
* @return {string} 'jumping-dots' to enable animation, '' otherwise.
* @private
*/
- getJumpingDots_: function() {
+ getJumpingDots_() {
return this.isPreviewLoading_() ? 'jumping-dots' : '';
},
@@ -266,7 +265,7 @@ Polymer({
* page should be shown.
* @private
*/
- shouldShowLearnMoreLink_: function() {
+ shouldShowLearnMoreLink_() {
return this.error === Error.UNSUPPORTED_PRINTER;
},
@@ -274,7 +273,7 @@ Polymer({
* @return {string} The current preview area message to display.
* @private
*/
- currentMessage_: function() {
+ currentMessage_() {
switch (this.previewState) {
case PreviewAreaState.LOADING:
return this.i18n('loading');
@@ -298,7 +297,7 @@ Polymer({
* @param {boolean} forceUpdate Whether to force the preview area to update
* regardless of whether the print ticket has changed.
*/
- startPreview: function(forceUpdate) {
+ startPreview(forceUpdate) {
if (!this.hasTicketChanged_() && !forceUpdate &&
this.previewState !== PreviewAreaState.ERROR) {
return;
@@ -313,10 +312,10 @@ Polymer({
this.documentReady_ = true;
},
type => {
- if (/** @type{string} */ (type) == 'SETTINGS_INVALID') {
+ if (/** @type{string} */ (type) === 'SETTINGS_INVALID') {
this.error = Error.INVALID_PRINTER;
this.previewState = PreviewAreaState.ERROR;
- } else if (/** @type{string} */ (type) != 'CANCELLED') {
+ } else if (/** @type{string} */ (type) !== 'CANCELLED') {
this.error = Error.PREVIEW_FAILED;
this.previewState = PreviewAreaState.ERROR;
}
@@ -325,9 +324,9 @@ Polymer({
// <if expr="is_macosx">
/** Set the preview state to display the "opening in preview" message. */
- setOpeningPdfInPreview: function() {
+ setOpeningPdfInPreview() {
assert(isMac);
- this.previewState = this.previewState == PreviewAreaState.LOADING ?
+ this.previewState = this.previewState === PreviewAreaState.LOADING ?
PreviewAreaState.OPEN_IN_PREVIEW_LOADING :
PreviewAreaState.OPEN_IN_PREVIEW_LOADED;
},
@@ -338,19 +337,19 @@ Polymer({
* @param {number} index The index of the page to preview.
* @private
*/
- onPreviewStart_: function(previewUid, index) {
+ onPreviewStart_(previewUid, index) {
if (!this.pluginProxy_.pluginReady()) {
const plugin = this.pluginProxy_.createPlugin(previewUid, index);
this.pluginProxy_.setKeyEventCallback(this.keyEventCallback_);
this.$$('.preview-area-plugin-wrapper')
- .appendChild(
- /** @type {Node} */ (plugin));
- this.pluginProxy_.setLoadCallback(this.onPluginLoad_.bind(this));
+ .appendChild(/** @type {Node} */ (plugin));
+ this.pluginProxy_.setLoadCompleteCallback(
+ this.onPluginLoadComplete_.bind(this));
this.pluginProxy_.setViewportChangedCallback(
this.onPreviewVisualStateChange_.bind(this));
}
- this.pluginLoaded_ = false;
+ this.pluginLoadComplete_ = false;
if (this.inDarkMode) {
this.pluginProxy_.darkModeChanged(true);
}
@@ -361,15 +360,13 @@ Polymer({
},
/**
- * Called when the plugin loads. This is a consequence of calling
- * plugin.reload(). Certain plugin state can only be set after the plugin
- * has loaded.
+ * Called when the plugin loads the preview completely.
* @param {boolean} success Whether the plugin load succeeded or not.
* @private
*/
- onPluginLoad_: function(success) {
+ onPluginLoadComplete_(success) {
if (success) {
- this.pluginLoaded_ = true;
+ this.pluginLoadComplete_ = true;
} else {
this.error = Error.PREVIEW_FAILED;
this.previewState = PreviewAreaState.ERROR;
@@ -387,7 +384,7 @@ Polymer({
* @param {number} viewportHeight The viewport height in pixels.
* @private
*/
- onPreviewVisualStateChange_: function(
+ onPreviewVisualStateChange_(
pageX, pageY, pageWidth, viewportWidth, viewportHeight) {
// Ensure the PDF viewer isn't tabbable if the window is small enough that
// the zoom toolbar isn't displayed.
@@ -399,6 +396,14 @@ Polymer({
pageWidth / this.pageSize.width);
this.$.marginControlContainer.updateClippingMask(
new Size(viewportWidth, viewportHeight));
+ // Align the margin control container with the preview content area.
+ // The offset may be caused by the scrollbar on the left in the preview
+ // area in right-to-left direction.
+ const previewDocument = this.$$('.preview-area-plugin').contentDocument;
+ if (previewDocument && previewDocument.documentElement) {
+ this.$.marginControlContainer.style.left =
+ previewDocument.documentElement.offsetLeft + 'px';
+ }
},
/**
@@ -409,8 +414,8 @@ Polymer({
* preview is a response to.
* @private
*/
- onPagePreviewReady_: function(pageIndex, previewUid, previewResponseId) {
- if (this.inFlightRequestId_ != previewResponseId) {
+ onPagePreviewReady_(pageIndex, previewUid, previewResponseId) {
+ if (this.inFlightRequestId_ !== previewResponseId) {
return;
}
const pageNumber = pageIndex + 1;
@@ -422,16 +427,16 @@ Polymer({
if (pagesPerSheet > 1) {
index = pageIndex;
}
- if (index == 0) {
+ if (index === 0) {
this.onPreviewStart_(previewUid, pageIndex);
}
- if (index != -1) {
+ if (index !== -1) {
this.pluginProxy_.loadPreviewPage(previewUid, pageIndex, index);
}
},
/** @private */
- onDarkModeChanged_: function() {
+ onDarkModeChanged_() {
if (this.pluginProxy_.pluginReady()) {
this.pluginProxy_.darkModeChanged(this.inDarkMode);
}
@@ -446,7 +451,7 @@ Polymer({
* the preview plugin.
* @param {!KeyboardEvent} e Keyboard event to process.
*/
- handleDirectionalKeyEvent: function(e) {
+ handleDirectionalKeyEvent(e) {
// Make sure the PDF plugin is there.
// We only care about: PageUp, PageDown, Left, Up, Right, Down.
// If the user is holding a modifier key, ignore.
@@ -487,7 +492,7 @@ Polymer({
/**
* Sends a message to the plugin to hide the toolbars after a delay.
*/
- hideToolbars: function() {
+ hideToolbars() {
if (!this.pluginProxy_.pluginReady()) {
return;
}
@@ -501,14 +506,14 @@ Polymer({
* @param {function(KeyboardEvent)} callback The callback to be called with
* a key event.
*/
- setPluginKeyEventCallback: function(callback) {
+ setPluginKeyEventCallback(callback) {
this.keyEventCallback_ = callback;
},
/**
* Called when dragging margins starts or stops.
*/
- onMarginDragChanged_: function(e) {
+ onMarginDragChanged_(e) {
if (!this.pluginProxy_.pluginReady()) {
return;
}
@@ -525,7 +530,7 @@ Polymer({
* where the plugin should scroll to.
* @private
*/
- onTextFocusPosition_: function(e) {
+ onTextFocusPosition_(e) {
// TODO(tkent): This is a workaround of a preview-area scrolling
// issue. Blink scrolls preview-area on focus, but we don't want it. We
// should adjust scroll position of PDF preview and positions of
@@ -547,7 +552,7 @@ Polymer({
* @return {boolean} Whether margin settings are valid for the print ticket.
* @private
*/
- marginsValid_: function() {
+ marginsValid_() {
const type = this.getSettingValue('margins');
if (!Object.values(MarginsType).includes(type)) {
// Unrecognized margins type.
@@ -569,7 +574,7 @@ Polymer({
* @return {boolean}
* @private
*/
- hasTicketChanged_: function() {
+ hasTicketChanged_() {
if (!this.marginsValid_()) {
// Log so that we can try to debug how this occurs. See
// https://crbug.com/942211
@@ -597,10 +602,10 @@ Polymer({
// Change in custom margins values.
if (!!lastTicket.marginsCustom &&
- (lastTicket.marginsCustom.marginTop != customMargins.marginTop ||
- lastTicket.marginsCustom.marginLeft != customMargins.marginLeft ||
- lastTicket.marginsCustom.marginRight != customMargins.marginRight ||
- lastTicket.marginsCustom.marginBottom !=
+ (lastTicket.marginsCustom.marginTop !== customMargins.marginTop ||
+ lastTicket.marginsCustom.marginLeft !== customMargins.marginLeft ||
+ lastTicket.marginsCustom.marginRight !== customMargins.marginRight ||
+ lastTicket.marginsCustom.marginBottom !==
customMargins.marginBottom)) {
return true;
}
@@ -651,8 +656,8 @@ Polymer({
// Media size
const newValue =
/** @type {!MediaSizeValue} */ (this.getSettingValue('mediaSize'));
- if (newValue.height_microns != lastTicket.mediaSize.height_microns ||
- newValue.width_microns != lastTicket.mediaSize.width_microns ||
+ if (newValue.height_microns !== lastTicket.mediaSize.height_microns ||
+ newValue.width_microns !== lastTicket.mediaSize.width_microns ||
(this.destination.id !== lastTicket.deviceName &&
this.getSettingValue('margins') === MarginsType.MINIMUM)) {
return true;
@@ -668,13 +673,13 @@ Polymer({
},
/** @return {number} Native color model of the destination. */
- getColorForTicket_: function() {
+ getColorForTicket_() {
return this.destination.getNativeColorModel(
/** @type {boolean} */ (this.getSettingValue('color')));
},
/** @return {number} Scale factor for print ticket. */
- getScaleFactorForTicket_: function() {
+ getScaleFactorForTicket_() {
return this.getSettingValue(this.getScalingSettingKey_()) ===
ScalingType.CUSTOM ?
parseInt(this.getSettingValue('scaling'), 10) :
@@ -682,7 +687,7 @@ Polymer({
},
/** @return {string} Appropriate key for the scaling type setting. */
- getScalingSettingKey_: function() {
+ getScalingSettingKey_() {
return this.getSetting('scalingTypePdf').available ? 'scalingTypePdf' :
'scalingType';
},
@@ -692,7 +697,7 @@ Polymer({
* @return {boolean} Whether new scaling settings update the previewed
* document.
*/
- isScalingChanged_: function(lastTicket) {
+ isScalingChanged_(lastTicket) {
// Preview always updates if the scale factor is changed.
if (this.getScaleFactorForTicket_() !== lastTicket.scaleFactor) {
return true;
@@ -719,7 +724,7 @@ Polymer({
* @param {string} dpiField The field in dpi to retrieve.
* @return {number} Field value.
*/
- getDpiForTicket_: function(dpiField) {
+ getDpiForTicket_(dpiField) {
const dpi =
/**
@type {{horizontal_dpi: (number | undefined),
@@ -736,7 +741,7 @@ Polymer({
* @return {!Promise} Promise that resolves when the preview has been
* generated.
*/
- getPreview_: function() {
+ getPreview_() {
this.inFlightRequestId_++;
const ticket = {
pageRange: this.getSettingValue('ranges'),
@@ -746,7 +751,7 @@ Polymer({
headerFooterEnabled: this.getSettingValue('headerFooter'),
marginsType: this.getSettingValue('margins'),
pagesPerSheet: this.getSettingValue('pagesPerSheet'),
- isFirstRequest: this.inFlightRequestId_ == 0,
+ isFirstRequest: this.inFlightRequestId_ === 0,
requestID: this.inFlightRequestId_,
previewModifiable: this.documentModifiable,
scaleFactor: this.getScaleFactorForTicket_(),
@@ -772,7 +777,7 @@ Polymer({
ticket.cloudPrintID = this.destination.id;
}
- if (this.getSettingValue('margins') == MarginsType.CUSTOM) {
+ if (this.getSettingValue('margins') === MarginsType.CUSTOM) {
ticket.marginsCustom = this.getSettingValue('customMargins');
}
this.lastTicket_ = ticket;
@@ -782,7 +787,7 @@ Polymer({
},
/** @private */
- onStateOrErrorChange_: function() {
+ onStateOrErrorChange_() {
if ((this.state === State.ERROR || this.state === State.FATAL_ERROR) &&
this.getErrorMessage_() !== '') {
this.previewState = PreviewAreaState.ERROR;
@@ -790,7 +795,7 @@ Polymer({
},
/** @return {string} The error message to display in the preview area. */
- getErrorMessage_: function() {
+ getErrorMessage_() {
switch (this.error) {
case Error.INVALID_PRINTER:
return this.i18nAdvanced('invalidPrinterSettings', {
diff --git a/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.html b/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.html
index db69f9be140..816b95996fe 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.html
@@ -1,7 +1,6 @@
<style include="print-preview-shared cr-input-style">
:host {
display: flex;
- font-size: calc(13/15 * 1em);
--cr-input-error-display: none;
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.js b/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.js
index 3c0e569fc8e..ebbc6056c40 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/print_preview_search_box.js
@@ -9,6 +9,7 @@ import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
import './print_preview_shared_css.js';
import {CrSearchFieldBehavior} from 'chrome://resources/cr_elements/cr_search_field/cr_search_field_behavior.m.js';
+import {stripDiacritics} from 'chrome://resources/js/search_highlight_utils.m.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
/** @type {!RegExp} */
@@ -39,14 +40,14 @@ Polymer({
* The last search query.
* @private {string}
*/
- lastString_: '',
+ lastQuery_: '',
/** @return {!CrInputElement} */
- getSearchInput: function() {
+ getSearchInput() {
return /** @type {!CrInputElement} */ (this.$.searchInput);
},
- focus: function() {
+ focus() {
this.$.searchInput.focus();
},
@@ -54,20 +55,20 @@ Polymer({
* @param {!CustomEvent<string>} e Event containing the new search.
* @private
*/
- onSearchChanged_: function(e) {
- const safeQueryString = e.detail.trim().replace(SANITIZE_REGEX, '\\$&');
- if (safeQueryString === this.lastString_) {
+ onSearchChanged_(e) {
+ const strippedQuery = stripDiacritics(e.detail.trim());
+ const safeQuery = strippedQuery.replace(SANITIZE_REGEX, '\\$&');
+ if (safeQuery === this.lastQuery_) {
return;
}
- this.lastString_ = safeQueryString;
- this.searchQuery = safeQueryString.length > 0 ?
- new RegExp(`(${safeQueryString})`, 'i') :
- null;
+ this.lastQuery_ = safeQuery;
+ this.searchQuery =
+ safeQuery.length > 0 ? new RegExp(`(${safeQuery})`, 'ig') : null;
},
/** @private */
- onClearClick_: function() {
+ onClearClick_() {
this.setValue('');
this.$.searchInput.focus();
},
diff --git a/chromium/chrome/browser/resources/print_preview/ui/print_preview_shared_css.html b/chromium/chrome/browser/resources/print_preview/ui/print_preview_shared_css.html
index d90cef075f7..8b264fa03a0 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/print_preview_shared_css.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/print_preview_shared_css.html
@@ -64,7 +64,7 @@
}
#dialog div[slot='title'] {
- padding-bottom: 0;
+ padding-bottom: 8px;
}
#dialog div[slot='button-container'] {
diff --git a/chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html b/chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html
index 9aa28273acb..d3207591c2d 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.html
@@ -15,7 +15,7 @@
line-height: calc(20/13 * 1em);
margin: 0;
padding-bottom: 12px;
- padding-top: 16px;
+ padding-top: 8px;
}
.extension-desc {
diff --git a/chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.js b/chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.js
index 62dfcd2837e..dd49f8d656e 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.js
@@ -80,7 +80,7 @@ Polymer({
* @return {!Promise} Promise that is resolved when the destination has been
* resolved.
*/
- resolveDestination: function(destination) {
+ resolveDestination(destination) {
this.state_ = ResolverState.ACTIVE;
this.destination_ = destination;
this.$.dialog.showModal();
@@ -100,9 +100,9 @@ Polymer({
* resolved destination and the dialog closes.
* @private
*/
- startResolveDestination_: function() {
+ startResolveDestination_() {
assert(
- this.state_ == ResolverState.ACTIVE,
+ this.state_ === ResolverState.ACTIVE,
'Invalid state in request grant permission');
this.state_ = ResolverState.GRANTING_PERMISSION;
@@ -112,11 +112,11 @@ Polymer({
.then(
/** @param {?Destination} resolvedDestination */
(resolvedDestination) => {
- if (this.state_ != ResolverState.GRANTING_PERMISSION) {
+ if (this.state_ !== ResolverState.GRANTING_PERMISSION) {
return;
}
- if (destination.id != this.destination_.id) {
+ if (destination.id !== this.destination_.id) {
return;
}
@@ -135,21 +135,21 @@ Polymer({
* @param {!KeyboardEvent} e Event containing the key
* @private
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
e.stopPropagation();
- if (e.key == 'Escape') {
+ if (e.key === 'Escape') {
this.$.dialog.cancel();
e.preventDefault();
}
},
/** @private */
- onCancelClick_: function() {
+ onCancelClick_() {
this.$.dialog.cancel();
},
/** @private */
- onCancel_: function() {
+ onCancel_() {
this.promiseResolver_.reject();
this.state_ = ResolverState.INITIAL;
},
@@ -158,8 +158,8 @@ Polymer({
* @return {string} The USB permission message to display.
* @private
*/
- getPermissionMessage_: function() {
- return this.state_ == ResolverState.ERROR ?
+ getPermissionMessage_() {
+ return this.state_ === ResolverState.ERROR ?
this.i18n(
'resolveExtensionUSBErrorMessage',
this.destination_.extensionName) :
@@ -170,23 +170,23 @@ Polymer({
* @return {boolean} Whether the resolver is in the ERROR state.
* @private
*/
- isInErrorState_: function() {
- return this.state_ == ResolverState.ERROR;
+ isInErrorState_() {
+ return this.state_ === ResolverState.ERROR;
},
/**
* @return {boolean} Whether the resolver is in the ACTIVE state.
* @private
*/
- isInActiveState_: function() {
- return this.state_ == ResolverState.ACTIVE;
+ isInActiveState_() {
+ return this.state_ === ResolverState.ACTIVE;
},
/**
* @return {string} 'throbber' if the resolver is in the GRANTING_PERMISSION
* state, empty otherwise.
*/
- getThrobberClass_: function() {
- return this.state_ == ResolverState.GRANTING_PERMISSION ? 'throbber' : '';
+ getThrobberClass_() {
+ return this.state_ === ResolverState.GRANTING_PERMISSION ? 'throbber' : '';
},
});
diff --git a/chromium/chrome/browser/resources/print_preview/ui/scaling_settings.js b/chromium/chrome/browser/resources/print_preview/ui/scaling_settings.js
index 1dedfd94310..07defb7a22a 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/scaling_settings.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/scaling_settings.js
@@ -95,7 +95,7 @@ Polymer({
*/
userSelectedCustomScaling_: false,
- onProcessSelectChange: function(value) {
+ onProcessSelectChange(value) {
const isCustom = value === ScalingType.CUSTOM.toString();
if (isCustom && !this.customScalingSettingSet_) {
this.userSelectedCustomScaling_ = true;
@@ -119,7 +119,7 @@ Polymer({
},
/** @private */
- updateScalingToValid_: function() {
+ updateScalingToValid_() {
if (!this.getSetting('scaling').valid) {
this.currentValue_ = this.lastValidScaling_;
} else {
@@ -131,14 +131,14 @@ Polymer({
* Updates the input string when scaling setting is set.
* @private
*/
- onScalingSettingChanged_: function() {
+ onScalingSettingChanged_() {
const value = /** @type {string} */ (this.getSetting('scaling').value);
this.lastValidScaling_ = value;
this.currentValue_ = value;
},
/** @private */
- onScalingTypeSettingChanged_: function() {
+ onScalingTypeSettingChanged_() {
if (!this.settingKey_) {
return;
}
@@ -158,7 +158,7 @@ Polymer({
* scaling input.
* @private
*/
- onInputChanged_: function() {
+ onInputChanged_() {
this.setSettingValid('scaling', this.inputValid_);
if (this.currentValue_ !== '' && this.inputValid_ &&
@@ -168,7 +168,7 @@ Polymer({
},
/** @private */
- onDisabledChanged_: function() {
+ onDisabledChanged_() {
this.dropdownDisabled_ = this.disabled && this.inputValid_;
},
@@ -176,7 +176,7 @@ Polymer({
* @return {boolean} Whether the input should be disabled.
* @private
*/
- inputDisabled_: function() {
+ inputDisabled_() {
return !this.customSelected_ || this.dropdownDisabled_;
},
@@ -184,7 +184,7 @@ Polymer({
* @return {boolean} Whether the custom scaling option is selected.
* @private
*/
- computeCustomSelected_: function() {
+ computeCustomSelected_() {
return !!this.settingKey_ &&
this.getSettingValue(this.settingKey_) === ScalingType.CUSTOM;
},
@@ -193,12 +193,12 @@ Polymer({
* @return {string} The key of the appropriate scaling setting.
* @private
*/
- computeSettingKey_: function() {
+ computeSettingKey_() {
return this.isPdf ? 'scalingTypePdf' : 'scalingType';
},
/** @private */
- onCollapseChanged_: function() {
+ onCollapseChanged_() {
if (this.customSelected_ && this.userSelectedCustomScaling_) {
this.$$('print-preview-number-settings-section').getInput().focus();
}
diff --git a/chromium/chrome/browser/resources/print_preview/ui/select_behavior.js b/chromium/chrome/browser/resources/print_preview/ui/select_behavior.js
index 4cba7a32e01..4e21bb4d903 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/select_behavior.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/select_behavior.js
@@ -24,7 +24,7 @@ export const SelectBehavior = {
* @param {?string} previous
* @private
*/
- onSelectedValueChange_: function(current, previous) {
+ onSelectedValueChange_(current, previous) {
// Don't trigger an extra preview request at startup.
if (previous === undefined) {
return;
@@ -43,5 +43,5 @@ export const SelectBehavior = {
* value updates.
* @param {string} value The new select value to process.
*/
- onProcessSelectChange: function(value) {},
+ onProcessSelectChange(value) {},
};
diff --git a/chromium/chrome/browser/resources/print_preview/ui/settings_behavior.js b/chromium/chrome/browser/resources/print_preview/ui/settings_behavior.js
index 5b5979534d9..bbe8a79b28a 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/settings_behavior.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/settings_behavior.js
@@ -15,7 +15,7 @@ export const SettingsBehavior = {
* @param {string} settingName Name of the setting to get.
* @return {Setting} The setting object.
*/
- getSetting: function(settingName) {
+ getSetting(settingName) {
return getInstance().getSetting(settingName);
},
@@ -23,7 +23,7 @@ export const SettingsBehavior = {
* @param {string} settingName Name of the setting to get the value for.
* @return {*} The value of the setting, accounting for availability.
*/
- getSettingValue: function(settingName) {
+ getSettingValue(settingName) {
return getInstance().getSettingValue(settingName);
},
@@ -37,7 +37,7 @@ export const SettingsBehavior = {
* @param {boolean=} noSticky Whether to avoid stickying the setting. Defaults
* to false.
*/
- setSetting: function(settingName, value, noSticky) {
+ setSetting(settingName, value, noSticky) {
getInstance().setSetting(settingName, value, noSticky);
},
@@ -49,7 +49,7 @@ export const SettingsBehavior = {
* @param {boolean=} noSticky Whether to avoid stickying the setting. Defaults
* to false.
*/
- setSettingSplice: function(settingName, start, end, newValue, noSticky) {
+ setSettingSplice(settingName, start, end, newValue, noSticky) {
getInstance().setSettingSplice(settingName, start, end, newValue, noSticky);
},
@@ -59,7 +59,7 @@ export const SettingsBehavior = {
* @param {string} settingName Name of the setting to set
* @param {boolean} valid Whether the setting value is currently valid.
*/
- setSettingValid: function(settingName, valid) {
+ setSettingValid(settingName, valid) {
getInstance().setSettingValid(settingName, valid);
},
};
diff --git a/chromium/chrome/browser/resources/print_preview/ui/settings_select.js b/chromium/chrome/browser/resources/print_preview/ui/settings_select.js
index 857569ecae9..8325d8e3d3d 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/settings_select.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/settings_select.js
@@ -45,13 +45,13 @@ Polymer({
* @return {boolean} Whether the option is selected.
* @private
*/
- isSelected_: function(option) {
- return this.getValue_(option) == this.selectedValue ||
- (!!option.is_default && this.selectedValue == '');
+ isSelected_(option) {
+ return this.getValue_(option) === this.selectedValue ||
+ (!!option.is_default && this.selectedValue === '');
},
/** @param {string} value The value to select. */
- selectValue: function(value) {
+ selectValue(value) {
this.selectedValue = value;
},
@@ -61,7 +61,7 @@ Polymer({
* @return {string} Value for the option.
* @private
*/
- getValue_: function(option) {
+ getValue_(option) {
return JSON.stringify(option);
},
@@ -71,7 +71,7 @@ Polymer({
* @return {string} Display name for the option.
* @private
*/
- getDisplayName_: function(option) {
+ getDisplayName_(option) {
let displayName = option.custom_display_name;
if (!displayName && option.custom_display_name_localized) {
displayName = getStringForCurrentLocale(
@@ -81,7 +81,7 @@ Polymer({
},
/** @param {string} value The new select value. */
- onProcessSelectChange: function(value) {
+ onProcessSelectChange(value) {
let newValue = null;
try {
newValue = JSON.parse(value);
diff --git a/chromium/chrome/browser/resources/print_preview/ui/sidebar.html b/chromium/chrome/browser/resources/print_preview/ui/sidebar.html
index f370c61a620..81f744fcd68 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/sidebar.html
+++ b/chromium/chrome/browser/resources/print_preview/ui/sidebar.html
@@ -37,7 +37,7 @@
</style>
<print-preview-header id="header" destination="[[destination]]"
cloud-print-error-message="[[cloudPrintErrorMessage]]"
- error="[[error]]" state="[[state]]"
+ error="[[error]]" sheet-count="[[sheetCount_]]" state="[[state]]"
settings="[[settings]]" managed="[[controlsManaged]]">
</print-preview-header>
<div id="container" show-bottom-shadow>
@@ -60,6 +60,7 @@
hidden$="[[!settings.pages.available]]" class="settings-section">
</print-preview-pages-settings>
<print-preview-copies-settings settings="[[settings]]"
+ capability="[[destination.capabilities.printer.copies]]"
disabled="[[controlsDisabled_]]"
hidden$="[[!settings.copies.available]]" class="settings-section">
</print-preview-copies-settings>
@@ -90,7 +91,7 @@
hidden$="[[!settings.pagesPerSheet.available]]"
class="settings-section">
</print-preview-pages-per-sheet-settings>
- <print-preview-margins-settings settings="[[settings]]"
+ <print-preview-margins-settings settings="[[settings]]" state="[[state]]"
disabled="[[controlsDisabled_]]"
hidden$="[[!settings.margins.available]]"
class="settings-section">
diff --git a/chromium/chrome/browser/resources/print_preview/ui/sidebar.js b/chromium/chrome/browser/resources/print_preview/ui/sidebar.js
index c3d04728275..53ae52d65ea 100644
--- a/chromium/chrome/browser/resources/print_preview/ui/sidebar.js
+++ b/chromium/chrome/browser/resources/print_preview/ui/sidebar.js
@@ -104,6 +104,13 @@ Polymer({
computed: 'computeControlsDisabled_(state)',
},
+ /** @private {number} */
+ sheetCount_: {
+ type: Number,
+ computed: 'computeSheetCount_(' +
+ 'settings.pages.*, settings.duplex.*, settings.copies.*)',
+ },
+
/** @private {boolean} */
firstLoad_: {
type: Boolean,
@@ -144,7 +151,7 @@ Polymer({
* @param {boolean} syncAvailable
* @param {boolean} pdfPrinterDisabled Whether the PDF printer is disabled.
*/
- init: function(
+ init(
appKioskMode, defaultPrinter, serializedDestinationSelectionRulesStr,
userAccounts, syncAvailable, pdfPrinterDisabled) {
this.isInAppKioskMode_ = appKioskMode;
@@ -158,15 +165,27 @@ Polymer({
* @return {boolean} Whether the controls should be disabled.
* @private
*/
- computeControlsDisabled_: function() {
- return this.state != State.READY;
+ computeControlsDisabled_() {
+ return this.state !== State.READY;
+ },
+
+ /**
+ * @return {number} The number of sheets that will be printed.
+ * @private
+ */
+ computeSheetCount_() {
+ let sheets = this.getSettingValue('pages').length;
+ if (this.getSettingValue('duplex')) {
+ sheets = Math.ceil(sheets / 2);
+ }
+ return sheets * /** @type {number} */ (this.getSettingValue('copies'));
},
/**
* @return {boolean} Whether to show the "More settings" link.
* @private
*/
- computeShouldShowMoreSettings_: function() {
+ computeShouldShowMoreSettings_() {
// Destination settings is always available. See if the total number of
// available sections exceeds the maximum number to show.
return [
@@ -181,7 +200,7 @@ Polymer({
* @return {boolean} Whether the "more settings" collapse should be expanded.
* @private
*/
- shouldExpandSettings_: function() {
+ shouldExpandSettings_() {
if (this.settingsExpandedByUser_ === undefined ||
this.shouldShowMoreSettings_ === undefined) {
return false;
@@ -193,11 +212,11 @@ Polymer({
},
/** @private */
- onPrintButtonFocused_: function() {
+ onPrintButtonFocused_() {
this.firstLoad_ = false;
},
- onStateChanged_: function() {
+ onStateChanged_() {
if (this.state !== State.PRINTING) {
return;
}
@@ -211,7 +230,7 @@ Polymer({
},
/** @return {boolean} Whether the system dialog link is available. */
- systemDialogLinkAvailable: function() {
+ systemDialogLinkAvailable() {
const linkContainer = this.$$('print-preview-link-container');
return !!linkContainer && linkContainer.systemDialogLinkAvailable();
},
diff --git a/chromium/chrome/browser/resources/protobufs/OWNERS b/chromium/chrome/browser/resources/protobufs/OWNERS
deleted file mode 100644
index f93bbac403b..00000000000
--- a/chromium/chrome/browser/resources/protobufs/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-drubery@chromium.org
-meacer@chromium.org
-nparker@chromium.org
-vakh@chromium.org
diff --git a/chromium/chrome/browser/resources/protobufs/binary_proto_generator.py b/chromium/chrome/browser/resources/protobufs/binary_proto_generator.py
deleted file mode 100755
index 7422ead9697..00000000000
--- a/chromium/chrome/browser/resources/protobufs/binary_proto_generator.py
+++ /dev/null
@@ -1,207 +0,0 @@
-#!/usr/bin/python
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""
- Converts a given ASCII proto into a binary resource.
-
-"""
-
-import abc
-import imp
-import optparse
-import os
-import re
-import subprocess
-import sys
-import traceback
-
-
-class GoogleProtobufModuleImporter:
- """A custom module importer for importing google.protobuf.
-
- See PEP #302 (https://www.python.org/dev/peps/pep-0302/) for full information
- on the Importer Protocol.
- """
-
- def __init__(self, paths):
- """Creates a loader that searches |paths| for google.protobuf modules."""
- self._paths = paths
-
- def _fullname_to_filepath(self, fullname):
- """Converts a full module name to a corresponding path to a .py file.
-
- e.g. google.protobuf.text_format -> pyproto/google/protobuf/text_format.py
- """
- for path in self._paths:
- filepath = os.path.join(path, fullname.replace('.', os.sep) + '.py')
- if os.path.isfile(filepath):
- return filepath
- return None
-
- def _module_exists(self, fullname):
- return self._fullname_to_filepath(fullname) is not None
-
- def find_module(self, fullname, path=None):
- """Returns a loader module for the google.protobuf module in pyproto."""
- if (fullname.startswith('google.protobuf.')
- and self._module_exists(fullname)):
- # Per PEP #302, this will result in self.load_module getting used
- # to load |fullname|.
- return self
-
- # Per PEP #302, if the module cannot be loaded, then return None.
- return None
-
- def load_module(self, fullname):
- """Loads the module specified by |fullname| and returns the module."""
- if fullname in sys.modules:
- # Per PEP #302, if |fullname| is in sys.modules, it must be returned.
- return sys.modules[fullname]
-
- if (not fullname.startswith('google.protobuf.') or
- not self._module_exists(fullname)):
- # Per PEP #302, raise ImportError if the requested module/package
- # cannot be loaded. This should never get reached for this simple loader,
- # but is included for completeness.
- raise ImportError(fullname)
-
- filepath = self._fullname_to_filepath(fullname)
- return imp.load_source(fullname, filepath)
-
-class BinaryProtoGenerator:
-
- # If the script is run in a virtualenv
- # (https://virtualenv.pypa.io/en/stable/), then no google.protobuf library
- # should be brought in from site-packages. Passing -S into the interpreter in
- # a virtualenv actually destroys the ability to import standard library
- # functions like optparse, so this script should not be wrapped if we're in a
- # virtualenv.
- def _IsInVirtualEnv(self):
- # This is the way used by pip and other software to detect virtualenv.
- return hasattr(sys, 'real_prefix')
-
- def _ImportProtoModules(self, paths):
- """Import the protobuf modules we need. |paths| is list of import paths"""
- for path in paths:
- # Put the path to our proto libraries in front, so that we don't use
- # system protobuf.
- sys.path.insert(1, path)
-
- if self._IsInVirtualEnv():
- # Add a custom module loader. When run in a virtualenv that has
- # google.protobuf installed, the site-package was getting searched first
- # despite that pyproto/ is at the start of the sys.path. The module
- # loaders in the meta_path precede all other imports (including even
- # builtins), which allows the proper google.protobuf from pyproto to be
- # found.
- sys.meta_path.append(GoogleProtobufModuleImporter(paths))
-
- import google.protobuf.text_format as text_format
- globals()['text_format'] = text_format
- self.ImportProtoModule()
-
- def _GenerateBinaryProtos(self, opts):
- """ Read the ASCII proto and generate one or more binary protos. """
- # Read the ASCII
- with open(opts.infile, 'r') as ifile:
- ascii_pb_str = ifile.read()
-
- # Parse it into a structured PB
- full_pb = self.EmptyProtoInstance()
- text_format.Merge(ascii_pb_str, full_pb)
-
- self.ValidatePb(opts, full_pb);
- self.ProcessPb(opts, full_pb)
-
- @abc.abstractmethod
- def ImportProtoModule(self):
- """ Import the proto module to be used by the generator. """
- pass
-
- @abc.abstractmethod
- def EmptyProtoInstance(self):
- """ Returns an empty proto instance to be filled by the generator."""
- pass
-
- @abc.abstractmethod
- def ValidatePb(self, opts, pb):
- """ Validate the basic values of the protobuf. The
- file_type_policies_unittest.cc will also validate it by platform,
- but this will catch errors earlier.
- """
- pass
-
- @abc.abstractmethod
- def ProcessPb(self, opts, pb):
- """ Process the parsed prototobuf. """
- pass
-
- def AddCommandLineOptions(self, parser):
- """ Allows subclasses to add any options the command line parser. """
- pass
-
- def AddExtraCommandLineArgsForVirtualEnvRun(self, opts, command):
- """ Allows subclasses to add any extra command line arguments when running
- this under a virtualenv."""
- pass
-
- def VerifyArgs(self, opts):
- """ Allows subclasses to check command line parameters before running. """
- return True
-
- def Run(self):
- parser = optparse.OptionParser()
- # TODO(crbug.com/614082): Remove this once the bug is fixed.
- parser.add_option('-w', '--wrap', action="store_true", default=False,
- help='Wrap this script in another python '
- 'execution to disable site-packages. This is a '
- 'fix for http://crbug.com/605592')
-
- parser.add_option('-i', '--infile',
- help='The ASCII proto file to read.')
- parser.add_option('-d', '--outdir',
- help='Directory underwhich binary file(s) will be ' +
- 'written')
- parser.add_option('-o', '--outbasename',
- help='Basename of the binary file to write to.')
- parser.add_option('-p', '--path', action="append",
- help='Repeat this as needed. Directory(s) containing ' +
- 'the your_proto_definition_pb2.py and ' +
- 'google.protobuf.text_format modules')
- self.AddCommandLineOptions(parser)
-
- (opts, args) = parser.parse_args()
- if opts.infile is None or opts.outdir is None or opts.outbasename is None:
- parser.print_help()
- return 1
-
- if opts.wrap and not self._IsInVirtualEnv():
- # Run this script again with different args to the interpreter to suppress
- # the inclusion of libraries, like google.protobuf, from site-packages,
- # which is checked before sys.path when resolving imports. We want to
- # specifically import the libraries injected into the sys.path in
- # ImportProtoModules().
- command = [sys.executable, '-S', '-s', sys.argv[0]]
- command += ['-i', opts.infile]
- command += ['-d', opts.outdir]
- command += ['-o', opts.outbasename]
- for path in opts.path:
- command += ['-p', path]
-
- self.AddExtraCommandLineArgsForVirtualEnvRun(opts, command);
- sys.exit(subprocess.call(command))
-
- self._ImportProtoModules(opts.path)
-
- if not self.VerifyArgs(opts):
- print "Wrong arguments"
- return 1
-
- try:
- self._GenerateBinaryProtos(opts)
- except Exception as e:
- print "ERROR: Failed to render binary version of %s:\n %s\n%s" % (
- opts.infile, str(e), traceback.format_exc())
- return 1
diff --git a/chromium/chrome/browser/resources/quota_internals/BUILD.gn b/chromium/chrome/browser/resources/quota_internals/BUILD.gn
index 84aa0b4ccc6..64a65073c09 100644
--- a/chromium/chrome/browser/resources/quota_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/quota_internals/BUILD.gn
@@ -23,9 +23,7 @@ js_library("event_handler") {
}
js_library("message_dispatcher") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
grit("quota_internals_resources") {
diff --git a/chromium/chrome/browser/resources/quota_internals/event_handler.js b/chromium/chrome/browser/resources/quota_internals/event_handler.js
index e4594b73cab..512ecd473fa 100644
--- a/chromium/chrome/browser/resources/quota_internals/event_handler.js
+++ b/chromium/chrome/browser/resources/quota_internals/event_handler.js
@@ -491,6 +491,10 @@ function onLoad() {
$('refresh-button').addEventListener('click', cr.quota.requestInfo, false);
$('dump-button').addEventListener('click', dump, false);
+ $('trigger-notification').addEventListener('click', () => {
+ const origin = $('storage-pressure-origin').value;
+ cr.quota.triggerStoragePressure(origin);
+ }, false);
}
document.addEventListener('DOMContentLoaded', onLoad, false);
diff --git a/chromium/chrome/browser/resources/quota_internals/main.css b/chromium/chrome/browser/resources/quota_internals/main.css
index ab3de652bdc..1122a707774 100644
--- a/chromium/chrome/browser/resources/quota_internals/main.css
+++ b/chromium/chrome/browser/resources/quota_internals/main.css
@@ -22,3 +22,10 @@ tr:nth-child(odd) {
.tree-item:not([may-have-children]) > .tree-row > .tree-label-icon {
background-image: url(../../../../ui/webui/resources/images/icon_file.png);
}
+
+.pressure {
+ margin: 10px 0;
+}
+#storage-pressure-origin {
+ min-width: 20em;
+}
diff --git a/chromium/chrome/browser/resources/quota_internals/main.html b/chromium/chrome/browser/resources/quota_internals/main.html
index 51eb50ca2d1..c8af0620678 100644
--- a/chromium/chrome/browser/resources/quota_internals/main.html
+++ b/chromium/chrome/browser/resources/quota_internals/main.html
@@ -48,6 +48,17 @@ found in the LICENSE file.
<table>
<tbody id="stat-entries" class="entries"></tbody>
</table>
+ <h2>Test Storage Pressure Behavior</h2>
+ <div class="pressure">
+ Origin to test:
+ <input id="storage-pressure-origin"
+ value="https://www.example.com">
+ </div>
+ <div class="pressure">
+ <button id="trigger-notification">
+ Trigger Storage Pressure Notification
+ </button>
+ </div>
</tabpanel>
<tabpanel>
diff --git a/chromium/chrome/browser/resources/quota_internals/message_dispatcher.js b/chromium/chrome/browser/resources/quota_internals/message_dispatcher.js
index a387094e4b9..473ce67bfd7 100644
--- a/chromium/chrome/browser/resources/quota_internals/message_dispatcher.js
+++ b/chromium/chrome/browser/resources/quota_internals/message_dispatcher.js
@@ -25,6 +25,13 @@ cr.define('cr.quota', function() {
}
/**
+ * Post triggerStoragePressure message to Browser.
+ */
+ function triggerStoragePressure(origin) {
+ chrome.send('triggerStoragePressure', [origin]);
+ }
+
+ /**
* Callback entry point from Browser.
* Messages are Dispatched as Event to:
* * onAvailableSpaceUpdated,
@@ -77,6 +84,7 @@ cr.define('cr.quota', function() {
onStatisticsUpdated: new cr.EventTarget(),
requestInfo: requestInfo,
+ triggerStoragePressure: triggerStoragePressure,
messageHandler: messageHandler
};
});
diff --git a/chromium/chrome/browser/resources/reset_password/BUILD.gn b/chromium/chrome/browser/resources/reset_password/BUILD.gn
index f00ec6705a1..8f9b1c856cb 100644
--- a/chromium/chrome/browser/resources/reset_password/BUILD.gn
+++ b/chromium/chrome/browser/resources/reset_password/BUILD.gn
@@ -6,9 +6,7 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
uses_js_modules = true
- deps = [
- ":reset_password",
- ]
+ deps = [ ":reset_password" ]
}
js_library("reset_password") {
diff --git a/chromium/chrome/browser/resources/safe_browsing/BUILD.gn b/chromium/chrome/browser/resources/safe_browsing/BUILD.gn
deleted file mode 100644
index 89a3efdbfba..00000000000
--- a/chromium/chrome/browser/resources/safe_browsing/BUILD.gn
+++ /dev/null
@@ -1,106 +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.
-
-# TODO(nparker): reduce the duplication between these two, somehow.
-
-# Generate the binary proto form of "file_types" from the ascii proto.
-action("make_file_types_protobuf") {
- script = "gen_file_type_proto.py"
-
- # The output goes in $target_gen_dir since that's where
- # chrome/browser/browser_resources.grd will look for it.
-
- input_filename = "download_file_types.asciipb"
- output_dir = target_gen_dir
- output_basename = "download_file_types.pb"
- python_path_root = "$root_out_dir/pyproto"
- python_path_safe_browsing = "$python_path_root/chrome/common/safe_browsing"
-
- # Pick an architecture to generate for. These string match those
- # in the python script.
- if (is_android) {
- target_arch = "android"
- } else if (is_chromeos) {
- target_arch = "chromeos"
- } else if (is_win) {
- target_arch = "win"
- } else if (is_mac) {
- target_arch = "mac"
- } else if (is_linux) {
- target_arch = "linux"
- } else {
- # This will cause the script to fail.
- target_arch = "unknown_target_arch"
- }
-
- inputs = [
- input_filename,
- ]
-
- deps = [
- "//chrome/common/safe_browsing:proto",
- "//third_party/protobuf:py_proto",
- ]
-
- outputs = [
- "$output_dir/$output_basename",
- ]
-
- args = [
- "-w",
- "-t",
- target_arch,
- "-i",
- rebase_path(input_filename, root_build_dir),
- "-d",
- rebase_path(output_dir, root_build_dir),
- "-o",
- output_basename,
- "-p",
- rebase_path(python_path_root, root_build_dir),
- "-p",
- rebase_path(python_path_safe_browsing, root_build_dir),
- ]
-}
-
-# Generate the binary proto for ALL platforms. This is only run manually
-# when pushing the files to GCS for the component-updater to pick up.
-action("make_all_file_types_protobuf") {
- script = "gen_file_type_proto.py"
-
- input_filename = "download_file_types.asciipb"
- output_dir = "$target_gen_dir/all"
- output_basename = "download_file_types.pb"
- python_path_root = "$root_build_dir/pyproto"
- python_path_safe_browsing = "$python_path_root/chrome/common/safe_browsing"
-
- inputs = [
- input_filename,
- ]
-
- deps = [
- "//chrome/common/safe_browsing:proto",
- "//third_party/protobuf:py_proto",
- ]
-
- # A directory, since we can't derive the actual file names here.
- outputs = [
- output_dir,
- ]
-
- args = [
- "-w",
- "-a",
- "-i",
- rebase_path(input_filename, root_build_dir),
- "-d",
- rebase_path(output_dir, root_build_dir),
- "-o",
- output_basename,
- "-p",
- rebase_path(python_path_root, root_build_dir),
- "-p",
- rebase_path(python_path_safe_browsing, root_build_dir),
- ]
-}
diff --git a/chromium/chrome/browser/resources/safe_browsing/PRESUBMIT.py b/chromium/chrome/browser/resources/safe_browsing/PRESUBMIT.py
deleted file mode 100644
index d617bd57210..00000000000
--- a/chromium/chrome/browser/resources/safe_browsing/PRESUBMIT.py
+++ /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.
-
-"""Presubmit checks for SafeBrowsing download_file_types.
-"""
-
-def CheckVersionUpdatedInDownloadFileTypeList(input_api, output_api):
- def IsDownloadFileTypeList(x):
- return (input_api.os_path.basename(x.LocalPath()) ==
- 'download_file_types.asciipb')
-
- download_file_types = input_api.AffectedFiles(
- file_filter=IsDownloadFileTypeList)
- if not download_file_types:
- return []
-
- for _, line in download_file_types[0].ChangedContents():
- if line.strip().startswith('version_id: '):
- return []
-
- # It's enticing to do something fancy like checking whether the ID was in fact
- # incremented or whether this is a whitespace-only or comment-only change.
- # However, currently deleted lines don't show up in ChangedContents() and
- # attempting to parse the asciipb file any more than we are doing above is
- # likely not worth the trouble.
- #
- # At worst, the submitter can skip the presubmit check on upload if it isn't
- # correct.
- return [output_api.PresubmitError(
- 'Increment |version_id| in download_file_types.asciipb if you are '
- 'updating the file types proto.')]
-
-def CheckChangeOnUpload(input_api, output_api):
- # TODO(asanka): Add a PRESUBMIT check for verifying that the
- # download_file_types.asciipb file is valid.
- return CheckVersionUpdatedInDownloadFileTypeList(input_api, output_api)
diff --git a/chromium/chrome/browser/resources/safe_browsing/README.md b/chromium/chrome/browser/resources/safe_browsing/README.md
index 0f4ae81076b..4b6f8f24e18 100644
--- a/chromium/chrome/browser/resources/safe_browsing/README.md
+++ b/chromium/chrome/browser/resources/safe_browsing/README.md
@@ -10,7 +10,7 @@ Rendered version of this file: https://chromium.googlesource.com/chromium/src/+/
## Procedure for adding/modifying file type(s)
- * **Edit** `download_file_types.asciipb`, `enums.xml`, and `download_stats.cc`
+ * **Edit** `download_file_types.asciipb` and `enums.xml`.
* Get it reviewed, **submit.**
* **Push** it to all users via component update:
* Wait 1-3 day for this to run on Canary to verify it doesn't crash Chrome.
diff --git a/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb b/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
deleted file mode 100644
index 39734614bea..00000000000
--- a/chromium/chrome/browser/resources/safe_browsing/download_file_types.asciipb
+++ /dev/null
@@ -1,3599 +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.
-
-# See README.md before editing this file.
-# Keep sorted by extension within logical groupings where possible.
-
-##
-## Top level settings
-##
-version_id: 41
-sampled_ping_probability: 0.01
-max_archived_binaries_to_report: 10
-default_file_type {
- uma_value: 18
- ping_setting: FULL_PING
- platform_settings {
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-
-##
-## General cross-platform file types
-##
-
-# Files that are not dangerous, and are popular enough that we'd like to
-# exclude them from download pings.
-file_types {
- extension: "jpg"
- uma_value: 322
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "jpeg"
- uma_value: 323
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "mp3"
- uma_value: 324
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "mp4"
- uma_value: 325
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "png"
- uma_value: 326
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "csv"
- uma_value: 330
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "ica"
- uma_value: 331
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "gif"
- uma_value: 333
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "txt"
- uma_value: 334
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "package"
- uma_value: 335
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "tif"
- uma_value: 336
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "webp"
- uma_value: 338
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "mkv"
- uma_value: 339
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "wav"
- uma_value: 340
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "mov"
- uma_value: 341
- ping_setting: SAMPLED_PING
-}
-
-# Flash files downloaded locally can sometimes access the local filesystem
-file_types {
- extension: "swf"
- uma_value: 68
- ping_setting: FULL_PING
- platform_settings {
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "spl"
- uma_value: 69
- ping_setting: FULL_PING
- platform_settings {
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Chrome extensions should be obtained through the web store. Allowed to
-# open automatically because Chrome displays a prompt prior to
-# installation.
-file_types {
- extension: "crx"
- uma_value: 19
- ping_setting: FULL_PING
- platform_settings {
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-
-# Archive file types. Not inherently dangerous, but could contain dangerous
-# files.
-file_types {
- extension: "001"
- uma_value: 171
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "7z"
- uma_value: 52
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "ace"
- uma_value: 172
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "arc"
- uma_value: 173
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "arj"
- uma_value: 58
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "b64"
- uma_value: 174
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "balz"
- uma_value: 175
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "bhx"
- uma_value: 176
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- # On MacOS, BIN files are automatically extracted as ZIPs
- # See: http://crbug/933637
- extension: "bin"
- uma_value: 159
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: ZIP
-}
-file_types {
- extension: "bz"
- uma_value: 177
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "bz2"
- uma_value: 56
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "bzip2"
- uma_value: 148
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "cab"
- uma_value: 2
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "cpio"
- uma_value: 64
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "fat"
- uma_value: 178
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "gz"
- uma_value: 54
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "gzip"
- uma_value: 149
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "hfs"
- uma_value: 179
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "hqx"
- uma_value: 180
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "iso"
- uma_value: 181
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: DMG
-}
-file_types {
- extension: "lha"
- uma_value: 60
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "lpaq1"
- uma_value: 182
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "lpaq5"
- uma_value: 183
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "lpaq8"
- uma_value: 184
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "lzh"
- uma_value: 59
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "lzma"
- uma_value: 63
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "mim"
- uma_value: 185
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "ntfs"
- uma_value: 186
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "paq8f"
- uma_value: 187
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "paq8jd"
- uma_value: 188
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "paq8l"
- uma_value: 189
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "paq8o"
- uma_value: 190
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "pea"
- uma_value: 191
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "quad"
- uma_value: 194
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "r00"
- uma_value: 195
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r01"
- uma_value: 196
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r02"
- uma_value: 197
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r03"
- uma_value: 198
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r04"
- uma_value: 199
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r05"
- uma_value: 200
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r06"
- uma_value: 201
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r07"
- uma_value: 202
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r08"
- uma_value: 203
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r09"
- uma_value: 204
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r10"
- uma_value: 205
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r11"
- uma_value: 206
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r12"
- uma_value: 207
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r13"
- uma_value: 208
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r14"
- uma_value: 209
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r15"
- uma_value: 210
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r16"
- uma_value: 211
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r17"
- uma_value: 212
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r18"
- uma_value: 213
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r19"
- uma_value: 214
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r20"
- uma_value: 215
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r21"
- uma_value: 216
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r22"
- uma_value: 217
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r23"
- uma_value: 218
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r24"
- uma_value: 219
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r25"
- uma_value: 220
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r26"
- uma_value: 221
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r27"
- uma_value: 222
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r28"
- uma_value: 223
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "r29"
- uma_value: 224
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
-}
-file_types {
- extension: "rar"
- uma_value: 8
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: RAR
- platform_settings {
- auto_open_hint: ALLOW_AUTO_OPEN
- max_file_size_to_analyze: 52428800 # 50MB
- }
-}
-file_types {
- extension: "squashfs"
- uma_value: 226
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "swm"
- uma_value: 227
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "tar"
- uma_value: 57
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "taz"
- uma_value: 150
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "tbz"
- uma_value: 151
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "tbz2"
- uma_value: 152
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "tgz"
- uma_value: 55
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "tpz"
- uma_value: 228
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "txz"
- uma_value: 229
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "tz"
- uma_value: 230
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "udf"
- uma_value: 231
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "uu"
- uma_value: 232
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "uue"
- uma_value: 233
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "vhd"
- uma_value: 234
- is_archive: true
- ping_setting: FULL_PING
-
-}
-file_types {
- # Opens in IE, drops MOTW
- extension: "vhdx"
- uma_value: 245
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "vmdk"
- uma_value: 235
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "wim"
- uma_value: 61
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "wrc"
- uma_value: 236
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xar"
- uma_value: 237
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xxe"
- uma_value: 238
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xz"
- uma_value: 53
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "z"
- uma_value: 62
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "zip"
- uma_value: 7
- is_archive: true
- ping_setting: FULL_PING
- inspection_type: ZIP
- platform_settings {
- auto_open_hint: ALLOW_AUTO_OPEN
- max_file_size_to_analyze: 52428800 # 50MB
- }
-}
-file_types {
- extension: "zipx"
- uma_value: 239
- is_archive: true
- ping_setting: FULL_PING
-}
-file_types {
- extension: "zpaq"
- uma_value: 240
- is_archive: true
- ping_setting: FULL_PING
-}
-
-# Java
-file_types {
- extension: "class"
- uma_value: 13
- ping_setting: FULL_PING
- platform_settings {
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_CHROME_OS
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "jar"
- uma_value: 12
- ping_setting: FULL_PING
- platform_settings {
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_CHROME_OS
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "jnlp"
- uma_value: 128
- ping_setting: FULL_PING
- platform_settings {
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_CHROME_OS
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-
-# Cross-platform scripting languages (non-shell)
-file_types {
- extension: "pl"
- uma_value: 129
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "py"
- uma_value: 130
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "pyc"
- uma_value: 131
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Equivalent of a DLL, for python libraries
- # Added with crbug.com/902234
- extension: "pyd"
- uma_value: 318
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Compiled python code
- # Added with crbug.com/902234
- extension: "pyo"
- uma_value: 319
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "pyw"
- uma_value: 132
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "rb"
- uma_value: 133
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Other cross-platform files
-file_types {
- # Extensible Firmware Interface executable
- extension: "efi"
- uma_value: 146
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "torrent"
- uma_value: 23
- ping_setting: FULL_PING
-}
-file_types {
- # Opened by uTorrent and Transmission (can be a renamed .torrent)
- # Added crbug.com/767502
- extension: "btapp"
- uma_value: 298
- ping_setting: FULL_PING
-}
-file_types {
- # Opened by uTorrent and Transmission (can be a renamed .torrent)
- # Added crbug.com/767502
- extension: "btskin"
- uma_value: 299
- ping_setting: FULL_PING
-}
-file_types {
- # Opened by uTorrent and Transmission (can be a renamed .torrent)
- # Added crbug.com/767502
- extension: "btinstall"
- uma_value: 300
- ping_setting: FULL_PING
-}
-file_types {
- # Opened by uTorrent and Transmission (can be a renamed .torrent)
- # Added crbug.com/767502
- extension: "btkey"
- uma_value: 301
- ping_setting: FULL_PING
-}
-file_types {
- # Opened by uTorrent and Transmission (can be a renamed .torrent)
- # Added crbug.com/767502
- extension: "btsearch"
- uma_value: 302
- ping_setting: FULL_PING
-}
-file_types {
- # OpenOffice extension, can execute arbitrary code.
- # https://crbug.com/862163
- extension: "oxt"
- uma_value: 317
- ping_setting: FULL_PING
- platform_settings {
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-##
-## Windows-specific files
-##
-## Some file descriptions are based on
-## https://support.office.com/article/Blocked-attachments-in-Outlook-3811cddc-17c3-4279-a30c-060ba0207372
-
-# Windows installer files
-file_types {
- extension: "msi"
- uma_value: 1
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "msp"
- uma_value: 33
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "mst"
- uma_value: 34
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Microsoft Access files
-file_types {
- # Project extension [MS Access]
- extension: "ade"
- uma_value: 98
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Project [MS Access]
- extension: "adp"
- uma_value: 99
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Module shortcut [MS Access]
- extension: "mad"
- uma_value: 100
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Form shortcut [MS Access]
- extension: "maf"
- uma_value: 101
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Diagram Shortcut [MS Access]
- extension: "mag"
- uma_value: 102
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Macro Shortcut [MS Access]
- extension: "mam"
- uma_value: 103
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Query Shortcut [MS Access]
- extension: "maq"
- uma_value: 104
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Report Shortcut [MS Access]
- extension: "mar"
- uma_value: 105
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Stored Procedures [MS Access]
- extension: "mas"
- uma_value: 106
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Table Shortcut [MS Access]
- extension: "mat"
- uma_value: 107
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # View Shortcut [MS Access]
- extension: "mav"
- uma_value: 108
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Data Access Page [MS Access]
- extension: "maw"
- uma_value: 109
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Access Add-In [MS Access]
- extension: "mda"
- uma_value: 110
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Database [MS Access]
- extension: "mdb"
- uma_value: 111
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Database [MS Access]
- extension: "mde"
- uma_value: 112
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Add-In Data [MS Access]
- extension: "mdt"
- uma_value: 113
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Workgroup Information [MS Access]
- extension: "mdw"
- uma_value: 114
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Wizard Template [MS Access]
- extension: "mdz"
- uma_value: 115
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # MS Access database
- # Similar to mdb
- extension: "accdb"
- uma_value: 388
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # MS Access database
- # Similar to mdb
- extension: "accde"
- uma_value: 389
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # MS Access database
- # Similar to mdb
- extension: "accdr"
- uma_value: 390
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # MS Access database
- # Similar to mdb
- extension: "accda"
- uma_value: 391
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # ActiveX Control
- extension: "ocx"
- uma_value: 90
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Office Profile Settings File.
- extension: "ops"
- uma_value: 91
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Portable Application Installer File.
- extension: "paf"
- uma_value: 166
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Visual Test
- extension: "pcd"
- uma_value: 92
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Program Information File. Originally intended to configure execution
- # environment for legacy DOS files. They aren't meant to contain
- # executable code. But Windows may execute a PIF file that is sniffed as a
- # PE file.
- extension: "pif"
- uma_value: 10
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Developer Studio Build Log.
- extension: "plg"
- uma_value: 93
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Windows System File.
- extension: "prf"
- uma_value: 94
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Program File
- extension: "prg"
- uma_value: 95
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Exchange Address Book File. Microsoft Outlook Personal Folder
- # File.
- extension: "pst"
- uma_value: 96
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Control Panel Item. Executable used for adding icons to Control Panel.
- # Added in crbug.com/914400
- extension: "cpi"
- uma_value: 321
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Office Docs. These have been abused in the past through embedded
-# executables, so send a FULL_PING.
-file_types {
- extension: "doc"
- uma_value: 328
- ping_setting: FULL_PING
-}
-file_types {
- extension: "docb"
- uma_value: 272
- ping_setting: FULL_PING
-}
-file_types {
- extension: "docm"
- uma_value: 269
- ping_setting: FULL_PING
-}
-file_types {
- extension: "docx"
- uma_value: 268
- ping_setting: FULL_PING
-}
-file_types {
- extension: "dot"
- uma_value: 342
- ping_setting: FULL_PING
-}
-file_types {
- extension: "dotm"
- uma_value: 271
- ping_setting: FULL_PING
-}
-file_types {
- extension: "dott"
- uma_value: 270
- ping_setting: FULL_PING
-}
-file_types {
- extension: "dotx"
- uma_value: 343
- ping_setting: FULL_PING
-}
-file_types {
- extension: "pdf"
- uma_value: 14
- ping_setting: FULL_PING
-}
-file_types {
- extension: "pot"
- uma_value: 352
- ping_setting: FULL_PING
-}
-file_types {
- extension: "potm"
- uma_value: 353
- ping_setting: FULL_PING
-}
-file_types {
- extension: "potx"
- uma_value: 279
- ping_setting: FULL_PING
-}
-file_types {
- extension: "ppam"
- uma_value: 280
- ping_setting: FULL_PING
-}
-file_types {
- extension: "pps"
- uma_value: 355
- ping_setting: FULL_PING
-}
-file_types {
- extension: "ppsm"
- uma_value: 354
- ping_setting: FULL_PING
-}
-file_types {
- extension: "ppsx"
- uma_value: 281
- ping_setting: FULL_PING
-}
-file_types {
- extension: "ppt"
- uma_value: 332
- ping_setting: FULL_PING
-}
-file_types {
- extension: "pptm"
- uma_value: 278
- ping_setting: FULL_PING
-}
-file_types {
- extension: "pptx"
- uma_value: 277
- ping_setting: FULL_PING
-}
-file_types {
- extension: "rtf"
- uma_value: 244
- ping_setting: FULL_PING
-}
-file_types {
- extension: "sldm"
- uma_value: 283
- ping_setting: FULL_PING
-}
-file_types {
- extension: "sldx"
- uma_value: 282
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xla"
- uma_value: 348
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xlam"
- uma_value: 349
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xldm"
- uma_value: 347
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xll"
- uma_value: 350
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xlm"
- uma_value: 346
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xls"
- uma_value: 327
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xlsb"
- uma_value: 344
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xlsm"
- uma_value: 274
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xlsx"
- uma_value: 273
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xlt"
- uma_value: 345
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xltm"
- uma_value: 276
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xltx"
- uma_value: 275
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xlw"
- uma_value: 351
- ping_setting: FULL_PING
-}
-
-# Extensions that will open in IE even when chrome is set as default browser.
-file_types {
- extension: "partial"
- uma_value: 153
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "xrm-ms"
- uma_value: 156
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "rels"
- uma_value: 241
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "svg"
- uma_value: 154
- ping_setting: FULL_PING
-}
-file_types {
- extension: "xml"
- uma_value: 155
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "xsl"
- uma_value: 157
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Windows PowerShell files
-file_types {
- extension: "ps1"
- uma_value: 43
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "ps1xml"
- uma_value: 44
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "ps2"
- uma_value: 45
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "ps2xml"
- uma_value: 46
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "psc1"
- uma_value: 47
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "psc2"
- uma_value: 48
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Internet Shortcuts (new since IE9). Both .url and .website are .ini
-# files that describe a shortcut that points to a URL. They can point at
-# anything. Dropping a download of this type and opening it automatically
-# can in effect sidestep origin restrictions etc.
-file_types {
- extension: "url"
- uma_value: 25
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "website"
- uma_value: 24
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Internet shortcuts for MacOS. These are similar in functionality to .url or
-# .website, allowing automatic opening of files or URLs.
-file_types {
- extension: "fileloc"
- uma_value: 394
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "webloc"
- uma_value: 395
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# VBScript files. May open with Windows Script Host and execute with
-# user privileges.
-file_types {
- # JavaScript file. May open using Windows Script Host with user level
- # privileges.
- extension: "js"
- uma_value: 28
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # JScript encoded script file. Usually produced by running Microsoft Script
- # Encoder over a .js file.
- # See https://msdn.microsoft.com/library/d14c8zsc.aspx
- extension: "jse"
- uma_value: 29
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "vb"
- uma_value: 15
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "vbe"
- uma_value: 26
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "vbs"
- uma_value: 27
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Some sites claim .vbscript is a valid extension for vbs files.
- extension: "vbscript"
- uma_value: 169
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Windows script Host related
-file_types {
- extension: "ws"
- uma_value: 123
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "wsc"
- uma_value: 124
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "wsf"
- uma_value: 51
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "wsh"
- uma_value: 125
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Microsoft Shell files
-file_types {
- extension: "msh"
- uma_value: 37
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "msh1"
- uma_value: 38
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "msh2"
- uma_value: 40
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "mshxml"
- uma_value: 42
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "msh1xml"
- uma_value: 39
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "msh2xml"
- uma_value: 41
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Other Windows files (some cross-platform too)
-file_types {
- extension: "ad"
- uma_value: 262
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Executable Application
- extension: "app"
- uma_value: 66
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft ClickOnce depolyment manifest. By default, opens with
- # dfshim.dll which should prompt the user before running untrusted code.
- extension: "application"
- uma_value: 70
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # ClickOnce application reference. Basically a .lnk for ClickOnce apps.
- extension: "appref-ms"
- uma_value: 144
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Active Server Pages source file.
- extension: "asp"
- uma_value: 71
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Advanced Stream Redirector. Contains a playlist of media files.
- extension: "asx"
- uma_value: 72
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Visual Basic source file. Opens by default in an editor
- extension: "bas"
- uma_value: 35
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Command Script
- extension: "bat"
- uma_value: 6
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "cfg"
- uma_value: 73
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Windows Compiled HTML Help files.
- extension: "chi"
- uma_value: 74
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Windows Compiled HTML Help files.
- extension: "chm"
- uma_value: 75
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Command script
- extension: "cmd"
- uma_value: 65
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Windows legacy executable
- extension: "com"
- uma_value: 11
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Control panel tool. Executable
- extension: "cpl"
- uma_value: 76
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Signed certificate file.
- extension: "crt"
- uma_value: 97
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Signed certificate file.
- extension: "cer"
- uma_value: 392
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Signed certificate file.
- extension: "der"
- uma_value: 393
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # HTML-like file. This extension can be abused by UwS campaigns to evade
- # referrer attribution via a two-level download scheme. crbug.com/719784
- # Added in https://crbug.com/762702
- extension: "dhtml"
- uma_value: 303
- ping_setting: FULL_PING
-}
-file_types {
- # HTML-like file. This extension can be abused by UwS campaigns to evade
- # referrer attribution via a two-level download scheme. crbug.com/719784
- # Added in https://crbug.com/762702
- extension: "dhtm"
- uma_value: 304
- ping_setting: FULL_PING
-}
-file_types {
- # HTML-like file. This extension can be abused by UwS campaigns to evade
- # referrer attribution via a two-level download scheme. crbug.com/719784
- # Added in https://crbug.com/762702
- extension: "dht"
- uma_value: 305
- ping_setting: FULL_PING
-}
-file_types {
- # Windows executable. It can gain control of an executable launched from the
- # same directory, so it can do bad things without ever being clicked on.
- extension: "dll"
- uma_value: 9
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Windows executable
- extension: "drv"
- uma_value: 5
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Opens in Outlook. Not common, but could be exploited (CVE-2015-6172)
- extension: "eml"
- uma_value: 243
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Executable
- extension: "exe"
- uma_value: 0
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Font file, uses Portable Executable or New Executable format. Not
- # supposed to contain executable code.
- extension: "fon"
- uma_value: 147
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft FoxPro Compiled Source.
- extension: "fxp"
- uma_value: 77
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Windows Sidebar Gadget (Vista & Win 7). ZIP archive containing html + js.
- # Deprecated by Microsoft. Can run arbitrary code with user privileges.
- # (https://technet.microsoft.com/library/security/2719662)
- extension: "gadget"
- uma_value: 145
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # MSProgramGroup (?)
- extension: "grp"
- uma_value: 17
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Windows legacy help file format.
- extension: "hlp"
- uma_value: 78
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # HTML Application. Executes as a fully trusted application.
- extension: "hta"
- uma_value: 36
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # HTML file. This extension is abused by UwS campaigns to evade referrer
- # attribution via a two-level download scheme. crbug.com/719784
- extension: "htm"
- uma_value: 284
- ping_setting: FULL_PING
-}
-file_types {
- # HTML file. This extension is abused by UwS campaigns to evade referrer
- # attribution via a two-level download scheme. crbug.com/719784
- extension: "html"
- uma_value: 285
- ping_setting: FULL_PING
-}
-file_types {
- # Hypertext Template File. See https://support.microsoft.com/kb/181689.
- extension: "htt"
- uma_value: 79
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Device installation information.
- extension: "inf"
- uma_value: 80
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Generic configuration file.
- extension: "ini"
- uma_value: 81
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft IIS Internet Communication Settings.
- extension: "ins"
- uma_value: 82
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # InstallShield Compiled Script
- extension: "inx"
- uma_value: 160
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # InstallShield Uninstaller Script
- extension: "isu"
- uma_value: 162
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft IIS Internet Service Provider Settings.
- extension: "isp"
- uma_value: 83
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Windows Task Scheduler Job file. No handler is registered by default, so
- # this is probably normally not dangerous unless saved into the task
- # scheduler directory.
- extension: "job"
- uma_value: 163
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Shortcuts. May open anything.
- extension: "lnk"
- uma_value: 84
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # .local files affect DLL search path for .exe file with same base name.
- extension: "local"
- uma_value: 85
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # While being a generic name, having a .manifest file with the same
- # basename as .exe file (foo.exe + foo.exe.manifest) changes the DLL search
- # order for the .exe file. Downloading this kind of file to the users'
- # download directory is almost always the wrong thing to do.
- extension: "manifest"
- uma_value: 86
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Media Attachment Unit.
- extension: "mau"
- uma_value: 87
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Multipart HTML
- extension: "mht"
- uma_value: 30
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Multipart HTML
- extension: "mhtml"
- uma_value: 31
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "mmc"
- uma_value: 88
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "mof"
- uma_value: 89
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Management Console Snap-in. Contains executable code.
- extension: "msc"
- uma_value: 32
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Opens in Outlook. Not common, but could be exploited (CVE-2015-6172)
- extension: "msg"
- uma_value: 242
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Registry file. Opening may cause registry settings to change. Users still
- # need to click through a prompt. So we could consider relaxing the
- # DISALLOW_AUTO_OPEN restriction.
- extension: "reg"
- uma_value: 16
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Registry Script Windows.
- extension: "rgs"
- uma_value: 167
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Windows Explorer Command.
- # See https://support.microsoft.com/kb/190355 for an example
- #
- # http://crbug.com/722524: Can trigger dangerous network requests just
- # by being displayed in Windows Explorer.
- extension: "scf"
- uma_value: 49
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Windows Screen Saver.
- extension: "scr"
- uma_value: 4
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Windows Script Component. Microsoft FoxPro Screen.
- # A Script Component is a COM component created using script.
- # See https://msdn.microsoft.com/library/aa233148.aspx for an
- # example.
- extension: "sct"
- uma_value: 50
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Windows Vista Index Search Data, for local file system.
- # Used to find files landed surreptitiously w/o UI.
- extension: "search-ms"
- uma_value: 246
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Used to create shortcuts to various Windows 10 setting pages.
- # Allows invoking any binary file with any parameters.
- extension: "settingcontent-ms"
- uma_value: 316
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Windows Shortcut into a document.
- # See https://support.microsoft.com/kb/212344
- extension: "shb"
- uma_value: 116
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Shell Scrap Object File.
- extension: "shs"
- uma_value: 117
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # HTML-like file. This extension can be abused by UwS campaigns to evade
- # referrer attribution via a two-level download scheme. crbug.com/719784
- # Added in https://crbug.com/762702
- extension: "shtml"
- uma_value: 306
- ping_setting: FULL_PING
-}
-file_types {
- # HTML-like file. This extension can be abused by UwS campaigns to evade
- # referrer attribution via a two-level download scheme. crbug.com/719784
- # Added in https://crbug.com/762702
- extension: "shtm"
- uma_value: 307
- ping_setting: FULL_PING
-}
-file_types {
- # HTML-like file. This extension can be abused by UwS campaigns to evade
- # referrer attribution via a two-level download scheme. crbug.com/719784
- # Added in https://crbug.com/762702
- extension: "sht"
- uma_value: 308
- ping_setting: FULL_PING
-}
-file_types {
- # Symbolic link file. Can be used to pass a script to Excel, etc.
- # Added in https://crbug.com/845618
- extension: "slk"
- uma_value: 309
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # System executable. Windows tries hard to prevent you from opening these
- # types of files.
- extension: "sys"
- uma_value: 3
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # U3 Smart Application.
- extension: "u3p"
- uma_value: 168
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # A Visio file type. Added in https://crbug.com/771469
- extension: "vdx"
- uma_value: 289
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # A Visio file type. Added in https://crbug.com/771469
- extension: "vsx"
- uma_value: 290
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # A Visio file type. Added in https://crbug.com/771469
- extension: "vtx"
- uma_value: 291
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # A Visio file type. Added in https://crbug.com/771469
- extension: "vsdx"
- uma_value: 292
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- # A Visio file type. Added in https://crbug.com/771469
- extension: "vssx"
- uma_value: 293
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- # A Visio file type. Added in https://crbug.com/771469
- extension: "vstx"
- uma_value: 294
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- # A Visio file type. Added in https://crbug.com/771469
- extension: "vsdm"
- uma_value: 295
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- # A Visio file type. Added in https://crbug.com/771469
- extension: "vssm"
- uma_value: 296
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- # A Visio file type. Added in https://crbug.com/771469
- extension: "vstm"
- uma_value: 297
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- # An older Visio file type. See https://crbug.com/771469
- extension: "vsd"
- uma_value: 118
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Visual Studio Binary-based Macro Project.
- extension: "vsmacros"
- uma_value: 119
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # An older Visio file type. See https://crbug.com/771469
- extension: "vss"
- uma_value: 120
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # An older Visio file type. See https://crbug.com/771469
- extension: "vst"
- uma_value: 121
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Microsoft Visio Workspace
- extension: "vsw"
- uma_value: 122
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # XAML Browser Application.
- extension: "xbap"
- uma_value: 126
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Similar to "html". Added for https://crbug.com/762702
- extension: "xht"
- uma_value: 286
- ping_setting: FULL_PING
-}
-file_types {
- # Similar to "html". Added for https://crbug.com/762702
- extension: "xhtm"
- uma_value: 287
- ping_setting: FULL_PING
-}
-file_types {
- # Similar to "html". Added for https://crbug.com/762702
- extension: "xhtml"
- uma_value: 288
- ping_setting: FULL_PING
-}
-file_types {
- # Microsoft Exchange Public Folder Shortcut
- extension: "xnk"
- uma_value: 127
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-
-##
-## MacOS-specific files
-##
-
-# Executable files on MacOS
-file_types {
- extension: "cdr"
- uma_value: 251
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "dart"
- uma_value: 254
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "dc42"
- uma_value: 255
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "diskcopy42"
- uma_value: 256
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "dmg"
- uma_value: 21
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- max_file_size_to_analyze: 52428800 # 50MB
- }
- inspection_type: DMG
-}
-file_types {
- extension: "dmgpart"
- uma_value: 252
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "dvdr"
- uma_value: 253
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "dylib"
- uma_value: 357
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "img"
- uma_value: 247
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "imgpart"
- uma_value: 257
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "ndif"
- uma_value: 258
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "service"
- uma_value: 358
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "smi"
- uma_value: 248
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "sparsebundle"
- uma_value: 249
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "sparseimage"
- uma_value: 250
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "toast"
- uma_value: 260
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-file_types {
- extension: "udif"
- uma_value: 259
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: DMG
-}
-
-# Other MacOS files
-file_types {
- # Automator action
- extension: "action"
- uma_value: 158
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Automator action
- extension: "definition"
- uma_value: 359
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Automator action
- extension: "wflow"
- uma_value: 360
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Automator action
- extension: "caction"
- uma_value: 361
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Opened as a .gz on Mac. http://crbug.com/600907
- extension: "as"
- uma_value: 264
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- # Opened as a .gz on Mac. http://crbug.com/600907
- # Similar to a TGZ file
- extension: "cpgz"
- uma_value: 265
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- extension: "command"
- uma_value: 140
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "applescript"
- uma_value: 310
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "scpt"
- uma_value: 311
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "scptd"
- uma_value: 312
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "seplugin"
- uma_value: 313
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "osas"
- uma_value: 314
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "osax"
- uma_value: 315
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: DANGEROUS
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # An alias for PKG files, opened by the Mac installer. http://crbug.com/600908
- extension: "mpkg"
- uma_value: 263
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Opened as a .zip on Mac. http://crbug.com/600907
- # Also: Portable Archive Exchange format, like tar
- extension: "pax"
- uma_value: 266
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- # Automator workflow
- extension: "workflow"
- uma_value: 170
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # Opened as a .zip on Mac. http://crbug.com/600907
- extension: "xip"
- uma_value: 267
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- inspection_type: ZIP
-}
-file_types {
- extension: "mobileconfig"
- uma_value: 356
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "configprofile"
- uma_value: 362
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "internetconnect"
- uma_value: 363
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "networkconnect"
- uma_value: 364
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-
-##
-## Linux-specific files
-##
-
-## Package management formats (non-windows)
-file_types {
- # Used by Mac installer as well as linux
- extension: "pkg"
- uma_value: 22
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_MAC
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "deb"
- uma_value: 141
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "pet"
- uma_value: 192
- is_archive: true
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "pup"
- uma_value: 193
- is_archive: true
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "rpm"
- uma_value: 142
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "slp"
- uma_value: 225
- is_archive: true
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- # "Common" executable file extension for Linux. There's not really much
- # reason to block since they require execute bit to actually run.
- # Included for UMA histograms.
- extension: "out"
- uma_value: 164
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "run"
- uma_value: 261
- ping_setting: SAMPLED_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Non-windows Shell Languages
-file_types {
- extension: "bash"
- uma_value: 134
- ping_setting: FULL_PING
- platform_settings {
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "csh"
- uma_value: 135
- ping_setting: FULL_PING
- platform_settings {
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "ksh"
- uma_value: 136
- ping_setting: FULL_PING
- platform_settings {
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "sh"
- uma_value: 137
- ping_setting: FULL_PING
- platform_settings {
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "shar"
- uma_value: 138
- ping_setting: FULL_PING
- platform_settings {
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "tcsh"
- uma_value: 139
- ping_setting: FULL_PING
- platform_settings {
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_WINDOWS
- danger_level: NOT_DANGEROUS
- auto_open_hint: ALLOW_AUTO_OPEN
- }
-}
-file_types {
- # .desktop file is a shortcut that runs other files.
- # Added in crbug/904182
- extension: "desktop"
- uma_value: 320
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-##
-## Android-specific files
-##
-# Android doesn't have real download-protection, but we can show a
-# warning to provide a speed bump for dangerous file types.
-file_types {
- extension: "dex"
- uma_value: 143
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_ANDROID
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_CHROME_OS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-file_types {
- extension: "apk"
- uma_value: 20
- ping_setting: FULL_PING
- platform_settings {
- platform: PLATFORM_ANDROID
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_CHROME_OS
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
- platform_settings {
- platform: PLATFORM_LINUX
- danger_level: ALLOW_ON_USER_GESTURE
- auto_open_hint: DISALLOW_AUTO_OPEN
- }
-}
-
-# Other file types supported by Web Share API on Android
-file_types {
- extension: "bmp"
- uma_value: 365
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "css"
- uma_value: 366
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "ehtml"
- uma_value: 367
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "flac"
- uma_value: 368
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "ico"
- uma_value: 369
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "jfif"
- uma_value: 370
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "m4a"
- uma_value: 371
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "m4v"
- uma_value: 372
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "mpeg"
- uma_value: 373
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "mpg"
- uma_value: 374
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "oga"
- uma_value: 375
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "ogg"
- uma_value: 376
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "ogm"
- uma_value: 377
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "ogv"
- uma_value: 378
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "opus"
- uma_value: 379
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "pjp"
- uma_value: 380
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "pjpeg"
- uma_value: 381
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "svgz"
- uma_value: 382
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "text"
- uma_value: 383
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "tiff"
- uma_value: 384
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "weba"
- uma_value: 385
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "webm"
- uma_value: 386
- ping_setting: SAMPLED_PING
-}
-file_types {
- extension: "xbm"
- uma_value: 387
- ping_setting: SAMPLED_PING
-}
diff --git a/chromium/chrome/browser/resources/safe_browsing/gen_file_type_proto.py b/chromium/chrome/browser/resources/safe_browsing/gen_file_type_proto.py
deleted file mode 100755
index 1898dcf29e4..00000000000
--- a/chromium/chrome/browser/resources/safe_browsing/gen_file_type_proto.py
+++ /dev/null
@@ -1,196 +0,0 @@
-#!/usr/bin/python
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""
- Convert the ASCII download_file_types.asciipb proto into a binary resource.
-
- We generate a separate variant of the binary proto for each platform,
- each which contains only the values that platform needs.
-"""
-
-import os
-import re
-import sys
-
-# Import the binary proto generator. Walks up to the root of the source tree
-# which is five directories above, and the finds the protobufs directory from
-# there.
-proto_generator_path = os.path.normpath(os.path.join(os.path.abspath(__file__),
- *[os.path.pardir] * 5 + ['chrome/browser/resources/protobufs']))
-sys.path.insert(0, proto_generator_path)
-from binary_proto_generator import BinaryProtoGenerator
-
-# Map of platforms for which we can generate binary protos.
-# This must be run after the custom imports.
-# key: type-name
-# value: proto-platform_type (int)
-def PlatformTypes():
- return {
- "android": download_file_types_pb2.DownloadFileType.PLATFORM_ANDROID,
- "chromeos": download_file_types_pb2.DownloadFileType.PLATFORM_CHROME_OS,
- "linux": download_file_types_pb2.DownloadFileType.PLATFORM_LINUX,
- "mac": download_file_types_pb2.DownloadFileType.PLATFORM_MAC,
- "win": download_file_types_pb2.DownloadFileType.PLATFORM_WINDOWS,
- }
-
-
-def PrunePlatformSettings(file_type, default_settings, platform_type):
- # Modify this file_type's platform_settings by keeping the only the
- # best one for this platform_type. In order of preference:
- # * Exact match to platform_type
- # * PLATFORM_ANY entry
- # * or copy from the default file type.
-
- last_platform = -1
- setting_match = None
- for s in file_type.platform_settings:
- # Enforce: sorted and no dups (signs of mistakes).
- assert last_platform < s.platform, (
- "Extension '%s' has duplicate or out of order platform: '%s'" %
- (file_type.extension, s.platform))
- last_platform = s.platform
-
- # Pick the most specific match.
- if ((s.platform == platform_type) or
- (s.platform == download_file_types_pb2.DownloadFileType.PLATFORM_ANY and
- setting_match is None)):
- setting_match = s
-
- # If platform_settings was empty, we'll fill in from the default
- if setting_match is None:
- assert default_settings is not None, (
- "Missing default settings for platform %d" % platform_type)
- setting_match = default_settings
-
- # Now clear out the full list and replace it with 1 entry.
- del file_type.platform_settings[:]
- new_setting = file_type.platform_settings.add()
- new_setting.CopyFrom(setting_match)
- new_setting.ClearField('platform')
-
-
-def FilterPbForPlatform(full_pb, platform_type):
- """ Return a filtered protobuf for this platform_type """
- assert type(platform_type) is int, "Bad platform_type type"
-
- new_pb = download_file_types_pb2.DownloadFileTypeConfig();
- new_pb.CopyFrom(full_pb)
-
- # Ensure there's only one platform_settings for the default.
- PrunePlatformSettings(new_pb.default_file_type, None, platform_type)
-
- # This can be extended if we want to match weird extensions.
- # Just no dots, non-UTF8, or uppercase chars.
- invalid_char_re = re.compile('[^a-z0-9_-]')
-
- # Filter platform_settings for each type.
- uma_values_used = set()
- extensions_used = set()
- for file_type in new_pb.file_types:
- assert not invalid_char_re.search(file_type.extension), (
- "File extension '%s' contains non alpha-num-dash chars" % (
- file_type.extension))
- assert file_type.extension not in extensions_used, (
- "Duplicate extension '%s'" % file_type.extension)
- extensions_used.add(file_type.extension)
-
- assert file_type.uma_value not in uma_values_used, (
- "Extension '%s' reused UMA value %d." % (
- file_type.extension, file_type.uma_value))
- uma_values_used.add(file_type.uma_value)
-
- # Modify file_type to include only the best match platform_setting.
- PrunePlatformSettings(
- file_type, new_pb.default_file_type.platform_settings[0], platform_type)
-
- return new_pb
-
-
-def FilterForPlatformAndWrite(full_pb, platform_type, outfile):
- """ Filter and write out a file for this platform """
- # Filter it
- filtered_pb = FilterPbForPlatform(full_pb, platform_type);
- # Serialize it
- binary_pb_str = filtered_pb.SerializeToString()
- # Write it to disk
- open(outfile, 'wb').write(binary_pb_str)
-
-
-def MakeSubDirs(outfile):
- """ Make the subdirectories needed to create file |outfile| """
- dirname = os.path.dirname(outfile)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
-
-
-class DownloadFileTypeProtoGenerator(BinaryProtoGenerator):
-
- def ImportProtoModule(self):
- import download_file_types_pb2
- globals()['download_file_types_pb2'] = download_file_types_pb2
-
- def EmptyProtoInstance(self):
- return download_file_types_pb2.DownloadFileTypeConfig()
-
- def ValidatePb(self, opts, pb):
- """ Validate the basic values of the protobuf. The
- file_type_policies_unittest.cc will also validate it by platform,
- but this will catch errors earlier.
- """
- assert pb.version_id > 0;
- assert pb.sampled_ping_probability >= 0.0;
- assert pb.sampled_ping_probability <= 1.0;
- assert len(pb.default_file_type.platform_settings) >= 1;
- assert len(pb.file_types) > 1;
-
- def ProcessPb(self, opts, pb):
- """ Generate one or more binary protos using the parsed proto. """
- if opts.type is not None:
- # Just one platform type
- platform_enum = PlatformTypes()[opts.type]
- outfile = os.path.join(opts.outdir, opts.outbasename)
- FilterForPlatformAndWrite(pb, platform_enum, outfile)
- else:
- # Make a separate file for each platform
- for platform_type, platform_enum in PlatformTypes().iteritems():
- # e.g. .../all/77/chromeos/download_file_types.pb
- outfile = os.path.join(opts.outdir,
- str(pb.version_id),
- platform_type,
- opts.outbasename)
- MakeSubDirs(outfile)
- FilterForPlatformAndWrite(pb, platform_enum, outfile)
-
- def AddCommandLineOptions(self, parser):
- parser.add_option('-a', '--all', action="store_true", default=False,
- help='Write a separate file for every platform. '
- 'Outfile must have a %d for version and %s for platform.')
- parser.add_option('-t', '--type',
- help='The platform type. One of android, chromeos, ' +
- 'linux, mac, win')
-
- def AddExtraCommandLineArgsForVirtualEnvRun(self, opts, command):
- if opts.type is not None:
- command += ['-t', opts.type]
- if opts.all:
- command += ['-a']
-
- def VerifyArgs(self, opts):
- if (not opts.all and opts.type not in PlatformTypes()):
- print "ERROR: Unknown platform type '%s'" % opts.type
- self.opt_parser.print_help()
- return False
-
- if (bool(opts.all) == bool(opts.type)):
- print "ERROR: Need exactly one of --type or --all"
- self.opt_parser.print_help()
- return False
- return True
-
-def main():
- return DownloadFileTypeProtoGenerator().Run()
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/chrome/browser/resources/safe_browsing/push_file_type_proto.py b/chromium/chrome/browser/resources/safe_browsing/push_file_type_proto.py
deleted file mode 100755
index 131414c77fb..00000000000
--- a/chromium/chrome/browser/resources/safe_browsing/push_file_type_proto.py
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/python
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Build and push the {vers}/{platform}/download_file_types.pb files to GCS so
-# that the component update system will pick them up and push them
-# to users. See README.md before running this.
-#
-# Requires ninja and gsutil to be in the user's path.
-
-import optparse
-import os
-import shutil
-import subprocess
-import sys
-
-
-DEST_BUCKET = 'gs://chrome-component-file-type-policies'
-RESOURCE_SUBDIR = 'chrome/browser/resources/safe_browsing'
-
-
-def main():
- parser = optparse.OptionParser()
- parser.add_option('-d', '--dir',
- help='An up-to-date GN/Ninja build directory, '
- 'such as ./out/Debug')
-
- (opts, args) = parser.parse_args()
- if opts.dir is None:
- parser.print_help()
- return 1
-
- # Clear out the target dir before we build so we can be sure we've got
- # the freshest version.
- all_dir = os.path.join(opts.dir, "gen", RESOURCE_SUBDIR, 'all')
- if os.path.isdir(all_dir):
- shutil.rmtree(all_dir)
-
- gn_command = ['ninja',
- '-C', opts.dir,
- RESOURCE_SUBDIR + ':make_all_file_types_protobuf']
- print "Running the following"
- print " " + (' '.join(gn_command))
- if subprocess.call(gn_command):
- print "Ninja failed."
- return 1
-
- os.chdir(all_dir)
-
- # Sanity check that we're in the right place
- dirs = os.listdir('.')
- assert len(dirs) == 1 and dirs[0].isdigit(), (
- "Confused by lack of single versioned dir under " + all_dir)
-
- # Push the files with their directories, in the form
- # {vers}/{platform}/download_file_types.pb
- # Don't overwrite existing files, in case we forgot to increment the
- # version.
- vers_dir = dirs[0]
- command = ['gsutil', 'cp', '-Rn', vers_dir, DEST_BUCKET]
-
- print '\nGoing to run the following command'
- print ' ', ' '.join(command)
- print '\nIn directory'
- print ' ', all_dir
- print '\nWhich should push the following files'
- expected_files = [os.path.join(dp, f) for dp, dn, fn in
- os.walk(vers_dir) for f in fn]
- for f in expected_files:
- print ' ', f
-
- shall = raw_input('\nAre you sure (y/N) ').lower() == 'y'
- if not shall:
- print 'aborting'
- return 1
- return subprocess.call(command)
-
-
-if __name__ == '__main__':
- sys.exit(main())
-
diff --git a/chromium/chrome/browser/resources/sandbox_internals/BUILD.gn b/chromium/chrome/browser/resources/sandbox_internals/BUILD.gn
index 121a5e8f54e..edf3d6e60e0 100644
--- a/chromium/chrome/browser/resources/sandbox_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/sandbox_internals/BUILD.gn
@@ -6,14 +6,10 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
if (is_win) {
- deps = [
- ":sandbox_internals_win",
- ]
+ deps = [ ":sandbox_internals_win" ]
}
if (is_android || is_linux) {
- deps = [
- ":sandbox_internals",
- ]
+ deps = [ ":sandbox_internals" ]
}
}
diff --git a/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals_win.js b/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals_win.js
index 20024acea1b..3797fb87e4d 100644
--- a/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals_win.js
+++ b/chromium/chrome/browser/resources/sandbox_internals/sandbox_internals_win.js
@@ -7,7 +7,8 @@
* processId: number,
* processType: string,
* name: string,
- * metricsName: string
+ * metricsName: string,
+ * sandboxType: string
* }}
*/
let BrowserHostProcess;
@@ -58,16 +59,17 @@ function addRow(args) {
* @param {number} pid
* @param {string} type
* @param {string} name
+ * @param {string} sandbox
* @param {PolicyDiagnostic} policy
*/
-function addRowForProcess(pid, type, name, policy) {
+function addRowForProcess(pid, type, name, sandbox, policy) {
if (policy) {
addRow([
- pid, type, name, policy.lockdownLevel, policy.desiredIntegrityLevel,
- policy.platformMitigations
+ pid, type, name, sandbox, policy.lockdownLevel,
+ policy.desiredIntegrityLevel, policy.platformMitigations
]);
} else {
- addRow([pid, type, name, 'Not Sandboxed', '', '']);
+ addRow([pid, type, name, 'Not Sandboxed', '', '', '']);
}
}
@@ -83,19 +85,22 @@ function onGetSandboxDiagnostics(results) {
}
// Titles.
- addRow(['Process', 'Type', 'Name', 'Sandbox', 'Integrity', 'Mitigations']);
+ addRow([
+ 'Process', 'Type', 'Name', 'Sandbox', 'Lockdown', 'Integrity', 'Mitigations'
+ ]);
// Browser Processes.
for (const process of results.browser) {
const pid = process.processId;
const name = process.name || process.metricsName;
- addRowForProcess(pid, process.processType, name, policies.get(pid));
+ addRowForProcess(
+ pid, process.processType, name, process.sandboxType, policies.get(pid));
}
// Renderer Processes.
for (const process of results.renderer) {
const pid = process.processId;
- addRowForProcess(pid, 'Renderer', '', policies.get(pid));
+ addRowForProcess(pid, 'Renderer', '', 'Renderer', policies.get(pid));
}
// Raw Diagnostics.
diff --git a/chromium/chrome/browser/resources/settings/BUILD.gn b/chromium/chrome/browser/resources/settings/BUILD.gn
index e01cd90af97..e05a2589a3e 100644
--- a/chromium/chrome/browser/resources/settings/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/BUILD.gn
@@ -5,8 +5,11 @@
import("//chrome/common/features.gni")
import("//third_party/closure_compiler/compile_js.gni")
import("//tools/grit/grit_rule.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
import("//ui/webui/webui_features.gni")
import("../optimize_webui.gni")
+import("settings.gni")
if (optimize_webui) {
settings_pak_file = "settings_resources.pak"
@@ -30,26 +33,45 @@ if (optimize_webui) {
]
excludes = [ "chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom.html" ]
+ deps = [ ":unpak" ]
+ }
+
+ optimize_webui("build_polymer3") {
+ host = "settings"
+ input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir)
+ js_module_in_files = [
+ "settings.js",
+ "lazy_load.js",
+ ]
+ js_out_files = [
+ "settings.rollup.js",
+ "lazy_load.rollup.js",
+ "shared.rollup.js",
+ ]
+
deps = [
":unpak",
+ "../../../../ui/webui/resources:modulize",
]
+ excludes = [ "chrome://resources/js/cr.m.js" ]
}
unpak("unpak") {
pak_file = settings_pak_file
out_folder = unpak_folder
- deps = [
- ":flattened_resources",
- ]
+ deps = [ ":flattened_resources" ]
}
grit("flattened_resources") {
source = "settings_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
+ deps = [ ":polymer3_elements" ]
defines = chrome_grit_defines
outputs = [
"grit/settings_resources.h",
@@ -69,7 +91,6 @@ group("closure_compile") {
"appearance_page:closure_compile",
"autofill_page:closure_compile",
"basic_page:closure_compile",
- "change_password_page:closure_compile",
"clear_browsing_data_dialog:closure_compile",
"controls:closure_compile",
"downloads_page:closure_compile",
@@ -80,6 +101,7 @@ group("closure_compile") {
"printing_page:closure_compile",
"privacy_page:closure_compile",
"reset_page:closure_compile",
+ "safety_check_page:closure_compile",
"search_engines_page:closure_compile",
"search_page:closure_compile",
"settings_main:closure_compile",
@@ -106,16 +128,8 @@ group("closure_compile") {
if (is_chromeos) {
deps += [
- "android_apps_page:closure_compile",
- "bluetooth_page:closure_compile",
+ "../../../test/data/webui/settings/chromeos:closure_compile",
"chromeos:closure_compile",
- "crostini_page:closure_compile",
- "date_time_page:closure_compile",
- "device_page:closure_compile",
- "internet_page:closure_compile",
- "multidevice_page:closure_compile",
- "parental_controls_page:closure_compile",
- "plugin_vm_page:closure_compile",
]
}
}
@@ -124,12 +138,16 @@ js_type_check("settings_resources") {
deps = [
":extension_control_browser_proxy",
":global_scroll_target_behavior",
+ ":hats_browser_proxy",
":lifetime_browser_proxy",
+ ":metrics_browser_proxy",
":open_window_proxy",
":page_visibility",
+ ":plural_string_proxy",
":route",
- ":route_origin_behavior",
+ ":router",
":search_settings",
+ ":settings_routes",
]
}
@@ -143,40 +161,56 @@ js_library("extension_control_browser_proxy") {
js_library("global_scroll_target_behavior") {
deps = [
- ":route",
+ ":router",
"//ui/webui/resources/js:cr",
]
}
+js_library("hats_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+}
+
js_library("lifetime_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+}
+
+js_library("metrics_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [ "$externs_path/chrome_send.js" ]
}
js_library("open_window_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
-js_library("route_origin_behavior") {
+js_library("plural_string_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_library("route") {
deps = [
- ":route",
+ ":page_visibility",
+ ":router",
+ ":settings_routes",
"//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:load_time_data",
]
}
-js_library("route") {
+js_library("router") {
deps = [
- ":page_visibility",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:load_time_data",
]
externs_list = [ "$externs_path/metrics_private.js" ]
}
+js_library("settings_routes") {
+ deps = [ ":router" ]
+}
+
js_library("page_visibility") {
deps = [
"//ui/webui/resources/js:cr",
@@ -186,8 +220,306 @@ js_library("page_visibility") {
js_library("search_settings") {
deps = [
+ "//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:search_highlight_utils",
+ "//ui/webui/resources/js:util",
]
externs_list = [ "$externs_path/pending_polymer.js" ]
}
+
+# Polymer 3 related rules.
+
+group("closure_compile_module") {
+ deps = [
+ ":closure_compile_local_module",
+ "a11y_page:closure_compile_module",
+ "about_page:closure_compile_module",
+ "appearance_page:closure_compile_module",
+ "autofill_page:closure_compile_module",
+ "basic_page:closure_compile_module",
+ "clear_browsing_data_dialog:closure_compile_module",
+ "controls:closure_compile_module",
+ "downloads_page:closure_compile_module",
+ "languages_page:closure_compile_module",
+ "on_startup_page:closure_compile_module",
+ "people_page:closure_compile_module",
+ "prefs:closure_compile_module",
+ "printing_page:closure_compile_module",
+ "privacy_page:closure_compile_module",
+ "reset_page:closure_compile_module",
+ "safety_check_page:closure_compile_module",
+ "search_engines_page:closure_compile_module",
+ "search_page:closure_compile_module",
+ "settings_main:closure_compile_module",
+ "settings_menu:closure_compile_module",
+ "settings_page:closure_compile_module",
+ "settings_ui:closure_compile_module",
+ "site_settings:closure_compile_module",
+ "site_settings_page:closure_compile_module",
+ ]
+ if (!is_chromeos) {
+ deps += [
+ "default_browser_page:closure_compile_module",
+ "system_page:closure_compile_module",
+ ]
+ }
+
+ if (is_win) {
+ deps += [
+ "chrome_cleanup_page:closure_compile_module",
+ "incompatible_applications_page:closure_compile_module",
+ ]
+ }
+}
+
+js_type_check("closure_compile_local_module") {
+ is_polymer3 = true
+ deps = [
+ ":extension_control_browser_proxy.m",
+ ":global_scroll_target_behavior.m",
+ ":hats_browser_proxy.m",
+ ":i18n_setup.m",
+ ":lifetime_browser_proxy.m",
+ ":metrics_browser_proxy.m",
+ ":open_window_proxy.m",
+ ":page_visibility.m",
+ ":plural_string_proxy.m",
+ ":route.m",
+ ":router.m",
+ ":search_settings.m",
+ ":settings_routes.m",
+ ":site_favicon.m",
+ ]
+}
+
+js_library("extension_control_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/extension_control_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+}
+
+js_library("i18n_setup.m") {
+ deps = [ "//ui/webui/resources/js:load_time_data.m" ]
+}
+
+js_library("global_scroll_target_behavior.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/global_scroll_target_behavior.m.js" ]
+ deps = [
+ ":router.m",
+ "//ui/webui/resources/js:promise_resolver.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("hats_browser_proxy.m") {
+ sources = [
+ "$root_gen_dir/chrome/browser/resources/settings/hats_browser_proxy.m.js",
+ ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("lifetime_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/lifetime_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("metrics_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/metrics_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("open_window_proxy.m") {
+ sources = [
+ "$root_gen_dir/chrome/browser/resources/settings/open_window_proxy.m.js",
+ ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("page_visibility.m") {
+ sources =
+ [ "$root_gen_dir/chrome/browser/resources/settings/page_visibility.m.js" ]
+ deps = [ "//ui/webui/resources/js:load_time_data.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("plural_string_proxy.m") {
+ sources = [
+ "$root_gen_dir/chrome/browser/resources/settings/plural_string_proxy.m.js",
+ ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("route.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/route.m.js" ]
+ deps = [
+ ":page_visibility.m",
+ ":router.m",
+ ":settings_routes.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("router.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/router.m.js" ]
+ deps = [
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":modulize" ]
+ externs_list = [ "$externs_path/metrics_private.js" ]
+}
+
+js_library("search_settings.m") {
+ sources =
+ [ "$root_gen_dir/chrome/browser/resources/settings/search_settings.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:promise_resolver.m",
+ "//ui/webui/resources/js:search_highlight_utils.m",
+ "//ui/webui/resources/js:util.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("settings_routes.m") {
+ sources =
+ [ "$root_gen_dir/chrome/browser/resources/settings/settings_routes.m.js" ]
+ deps = [ ":router.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("site_favicon.m") {
+ sources =
+ [ "$root_gen_dir/chrome/browser/resources/settings/site_favicon.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:icon.m",
+ ]
+ extra_deps = [ ":site_favicon_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ # Sub-folder targets
+ "a11y_page:polymer3_elements",
+ "about_page:polymer3_elements",
+ "appearance_page:polymer3_elements",
+ "autofill_page:polymer3_elements",
+ "basic_page:polymer3_elements",
+ "clear_browsing_data_dialog:polymer3_elements",
+ "controls:polymer3_elements",
+ "downloads_page:polymer3_elements",
+ "languages_page:polymer3_elements",
+ "on_startup_page:polymer3_elements",
+ "people_page:polymer3_elements",
+ "prefs:polymer3_elements",
+ "printing_page:polymer3_elements",
+ "privacy_page:polymer3_elements",
+ "reset_page:polymer3_elements",
+ "safety_check_page:polymer3_elements",
+ "search_engines_page:polymer3_elements",
+ "search_page:polymer3_elements",
+ "settings_main:polymer3_elements",
+ "settings_menu:polymer3_elements",
+ "settings_page:polymer3_elements",
+ "settings_ui:polymer3_elements",
+ "site_settings:polymer3_elements",
+ "site_settings_page:polymer3_elements",
+
+ # Local targets
+ ":ensure_lazy_loaded_module",
+ ":icons_module",
+ ":modulize",
+ ":settings_page_css_module",
+ ":settings_shared_css_module",
+ ":settings_vars_css_module",
+ ":site_favicon_module",
+ ]
+
+ if (!is_chromeos) {
+ public_deps += [
+ "default_browser_page:polymer3_elements",
+ "system_page:polymer3_elements",
+ ]
+ }
+
+ if (is_win) {
+ public_deps += [
+ "chrome_cleanup_page:polymer3_elements",
+ "incompatible_applications_page:polymer3_elements",
+ ]
+ }
+}
+
+polymer_modulizer("icons") {
+ js_file = "icons.m.js"
+ html_file = "icons.html"
+ html_type = "iron-iconset"
+}
+
+polymer_modulizer("settings_page_css") {
+ js_file = "settings_page_css.m.js"
+ html_file = "settings_page_css.html"
+ html_type = "style-module"
+}
+
+polymer_modulizer("settings_shared_css") {
+ js_file = "settings_shared_css.m.js"
+ html_file = "settings_shared_css.html"
+ html_type = "style-module"
+}
+
+polymer_modulizer("settings_vars_css") {
+ js_file = "settings_vars_css.m.js"
+ html_file = "settings_vars_css.html"
+ html_type = "custom-style"
+}
+
+polymer_modulizer("site_favicon") {
+ js_file = "site_favicon.js"
+ html_file = "site_favicon.html"
+ html_type = "dom-module"
+ auto_imports =
+ [ "ui/webui/resources/html/icon.html|getFavicon,getFaviconForPageURL" ]
+}
+
+polymer_modulizer("ensure_lazy_loaded") {
+ js_file = "ensure_lazy_loaded.m.js"
+ html_file = "ensure_lazy_loaded.html"
+ html_type = "v3-ready"
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "extension_control_browser_proxy.js",
+ "global_scroll_target_behavior.js",
+ "hats_browser_proxy.js",
+ "lifetime_browser_proxy.js",
+ "metrics_browser_proxy.js",
+ "open_window_proxy.js",
+ "plural_string_proxy.js",
+ "page_visibility.js",
+ "route.js",
+ "router.js",
+ "search_settings.js",
+ "settings_routes.js",
+ ]
+ namespace_rewrites = settings_namespace_rewrites + [
+ "cr.search_highlight_utils.createEmptySearchBubble|createEmptySearchBubble",
+ "cr.search_highlight_utils.findAndRemoveHighlights|findAndRemoveHighlights",
+ "cr.search_highlight_utils.highlight|highlight",
+ "cr.search_highlight_utils.removeHighlights|removeHighlights",
+ "cr.search_highlight_utils.stripDiacritics|stripDiacritics",
+ "Polymer.DomIf|DomIf",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/settings/a11y_page/BUILD.gn b/chromium/chrome/browser/resources/settings/a11y_page/BUILD.gn
index 675ee8c388e..0279924a335 100644
--- a/chromium/chrome/browser/resources/settings/a11y_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/a11y_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -10,21 +13,13 @@ js_type_check("closure_compile") {
":captions_browser_proxy",
":captions_subpage",
]
-
- if (is_chromeos) {
- deps += [
- ":externs",
- ":manage_a11y_page",
- ":switch_access_subpage",
- ":tts_subpage",
- ]
- }
}
js_library("captions_subpage") {
deps = [
"../appearance_page:fonts_browser_proxy",
"../controls:settings_dropdown_menu",
+ "../prefs:prefs_behavior",
"//ui/webui/resources/cr_elements/cr_slider:cr_slider",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
@@ -34,52 +29,93 @@ js_library("captions_subpage") {
js_library("a11y_page") {
deps = [
"..:route",
+ "..:router",
"../settings_page:settings_animated_pages",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
-js_library("manage_a11y_page") {
- deps = [
- "..:route",
- "..:route_origin_behavior",
- "../device_page:device_page_browser_proxy",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
- externs_list = [ "$externs_path/settings_private.js" ]
+js_library("captions_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
}
-js_library("switch_access_subpage") {
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
deps = [
- "..:route",
- "../prefs:prefs_behavior",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:web_ui_listener_behavior",
+ ":a11y_page.m",
+ ":captions_browser_proxy.m",
+ ":captions_subpage.m",
]
- externs_list = [ "$externs_path/settings_private.js" ]
}
-js_library("tts_subpage") {
+js_library("a11y_page.m") {
+ sources = [
+ "$root_gen_dir/chrome/browser/resources/settings/a11y_page/a11y_page.m.js",
+ ]
deps = [
- ":externs",
- "..:route",
- "../controls:settings_slider",
- "../languages_page:languages_browser_proxy",
- "../settings_page:settings_animated_pages",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:web_ui_listener_behavior",
+ ":captions_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
]
+ extra_deps = [ ":a11y_page_module" ]
}
-js_library("externs") {
+js_library("captions_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/a11y_page/captions_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
}
-js_library("captions_browser_proxy") {
+js_library("captions_subpage.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/a11y_page/captions_subpage.m.js" ]
deps = [
- "//ui/webui/resources/js:cr",
+ "../appearance_page:fonts_browser_proxy.m",
+ "../controls:settings_dropdown_menu.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":captions_subpage_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":a11y_page_module",
+ ":captions_subpage_module",
+ ":modulize",
]
}
+
+polymer_modulizer("a11y_page") {
+ js_file = "a11y_page.js"
+ html_file = "a11y_page.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/a11y_page/captions_browser_proxy.html|CaptionsBrowserProxyImpl",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("captions_subpage") {
+ js_file = "captions_subpage.js"
+ html_file = "captions_subpage.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/a11y_page/captions_browser_proxy.html|CaptionsBrowserProxy",
+ "chrome/browser/resources/settings/controls/settings_dropdown_menu.html|DropdownMenuOptionList",
+ "chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.html|FontsBrowserProxy, FontsBrowserProxyImpl, FontsData",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+js_modulizer("modulize") {
+ input_files = [ "captions_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/about_page/BUILD.gn b/chromium/chrome/browser/resources/settings/about_page/BUILD.gn
index 41910e9e5df..1589b17c9d6 100644
--- a/chromium/chrome/browser/resources/settings/about_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/about_page/BUILD.gn
@@ -3,28 +3,22 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
":about_page",
":about_page_browser_proxy",
]
-
- if (is_chromeos) {
- deps += [
- ":channel_switcher_dialog",
- ":detailed_build_info",
- ]
- }
}
js_library("about_page") {
deps = [
":about_page_browser_proxy",
"..:lifetime_browser_proxy",
- "..:route",
- "../settings_page:main_page_behavior",
- "../settings_page:settings_animated_pages",
+ "..:router",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:parse_html_subset",
@@ -33,25 +27,61 @@ js_library("about_page") {
}
js_library("about_page_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [ "$externs_path/chrome_send.js" ]
}
-js_library("detailed_build_info") {
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
deps = [
- ":about_page_browser_proxy",
- "//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ":about_page.m",
+ ":about_page_browser_proxy.m",
]
}
-js_library("channel_switcher_dialog") {
+js_library("about_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/about_page/about_page.m.js" ]
deps = [
- ":about_page_browser_proxy",
- "//ui/webui/resources/js:load_time_data",
+ ":about_page_browser_proxy.m",
+ "..:lifetime_browser_proxy.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:parse_html_subset.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
]
+ extra_deps = [ ":about_page_module" ]
+}
+
+js_library("about_page_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/about_page/about_page_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":about_page_module",
+ ":modulize",
+ ]
+}
+
+polymer_modulizer("about_page") {
+ js_file = "about_page.js"
+ html_file = "about_page.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/router.html|Router",
+ "chrome/browser/resources/settings/lifetime_browser_proxy.html|LifetimeBrowserProxy, LifetimeBrowserProxyImpl",
+ "chrome/browser/resources/settings/about_page/about_page_browser_proxy.html|AboutPageBrowserProxy, AboutPageBrowserProxyImpl, UpdateStatus, UpdateStatusChangedEvent, PromoteUpdaterStatus",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+js_modulizer("modulize") {
+ input_files = [ "about_page_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
}
diff --git a/chromium/chrome/browser/resources/settings/android_apps_page/BUILD.gn b/chromium/chrome/browser/resources/settings/android_apps_page/BUILD.gn
deleted file mode 100644
index 4ee22baac6c..00000000000
--- a/chromium/chrome/browser/resources/settings/android_apps_page/BUILD.gn
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":android_apps_browser_proxy",
- ":android_apps_page",
- ":android_apps_subpage",
- ]
-}
-
-js_library("android_apps_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
-}
-
-js_library("android_apps_page") {
- deps = [
- ":android_apps_browser_proxy",
- "..:route",
- "../prefs:prefs_behavior",
- "//ui/webui/resources/js:i18n_behavior",
- ]
- externs_list = [ "$externs_path/settings_private.js" ]
-}
-
-js_library("android_apps_subpage") {
- deps = [
- ":android_apps_browser_proxy",
- "..:route",
- "../prefs:prefs_behavior",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js/cr/ui:focus_without_ink",
- ]
-}
diff --git a/chromium/chrome/browser/resources/settings/appearance_page/BUILD.gn b/chromium/chrome/browser/resources/settings/appearance_page/BUILD.gn
index a3c3d26c232..a223588107a 100644
--- a/chromium/chrome/browser/resources/settings/appearance_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/appearance_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -12,10 +15,6 @@ js_type_check("closure_compile") {
":fonts_browser_proxy",
":home_url_input",
]
-
- if (is_chromeos) {
- deps += [ ":wallpaper_browser_proxy" ]
- }
}
js_library("appearance_fonts_page") {
@@ -46,9 +45,9 @@ js_library("appearance_browser_proxy") {
js_library("appearance_page") {
deps = [
":appearance_browser_proxy",
- ":wallpaper_browser_proxy",
"..:page_visibility",
"..:route",
+ "..:router",
"../controls:settings_dropdown_menu",
"../settings_page:settings_animated_pages",
"//ui/webui/resources/js:cr",
@@ -81,9 +80,136 @@ js_library("home_url_input") {
externs_list = [ "$externs_path/settings_private.js" ]
}
-js_library("wallpaper_browser_proxy") {
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
deps = [
- "//ui/webui/resources/js:cr",
+ ":appearance_browser_proxy.m",
+ ":appearance_fonts_page.m",
+ ":appearance_page.m",
+ ":fonts_browser_proxy.m",
+ ":home_url_input.m",
+ ]
+}
+
+js_library("appearance_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.m.js" ]
+ deps = [
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ externs_list = [
+ "$externs_path/chrome_send.js",
+ "$externs_path/management.js",
+ "$externs_path/settings_private.js",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("appearance_fonts_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.m.js" ]
+ deps = [
+ ":fonts_browser_proxy.m",
+ "../controls:settings_dropdown_menu.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_slider:cr_slider.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
]
externs_list = [ "$externs_path/chrome_send.js" ]
+ extra_deps = [ ":appearance_fonts_page_module" ]
+}
+
+js_library("appearance_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/appearance_page/appearance_page.m.js" ]
+ deps = [
+ ":appearance_browser_proxy.m",
+ "..:page_visibility.m",
+ "..:route.m",
+ "..:router.m",
+ "../controls:settings_dropdown_menu.m",
+ "../settings_page:settings_animated_pages.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ externs_list = [
+ "$externs_path/settings_private.js",
+ "$externs_path/chrome_send.js",
+ ]
+ extra_deps = [ ":appearance_page_module" ]
+}
+
+js_library("fonts_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("home_url_input.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/appearance_page/home_url_input.m.js" ]
+ deps = [
+ ":appearance_browser_proxy.m",
+ "../controls:pref_control_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior.m",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_pref_behavior.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":home_url_input_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":appearance_fonts_page_module",
+ ":appearance_page_module",
+ ":home_url_input_module",
+ ":modulize",
+ ]
+}
+
+polymer_modulizer("appearance_fonts_page") {
+ js_file = "appearance_fonts_page.js"
+ html_file = "appearance_fonts_page.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/cr_elements/cr_slider/cr_slider.html|SliderTick",
+ "chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.html|FontsBrowserProxy, FontsBrowserProxyImpl, FontsData",
+ "chrome/browser/resources/settings/controls/settings_dropdown_menu.html|DropdownMenuOptionList",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("appearance_page") {
+ js_file = "appearance_page.js"
+ html_file = "appearance_page.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.html|AppearanceBrowserProxy, AppearanceBrowserProxyImpl",
+ "chrome/browser/resources/settings/controls/settings_dropdown_menu.html|DropdownMenuOptionList",
+ "chrome/browser/resources/settings/page_visibility.html|AppearancePageVisibility",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("home_url_input") {
+ js_file = "home_url_input.js"
+ html_file = "home_url_input.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.html|AppearanceBrowserProxy, AppearanceBrowserProxyImpl",
+ ]
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "appearance_browser_proxy.js",
+ "fonts_browser_proxy.js",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
}
diff --git a/chromium/chrome/browser/resources/settings/autofill_page/BUILD.gn b/chromium/chrome/browser/resources/settings/autofill_page/BUILD.gn
index 1afa9c4b7ef..bae62b7a7f8 100644
--- a/chromium/chrome/browser/resources/settings/autofill_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/autofill_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -11,24 +14,32 @@ js_type_check("closure_compile") {
":autofill_section",
":blocking_request_manager",
":credit_card_edit_dialog",
- ":credit_card_list",
":credit_card_list_entry",
+ ":password_check",
+ ":password_check_behavior",
+ ":password_check_edit_dialog",
+ ":password_check_list_item",
":password_edit_dialog",
":password_list_item",
":password_manager_proxy",
+ ":password_remove_confirmation_dialog",
":passwords_section",
+ ":payments_list",
":payments_section",
":show_password_behavior",
+ ":upi_id_list_entry",
]
}
js_library("autofill_page") {
deps = [
":autofill_section",
+ ":password_check_behavior",
":passwords_section",
":payments_section",
"..:open_window_proxy",
"..:route",
+ "..:router",
"../prefs:prefs_behavior",
"../settings_page:settings_animated_pages",
"//ui/webui/resources/js:assert",
@@ -43,6 +54,7 @@ js_library("autofill_page") {
js_library("autofill_section") {
deps = [
":address_edit_dialog",
+ ":password_check_behavior",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:load_time_data",
@@ -57,8 +69,8 @@ js_library("blocking_request_manager") {
js_library("payments_section") {
deps = [
":credit_card_edit_dialog",
- ":credit_card_list",
- "../people_page:sync_browser_proxy",
+ ":payments_list",
+ "..:metrics_browser_proxy",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:load_time_data",
@@ -77,21 +89,60 @@ js_library("address_edit_dialog") {
}
js_library("credit_card_edit_dialog") {
+ deps = [ "//ui/webui/resources/js:i18n_behavior" ]
+ externs_list = [ "$externs_path/autofill_private.js" ]
+}
+
+js_library("credit_card_list_entry") {
+ deps = [ "//ui/webui/resources/js:i18n_behavior" ]
+ externs_list = [ "$externs_path/autofill_private.js" ]
+}
+
+js_library("password_check") {
deps = [
+ ":blocking_request_manager",
+ ":password_check_behavior",
+ ":password_manager_proxy",
+ "..:plural_string_proxy",
+ "../prefs:prefs_behavior",
+ "//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:util",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
]
- externs_list = [ "$externs_path/autofill_private.js" ]
+ externs_list = [ "$externs_path/quick_unlock_private.js" ]
}
-js_library("credit_card_list") {
+js_library("password_check_behavior") {
deps = [
- ":credit_card_list_entry",
+ ":password_manager_proxy",
+ "..:plural_string_proxy",
+ ]
+ externs_list = [ "$externs_path/passwords_private.js" ]
+}
+
+js_library("password_check_edit_dialog") {
+ deps = [
+ ":password_manager_proxy",
+ "//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
]
}
-js_library("credit_card_list_entry") {
+js_library("password_remove_confirmation_dialog") {
+ deps = [
+ ":password_manager_proxy",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+}
+
+js_library("password_check_list_item") {
deps = [
+ ":blocking_request_manager",
+ ":password_manager_proxy",
+ "..:open_window_proxy",
+ "//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
]
}
@@ -105,9 +156,7 @@ js_library("password_list_item") {
}
js_library("password_manager_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [ "$externs_path/passwords_private.js" ]
}
@@ -117,6 +166,8 @@ js_library("passwords_section") {
":password_list_item",
":password_manager_proxy",
"..:global_scroll_target_behavior",
+ "..:plural_string_proxy",
+ "..:route",
"../people_page:sync_browser_proxy",
"//third_party/polymer/v1_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer-extracted",
"//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted",
@@ -129,7 +180,10 @@ js_library("passwords_section") {
"//ui/webui/resources/js:web_ui_listener_behavior",
"//ui/webui/resources/js/cr/ui:focus_without_ink",
]
- externs_list = [ "$externs_path/passwords_private.js" ]
+ externs_list = [
+ "$externs_path/passwords_private.js",
+ "$externs_path/quick_unlock_private.js",
+ ]
}
js_library("password_edit_dialog") {
@@ -139,9 +193,506 @@ js_library("password_edit_dialog") {
]
}
+js_library("payments_list") {
+ deps = [
+ ":credit_card_list_entry",
+ ":upi_id_list_entry",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+}
+
js_library("show_password_behavior") {
+ deps = [ ":blocking_request_manager" ]
+ externs_list = [ "$externs_path/passwords_private.js" ]
+}
+
+js_library("upi_id_list_entry") {
+ deps = [ "//ui/webui/resources/js:i18n_behavior" ]
+}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
deps = [
- ":blocking_request_manager",
+ ":address_edit_dialog.m",
+ ":autofill_page.m",
+ ":autofill_section.m",
+ ":blocking_request_manager.m",
+ ":credit_card_edit_dialog.m",
+ ":credit_card_list_entry.m",
+ ":password_check.m",
+ ":password_check_behavior.m",
+ ":password_check_edit_dialog.m",
+ ":password_check_list_item.m",
+ ":password_edit_dialog.m",
+ ":password_list_item.m",
+ ":password_manager_proxy.m",
+ ":password_remove_confirmation_dialog.m",
+ ":passwords_export_dialog.m",
+ ":passwords_section.m",
+ ":payments_list.m",
+ ":payments_section.m",
+ ":show_password_behavior.m",
+ ":upi_id_list_entry.m",
+ ]
+}
+
+js_library("address_edit_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/address_edit_dialog.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ externs_list = [ "$externs_path/autofill_private.js" ]
+ extra_deps = [ ":address_edit_dialog_module" ]
+}
+
+js_library("autofill_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/autofill_page.m.js" ]
+ deps = [
+ ":password_check_behavior.m",
+ "..:open_window_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "../prefs:prefs_behavior.m",
+ ]
+ externs_list = [
+ "$externs_path/passwords_private.js",
+ "$externs_path/settings_private.js",
+ ]
+ extra_deps = [ ":autofill_page_module" ]
+}
+
+js_library("autofill_section.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/autofill_section.m.js" ]
+ deps = [
+ ":address_edit_dialog.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ externs_list = [
+ "$externs_path/autofill_private.js",
+ "$externs_path/metrics_private.js",
+ ]
+ extra_deps = [ ":autofill_section_module" ]
+}
+
+js_library("blocking_request_manager.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/blocking_request_manager.m.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("credit_card_edit_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ externs_list = [ "$externs_path/autofill_private.js" ]
+ extra_deps = [ ":credit_card_edit_dialog_module" ]
+}
+
+js_library("credit_card_list_entry.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ externs_list = [ "$externs_path/autofill_private.js" ]
+ extra_deps = [ ":credit_card_list_entry_module" ]
+}
+
+js_library("password_check.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/password_check.m.js" ]
+ deps = [
+ ":blocking_request_manager.m",
+ ":password_check_behavior.m",
+ ":password_manager_proxy.m",
+ "..:plural_string_proxy.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:util.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ externs_list = [ "$externs_path/quick_unlock_private.js" ]
+ extra_deps = [ ":password_check_module" ]
+}
+
+js_library("password_check_behavior.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/password_check_behavior.m.js" ]
+ deps = [
+ ":password_manager_proxy.m",
+ "..:plural_string_proxy.m",
]
externs_list = [ "$externs_path/passwords_private.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("password_check_edit_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.m.js" ]
+ deps = [
+ ":password_manager_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ extra_deps = [ ":password_check_edit_dialog_module" ]
+}
+
+js_library("password_check_list_item.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/password_check_list_item.m.js" ]
+ deps = [
+ ":blocking_request_manager.m",
+ ":password_manager_proxy.m",
+ "..:open_window_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+ extra_deps = [ ":password_check_list_item_module" ]
+}
+
+js_library("password_edit_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/password_edit_dialog.m.js" ]
+ deps = [
+ ":show_password_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
+ ]
+ extra_deps = [ ":password_edit_dialog_module" ]
+}
+
+js_library("password_remove_confirmation_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.m.js" ]
+ deps = [
+ ":password_manager_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ extra_deps = [ ":password_remove_confirmation_dialog_module" ]
+}
+
+js_library("password_list_item.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/password_list_item.m.js" ]
+ deps = [
+ ":blocking_request_manager.m",
+ ":show_password_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
+ ]
+ extra_deps = [ ":password_list_item_module" ]
+}
+
+js_library("password_manager_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/password_manager_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ externs_list = [ "$externs_path/passwords_private.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("passwords_export_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.m.js" ]
+ deps = [
+ ":blocking_request_manager.m",
+ ":password_manager_proxy.m",
+ ]
+ extra_deps = [ ":passwords_export_dialog_module" ]
+}
+
+js_library("passwords_section.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/passwords_section.m.js" ]
+ deps = [
+ ":password_edit_dialog.m",
+ ":password_list_item.m",
+ ":password_manager_proxy.m",
+ "..:global_scroll_target_behavior.m",
+ "..:plural_string_proxy.m",
+ "..:route.m",
+ "../people_page:sync_browser_proxy.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/cr_elements/cr_toast:cr_toast_manager.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:list_property_update_behavior.m",
+ "//ui/webui/resources/js:util.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ externs_list = [
+ "$externs_path/passwords_private.js",
+ "$externs_path/quick_unlock_private.js",
+ ]
+ extra_deps = [ ":passwords_section_module" ]
+}
+
+js_library("payments_list.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/payments_list.m.js" ]
+ deps = [
+ ":credit_card_list_entry.m",
+ ":upi_id_list_entry.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":payments_list_module" ]
+}
+
+js_library("payments_section.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/payments_section.m.js" ]
+ deps = [
+ ":autofill_section.m",
+ ":credit_card_edit_dialog.m",
+ ":payments_list.m",
+ "..:metrics_browser_proxy.m",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ externs_list = [ "$externs_path/autofill_private.js" ]
+ extra_deps = [ ":payments_section_module" ]
+}
+
+js_library("show_password_behavior.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/show_password_behavior.m.js" ]
+ deps = [
+ ":blocking_request_manager.m",
+ ":password_manager_proxy.m",
+ ]
+ externs_list = [ "$externs_path/passwords_private.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("upi_id_list_entry.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ extra_deps = [ ":upi_id_list_entry_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":address_edit_dialog_module",
+ ":autofill_page_module",
+ ":autofill_section_module",
+ ":credit_card_edit_dialog_module",
+ ":credit_card_list_entry_module",
+ ":modulize",
+ ":password_check_edit_dialog_module",
+ ":password_check_list_item_module",
+ ":password_check_module",
+ ":password_edit_dialog_module",
+ ":password_list_item_module",
+ ":password_remove_confirmation_dialog_module",
+ ":passwords_export_dialog_module",
+ ":passwords_section_module",
+ ":passwords_shared_css_module",
+ ":payments_list_module",
+ ":payments_section_module",
+ ":upi_id_list_entry_module",
+ ]
+}
+
+polymer_modulizer("address_edit_dialog") {
+ js_file = "address_edit_dialog.js"
+ html_file = "address_edit_dialog.html"
+ html_type = "dom-module"
+ auto_imports = [
+ "ui/webui/resources/html/assert.html|assertNotReached",
+ "ui/webui/resources/html/cr.html|addSingletonGetter",
+ "ui/webui/resources/html/polymer.html|html,flush,Polymer",
+ ]
+ namespace_rewrites =
+ settings_namespace_rewrites +
+ [ "settings.address.AddressComponentUI|AddressComponentUI" ]
+}
+
+polymer_modulizer("autofill_page") {
+ js_file = "autofill_page.js"
+ html_file = "autofill_page.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/autofill_page/password_manager_proxy.html|PasswordManagerImpl",
+ "chrome/browser/resources/settings/open_window_proxy.html|OpenWindowProxyImpl",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("autofill_section") {
+ js_file = "autofill_section.js"
+ html_file = "autofill_section.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/cr.html|addSingletonGetter",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("credit_card_edit_dialog") {
+ js_file = "credit_card_edit_dialog.js"
+ html_file = "credit_card_edit_dialog.html"
+ html_type = "dom-module"
+}
+
+polymer_modulizer("credit_card_list_entry") {
+ js_file = "credit_card_list_entry.js"
+ html_file = "credit_card_list_entry.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("password_check") {
+ js_file = "password_check.js"
+ html_file = "password_check.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/autofill_page/password_manager_proxy.html|PasswordManagerImpl,PasswordManagerProxy",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxyImpl,SyncPrefs,SyncStatus",
+ "chrome/browser/resources/settings/plural_string_proxy.html|PluralStringProxyImpl",
+ "chrome/browser/resources/settings/router.html|Router",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/util.html|getDeepActiveElement",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("password_check_edit_dialog") {
+ js_file = "password_check_edit_dialog.js"
+ html_file = "password_check_edit_dialog.html"
+ html_type = "dom-module"
+ auto_imports = [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/autofill_page/password_manager_proxy.html|PasswordManagerImpl,PasswordManagerProxy",
+ ]
+}
+
+polymer_modulizer("password_check_list_item") {
+ js_file = "password_check_list_item.js"
+ html_file = "password_check_list_item.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/open_window_proxy.html|OpenWindowProxyImpl",
+ "chrome/browser/resources/settings/autofill_page/password_manager_proxy.html|PasswordManagerImpl,PasswordManagerProxy",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("password_edit_dialog") {
+ js_file = "password_edit_dialog.js"
+ html_file = "password_edit_dialog.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports
+}
+
+polymer_modulizer("password_list_item") {
+ js_file = "password_list_item.js"
+ html_file = "password_list_item.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/autofill_page/password_manager_proxy.html|PasswordManagerProxy" ]
+}
+
+polymer_modulizer("passwords_export_dialog") {
+ js_file = "passwords_export_dialog.js"
+ html_file = "passwords_export_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/autofill_page/password_manager_proxy.html|PasswordManagerImpl, PasswordManagerProxy" ]
+}
+
+polymer_modulizer("password_remove_confirmation_dialog") {
+ js_file = "password_remove_confirmation_dialog.js"
+ html_file = "password_remove_confirmation_dialog.html"
+ html_type = "dom-module"
+ auto_imports = [
+ "chrome/browser/resources/settings/autofill_page/password_manager_proxy.html|PasswordManagerImpl,PasswordManagerProxy",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("passwords_section") {
+ js_file = "passwords_section.js"
+ html_file = "passwords_section.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites +
+ [ "Polymer.IronA11yKeysBehavior|IronA11yKeysBehavior" ]
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/autofill_page/password_manager_proxy.html|PasswordManagerImpl,PasswordManagerProxy",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxyImpl,SyncPrefs,SyncStatus",
+ "chrome/browser/resources/settings/plural_string_proxy.html|PluralStringProxyImpl",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ "third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior/iron-a11y-keys-behavior.html|IronA11yKeysBehavior",
+ "ui/webui/resources/cr_elements/cr_toast/cr_toast_manager.html|getToastManager",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/polymer.html|afterNextRender,html,Polymer",
+ "ui/webui/resources/html/util.html|getDeepActiveElement",
+ ]
+}
+
+polymer_modulizer("passwords_shared_css") {
+ js_file = "passwords_shared_css.m.js"
+ html_file = "passwords_shared_css.html"
+ html_type = "style-module"
+}
+
+polymer_modulizer("payments_list") {
+ js_file = "payments_list.js"
+ html_file = "payments_list.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("payments_section") {
+ js_file = "payments_section.js"
+ html_file = "payments_section.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/autofill_page/autofill_section.html|AutofillManager",
+ "chrome/browser/resources/settings/metrics_browser_proxy.html|MetricsBrowserProxyImpl,PrivacyElementInteractions",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/cr.html|addSingletonGetter",
+ ]
+ namespace_rewrites = settings_namespace_rewrites +
+ [ "settings.PaymentsManager|PaymentsManager" ]
+}
+
+polymer_modulizer("upi_id_list_entry") {
+ js_file = "upi_id_list_entry.js"
+ html_file = "upi_id_list_entry.html"
+ html_type = "dom-module"
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "blocking_request_manager.js",
+ "password_check_behavior.js",
+ "password_manager_proxy.js",
+ "show_password_behavior.js",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
}
diff --git a/chromium/chrome/browser/resources/settings/basic_page/BUILD.gn b/chromium/chrome/browser/resources/settings/basic_page/BUILD.gn
index 5cbc3c1c317..7d7144891ab 100644
--- a/chromium/chrome/browser/resources/settings/basic_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/basic_page/BUILD.gn
@@ -3,25 +3,63 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
- deps = [
- ":basic_page",
- ]
+ deps = [ ":basic_page" ]
}
js_library("basic_page") {
deps = [
"..:page_visibility",
"..:route",
+ "..:router",
"..:search_settings",
- "../android_apps_page:android_apps_browser_proxy",
- "../change_password_page:change_password_browser_proxy",
"../chrome_cleanup_page:chrome_cleanup_proxy",
"../prefs:prefs_behavior",
"../settings_page:main_page_behavior",
"//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:web_ui_listener_behavior",
]
externs_list = [ "$externs_path/pending_polymer.js" ]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [ ":basic_page.m" ]
+}
+
+js_library("basic_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/basic_page/basic_page.m.js" ]
+ deps = [
+ "..:page_visibility.m",
+ "..:route.m",
+ "..:router.m",
+ "..:search_settings.m",
+ "../chrome_cleanup_page:chrome_cleanup_proxy.m",
+ "../prefs:prefs_behavior.m",
+ "../settings_page:main_page_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":basic_page_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [ ":basic_page_module" ]
+}
+
+polymer_modulizer("basic_page") {
+ js_file = "basic_page.js"
+ html_file = "basic_page.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/page_visibility.html|PageVisibility",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route, Router, RouteObserverBehavior",
+ "chrome/browser/resources/settings/settings_page/main_page_behavior.html|MainPageBehavior",
+ "chrome/browser/resources/settings/search_settings.html|getSearchManager, SearchResult",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/polymer.html|beforeNextRender,html,Polymer",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/change_password_page/BUILD.gn b/chromium/chrome/browser/resources/settings/change_password_page/BUILD.gn
deleted file mode 100644
index 183eb500816..00000000000
--- a/chromium/chrome/browser/resources/settings/change_password_page/BUILD.gn
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-js_type_check("closure_compile") {
- deps = [
- ":change_password_browser_proxy",
- ":change_password_page",
- ]
-}
-
-js_library("change_password_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:cr",
- ]
-}
-
-js_library("change_password_page") {
- deps = [
- ":change_password_browser_proxy",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:util",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
- externs_list = [ "$externs_path/settings_private.js" ]
-}
diff --git a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/BUILD.gn
index e300b7d3bea..71b108e45e9 100644
--- a/chromium/chrome/browser/resources/settings/chrome_cleanup_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chrome_cleanup_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -38,3 +41,77 @@ js_library("items_to_remove_list") {
"//ui/webui/resources/js:cr",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":chrome_cleanup_page.m",
+ ":chrome_cleanup_proxy.m",
+ ":items_to_remove_list.m",
+ ]
+}
+
+js_library("chrome_cleanup_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.m.js" ]
+ deps = [
+ ":chrome_cleanup_proxy.m",
+ ":items_to_remove_list.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":chrome_cleanup_page_module" ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+}
+
+js_library("chrome_cleanup_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("items_to_remove_list.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.m.js" ]
+ deps = [
+ ":chrome_cleanup_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":items_to_remove_list_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":chrome_cleanup_page_module",
+ ":items_to_remove_list_module",
+ ":modulize",
+ ]
+}
+
+polymer_modulizer("chrome_cleanup_page") {
+ js_file = "chrome_cleanup_page.js"
+ html_file = "chrome_cleanup_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites + [
+ "settings.ChromeCleaner|ChromeCleaner",
+ "settings.ChromeCleanup|ChromeCleanup",
+ ]
+ auto_imports = [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.html|ChromeCleanupProxyImpl,ChromeCleanupProxy",
+ "chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.html|ChromeCleanupRemovalListItem",
+ ]
+}
+
+polymer_modulizer("items_to_remove_list") {
+ js_file = "items_to_remove_list.js"
+ html_file = "items_to_remove_list.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = [ "chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.html|ChromeCleanupProxyImpl" ]
+}
+
+js_modulizer("modulize") {
+ input_files = [ "chrome_cleanup_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/BUILD.gn
index 9bd2231c54b..01feaf04caa 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -29,35 +29,45 @@ if (optimize_webui) {
"lazy_load.crisper.js",
]
excludes = [
+ # TODO(calamity): Update optimize_webui to handle generated files.
+ "chrome://resources/css/cros_colors.generated.css",
"chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom.html",
"chrome://os-settings/app-management/app_management.mojom-lite.js",
"chrome://os-settings/app-management/bitmap.mojom-lite.js",
+ "chrome://os-settings/app-management/file_path.mojom-lite.js",
"chrome://os-settings/app-management/image_info.mojom-lite.js",
"chrome://os-settings/app-management/image.mojom-lite.js",
"chrome://os-settings/app-management/types.mojom-lite.js",
+ "chrome://os-settings/search/search.mojom-lite.js",
+ "chrome://os-settings/search/search_result_icon.mojom-lite.js",
+ "chrome://os-settings/search/user_action_recorder.mojom-lite.js",
"chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom.html",
+ "chrome://resources/mojo/mojo/public/mojom/base/string16.mojom.html",
"chrome://resources/mojo/mojo/public/mojom/base/time.mojom.html",
]
- deps = [
- ":unpak",
- ]
+ deps = [ ":unpak" ]
}
unpak("unpak") {
pak_file = settings_pak_file
out_folder = unpak_folder
- deps = [
- ":flattened_resources",
- ]
+ deps = [ ":flattened_resources" ]
}
grit("flattened_resources") {
source = "../os_settings_resources.grd"
- # The .grd contains references to generated files.
- source_is_generated = true
+ deps = [
+ "//chrome/browser/ui/webui/app_management:mojo_bindings_js",
+ "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings_js",
+ ]
+
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
defines = chrome_grit_defines
outputs = [
@@ -72,8 +82,23 @@ if (optimize_webui) {
group("closure_compile") {
deps = [
+ ":metrics_recorder",
+ ":os_page_visibility",
+ ":os_route",
+ ":os_settings_routes",
+ ":route_origin_behavior",
+ "ambient_mode_page:closure_compile",
+ "bluetooth_page:closure_compile",
+ "crostini_page:closure_compile",
+ "date_time_page:closure_compile",
+ "device_page:closure_compile",
+ "google_assistant_page:closure_compile",
+ "internet_page:closure_compile",
+ "localized_link:closure_compile",
+ "multidevice_page:closure_compile",
"os_a11y_page:closure_compile",
"os_apps_page:closure_compile",
+ "os_apps_page/app_management_page:closure_compile",
"os_files_page:closure_compile",
"os_languages_page:closure_compile",
"os_people_page:closure_compile",
@@ -84,7 +109,47 @@ group("closure_compile") {
"os_settings_main:closure_compile",
"os_settings_menu:closure_compile",
"os_settings_page:closure_compile",
+ "os_settings_search_box:closure_compile",
"os_settings_ui:closure_compile",
+ "parental_controls_page:closure_compile",
"personalization_page:closure_compile",
+ "plugin_vm_page:closure_compile",
+ ]
+}
+
+js_library("os_page_visibility") {
+ deps = [
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:load_time_data",
+ ]
+}
+
+js_library("os_route") {
+ deps = [
+ ":os_settings_routes",
+ "..:router",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:load_time_data",
+ ]
+}
+
+js_library("os_settings_routes") {
+ deps = [
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:load_time_data",
+ ]
+}
+
+js_library("route_origin_behavior") {
+ deps = [
+ ":os_route",
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
+js_library("metrics_recorder") {
+ deps = [
+ "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings_js_library_for_compile",
+ "//ui/webui/resources/js:cr",
]
}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn
new file mode 100644
index 00000000000..583c5bdb26d
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/chromeos/ambient_mode_page/BUILD.gn
@@ -0,0 +1,27 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+ deps = [
+ ":ambient_mode_browser_proxy",
+ ":ambient_mode_page",
+ ]
+}
+
+js_library("ambient_mode_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+}
+
+js_library("ambient_mode_page") {
+ deps = [
+ ":ambient_mode_browser_proxy",
+ "../../prefs:prefs_behavior",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:load_time_data",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/settings/bluetooth_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/bluetooth_page/BUILD.gn
index 6cc32f17472..8e257d5727e 100644
--- a/chromium/chrome/browser/resources/settings/bluetooth_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/bluetooth_page/BUILD.gn
@@ -15,9 +15,10 @@ js_type_check("closure_compile") {
js_library("bluetooth_page") {
deps = [
":bluetooth_system_on_extensions",
- "..:route",
- "../prefs:prefs_behavior",
- "../settings_page:settings_animated_pages",
+ "..:os_route",
+ "../..:router",
+ "../../prefs:prefs_behavior",
+ "../../settings_page:settings_animated_pages",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
]
@@ -34,11 +35,14 @@ js_library("bluetooth_page") {
js_library("bluetooth_subpage") {
deps = [
":bluetooth_system_on_extensions",
- "..:route",
+ "..:metrics_recorder",
+ "..:os_route",
+ "../..:router",
"//ui/webui/resources/cr_components/chromeos:bluetooth_dialog",
"//ui/webui/resources/cr_elements:cr_scrollable_behavior",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:list_property_update_behavior",
]
externs_list = [
"$externs_path/bluetooth.js",
@@ -55,13 +59,12 @@ js_library("bluetooth_device_list_item") {
":bluetooth_system_on_extensions",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior",
]
externs_list = [ "$externs_path/bluetooth.js" ]
}
js_library("bluetooth_system_on_extensions") {
sources = []
- deps = [
- "//services/device/public/mojom:mojom_js_library_for_compile",
- ]
+ deps = [ "//services/device/public/mojom:mojom_js_library_for_compile" ]
}
diff --git a/chromium/chrome/browser/resources/settings/crostini_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/crostini_page/BUILD.gn
index 68c42047a38..2cf11208bdd 100644
--- a/chromium/chrome/browser/resources/settings/crostini_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/crostini_page/BUILD.gn
@@ -8,8 +8,10 @@ js_type_check("closure_compile") {
deps = [
":crostini_arc_adb",
":crostini_browser_proxy",
+ ":crostini_disk_resize_dialog",
":crostini_export_import",
":crostini_page",
+ ":crostini_port_forwarding",
":crostini_shared_paths",
":crostini_shared_usb_devices",
":crostini_subpage",
@@ -19,7 +21,9 @@ js_type_check("closure_compile") {
js_library("crostini_arc_adb") {
deps = [
":crostini_browser_proxy",
- "..:route",
+ "..:metrics_recorder",
+ "..:os_route",
+ "../localized_link:localized_link",
"//ui/webui/resources/cr_elements/policy:cr_policy_indicator",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
@@ -27,14 +31,20 @@ js_library("crostini_arc_adb") {
}
js_library("crostini_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_library("crostini_export_import") {
deps = [
- "//ui/webui/resources/js:cr",
+ ":crostini_browser_proxy",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
]
}
-js_library("crostini_export_import") {
+js_library("crostini_disk_resize_dialog") {
deps = [
":crostini_browser_proxy",
+ "//ui/webui/resources/cr_elements/cr_slider:cr_slider",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
@@ -42,8 +52,10 @@ js_library("crostini_export_import") {
js_library("crostini_page") {
deps = [
":crostini_browser_proxy",
- "..:route",
- "../prefs:prefs_behavior",
+ "..:os_route",
+ "../..:router",
+ "../../prefs:prefs_behavior",
+ "../localized_link:localized_link",
"//ui/webui/resources/js:i18n_behavior",
]
externs_list = [ "$externs_path/settings_private.js" ]
@@ -52,24 +64,37 @@ js_library("crostini_page") {
js_library("crostini_shared_paths") {
deps = [
":crostini_browser_proxy",
- "..:route",
- "../prefs:prefs_behavior",
+ "..:metrics_recorder",
+ "..:os_route",
+ "../../prefs:prefs_behavior",
]
}
js_library("crostini_shared_usb_devices") {
deps = [
":crostini_browser_proxy",
- "..:route",
+ "..:metrics_recorder",
+ "..:os_route",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
+js_library("crostini_port_forwarding") {
+ deps = [
+ ":crostini_browser_proxy",
+ "../..:route",
+ "../../prefs:prefs_behavior",
+ ]
+}
+
js_library("crostini_subpage") {
deps = [
":crostini_browser_proxy",
- "..:route",
+ "..:metrics_recorder",
+ "..:os_route",
"..:route_origin_behavior",
- "../prefs:prefs_behavior",
+ "../..:router",
+ "../../controls:settings_toggle_button",
+ "../../prefs:prefs_behavior",
]
}
diff --git a/chromium/chrome/browser/resources/settings/date_time_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/date_time_page/BUILD.gn
index 60ec09b4790..7cbb19ab5e7 100644
--- a/chromium/chrome/browser/resources/settings/date_time_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/date_time_page/BUILD.gn
@@ -18,8 +18,9 @@ js_library("date_time_page") {
":date_time_types",
":timezone_selector",
":timezone_subpage",
- "..:route",
- "../prefs:prefs_behavior",
+ "..:os_route",
+ "../..:router",
+ "../../prefs:prefs_behavior",
"//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:i18n_behavior",
@@ -29,16 +30,14 @@ js_library("date_time_page") {
}
js_library("date_time_types") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("timezone_selector") {
deps = [
":date_time_types",
- "../controls:settings_dropdown_menu",
- "../prefs:prefs_behavior",
+ "../../controls:settings_dropdown_menu",
+ "../../prefs:prefs_behavior",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:i18n_behavior",
]
@@ -48,7 +47,7 @@ js_library("timezone_subpage") {
deps = [
":date_time_types",
":timezone_selector",
- "../prefs:prefs_behavior",
+ "../../prefs:prefs_behavior",
"//ui/webui/resources/js:cr",
]
}
diff --git a/chromium/chrome/browser/resources/settings/device_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/device_page/BUILD.gn
index c8f980233e4..94869ce7620 100644
--- a/chromium/chrome/browser/resources/settings/device_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/device_page/BUILD.gn
@@ -25,31 +25,32 @@ js_type_check("closure_compile") {
js_library("device_page") {
deps = [
":device_page_browser_proxy",
- "..:route",
+ "..:os_route",
+ "../..:router",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
js_library("device_page_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("pointers") {
deps = [
":device_page_browser_proxy",
- "../controls:settings_toggle_button",
+ "../../controls:settings_toggle_button",
+ "../localized_link:localized_link",
]
}
js_library("keyboard") {
deps = [
":device_page_browser_proxy",
- "..:route",
- "../controls:settings_dropdown_menu",
- "../prefs:prefs_types",
+ "..:os_route",
+ "../..:router",
+ "../../controls:settings_dropdown_menu",
+ "../../prefs:prefs_types",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:load_time_data",
@@ -60,7 +61,8 @@ js_library("keyboard") {
js_library("stylus") {
deps = [
":device_page_browser_proxy",
- "../prefs:prefs_types",
+ "..:metrics_recorder",
+ "../../prefs:prefs_types",
"//ui/webui/resources/cr_elements/policy:cr_policy_indicator",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:load_time_data",
@@ -70,9 +72,9 @@ js_library("stylus") {
js_library("display") {
deps = [
":display_layout",
- "../controls:settings_dropdown_menu",
- "../controls:settings_slider",
- "../prefs:prefs_behavior",
+ "../../controls:settings_dropdown_menu",
+ "../../controls:settings_slider",
+ "../../prefs:prefs_behavior",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:i18n_behavior",
@@ -106,22 +108,18 @@ js_library("display_overscan_dialog") {
}
js_library("drag_behavior") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("layout_behavior") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [ "$externs_path/system_display.js" ]
extra_sources = [ "$interfaces_path/system_display_interface.js" ]
}
js_library("night_light_slider") {
deps = [
- "../prefs:prefs_behavior",
+ "../../prefs:prefs_behavior",
"//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted",
"//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted",
]
@@ -130,8 +128,9 @@ js_library("night_light_slider") {
js_library("power") {
deps = [
":device_page_browser_proxy",
- "..:route",
- "../prefs:prefs_types",
+ "..:metrics_recorder",
+ "../..:router",
+ "../../prefs:prefs_types",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
@@ -140,8 +139,10 @@ js_library("power") {
js_library("storage") {
deps = [
- "..:route",
+ "..:os_route",
"..:route_origin_behavior",
+ "../..:router",
+ "../localized_link:localized_link",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:web_ui_listener_behavior",
diff --git a/chromium/chrome/browser/resources/settings/google_assistant_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/google_assistant_page/BUILD.gn
index b75831dd07b..0c330bb0e5e 100644
--- a/chromium/chrome/browser/resources/settings/google_assistant_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/google_assistant_page/BUILD.gn
@@ -12,17 +12,18 @@ js_type_check("closure_compile") {
}
js_library("google_assistant_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [ "$externs_path/chrome_send.js" ]
}
js_library("google_assistant_page") {
deps = [
":google_assistant_browser_proxy",
- "../prefs:prefs_behavior",
+ "..:metrics_recorder",
+ "../../prefs:prefs_behavior",
"//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
]
}
diff --git a/chromium/chrome/browser/resources/settings/internet_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
index 6eca7442c66..e5182752260 100644
--- a/chromium/chrome/browser/resources/settings/internet_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
@@ -23,8 +23,10 @@ js_library("internet_page") {
deps = [
":internet_config",
":internet_page_browser_proxy",
- "..:route",
- "../settings_page:settings_animated_pages",
+ "..:metrics_recorder",
+ "..:os_route",
+ "../..:router",
+ "../../settings_page:settings_animated_pages",
"//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile",
"//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider",
"//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
@@ -41,14 +43,13 @@ js_library("internet_page") {
}
js_library("internet_page_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("internet_config") {
deps = [
- "..:route",
+ "..:metrics_recorder",
+ "../..:router",
"//ui/webui/resources/cr_components/chromeos/network:network_config",
"//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
"//ui/webui/resources/js:assert",
@@ -63,7 +64,9 @@ js_library("internet_detail_page") {
deps = [
":internet_page_browser_proxy",
":tether_connection_dialog",
- "..:route",
+ "..:metrics_recorder",
+ "..:os_route",
+ "../..:router",
"//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
"//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo",
"//ui/webui/resources/js:assert",
@@ -78,6 +81,7 @@ js_library("internet_detail_page") {
js_library("internet_known_networks_page") {
deps = [
+ "..:metrics_recorder",
"//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo",
@@ -90,8 +94,11 @@ js_library("internet_known_networks_page") {
js_library("internet_subpage") {
deps = [
":internet_page_browser_proxy",
- "..:route",
+ "..:metrics_recorder",
+ "..:os_route",
"..:route_origin_behavior",
+ "../..:router",
+ "../localized_link:localized_link",
"//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
"//ui/webui/resources/cr_components/chromeos/network:onc_mojo",
"//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo",
@@ -104,9 +111,10 @@ js_library("internet_subpage") {
js_library("network_proxy_section") {
deps = [
- "..:route",
- "../controls:settings_checkbox",
- "../prefs:prefs_behavior",
+ "..:os_route",
+ "../..:router",
+ "../../controls:settings_toggle_button",
+ "../../prefs:prefs_behavior",
"//ui/webui/resources/cr_components/chromeos/network:network_proxy",
"//ui/webui/resources/cr_components/chromeos/network:onc_mojo",
"//ui/webui/resources/cr_elements/policy:cr_policy_network_behavior_mojo",
diff --git a/chromium/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn
new file mode 100644
index 00000000000..c480094420a
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/chromeos/localized_link/BUILD.gn
@@ -0,0 +1,13 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+ deps = [ ":localized_link" ]
+}
+
+js_library("localized_link") {
+ deps = [ "//ui/webui/resources/js:assert" ]
+}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
new file mode 100644
index 00000000000..9906b2220f9
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
@@ -0,0 +1,115 @@
+# Copyright 2018 The Chromium 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/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+ deps = [
+ ":multidevice_feature_behavior",
+ ":multidevice_feature_item",
+ ":multidevice_feature_toggle",
+ ":multidevice_page",
+ ":multidevice_smartlock_subpage",
+ ":multidevice_subpage",
+ ":multidevice_tether_item",
+ ]
+}
+
+js_library("multidevice_browser_proxy") {
+ deps = [
+ ":multidevice_constants",
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
+js_library("multidevice_constants") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_library("multidevice_feature_behavior") {
+ deps = [
+ ":multidevice_constants",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+}
+
+js_library("multidevice_feature_item") {
+ deps = [
+ ":multidevice_constants",
+ ":multidevice_feature_behavior",
+ "..:os_route",
+ "..:route_origin_behavior",
+ "../..:router",
+ "../localized_link:localized_link",
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
+js_library("multidevice_feature_toggle") {
+ deps = [
+ ":multidevice_constants",
+ ":multidevice_feature_behavior",
+ ]
+}
+
+js_library("multidevice_page") {
+ deps = [
+ ":multidevice_browser_proxy",
+ ":multidevice_constants",
+ ":multidevice_feature_behavior",
+ "..:metrics_recorder",
+ "..:os_route",
+ "../..:router",
+ "../../controls:password_prompt_dialog",
+ "../localized_link:localized_link",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("multidevice_radio_button") {
+ deps = [
+ "//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted",
+ "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button_behavior",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_indicator",
+ ]
+}
+
+js_library("multidevice_smartlock_subpage") {
+ deps = [
+ ":multidevice_constants",
+ ":multidevice_feature_behavior",
+ "..:metrics_recorder",
+ "..:os_route",
+ "..:os_settings_routes",
+ "../../prefs:prefs_behavior",
+ "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button",
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
+js_library("multidevice_subpage") {
+ deps = [
+ ":multidevice_constants",
+ "..:os_route",
+ "..:os_settings_routes",
+ "../..:settings_routes",
+ "//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
+ ]
+ externs_list = [ "$externs_path/networking_private.js" ]
+ extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
+}
+
+js_library("multidevice_tether_item") {
+ deps = [
+ ":multidevice_feature_behavior",
+ "..:os_route",
+ "..:os_settings_routes",
+ "//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
+ "//ui/webui/resources/cr_components/chromeos/network:onc_mojo",
+ ]
+ externs_list = [ "$externs_path/networking_private.js" ]
+ extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
+}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_a11y_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_a11y_page/BUILD.gn
index 75b6aea70fc..c34b0f10c6e 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_a11y_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_a11y_page/BUILD.gn
@@ -6,21 +6,61 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
deps = [
+ ":externs",
+ ":manage_a11y_page",
":os_a11y_page",
+ ":switch_access_subpage",
+ ":tts_subpage",
"../../a11y_page:captions_subpage",
- "../../a11y_page:externs",
- "../../a11y_page:manage_a11y_page",
- "../../a11y_page:switch_access_subpage",
- "../../a11y_page:tts_subpage",
"../../appearance_page:fonts_browser_proxy",
]
}
js_library("os_a11y_page") {
deps = [
- "../../:route",
+ "..:os_route",
+ "../../:router",
"../../settings_page:settings_animated_pages",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
+
+js_library("manage_a11y_page") {
+ deps = [
+ "..:os_route",
+ "..:route_origin_behavior",
+ "../..:router",
+ "../device_page:device_page_browser_proxy",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+}
+
+js_library("switch_access_subpage") {
+ deps = [
+ "../..:router",
+ "../../prefs:prefs_behavior",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+}
+
+js_library("tts_subpage") {
+ deps = [
+ ":externs",
+ "../..:router",
+ "../../controls:settings_slider",
+ "../../languages_page:languages_browser_proxy",
+ "../../settings_page:settings_animated_pages",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("externs") {
+}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_about_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_about_page/BUILD.gn
index 2a904712142..c49063b1f47 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_about_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_about_page/BUILD.gn
@@ -6,20 +6,43 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
deps = [
+ ":channel_switcher_dialog",
+ ":detailed_build_info",
":os_about_page",
]
}
js_library("os_about_page") {
deps = [
+ "..:metrics_recorder",
+ "..:os_route",
"../..:lifetime_browser_proxy",
- "../..:route",
+ "../..:router",
"../../about_page:about_page_browser_proxy",
"../../settings_page:main_page_behavior",
"../../settings_page:settings_animated_pages",
+ "../localized_link:localized_link",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:parse_html_subset",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
+
+js_library("detailed_build_info") {
+ deps = [
+ "../../about_page:about_page_browser_proxy",
+ "../localized_link:localized_link",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ]
+}
+
+js_library("channel_switcher_dialog") {
+ deps = [
+ "../../about_page:about_page_browser_proxy",
+ "//ui/webui/resources/js:load_time_data",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn
index 664cc90da69..0a79aec884e 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/BUILD.gn
@@ -6,17 +6,37 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
deps = [
+ ":android_apps_browser_proxy",
+ ":android_apps_subpage",
":os_apps_page",
]
}
+js_library("android_apps_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_library("android_apps_subpage") {
+ deps = [
+ ":android_apps_browser_proxy",
+ "..:os_route",
+ "../..:router",
+ "../../prefs:prefs_behavior",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ]
+}
+
js_library("os_apps_page") {
deps = [
- "../../:route",
- "../../android_apps_page:android_apps_browser_proxy",
- "../../android_apps_page:android_apps_subpage",
+ ":android_apps_browser_proxy",
+ ":android_apps_subpage",
+ "..:os_route",
+ "../../:router",
"../../prefs:prefs_behavior",
"../../settings_page:settings_animated_pages",
+ "../localized_link:localized_link",
"app_management_page",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:i18n_behavior",
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn
index 0cfdcea2a1b..8c4309e620a 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/BUILD.gn
@@ -72,7 +72,8 @@ js_library("app_detail_view") {
":dom_switch",
":pwa_detail_view",
":store_client",
- "../../..:route",
+ "../..:os_route",
+ "../../..:router",
]
}
@@ -134,6 +135,7 @@ js_library("permission_item") {
":store_client",
":toggle_row",
":util",
+ "../..:metrics_recorder",
]
}
@@ -142,6 +144,7 @@ js_library("pin_to_shelf_item") {
":browser_proxy",
":toggle_row",
":types",
+ "../..:metrics_recorder",
]
}
@@ -191,15 +194,14 @@ js_library("toggle_row") {
}
js_library("types") {
- deps = [
- "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile",
- ]
+ deps = [ "//chrome/browser/ui/webui/app_management:mojo_bindings_js_library_for_compile" ]
}
js_library("uninstall_button") {
deps = [
":store_client",
":util",
+ "../..:metrics_recorder",
"//ui/webui/resources/cr_elements/cr_button:cr_button",
"//ui/webui/resources/cr_elements/policy:cr_tooltip_icon",
"//ui/webui/resources/js:i18n_behavior",
@@ -210,6 +212,8 @@ js_library("util") {
deps = [
":constants",
":types",
+ "../..:os_route",
+ "../../..:router",
"//ui/webui/resources/js:cr",
]
}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_files_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_files_page/BUILD.gn
index 38ac772a9b0..f5dbaca98bd 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_files_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_files_page/BUILD.gn
@@ -13,13 +13,16 @@ js_type_check("closure_compile") {
js_library("smb_shares_page") {
deps = [
- "../..:route",
+ "..:os_route",
+ "../..:router",
+ "../localized_link:localized_link",
"//ui/webui/resources/cr_components/chromeos/smb_shares:smb_browser_proxy",
]
}
js_library("os_files_page") {
deps = [
- "../..:route",
+ "..:os_route",
+ "../..:router",
]
}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
index 38b28886429..2fc4836f26f 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
@@ -6,23 +6,32 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
deps = [
+ ":manage_input_methods_page",
":os_add_languages_dialog",
":os_languages_page",
":os_languages_section",
"../../languages_page:languages",
"../../languages_page:languages_browser_proxy",
"../../languages_page:languages_types",
- "../../languages_page:manage_input_methods_page",
]
}
+js_library("manage_input_methods_page") {
+ deps = [
+ "../../languages_page:languages_types",
+ "../../prefs",
+ ]
+ externs_list = [ "$externs_path/language_settings_private.js" ]
+}
+
js_library("os_languages_section") {
deps = [
+ ":manage_input_methods_page",
":os_languages_page",
- "../..:route",
+ "..:os_route",
+ "../..:router",
"../../languages_page:languages",
"../../languages_page:languages_types",
- "../../languages_page:manage_input_methods_page",
"../../settings_page:settings_animated_pages",
"../../settings_page:settings_subpage",
"//ui/webui/resources/js:assert",
@@ -34,10 +43,13 @@ js_library("os_languages_section") {
js_library("os_languages_page") {
deps = [
+ "..:metrics_recorder",
+ "..:os_route",
"../..:lifetime_browser_proxy",
- "../..:route",
+ "../..:router",
"../../languages_page:languages_types",
"../../settings_page:settings_animated_pages",
+ "../localized_link:localized_link",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/cr_elements/cr_expand_button:cr_expand_button",
"//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render",
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
index 11d0c4e3bea..2b0c1a7178d 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
@@ -6,43 +6,139 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
deps = [
+ ":account_manager",
+ ":fingerprint_browser_proxy",
+ ":fingerprint_list",
+ ":kerberos_accounts",
+ ":kerberos_accounts_browser_proxy",
+ ":lock_screen",
+ ":lock_screen_password_prompt_dialog",
+ ":lock_state_behavior",
":os_people_page",
- "//chrome/browser/resources/settings/people_page:account_manager",
+ ":setup_fingerprint_dialog",
+ ":setup_pin_dialog",
+ ":user_list",
+ ":users_add_user_dialog",
+ ":users_page",
"//chrome/browser/resources/settings/people_page:account_manager_browser_proxy",
- "//chrome/browser/resources/settings/people_page:change_picture",
- "//chrome/browser/resources/settings/people_page:change_picture_browser_proxy",
- "//chrome/browser/resources/settings/people_page:fingerprint_browser_proxy",
- "//chrome/browser/resources/settings/people_page:fingerprint_list",
- "//chrome/browser/resources/settings/people_page:kerberos_accounts",
- "//chrome/browser/resources/settings/people_page:kerberos_accounts_browser_proxy",
- "//chrome/browser/resources/settings/people_page:lock_screen",
- "//chrome/browser/resources/settings/people_page:lock_screen_password_prompt_dialog",
- "//chrome/browser/resources/settings/people_page:lock_state_behavior",
"//chrome/browser/resources/settings/people_page:profile_info_browser_proxy",
- "//chrome/browser/resources/settings/people_page:setup_fingerprint_dialog",
- "//chrome/browser/resources/settings/people_page:setup_pin_dialog",
"//chrome/browser/resources/settings/people_page:signout_dialog",
"//chrome/browser/resources/settings/people_page:sync_browser_proxy",
"//chrome/browser/resources/settings/people_page:sync_page",
- "//chrome/browser/resources/settings/people_page:user_list",
- "//chrome/browser/resources/settings/people_page:users_add_user_dialog",
- "//chrome/browser/resources/settings/people_page:users_page",
]
}
+js_library("account_manager") {
+ deps = [
+ "../../people_page:account_manager_browser_proxy",
+ "../localized_link:localized_link",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:icon",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("fingerprint_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_library("fingerprint_list") {
+ deps = [
+ ":fingerprint_browser_proxy",
+ "..:metrics_recorder",
+ "..:os_route",
+ "../..:router",
+ "//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted",
+ "//third_party/polymer/v1_0/components-chromium/paper-ripple:paper-ripple-extracted",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ]
+}
+
+js_library("kerberos_accounts") {
+ deps = [
+ ":kerberos_accounts_browser_proxy",
+ "..:metrics_recorder",
+ "../..:router",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:icon",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("kerberos_accounts_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_library("kerberos_add_account_dialog") {
+ deps = [
+ ":kerberos_accounts_browser_proxy",
+ "..:metrics_recorder",
+ "//chrome/browser/resources/settings/controls:settings_textarea",
+ "//ui/webui/resources/cr_elements/cr_input:cr_input",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("lock_screen") {
+ deps = [
+ ":fingerprint_browser_proxy",
+ ":lock_screen_password_prompt_dialog",
+ ":lock_state_behavior",
+ "..:os_route",
+ "../..:router",
+ "../../controls:settings_dropdown_menu",
+ "../../controls:settings_toggle_button",
+ "//ui/webui/resources/cr_components/chromeos/quick_unlock:lock_screen_constants",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ]
+}
+
+js_library("lock_screen_password_prompt_dialog") {
+ deps = [
+ ":lock_state_behavior",
+ "../../controls:password_prompt_dialog",
+ "//ui/webui/resources/cr_components/chromeos/quick_unlock:lock_screen_constants",
+ ]
+}
+
+js_library("lock_state_behavior") {
+ deps = [
+ "../..:router",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+ externs_list = [ "$externs_path/quick_unlock_private.js" ]
+ extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ]
+}
+
js_library("os_people_page") {
deps = [
+ ":lock_screen",
+ ":lock_state_behavior",
":os_sync_controls",
- "../../:page_visibility",
- "../../:route",
+ "..:os_page_visibility",
+ "..:os_route",
+ "../..:router",
"../../settings_page:settings_animated_pages",
- "//chrome/browser/resources/settings/people_page:lock_screen",
- "//chrome/browser/resources/settings/people_page:lock_state_behavior",
+ "../localized_link:localized_link",
"//chrome/browser/resources/settings/people_page:profile_info_browser_proxy",
"//chrome/browser/resources/settings/people_page:signout_dialog",
"//chrome/browser/resources/settings/people_page:sync_browser_proxy",
"//ui/webui/resources/cr_components/chromeos/quick_unlock:lock_screen_constants",
- "//ui/webui/resources/cr_elements/chromeos/cr_picture:cr_png_behavior",
+ "//ui/webui/resources/cr_elements/chromeos/cr_picture:png",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:icon",
@@ -52,19 +148,68 @@ js_library("os_people_page") {
]
}
+js_library("os_sync_browser_proxy") {
+ deps = [
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:load_time_data",
+ ]
+}
+
js_library("os_sync_controls") {
deps = [
":os_sync_browser_proxy",
- "../../:route",
+ "..:metrics_recorder",
+ "../../:router",
+ "../localized_link",
"//ui/webui/resources/cr_elements/cr_toggle:cr_toggle",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
-js_library("os_sync_browser_proxy") {
+js_library("setup_fingerprint_dialog") {
deps = [
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:load_time_data",
+ ":fingerprint_browser_proxy",
+ "..:metrics_recorder",
+ "//ui/webui/resources/cr_elements/chromeos/cr_lottie:cr_lottie",
+ "//ui/webui/resources/cr_elements/cr_fingerprint:cr_fingerprint_progress_arc",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("setup_pin_dialog") {
+ deps = [
+ ":lock_screen_password_prompt_dialog",
+ "../..:router",
+ "//ui/webui/resources/cr_components/chromeos/quick_unlock:setup_pin_keyboard",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+}
+
+js_library("user_list") {
+ deps = [
+ "..:os_route",
+ "../..:router",
+ "//ui/webui/resources/cr_elements:cr_scrollable_behavior",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+ externs_list = [
+ "$externs_path/settings_private.js",
+ "$externs_path/users_private.js",
+ ]
+}
+
+js_library("users_add_user_dialog") {
+ deps = [ "//ui/webui/resources/js:assert" ]
+ externs_list = [ "$externs_path/users_private.js" ]
+}
+
+js_library("users_page") {
+ deps = [
+ ":user_list",
+ ":users_add_user_dialog",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
]
}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_printing_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_printing_page/BUILD.gn
index eecae87d275..04f4ad8d05e 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_printing_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_printing_page/BUILD.gn
@@ -6,20 +6,125 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
deps = [
+ ":cups_add_printer_dialog",
+ ":cups_add_printer_dialog_elements",
+ ":cups_edit_printer_dialog",
+ ":cups_printer_dialog_util",
+ ":cups_printers",
+ ":cups_printers_browser_proxy",
":os_printing_page",
- "../../printing_page:cups_add_printer_dialog",
- "../../printing_page:cups_add_printer_dialog_elements",
- "../../printing_page:cups_edit_printer_dialog",
- "../../printing_page:cups_printer_dialog_util",
- "../../printing_page:cups_printers",
- "../../printing_page:cups_printers_browser_proxy",
- "../../printing_page:cups_printers_list",
+ ]
+}
+
+js_library("cups_add_printer_dialog") {
+ deps = [
+ ":cups_printers_browser_proxy",
+ "../localized_link:localized_link",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("cups_add_printer_dialog_elements") {
+ deps = [ ":cups_printers_browser_proxy" ]
+}
+
+js_library("cups_edit_printer_dialog") {
+ deps = [
+ "..:metrics_recorder",
+ "../localized_link:localized_link",
+ "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider",
+ "//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
+ "//ui/webui/resources/cr_components/chromeos/network:onc_mojo",
+ ]
+}
+
+js_library("cups_nearby_printers") {
+ deps = [
+ ":cups_printer_types",
+ ":cups_printers_browser_proxy",
+ ":cups_printers_entry",
+ ":cups_printers_entry_list_behavior",
+ ":cups_printers_entry_manager",
+ "..:metrics_recorder",
+ "//ui/webui/resources/js:list_property_update_behavior",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("cups_printer_dialog_util") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_library("cups_printer_types") {
+ deps = [ ":cups_printers_browser_proxy" ]
+}
+
+js_library("cups_printers") {
+ deps = [
+ ":cups_nearby_printers",
+ ":cups_printers_browser_proxy",
+ ":cups_printers_entry_manager",
+ ":cups_saved_printers",
+ "..:os_route",
+ "../..:router",
+ "../localized_link:localized_link",
+ "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider",
+ "//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
+ "//ui/webui/resources/cr_components/chromeos/network:onc_mojo",
+ "//ui/webui/resources/cr_elements/cr_toast:cr_toast",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ]
+}
+
+js_library("cups_printers_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_library("cups_printers_entry") {
+ deps = [
+ ":cups_printer_types",
+ ":cups_printers_browser_proxy",
+ ]
+}
+
+js_library("cups_printers_entry_list_behavior") {
+ deps = [
+ ":cups_printer_types",
+ "//ui/webui/resources/js:list_property_update_behavior",
+ ]
+}
+
+js_library("cups_printers_entry_manager") {
+ deps = [
+ ":cups_printer_types",
+ ":cups_printers_browser_proxy",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
+js_library("cups_saved_printers") {
+ deps = [
+ ":cups_printer_types",
+ ":cups_printers_browser_proxy",
+ ":cups_printers_entry",
+ ":cups_printers_entry_list_behavior",
+ ":cups_printers_entry_manager",
+ "..:metrics_recorder",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
+ "//ui/webui/resources/js:list_property_update_behavior",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
]
}
js_library("os_printing_page") {
deps = [
- "../..:route",
+ "..:os_route",
+ "../..:router",
"../../settings_page:settings_animated_pages",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:load_time_data",
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn
index c4ae127beaa..84cb81f6e22 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_privacy_page/BUILD.gn
@@ -5,13 +5,10 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":os_privacy_page",
- ]
+ deps = [ ":os_privacy_page" ]
}
js_library("os_privacy_page") {
- deps = [
- "//chrome/browser/resources/settings/controls:settings_toggle_button",
- ]
+ deps =
+ [ "//chrome/browser/resources/settings/controls:settings_toggle_button" ]
}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn
index 42ff0d047c9..b9af9f2bccf 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_reset_page/BUILD.gn
@@ -15,7 +15,9 @@ js_type_check("closure_compile") {
js_library("os_powerwash_dialog") {
deps = [
":os_reset_browser_proxy",
+ "..:metrics_recorder",
"../..:lifetime_browser_proxy",
+ "../localized_link:localized_link",
]
}
@@ -28,8 +30,6 @@ js_library("os_reset_page") {
}
js_library("os_reset_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [ "$externs_path/chrome_send.js" ]
}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_search_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_search_page/BUILD.gn
index 53fc8b565b8..03206cb5851 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_search_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_search_page/BUILD.gn
@@ -5,14 +5,13 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":os_search_page",
- ]
+ deps = [ ":os_search_page" ]
}
js_library("os_search_page") {
deps = [
- "../..:route",
+ "..:os_route",
+ "../..:router",
"../../prefs",
"../../search_engines_page:search_engines_browser_proxy",
"../../settings_page:settings_animated_pages",
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn
index 7323018a408..de7de58cf2a 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_settings_main/BUILD.gn
@@ -5,15 +5,13 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":os_settings_main",
- ]
+ deps = [ ":os_settings_main" ]
}
js_library("os_settings_main") {
deps = [
- "../..:page_visibility",
- "../..:route",
+ "..:os_page_visibility",
+ "../..:router",
"../..:search_settings",
"../../settings_page:main_page_behavior",
"../os_settings_page:os_settings_page",
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_settings_menu/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_settings_menu/BUILD.gn
index 3c3c14e9d3d..f440c89ec61 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_settings_menu/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_settings_menu/BUILD.gn
@@ -5,15 +5,14 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":os_settings_menu",
- ]
+ deps = [ ":os_settings_menu" ]
}
js_library("os_settings_menu") {
deps = [
- "../..:route",
+ "../..:router",
"//third_party/polymer/v1_0/components-chromium/iron-collapse:iron-collapse-extracted",
"//third_party/polymer/v1_0/components-chromium/paper-ripple:paper-ripple-extracted",
+ "//ui/webui/resources/js:load_time_data",
]
}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn
index 11525a13645..3588ee98f95 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_settings_page/BUILD.gn
@@ -5,20 +5,18 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":os_settings_page",
- ]
+ deps = [ ":os_settings_page" ]
}
js_library("os_settings_page") {
deps = [
- "../..:page_visibility",
- "../..:route",
+ "..:os_page_visibility",
+ "..:os_route",
+ "../..:router",
"../..:search_settings",
- "../../android_apps_page:android_apps_browser_proxy",
- "../../chrome_cleanup_page:chrome_cleanup_proxy",
"../../prefs:prefs_behavior",
"../../settings_page:main_page_behavior",
+ "../os_apps_page:android_apps_browser_proxy",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_settings_search_box/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_settings_search_box/BUILD.gn
new file mode 100644
index 00000000000..91cddc459c6
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_settings_search_box/BUILD.gn
@@ -0,0 +1,32 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+ deps = [
+ ":os_search_result_row",
+ ":os_settings_search_box",
+ ]
+}
+
+js_library("os_settings_search_box") {
+ deps = [
+ ":os_search_result_row",
+ "..:metrics_recorder",
+ "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings_js_library_for_compile",
+ "//third_party/polymer/v1_0/components-chromium/iron-dropdown:iron-dropdown-extracted",
+ "//third_party/polymer/v1_0/components-chromium/iron-list:iron-list-extracted",
+ "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar_search_field",
+ "//ui/webui/resources/js:assert",
+ ]
+}
+
+js_library("os_search_result_row") {
+ deps = [
+ "..:os_route",
+ "../..:router",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_settings_ui/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_settings_ui/BUILD.gn
index d0e60076dee..ffdf1bb4d37 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_settings_ui/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_settings_ui/BUILD.gn
@@ -5,15 +5,16 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":os_settings_ui",
- ]
+ deps = [ ":os_settings_ui" ]
}
js_library("os_settings_ui") {
deps = [
+ "..:metrics_recorder",
+ "..:os_page_visibility",
+ "..:os_route",
"../..:global_scroll_target_behavior",
- "../..:page_visibility",
+ "../..:router",
"../../prefs",
"../os_settings_main:os_settings_main",
"../os_toolbar",
diff --git a/chromium/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn
index 4b50354595c..eb6484e5902 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/os_toolbar/BUILD.gn
@@ -5,13 +5,12 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":os_toolbar",
- ]
+ deps = [ ":os_toolbar" ]
}
js_library("os_toolbar") {
deps = [
+ "../os_settings_search_box",
"//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar_search_field",
]
}
diff --git a/chromium/chrome/browser/resources/settings/parental_controls_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/parental_controls_page/BUILD.gn
index bf02be96291..1f0323fbd66 100644
--- a/chromium/chrome/browser/resources/settings/parental_controls_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/parental_controls_page/BUILD.gn
@@ -5,21 +5,17 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":parental_controls_page",
- ]
+ deps = [ ":parental_controls_page" ]
}
js_library("parental_controls_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("parental_controls_page") {
deps = [
":parental_controls_browser_proxy",
- "..:route",
+ "../..:router",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
diff --git a/chromium/chrome/browser/resources/settings/chromeos/personalization_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/personalization_page/BUILD.gn
index ca1cedfb81c..5b6f3667c12 100644
--- a/chromium/chrome/browser/resources/settings/chromeos/personalization_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/personalization_page/BUILD.gn
@@ -6,14 +6,46 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
deps = [
+ ":change_picture",
+ ":change_picture_browser_proxy",
":personalization_page",
]
}
+js_library("change_picture") {
+ deps = [
+ ":change_picture_browser_proxy",
+ "..:metrics_recorder",
+ "..:os_route",
+ "//third_party/polymer/v1_0/components-chromium/iron-selector:iron-selector-extracted",
+ "//ui/webui/resources/cr_elements/chromeos/cr_picture:cr_picture_list",
+ "//ui/webui/resources/cr_elements/chromeos/cr_picture:cr_picture_pane",
+ "//ui/webui/resources/cr_elements/chromeos/cr_picture:cr_picture_types",
+ "//ui/webui/resources/cr_elements/chromeos/cr_picture:png",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:util",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("change_picture_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
js_library("personalization_page") {
deps = [
- "../../appearance_page:wallpaper_browser_proxy",
+ ":wallpaper_browser_proxy",
+ "..:os_route",
+ "../..:router",
+ "../../prefs",
"../../settings_page:settings_animated_pages",
+ "../ambient_mode_page:ambient_mode_browser_proxy",
"//ui/webui/resources/js:cr",
]
}
+
+js_library("wallpaper_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+}
diff --git a/chromium/chrome/browser/resources/settings/plugin_vm_page/BUILD.gn b/chromium/chrome/browser/resources/settings/chromeos/plugin_vm_page/BUILD.gn
index 4f0b8f1bade..aab887277ef 100644
--- a/chromium/chrome/browser/resources/settings/plugin_vm_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/chromeos/plugin_vm_page/BUILD.gn
@@ -8,20 +8,22 @@ js_type_check("closure_compile") {
deps = [
":plugin_vm_browser_proxy",
":plugin_vm_page",
+ ":plugin_vm_remove_confirmation_dialog",
":plugin_vm_shared_paths",
":plugin_vm_subpage",
+ "..:metrics_recorder",
]
}
js_library("plugin_vm_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("plugin_vm_page") {
deps = [
- "..:route",
+ "..:os_route",
+ "../..:router",
+ "../../prefs:prefs_behavior",
"//ui/webui/resources/js:i18n_behavior",
]
externs_list = [ "$externs_path/settings_private.js" ]
@@ -30,12 +32,18 @@ js_library("plugin_vm_page") {
js_library("plugin_vm_shared_paths") {
deps = [
":plugin_vm_browser_proxy",
- "..:route",
+ "../..:router",
]
}
js_library("plugin_vm_subpage") {
deps = [
- "..:route",
+ "..:os_route",
+ "../..:router",
+ "../../prefs:prefs_behavior",
]
}
+
+js_library("plugin_vm_remove_confirmation_dialog") {
+ deps = [ ":plugin_vm_browser_proxy" ]
+}
diff --git a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
index 272d36e080d..c296d8d5edd 100644
--- a/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/clear_browsing_data_dialog/BUILD.gn
@@ -3,11 +3,15 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
":clear_browsing_data_browser_proxy",
":clear_browsing_data_dialog",
+ ":installed_app_checkbox",
]
}
@@ -21,7 +25,10 @@ js_library("clear_browsing_data_browser_proxy") {
js_library("clear_browsing_data_dialog") {
deps = [
":clear_browsing_data_browser_proxy",
- "../device_page:keyboard",
+ "..:route",
+ "..:router",
+ "../controls:settings_checkbox",
+ "../controls:settings_dropdown_menu",
"../people_page:sync_browser_proxy",
"//third_party/polymer/v1_0/components-chromium/iron-pages:iron-pages-extracted",
"//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted",
@@ -30,3 +37,101 @@ js_library("clear_browsing_data_dialog") {
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
+
+js_library("installed_app_checkbox") {
+ deps = [
+ ":clear_browsing_data_browser_proxy",
+ "../controls:settings_boolean_control_behavior",
+ ]
+}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":clear_browsing_data_browser_proxy.m",
+ ":clear_browsing_data_dialog.m",
+ ":history_deletion_dialog.m",
+ ":installed_app_checkbox.m",
+ ]
+}
+
+js_library("clear_browsing_data_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("clear_browsing_data_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.m.js" ]
+ deps = [
+ ":clear_browsing_data_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "../controls:settings_checkbox.m",
+ "../controls:settings_dropdown_menu.m",
+ "../people_page:sync_browser_proxy.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":clear_browsing_data_dialog_module" ]
+}
+
+js_library("history_deletion_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ ]
+ extra_deps = [ ":history_deletion_dialog_module" ]
+}
+
+js_library("installed_app_checkbox.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.m.js" ]
+ deps = [
+ ":clear_browsing_data_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":installed_app_checkbox_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":clear_browsing_data_dialog_module",
+ ":history_deletion_dialog_module",
+ ":installed_app_checkbox_module",
+ ":modulize",
+ ]
+}
+
+polymer_modulizer("clear_browsing_data_dialog") {
+ js_file = "clear_browsing_data_dialog.js"
+ html_file = "clear_browsing_data_dialog.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route, Router, RouteObserverBehavior",
+ "chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html|ClearBrowsingDataBrowserProxy, ClearBrowsingDataBrowserProxyImpl, InstalledApp",
+ "chrome/browser/resources/settings/controls/settings_dropdown_menu.html|DropdownMenuOptionList",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|StatusAction, SyncBrowserProxy, SyncBrowserProxyImpl, SyncStatus",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("history_deletion_dialog") {
+ js_file = "history_deletion_dialog.js"
+ html_file = "history_deletion_dialog.html"
+ html_type = "dom-module"
+}
+
+polymer_modulizer("installed_app_checkbox") {
+ js_file = "installed_app_checkbox.js"
+ html_file = "installed_app_checkbox.html"
+ html_type = "dom-module"
+ auto_imports = [ "chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html|InstalledApp" ]
+}
+
+js_modulizer("modulize") {
+ input_files = [ "clear_browsing_data_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/controls/BUILD.gn b/chromium/chrome/browser/resources/settings/controls/BUILD.gn
index 7baf0b551a4..d8677c75898 100644
--- a/chromium/chrome/browser/resources/settings/controls/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/controls/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -14,6 +17,7 @@ js_type_check("closure_compile") {
":settings_boolean_control_behavior",
":settings_checkbox",
":settings_dropdown_menu",
+ ":settings_idle_load",
":settings_radio_group",
":settings_slider",
":settings_textarea",
@@ -50,7 +54,7 @@ js_library("extension_controlled_indicator") {
js_library("password_prompt_dialog") {
deps = [
- "..:route",
+ "..:router",
"//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
"//ui/webui/resources/cr_elements/cr_input:cr_input",
]
@@ -59,9 +63,7 @@ js_library("password_prompt_dialog") {
}
js_library("pref_control_behavior") {
- deps = [
- "../prefs:prefs_types",
- ]
+ deps = [ "../prefs:prefs_types" ]
}
js_library("settings_boolean_control_behavior") {
@@ -74,9 +76,7 @@ js_library("settings_boolean_control_behavior") {
}
js_library("settings_checkbox") {
- deps = [
- ":settings_boolean_control_behavior",
- ]
+ deps = [ ":settings_boolean_control_behavior" ]
}
js_library("settings_dropdown_menu") {
@@ -92,6 +92,11 @@ js_library("settings_dropdown_menu") {
externs_list = [ "$externs_path/settings_private.js" ]
}
+js_library("settings_idle_load") {
+ deps = [ "//ui/webui/resources/js:assert" ]
+ externs_list = [ "$externs_path/pending_polymer.js" ]
+}
+
js_library("settings_radio_group") {
deps = [
":pref_control_behavior",
@@ -119,3 +124,287 @@ js_library("settings_toggle_button") {
"//ui/webui/resources/cr_elements/cr_toggle:cr_toggle",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":controlled_button.m",
+ ":controlled_radio_button.m",
+ ":extension_controlled_indicator.m",
+ ":password_prompt_dialog.m",
+ ":pref_control_behavior.m",
+ ":settings_boolean_control_behavior.m",
+ ":settings_checkbox.m",
+ ":settings_dropdown_menu.m",
+ ":settings_idle_load.m",
+ ":settings_radio_group.m",
+ ":settings_slider.m",
+ ":settings_textarea.m",
+ ":settings_toggle_button.m",
+ ]
+}
+
+js_library("controlled_button.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/controlled_button.m.js" ]
+ deps = [
+ ":pref_control_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_pref_behavior.m",
+ "//ui/webui/resources/js:assert.m",
+ ]
+ extra_deps = [ ":controlled_button_module" ]
+}
+
+js_library("controlled_radio_button.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/controlled_radio_button.m.js" ]
+ deps = [
+ ":pref_control_behavior.m",
+ "../prefs:pref_util.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button_behavior.m",
+ "//ui/webui/resources/js:assert.m",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":controlled_radio_button_module" ]
+}
+
+js_library("extension_controlled_indicator.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/extension_controlled_indicator.m.js" ]
+ deps = [
+ "..:extension_control_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ extra_deps = [ ":extension_controlled_indicator_module" ]
+}
+
+js_library("password_prompt_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/password_prompt_dialog.m.js" ]
+ deps = [
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
+ ]
+ externs_list = [ "$externs_path/quick_unlock_private.js" ]
+ extra_deps = [ ":password_prompt_dialog_module" ]
+}
+
+js_library("pref_control_behavior.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/pref_control_behavior.m.js" ]
+ deps = [ "../prefs:prefs_types.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("settings_boolean_control_behavior.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/settings_boolean_control_behavior.m.js" ]
+ deps = [
+ ":pref_control_behavior.m",
+ "../prefs:prefs_types.m",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_pref_behavior.m",
+ "//ui/webui/resources/js:assert.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("settings_checkbox.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/settings_checkbox.m.js" ]
+ deps = [
+ ":settings_boolean_control_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":settings_checkbox_module" ]
+}
+
+js_library("settings_dropdown_menu.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/settings_dropdown_menu.m.js" ]
+ deps = [
+ ":pref_control_behavior.m",
+ "../prefs:pref_util.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior.m",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_pref_behavior.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":settings_dropdown_menu_module" ]
+}
+
+js_library("settings_idle_load.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/settings_idle_load.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ ]
+ extra_deps = [ ":settings_idle_load_module" ]
+}
+
+js_library("settings_radio_group.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/settings_radio_group.m.js" ]
+ deps = [
+ ":pref_control_behavior.m",
+ "../prefs:pref_util.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ ]
+ extra_deps = [ ":settings_radio_group_module" ]
+}
+
+js_library("settings_slider.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/settings_slider.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_slider:cr_slider.m",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_pref_behavior.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":settings_slider_module" ]
+}
+
+js_library("settings_textarea.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/settings_textarea.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":settings_textarea_module" ]
+}
+
+js_library("settings_toggle_button.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/controls/settings_toggle_button.m.js" ]
+ deps = [
+ ":settings_boolean_control_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_toggle:cr_toggle.m",
+ ]
+ extra_deps = [ ":settings_toggle_button_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":controlled_button_module",
+ ":controlled_radio_button_module",
+ ":extension_controlled_indicator_module",
+ ":modulize",
+ ":password_prompt_dialog_module",
+ ":settings_checkbox_module",
+ ":settings_dropdown_menu_module",
+ ":settings_idle_load_module",
+ ":settings_radio_group_module",
+ ":settings_slider_module",
+ ":settings_textarea_module",
+ ":settings_toggle_button_module",
+ ]
+}
+
+polymer_modulizer("controlled_button") {
+ js_file = "controlled_button.js"
+ html_file = "controlled_button.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports
+}
+
+polymer_modulizer("controlled_radio_button") {
+ js_file = "controlled_radio_button.js"
+ html_file = "controlled_radio_button.html"
+ html_type = "dom-module"
+ auto_imports =
+ settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/prefs/pref_util.html|prefToString",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("extension_controlled_indicator") {
+ js_file = "extension_controlled_indicator.js"
+ html_file = "extension_controlled_indicator.html"
+ html_type = "dom-module"
+ auto_imports = [
+ "chrome/browser/resources/settings/extension_control_browser_proxy.html|ExtensionControlBrowserProxyImpl",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("password_prompt_dialog") {
+ js_file = "password_prompt_dialog.js"
+ html_file = "password_prompt_dialog.html"
+ html_type = "dom-module"
+}
+
+polymer_modulizer("settings_checkbox") {
+ js_file = "settings_checkbox.js"
+ html_file = "settings_checkbox.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports
+}
+
+polymer_modulizer("settings_dropdown_menu") {
+ js_file = "settings_dropdown_menu.js"
+ html_file = "settings_dropdown_menu.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/prefs/pref_util.html|stringToPrefValue, prefToString",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("settings_idle_load") {
+ js_file = "settings_idle_load.js"
+ html_file = "settings_idle_load.html"
+ html_type = "dom-module"
+ auto_imports = [
+ "chrome/browser/resources/settings/ensure_lazy_loaded.html|ensureLazyLoaded",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/polymer.html|Polymer,html,templatize,TemplateInstanceBase",
+ ]
+ namespace_rewrites = settings_namespace_rewrites + [
+ "Polymer.Templatize.templatize|templatize",
+ ]
+}
+
+polymer_modulizer("settings_radio_group") {
+ js_file = "settings_radio_group.js"
+ html_file = "settings_radio_group.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/prefs/pref_util.html|stringToPrefValue, prefToString" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("settings_slider") {
+ js_file = "settings_slider.js"
+ html_file = "settings_slider.html"
+ html_type = "dom-module"
+ auto_imports =
+ settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/cr_elements/cr_slider/cr_slider.html|SliderTick",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("settings_textarea") {
+ js_file = "settings_textarea.js"
+ html_file = "settings_textarea.html"
+ html_type = "dom-module"
+}
+
+polymer_modulizer("settings_toggle_button") {
+ js_file = "settings_toggle_button.js"
+ html_file = "settings_toggle_button.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "pref_control_behavior.js",
+ "settings_boolean_control_behavior.js",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/settings/default_browser_page/BUILD.gn b/chromium/chrome/browser/resources/settings/default_browser_page/BUILD.gn
index efe93f1263c..dc82219540a 100644
--- a/chromium/chrome/browser/resources/settings/default_browser_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/default_browser_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -12,9 +15,7 @@ js_type_check("closure_compile") {
}
js_library("default_browser_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("default_browser_page") {
@@ -24,3 +25,47 @@ js_library("default_browser_page") {
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":default_browser_browser_proxy.m",
+ ":default_browser_page.m",
+ ]
+}
+
+js_library("default_browser_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/default_browser_page/default_browser_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("default_browser_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/default_browser_page/default_browser_page.m.js" ]
+ deps = [
+ ":default_browser_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":default_browser_page_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":default_browser_page_module",
+ ":modulize",
+ ]
+}
+
+polymer_modulizer("default_browser_page") {
+ js_file = "default_browser_page.js"
+ html_file = "default_browser_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = [ "chrome/browser/resources/settings/default_browser_page/default_browser_browser_proxy.html|DefaultBrowserBrowserProxyImpl,DefaultBrowserBrowserProxy,DefaultBrowserInfo" ]
+}
+
+js_modulizer("modulize") {
+ input_files = [ "default_browser_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn b/chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn
index 044f3b72730..9b31bc2d09c 100644
--- a/chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/downloads_page/BUILD.gn
@@ -3,15 +3,15 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
":downloads_browser_proxy",
":downloads_page",
]
- if (is_chromeos) {
- deps += [ ":smb_shares_page" ]
- }
}
js_library("downloads_browser_proxy") {
@@ -21,25 +21,58 @@ js_library("downloads_browser_proxy") {
]
}
-if (is_chromeos) {
- js_library("smb_shares_page") {
- deps = [
- "..:route",
- "//ui/webui/resources/cr_components/chromeos/smb_shares:smb_browser_proxy",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
- }
-}
-
js_library("downloads_page") {
deps = [
":downloads_browser_proxy",
- "..:page_visibility",
- "..:route",
"../prefs:prefs_behavior",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:util",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":downloads_browser_proxy.m",
+ ":downloads_page.m",
+ ]
+}
+
+js_library("downloads_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/downloads_page/downloads_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("downloads_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/downloads_page/downloads_page.m.js" ]
+ deps = [
+ ":downloads_browser_proxy.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:util.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":downloads_page_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":downloads_page_module",
+ ":modulize",
+ ]
+}
+
+polymer_modulizer("downloads_page") {
+ js_file = "downloads_page.js"
+ html_file = "downloads_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports =
+ settings_auto_imports + [ "ui/webui/resources/html/util.html|listenOnce" ]
+}
+
+js_modulizer("modulize") {
+ input_files = [ "downloads_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/incompatible_applications_page/BUILD.gn b/chromium/chrome/browser/resources/settings/incompatible_applications_page/BUILD.gn
index 78dfe00d561..29066a8fbe9 100644
--- a/chromium/chrome/browser/resources/settings/incompatible_applications_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/incompatible_applications_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -13,9 +16,7 @@ js_type_check("closure_compile") {
}
js_library("incompatible_applications_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("incompatible_applications_page") {
@@ -34,3 +35,78 @@ js_library("incompatible_application_item") {
"//ui/webui/resources/js:i18n_behavior",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":incompatible_application_item.m",
+ ":incompatible_applications_browser_proxy.m",
+ ":incompatible_applications_page.m",
+ ]
+}
+
+js_library("incompatible_application_item.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.m.js" ]
+ deps = [
+ ":incompatible_applications_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ extra_deps = [ ":incompatible_application_item_module" ]
+}
+
+js_library("incompatible_applications_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("incompatible_applications_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.m.js" ]
+ deps = [
+ ":incompatible_applications_browser_proxy.m",
+ "..:i18n_setup.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":incompatible_applications_page_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":incompatible_application_item_module",
+ ":incompatible_applications_page_module",
+ ":modulize",
+ ]
+}
+
+polymer_modulizer("incompatible_application_item") {
+ js_file = "incompatible_application_item.js"
+ html_file = "incompatible_application_item.html"
+ html_type = "dom-module"
+ namespace_rewrites =
+ settings_namespace_rewrites + [ "settings.ActionTypes|ActionTypes" ]
+ auto_imports = [
+ "ui/webui/resources/html/assert.html|assertNotReached",
+ "chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.html|ActionTypes,IncompatibleApplicationsBrowserProxyImpl,IncompatibleApplicationsBrowserProxy",
+ ]
+}
+
+polymer_modulizer("incompatible_applications_page") {
+ js_file = "incompatible_applications_page.js"
+ html_file = "incompatible_applications_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.html|IncompatibleApplicationsBrowserProxyImpl, IncompatibleApplication",
+ ]
+}
+
+js_modulizer("modulize") {
+ input_files = [ "incompatible_applications_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/languages_page/BUILD.gn b/chromium/chrome/browser/resources/settings/languages_page/BUILD.gn
index b0041ec678c..9bbcf64228c 100644
--- a/chromium/chrome/browser/resources/settings/languages_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/languages_page/BUILD.gn
@@ -3,25 +3,34 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
":add_languages_dialog",
+ ":edit_dictionary_page",
":languages",
":languages_browser_proxy",
":languages_page",
":languages_types",
]
-
- if (is_chromeos) {
- deps += [ ":manage_input_methods_page" ]
- }
}
-js_library("languages_browser_proxy") {
+js_library("edit_dictionary_page") {
deps = [
- "//ui/webui/resources/js:cr",
+ ":languages_browser_proxy",
+ "..:global_scroll_target_behavior",
+ "..:route",
+ "../prefs",
+ "//ui/webui/resources/cr_elements/cr_button:cr_button",
+ "//ui/webui/resources/cr_elements/cr_input:cr_input",
]
+}
+
+js_library("languages_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [
"$externs_path/chrome_send.js",
"$externs_path/input_method_private.js",
@@ -60,6 +69,7 @@ js_library("languages_page") {
":languages_types",
"..:lifetime_browser_proxy",
"..:route",
+ "..:router",
"../settings_page:settings_animated_pages",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/cr_elements/cr_expand_button:cr_expand_button",
@@ -76,14 +86,6 @@ js_library("languages_types") {
externs_list = [ "$externs_path/language_settings_private.js" ]
}
-js_library("manage_input_methods_page") {
- deps = [
- ":languages_types",
- "../prefs",
- ]
- externs_list = [ "$externs_path/language_settings_private.js" ]
-}
-
js_library("add_languages_dialog") {
deps = [
":languages",
@@ -93,3 +95,174 @@ js_library("add_languages_dialog") {
"//ui/webui/resources/js:find_shortcut_behavior",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":add_languages_dialog.m",
+ ":edit_dictionary_page.m",
+ ":languages.m",
+ ":languages_browser_proxy.m",
+ ":languages_page.m",
+ ":languages_types.m",
+ ]
+}
+
+js_library("add_languages_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/languages_page/add_languages_dialog.m.js" ]
+ deps = [
+ ":languages.m",
+ ":languages_types.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements:cr_scrollable_behavior.m",
+ "//ui/webui/resources/cr_elements/cr_search_field:cr_search_field.m",
+ "//ui/webui/resources/js:find_shortcut_behavior.m",
+ ]
+ extra_deps = [ ":add_languages_dialog_module" ]
+}
+
+js_library("edit_dictionary_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/languages_page/edit_dictionary_page.m.js" ]
+ deps = [
+ ":languages_browser_proxy.m",
+ "..:global_scroll_target_behavior.m",
+ "..:route.m",
+ "../prefs:prefs.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-list:iron-list",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
+ "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
+ ]
+ extra_deps = [ ":edit_dictionary_page_module" ]
+}
+
+js_library("languages.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/languages_page/languages.m.js" ]
+ deps = [
+ ":languages_browser_proxy.m",
+ ":languages_types.m",
+ "../prefs:prefs.m",
+ "../prefs:prefs_behavior.m",
+ "../prefs:prefs_types.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:promise_resolver.m",
+ ]
+ externs_list = [
+ "$externs_path/input_method_private.js",
+ "$externs_path/language_settings_private.js",
+ ]
+ extra_sources = [
+ "$interfaces_path/input_method_private_interface.js",
+ "$interfaces_path/language_settings_private_interface.js",
+ ]
+ extra_deps = [ ":languages_module" ]
+}
+
+js_library("languages_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/languages_page/languages_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ externs_list = [
+ "$externs_path/chrome_send.js",
+ "$externs_path/input_method_private.js",
+ "$externs_path/language_settings_private.js",
+ ]
+ extra_sources = [
+ "$interfaces_path/input_method_private_interface.js",
+ "$interfaces_path/language_settings_private_interface.js",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("languages_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/languages_page/languages_page.m.js" ]
+ deps = [
+ ":languages.m",
+ ":languages_types.m",
+ "..:lifetime_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "../settings_page:settings_animated_pages.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/cr_elements/cr_expand_button:cr_expand_button.m",
+ "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ extra_deps = [ ":languages_page_module" ]
+}
+
+js_library("languages_types.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/languages_page/languages_types.m.js" ]
+ externs_list = [ "$externs_path/language_settings_private.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":add_languages_dialog_module",
+ ":edit_dictionary_page_module",
+ ":languages_module",
+ ":languages_page_module",
+ ":modulize",
+ ]
+}
+
+polymer_modulizer("add_languages_dialog") {
+ js_file = "add_languages_dialog.js"
+ html_file = "add_languages_dialog.html"
+ html_type = "dom-module"
+}
+
+polymer_modulizer("edit_dictionary_page") {
+ js_file = "edit_dictionary_page.js"
+ html_file = "edit_dictionary_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/languages_page/languages_browser_proxy.html|LanguagesBrowserProxyImpl",
+ "chrome/browser/resources/settings/route.html|routes",
+ "ui/webui/resources/html/polymer.html|Polymer,html,flush",
+ ]
+}
+
+polymer_modulizer("languages") {
+ js_file = "languages.js"
+ html_file = "languages.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/languages_page/languages_browser_proxy.html|LanguagesBrowserProxy,LanguagesBrowserProxyImpl",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/cr.html|isChromeOS, isWindows",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("languages_page") {
+ js_file = "languages_page.js"
+ html_file = "languages_page.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/lifetime_browser_proxy.html|LifetimeBrowserProxyImpl",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route,Router",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/cr.html|isChromeOS, isWindows",
+ "ui/webui/resources/html/polymer.html|Polymer,html,flush",
+ ]
+ namespace_rewrites = settings_namespace_rewrites +
+ [ "settings.kMenuCloseDelay|kMenuCloseDelay" ]
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "languages_browser_proxy.js",
+ "languages_types.js",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/multidevice_page/BUILD.gn b/chromium/chrome/browser/resources/settings/multidevice_page/BUILD.gn
deleted file mode 100644
index e0ba90793d3..00000000000
--- a/chromium/chrome/browser/resources/settings/multidevice_page/BUILD.gn
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//third_party/closure_compiler/compile_js.gni")
-
-# Note: This file is not chromeos only because multidevice_browser_proxy is
-# required by site_settings:site_list.
-
-js_type_check("closure_compile") {
- deps = [
- ":multidevice_browser_proxy",
- ":multidevice_constants",
- ]
- if (is_chromeos) {
- deps += [
- ":multidevice_feature_behavior",
- ":multidevice_feature_item",
- ":multidevice_feature_toggle",
- ":multidevice_page",
- ":multidevice_smartlock_subpage",
- ":multidevice_subpage",
- ":multidevice_tether_item",
- ]
- }
-}
-
-js_library("multidevice_browser_proxy") {
- deps = [
- ":multidevice_constants",
- "//ui/webui/resources/js:cr",
- ]
-}
-
-js_library("multidevice_constants") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
-}
-
-if (is_chromeos) {
- js_library("multidevice_feature_behavior") {
- deps = [
- ":multidevice_constants",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
- ]
- }
-
- js_library("multidevice_feature_item") {
- deps = [
- ":multidevice_constants",
- ":multidevice_feature_behavior",
- "..:route",
- "..:route_origin_behavior",
- "//ui/webui/resources/js:cr",
- ]
- }
-
- js_library("multidevice_feature_toggle") {
- deps = [
- ":multidevice_constants",
- ":multidevice_feature_behavior",
- ]
- }
-
- js_library("multidevice_page") {
- deps = [
- ":multidevice_browser_proxy",
- ":multidevice_constants",
- ":multidevice_feature_behavior",
- "..:route",
- "../controls:password_prompt_dialog",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
- }
-
- js_library("multidevice_radio_button") {
- deps = [
- "//third_party/polymer/v1_0/components-chromium/iron-a11y-keys-behavior:iron-a11y-keys-behavior-extracted",
- "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button_behavior",
- "//ui/webui/resources/cr_elements/policy:cr_policy_indicator",
- ]
- }
-
- js_library("multidevice_smartlock_subpage") {
- deps = [
- ":multidevice_constants",
- ":multidevice_feature_behavior",
- "../prefs:prefs_behavior",
- "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button",
- "//ui/webui/resources/js:cr",
- ]
- }
-
- js_library("multidevice_subpage") {
- deps = [
- ":multidevice_constants",
- ":multidevice_feature_behavior",
- "..:route",
- "//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
- ]
- externs_list = [ "$externs_path/networking_private.js" ]
- extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
- }
-
- js_library("multidevice_tether_item") {
- deps = [
- ":multidevice_feature_behavior",
- "..:route",
- "//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
- "//ui/webui/resources/cr_components/chromeos/network:onc_mojo",
- ]
- externs_list = [ "$externs_path/networking_private.js" ]
- extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
- }
-}
diff --git a/chromium/chrome/browser/resources/settings/on_startup_page/BUILD.gn b/chromium/chrome/browser/resources/settings/on_startup_page/BUILD.gn
index 7f027564165..93a4ce2f937 100644
--- a/chromium/chrome/browser/resources/settings/on_startup_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/on_startup_page/BUILD.gn
@@ -3,11 +3,15 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
":on_startup_browser_proxy",
":on_startup_page",
+ ":startup_url_dialog",
":startup_url_entry",
":startup_urls_page",
":startup_urls_page_browser_proxy",
@@ -59,3 +63,139 @@ js_library("startup_url_entry") {
"//ui/webui/resources/js/cr/ui:focus_row_behavior",
]
}
+
+js_library("startup_url_dialog") {
+ deps = [
+ ":startup_urls_page_browser_proxy",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:load_time_data",
+ ]
+}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":on_startup_browser_proxy.m",
+ ":on_startup_page.m",
+ ":startup_url_dialog.m",
+ ":startup_url_entry.m",
+ ":startup_urls_page.m",
+ ":startup_urls_page_browser_proxy.m",
+ ]
+}
+
+js_library("on_startup_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/on_startup_page/on_startup_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("on_startup_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/on_startup_page/on_startup_page.m.js" ]
+ deps = [
+ ":on_startup_browser_proxy.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":on_startup_page_module" ]
+}
+
+js_library("startup_url_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.m.js" ]
+ deps = [
+ ":startup_urls_page_browser_proxy.m",
+ "..:i18n_setup.m",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ ]
+ extra_deps = [ ":startup_url_dialog_module" ]
+}
+
+js_library("startup_url_entry.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/on_startup_page/startup_url_entry.m.js" ]
+ deps = [
+ ":startup_urls_page_browser_proxy.m",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:icon.m",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
+ ]
+ extra_deps = [ ":startup_url_entry_module" ]
+}
+
+js_library("startup_urls_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/on_startup_page/startup_urls_page.m.js" ]
+ deps = [
+ ":startup_url_entry.m",
+ ":startup_urls_page_browser_proxy.m",
+ "//ui/webui/resources/cr_elements:cr_scrollable_behavior.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":startup_urls_page_module" ]
+}
+
+js_library("startup_urls_page_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":modulize",
+ ":on_startup_page_module",
+ ":startup_url_dialog_module",
+ ":startup_url_entry_module",
+ ":startup_urls_page_module",
+ ]
+}
+
+polymer_modulizer("on_startup_page") {
+ js_file = "on_startup_page.js"
+ html_file = "on_startup_page.html"
+ html_type = "dom-module"
+ auto_imports = [ "chrome/browser/resources/settings/on_startup_page/on_startup_browser_proxy.html|NtpExtension, OnStartupBrowserProxyImpl" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("startup_url_dialog") {
+ js_file = "startup_url_dialog.js"
+ html_file = "startup_url_dialog.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.html|StartupPageInfo, StartupUrlsPageBrowserProxy, StartupUrlsPageBrowserProxyImpl" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("startup_url_entry") {
+ js_file = "startup_url_entry.js"
+ html_file = "startup_url_entry.html"
+ html_type = "dom-module"
+ auto_imports = [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.html|StartupPageInfo, StartupUrlsPageBrowserProxyImpl",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("startup_urls_page") {
+ js_file = "startup_urls_page.js"
+ html_file = "startup_urls_page.html"
+ html_type = "dom-module"
+ auto_imports = [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/on_startup_page/startup_url_entry.html|EDIT_STARTUP_URL_EVENT",
+ "chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.html|StartupPageInfo, StartupUrlsPageBrowserProxy, StartupUrlsPageBrowserProxyImpl",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "on_startup_browser_proxy.js",
+ "startup_urls_page_browser_proxy.js",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/os_settings_resources.grd b/chromium/chrome/browser/resources/settings/os_settings_resources.grd
index fcdec13a423..05e7cf5cad9 100644
--- a/chromium/chrome/browser/resources/settings/os_settings_resources.grd
+++ b/chromium/chrome/browser/resources/settings/os_settings_resources.grd
@@ -11,14 +11,72 @@
<output filename="os_settings_resources.pak" type="data_package" />
</outputs>
<release seq="1">
+ <includes>
+ <!-- App Management -->
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_BITMAP_MOJO_LITE_JS"
+ file="${root_gen_dir}\skia\public\mojom\bitmap.mojom-lite.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_FILE_PATH_MOJO_LITE_JS"
+ file="${root_gen_dir}\mojo\public\mojom\base\file_path.mojom-lite.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS"
+ file="${root_gen_dir}\skia\public\mojom\image_info.mojom-lite.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_MOJO_LITE_JS"
+ file="${root_gen_dir}\ui\gfx\image\mojom\image.mojom-lite.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_MOJO_LITE_JS"
+ file="${root_gen_dir}\chrome\browser\ui\webui\app_management\app_management.mojom-lite.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_TYPES_MOJO_LITE_JS"
+ file="${root_gen_dir}\chrome\services\app_service\public\mojom\types.mojom-lite.js"
+ use_base_dir="false"
+ type="BINDATA" />
+
+ <!-- Search -->
+ <include name="IDR_OS_SETTINGS_SEARCH_MOJOM_LITE_JS"
+ file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\search.mojom-lite.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_SEARCH_RESULT_ICON_MOJOM_LITE_JS"
+ file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\search_result_icon.mojom-lite.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_USER_ACTION_RECORDER_MOJOM_LITE_JS"
+ file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\user_action_recorder.mojom-lite.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </includes>
<structures>
+ <structure name="IDR_OS_SETTINGS_LOCALIZED_LINK_JS"
+ file="chromeos/localized_link/localized_link.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_LOCALIZED_LINK_HTML"
+ file="chromeos/localized_link/localized_link.html"
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_A11Y_PAGE_JS"
file="chromeos/os_a11y_page/os_a11y_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_A11Y_PAGE_HTML"
file="chromeos/os_a11y_page/os_a11y_page.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_PAGE_JS"
+ file="chromeos/ambient_mode_page/ambient_mode_page.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_PAGE_HTML"
+ file="chromeos/ambient_mode_page/ambient_mode_page.html"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_BROWSER_PROXY_JS"
+ file="chromeos/ambient_mode_page/ambient_mode_browser_proxy.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_AMBIENT_MODE_PAGE_AMBIENT_MODE_BROWSER_PROXY_HTML"
+ file="chromeos/ambient_mode_page/ambient_mode_browser_proxy.html"
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_APPS_PAGE_JS"
file="chromeos/os_apps_page/os_apps_page.js"
type="chrome_html" />
@@ -173,22 +231,22 @@
file="appearance_page/fonts_browser_proxy.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MANAGE_A11Y_PAGE_JS"
- file="a11y_page/manage_a11y_page.js"
+ file="chromeos/os_a11y_page/manage_a11y_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MANAGE_A11Y_PAGE_HTML"
- file="a11y_page/manage_a11y_page.html"
+ file="chromeos/os_a11y_page/manage_a11y_page.html"
type="chrome_html" />
<structure name="IDS_OS_SETTINGS_SWITCH_ACCESS_SUBPAGE_JS"
- file="a11y_page/switch_access_subpage.js"
+ file="chromeos/os_a11y_page/switch_access_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_SWITCH_ACCESS_SUBPAGE_HTML"
- file="a11y_page/switch_access_subpage.html"
+ file="chromeos/os_a11y_page/switch_access_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_TTS_SUBPAGE_JS"
- file="a11y_page/tts_subpage.js"
+ file="chromeos/os_a11y_page/tts_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_TTS_SUBPAGE_HTML"
- file="a11y_page/tts_subpage.html"
+ file="chromeos/os_a11y_page/tts_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MANIFEST"
file="os_settings_manifest.json"
@@ -207,69 +265,24 @@
<structure name="IDR_OS_SETTINGS_ABOUT_PAGE_HTML"
file="chromeos/os_about_page/os_about_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_CHANNEL_SWITCHER_DIALOG_HTML"
- file="about_page/channel_switcher_dialog.html"
+ file="chromeos/os_about_page/channel_switcher_dialog.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CHANNEL_SWITCHER_DIALOG_JS"
- file="about_page/channel_switcher_dialog.js"
+ file="chromeos/os_about_page/channel_switcher_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DETAILED_BUILD_INFO_JS"
- file="about_page/detailed_build_info.js"
+ file="chromeos/os_about_page/detailed_build_info.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DETAILED_BUILD_INFO_HTML"
- file="about_page/detailed_build_info.html"
+ file="chromeos/os_about_page/detailed_build_info.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_UPDATE_WARNING_DIALOG_HTML"
- file="about_page/update_warning_dialog.html"
+ file="chromeos/os_about_page/update_warning_dialog.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_UPDATE_WARNING_DIALOG_JS"
- file="about_page/update_warning_dialog.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ADD_SITE_DIALOG_HTML"
- file="site_settings/add_site_dialog.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ADD_SITE_DIALOG_JS"
- file="site_settings/add_site_dialog.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ALL_SITES_HTML"
- file="site_settings/all_sites.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ALL_SITES_JS"
- file="site_settings/all_sites.js"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_SITE_ENTRY_HTML"
- file="site_settings/site_entry.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_ENTRY_JS"
- file="site_settings/site_entry.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CATEGORY_DEFAULT_SETTING_HTML"
- file="site_settings/category_default_setting.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CATEGORY_DEFAULT_SETTING_JS"
- file="site_settings/category_default_setting.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CATEGORY_SETTING_EXCEPTIONS_HTML"
- file="site_settings/category_setting_exceptions.html"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_CATEGORY_SETTING_EXCEPTIONS_JS"
- file="site_settings/category_setting_exceptions.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CHOOSER_EXCEPTION_LIST_HTML"
- file="site_settings/chooser_exception_list.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CHOOSER_EXCEPTION_LIST_JS"
- file="site_settings/chooser_exception_list.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CHOOSER_EXCEPTION_LIST_ENTRY_HTML"
- file="site_settings/chooser_exception_list_entry.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CHOOSER_EXCEPTION_LIST_ENTRY_JS"
- file="site_settings/chooser_exception_list_entry.js"
+ file="chromeos/os_about_page/update_warning_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CR_SETTINGS_ANIMATED_PAGES_HTML"
file="settings_page/settings_animated_pages.html"
@@ -280,8 +293,7 @@
preprocess="true" />
<structure name="IDR_OS_SETTINGS_PERSONALIZATION_PAGE_HTML"
file="chromeos/personalization_page/personalization_page.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PERSONALIZATION_PAGE_JS"
file="chromeos/personalization_page/personalization_page.js"
type="chrome_html" />
@@ -290,13 +302,9 @@
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_OS_SETTINGS_PAGE_HTML"
file="chromeos/os_settings_page/os_settings_page.html"
- type="chrome_html"
- allowexternalscript="true" />
- <structure name="IDR_OS_SETTINGS_EDIT_EXCEPTION_DIALOG_HTML"
- file="site_settings/edit_exception_dialog.html"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_EDIT_EXCEPTION_DIALOG_JS"
- file="site_settings/edit_exception_dialog.js"
+ <structure name="IDR_OS_SETTINGS_ENSURE_LAZY_LOADED_HTML"
+ file="ensure_lazy_loaded.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_EXTENSION_CONTROL_BROWSER_PROXY_JS"
file="extension_control_browser_proxy.js"
@@ -316,15 +324,13 @@
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CR_OS_SETTINGS_MAIN_HTML"
file="chromeos/os_settings_main/os_settings_main.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CR_OS_SETTINGS_MAIN_JS"
file="chromeos/os_settings_main/os_settings_main.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CR_OS_SETTINGS_MENU_HTML"
file="chromeos/os_settings_menu/os_settings_menu.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CR_OS_SETTINGS_MENU_JS"
file="chromeos/os_settings_menu/os_settings_menu.js"
type="chrome_html" />
@@ -359,8 +365,7 @@
preprocess="true" />
<structure name="IDR_OS_SETTINGS_CR_OS_SETTINGS_UI_HTML"
file="chromeos/os_settings_ui/os_settings_ui.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CR_OS_SETTINGS_UI_JS"
file="chromeos/os_settings_ui/os_settings_ui.js"
type="chrome_html" />
@@ -370,39 +375,6 @@
<structure name="IDR_OS_SETTINGS_GLOBAL_SCROLL_TARGET_BEHAVIOR_JS"
file="global_scroll_target_behavior.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CHANGE_PASSWORD_BROWSER_PROXY_HTML"
- file="change_password_page/change_password_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CHANGE_PASSWORD_BROWSER_PROXY_JS"
- file="change_password_page/change_password_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CHANGE_PASSWORD_PAGE_HTML"
- file="change_password_page/change_password_page.html"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_CHANGE_PASSWORD_PAGE_JS"
- file="change_password_page/change_password_page.js"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_CLEAR_BROWSING_DATA_BROWSER_PROXY_HTML"
- file="clear_browsing_data_dialog/clear_browsing_data_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CLEAR_BROWSING_DATA_BROWSER_PROXY_JS"
- file="clear_browsing_data_dialog/clear_browsing_data_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_HTML"
- file="clear_browsing_data_dialog/clear_browsing_data_dialog.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_JS"
- file="clear_browsing_data_dialog/clear_browsing_data_dialog.js"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_HISTORY_DELETION_DIALOG_HTML"
- file="clear_browsing_data_dialog/history_deletion_dialog.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_HISTORY_DELETION_DIALOG_JS"
- file="clear_browsing_data_dialog/history_deletion_dialog.js"
- type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CONTROLS_BOOLEAN_CONTROL_BEHAVIOR_HTML"
file="controls/settings_boolean_control_behavior.html"
type="chrome_html" />
@@ -427,12 +399,6 @@
<structure name="IDR_OS_SETTINGS_CONTROLS_EXTENSION_CONTROLLED_INDICATOR_HTML"
file="controls/extension_controlled_indicator.html"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CONTROLS_CHECKBOX_HTML"
- file="controls/settings_checkbox.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CONTROLS_CHECKBOX_JS"
- file="controls/settings_checkbox.js"
- type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CONTROLS_DROPDOWN_MENU_HTML"
file="controls/settings_dropdown_menu.html"
type="chrome_html" />
@@ -445,8 +411,7 @@
<structure name="IDR_OS_SETTINGS_CONTROLS_PASSWORD_PROMPT_DIALOG_HTML"
file="controls/password_prompt_dialog.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_CONTROLS_PREF_CONTROL_BEHAVIOR_HTML"
file="controls/pref_control_behavior.html"
type="chrome_html" />
@@ -483,106 +448,99 @@
<structure name="IDR_OS_SETTINGS_CONTROLS_TOGGLE_BUTTON_JS"
file="controls/settings_toggle_button.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_COOKIE_INFO_HTML"
- file="site_settings/cookie_info.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_COOKIE_INFO_JS"
- file="site_settings/cookie_info.js"
- type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_BROWSER_PROXY_HTML"
- file="device_page/device_page_browser_proxy.html"
+ file="chromeos/device_page/device_page_browser_proxy.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_BROWSER_PROXY_JS"
- file="device_page/device_page_browser_proxy.js"
+ file="chromeos/device_page/device_page_browser_proxy.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_DISPLAY_HTML"
- file="device_page/display.html"
+ file="chromeos/device_page/display.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_DISPLAY_JS"
- file="device_page/display.js"
+ file="chromeos/device_page/display.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_DISPLAY_LAYOUT_HTML"
- file="device_page/display_layout.html"
+ file="chromeos/device_page/display_layout.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_DISPLAY_LAYOUT_JS"
- file="device_page/display_layout.js"
+ file="chromeos/device_page/display_layout.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_DISPLAY_OVERSCAN_DIALOG_HTML"
- file="device_page/display_overscan_dialog.html"
+ file="chromeos/device_page/display_overscan_dialog.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_DISPLAY_OVERSCAN_DIALOG_JS"
- file="device_page/display_overscan_dialog.js"
+ file="chromeos/device_page/display_overscan_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_KEYBOARD_HTML"
- file="device_page/keyboard.html"
+ file="chromeos/device_page/keyboard.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_KEYBOARD_JS"
- file="device_page/keyboard.js"
+ file="chromeos/device_page/keyboard.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_POWER_HTML"
- file="device_page/power.html"
+ file="chromeos/device_page/power.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_POWER_JS"
- file="device_page/power.js"
+ file="chromeos/device_page/power.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_STORAGE_HTML"
- file="device_page/storage.html"
+ file="chromeos/device_page/storage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_STORAGE_JS"
- file="device_page/storage.js"
+ file="chromeos/device_page/storage.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_DEVICE_STORAGE_EXTERNAL_ENTRY_HTML"
- file="device_page/storage_external_entry.html"
+ file="chromeos/device_page/storage_external_entry.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_DEVICE_STORAGE_EXTERNAL_ENTRY_JS"
- file="device_page/storage_external_entry.js"
+ file="chromeos/device_page/storage_external_entry.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_DEVICE_STORAGE_EXTERNAL_HTML"
- file="device_page/storage_external.html"
+ file="chromeos/device_page/storage_external.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_DEVICE_STORAGE_EXTERNAL_JS"
- file="device_page/storage_external.js"
+ file="chromeos/device_page/storage_external.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_STYLUS_HTML"
- file="device_page/stylus.html"
+ file="chromeos/device_page/stylus.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_STYLUS_JS"
- file="device_page/stylus.js"
+ file="chromeos/device_page/stylus.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_PAGE_HTML"
- file="device_page/device_page.html"
+ file="chromeos/device_page/device_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_PAGE_JS"
- file="device_page/device_page.js"
+ file="chromeos/device_page/device_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_POINTERS_HTML"
- file="device_page/pointers.html"
+ file="chromeos/device_page/pointers.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_POINTERS_JS"
- file="device_page/pointers.js"
+ file="chromeos/device_page/pointers.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_DRAG_BEHAVIOR_HTML"
- file="device_page/drag_behavior.html"
+ file="chromeos/device_page/drag_behavior.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_DRAG_BEHAVIOR_JS"
- file="device_page/drag_behavior.js"
+ file="chromeos/device_page/drag_behavior.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_LAYOUT_BEHAVIOR_HTML"
- file="device_page/layout_behavior.html"
+ file="chromeos/device_page/layout_behavior.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_LAYOUT_BEHAVIOR_JS"
- file="device_page/layout_behavior.js"
+ file="chromeos/device_page/layout_behavior.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_NIGHT_LIGHT_SLIDER_HTML"
- file="device_page/night_light_slider.html"
+ file="chromeos/device_page/night_light_slider.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DEVICE_NIGHT_LIGHT_SLIDER_JS"
- file="device_page/night_light_slider.js"
+ file="chromeos/device_page/night_light_slider.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_FILES_PAGE_HTML"
file="chromeos/os_files_page/os_files_page.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_FILES_PAGE_JS"
file="chromeos/os_files_page/os_files_page.js"
type="chrome_html" />
@@ -631,8 +589,7 @@
<structure name="IDR_OS_SETTINGS_LANGUAGES_JS"
file="languages_page/languages.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_LANGUAGES_BROWSER_PROXY_HTML"
file="languages_page/languages_browser_proxy.html"
type="chrome_html" />
@@ -648,31 +605,33 @@
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_LANGUAGES_PAGE_HTML"
file="chromeos/os_languages_page/os_languages_page.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_LANGUAGES_PAGE_JS"
file="chromeos/os_languages_page/os_languages_page.js"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_LANGUAGES_SECTION_HTML"
file="chromeos/os_languages_page/os_languages_section.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_LANGUAGES_SECTION_JS"
file="chromeos/os_languages_page/os_languages_section.js"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_PAGE_HTML"
- file="languages_page/manage_input_methods_page.html"
+ file="chromeos/os_languages_page/manage_input_methods_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_PAGE_JS"
- file="languages_page/manage_input_methods_page.js"
+ file="chromeos/os_languages_page/manage_input_methods_page.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_MEDIA_PICKER_HTML"
- file="site_settings/media_picker.html"
+ <structure name="IDR_OS_SETTINGS_OS_SEARCH_RESULT_ROW_JS"
+ file="chromeos/os_settings_search_box/os_search_result_row.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_MEDIA_PICKER_JS"
- file="site_settings/media_picker.js"
+ <structure name="IDR_OS_SETTINGS_OS_SEARCH_RESULT_ROW_HTML"
+ file="chromeos/os_settings_search_box/os_search_result_row.html"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_OS_SETTINGS_SEARCH_BOX_JS"
+ file="chromeos/os_settings_search_box/os_settings_search_box.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_OS_SETTINGS_SEARCH_BOX_HTML"
+ file="chromeos/os_settings_search_box/os_settings_search_box.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_OS_TOOLBAR_JS"
file="chromeos/os_toolbar/os_toolbar.js"
@@ -682,13 +641,10 @@
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_HTML"
file="chromeos/os_people_page/os_people_page.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_JS"
file="chromeos/os_people_page/os_people_page.js"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_OS_SYNC_BROWSER_PROXY_HTML"
file="chromeos/os_people_page/os_sync_browser_proxy.html"
type="chrome_html" />
@@ -702,8 +658,7 @@
<structure name="IDR_OS_SETTINGS_OS_SYNC_CONTROLS_HTML"
file="chromeos/os_people_page/os_sync_controls.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_SIGNOUT_DIALOG_HTML"
file="people_page/signout_dialog.html"
type="chrome_html"
@@ -724,8 +679,7 @@
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_SYNC_BROWSER_PROXY_JS"
file="people_page/sync_browser_proxy.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_PREF_UTIL_HTML"
file="prefs/pref_util.html"
type="chrome_html" />
@@ -752,152 +706,101 @@
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PRINTING_PAGE_HTML"
file="chromeos/os_printing_page/os_printing_page.html"
- allowexternalscript="true"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PRINTING_PAGE_JS"
file="chromeos/os_printing_page/os_printing_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTER_TYPES_HTML"
- file="printing_page/cups_printer_types.html"
+ file="chromeos/os_printing_page/cups_printer_types.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTER_TYPES_JS"
- file="printing_page/cups_printer_types.js"
+ file="chromeos/os_printing_page/cups_printer_types.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTER_SHARED_CSS_HTML"
- file="printing_page/cups_printer_shared_css.html"
+ file="chromeos/os_printing_page/cups_printer_shared_css.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTING_PAGE_HTML"
- file="printing_page/cups_printers.html"
+ file="chromeos/os_printing_page/cups_printers.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTING_PAGE_JS"
- file="printing_page/cups_printers.js"
+ file="chromeos/os_printing_page/cups_printers.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_BROWSER_PROXY_HTML"
- file="printing_page/cups_printers_browser_proxy.html"
+ file="chromeos/os_printing_page/cups_printers_browser_proxy.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_BROWSER_PROXY_JS"
- file="printing_page/cups_printers_browser_proxy.js"
+ file="chromeos/os_printing_page/cups_printers_browser_proxy.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_ENTRY_HTML"
- file="printing_page/cups_printers_entry.html"
+ file="chromeos/os_printing_page/cups_printers_entry.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_ENTRY_JS"
- file="printing_page/cups_printers_entry.js"
+ file="chromeos/os_printing_page/cups_printers_entry.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_ENTRY_LIST_BEHAVIOR_HTML"
- file="printing_page/cups_printers_entry_list_behavior.html"
+ file="chromeos/os_printing_page/cups_printers_entry_list_behavior.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_ENTRY_LIST_BEHAVIOR_JS"
- file="printing_page/cups_printers_entry_list_behavior.js"
+ file="chromeos/os_printing_page/cups_printers_entry_list_behavior.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_ENTRY_MANAGER_HTML"
- file="printing_page/cups_printers_entry_manager.html"
+ file="chromeos/os_printing_page/cups_printers_entry_manager.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_ENTRY_MANAGER_JS"
- file="printing_page/cups_printers_entry_manager.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_LIST_HTML"
- file="printing_page/cups_printers_list.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CUPS_PRINTERS_LIST_JS"
- file="printing_page/cups_printers_list.js"
+ file="chromeos/os_printing_page/cups_printers_entry_manager.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_EDIT_PRINTER_DIALOG_HTML"
- file="printing_page/cups_edit_printer_dialog.html"
+ file="chromeos/os_printing_page/cups_edit_printer_dialog.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_EDIT_PRINTER_DIALOG_JS"
- file="printing_page/cups_edit_printer_dialog.js"
+ file="chromeos/os_printing_page/cups_edit_printer_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_ADD_PRINTER_DIALOG_HTML"
- file="printing_page/cups_add_printer_dialog.html"
+ file="chromeos/os_printing_page/cups_add_printer_dialog.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_ADD_PRINTER_DIALOG_JS"
- file="printing_page/cups_add_printer_dialog.js"
+ file="chromeos/os_printing_page/cups_add_printer_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_ADD_PRINTER_DIALOG_ELEMENTS_HTML"
- file="printing_page/cups_add_printer_dialog_elements.html"
+ file="chromeos/os_printing_page/cups_add_printer_dialog_elements.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_ADD_PRINTER_DIALOG_ELEMENTS_JS"
- file="printing_page/cups_add_printer_dialog_elements.js"
+ file="chromeos/os_printing_page/cups_add_printer_dialog_elements.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTER_DIALOG_UTIL_HTML"
- file="printing_page/cups_printer_dialog_util.html"
+ file="chromeos/os_printing_page/cups_printer_dialog_util.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_PRINTER_DIALOG_UTIL_JS"
- file="printing_page/cups_printer_dialog_util.js"
+ file="chromeos/os_printing_page/cups_printer_dialog_util.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_SAVED_PRINTERS_HTML"
- file="printing_page/cups_saved_printers.html"
+ file="chromeos/os_printing_page/cups_saved_printers.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_SAVED_PRINTERS_JS"
- file="printing_page/cups_saved_printers.js"
+ file="chromeos/os_printing_page/cups_saved_printers.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_NEARBY_PRINTERS_HTML"
- file="printing_page/cups_nearby_printers.html"
+ file="chromeos/os_printing_page/cups_nearby_printers.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CUPS_NEARBY_PRINTERS_JS"
- file="printing_page/cups_nearby_printers.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CLOUD_PRINTING_PAGE_HTML"
- file="printing_page/cloud_printers.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CLOUD_PRINTING_PAGE_JS"
- file="printing_page/cloud_printers.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_LOCAL_DATA_BROWSER_PROXY_HTML"
- file="site_settings/local_data_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_LOCAL_DATA_BROWSER_PROXY_JS"
- file="site_settings/local_data_browser_proxy.js"
+ file="chromeos/os_printing_page/cups_nearby_printers.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_OPEN_WINDOW_PROXY_HTML"
- file="open_window_proxy.html"
+ <structure name="IDR_OS_SETTINGS_OS_PAGE_VISIBILITY_HTML"
+ file="chromeos/os_page_visibility.html"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_OPEN_WINDOW_PROXY_JS"
- file="open_window_proxy.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_PAGE_VISIBILITY_HTML"
- file="page_visibility.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_PAGE_VISIBILITY_JS"
- file="page_visibility.js"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_PDF_DOCUMENTS_HTML"
- file="site_settings/pdf_documents.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_PDF_DOCUMENTS_JS"
- file="site_settings/pdf_documents.js"
+ <structure name="IDR_OS_SETTINGS_OS_PAGE_VISIBILITY_JS"
+ file="chromeos/os_page_visibility.js"
type="chrome_html" />
<!-- TODO(jamescook): Remove after sync settings is forked. -->
<structure name="IDR_OS_SETTINGS_PERSONALIZATION_OPTIONS_HTML"
file="privacy_page/personalization_options.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_PERSONALIZATION_OPTIONS_JS"
file="privacy_page/personalization_options.js"
preprocess="true"
type="chrome_html" />
<!-- TODO(jamescook): Remove after sync settings is forked. -->
- <structure name="IDR_OS_SETTINGS_PASSWORDS_LEAK_DETECTION_TOGGLE_HTML"
- file="privacy_page/passwords_leak_detection_toggle.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_PASSWORDS_LEAK_DETECTION_TOGGLE_JS"
- file="privacy_page/passwords_leak_detection_toggle.js"
- type="chrome_html"
- preprocess="true" />
- <!-- TODO(jamescook): Remove after sync settings is forked. -->
- <structure name="IDR_OS_SETTINGS_PRIVACY_PAGE_HTML"
- file="privacy_page/privacy_page.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
- <structure name="IDR_OS_SETTINGS_PRIVACY_PAGE_JS"
- file="privacy_page/privacy_page.js"
- preprocess="true"
- type="chrome_html" />
- <!-- TODO(jamescook): Remove after sync settings is forked. -->
<structure name="IDR_OS_SETTINGS_PRIVACY_PAGE_BROWSER_PROXY_HTML"
file="privacy_page/privacy_page_browser_proxy.html"
type="chrome_html" />
@@ -909,189 +812,54 @@
file="chromeos/os_privacy_page/os_privacy_page.html"
type="chrome_html"
flattenhtml="true"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_OS_PRIVACY_PAGE_JS"
file="chromeos/os_privacy_page/os_privacy_page.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_PROTOCOL_HANDLERS_HTML"
- file="site_settings/protocol_handlers.html"
- preprocess="true"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_PROTOCOL_HANDLERS_JS"
- file="site_settings/protocol_handlers.js"
- preprocess="true"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ROUTE_HTML"
- file="route.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ROUTE_JS"
- file="route.js"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_SETTINGS_ROUTE_ORIGIN_BEHAVIOR_HTML"
- file="route_origin_behavior.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_ROUTE_ORIGIN_BEHAVIOR_JS"
- file="route_origin_behavior.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_FAVICON_HTML"
- file="site_favicon.html"
+ <structure name="IDR_OS_SETTINGS_OS_ROUTE_HTML"
+ file="chromeos/os_route.html"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_FAVICON_JS"
- file="site_favicon.js"
+ <structure name="IDR_OS_SETTINGS_OS_ROUTE_JS"
+ file="chromeos/os_route.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_DATA_HTML"
- file="site_settings/site_data.html"
+ <structure name="IDR_OS_SETTINGS_ROUTER_HTML"
+ file="router.html"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_DATA_JS"
- file="site_settings/site_data.js"
+ <structure name="IDR_OS_SETTINGS_ROUTER_JS"
+ file="router.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_DATA_DETAILS_SUBPAGE_HTML"
- file="site_settings/site_data_details_subpage.html"
+ <structure name="IDR_OS_SETTINGS_ROUTE_ORIGIN_BEHAVIOR_HTML"
+ file="chromeos/route_origin_behavior.html"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_DATA_DETAILS_SUBPAGE_JS"
- file="site_settings/site_data_details_subpage.js"
+ <structure name="IDR_OS_SETTINGS_ROUTE_ORIGIN_BEHAVIOR_JS"
+ file="chromeos/route_origin_behavior.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_DATA_ENTRY_HTML"
- file="site_settings/site_data_entry.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_DATA_ENTRY_JS"
- file="site_settings/site_data_entry.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_LIST_HTML"
- file="site_settings/site_list.html"
- preprocess="true"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_LIST_JS"
- file="site_settings/site_list.js"
- preprocess="true"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_LIST_ENTRY_HTML"
- file="site_settings/site_list_entry.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_LIST_ENTRY_JS"
- file="site_settings/site_list_entry.js"
- preprocess="true"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_SETTINGS_BEHAVIOR_HTML"
- file="site_settings/site_settings_behavior.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_SETTINGS_BEHAVIOR_JS"
- file="site_settings/site_settings_behavior.js"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_CONSTANTS_JS"
- file="site_settings/constants.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_CONSTANTS_HTML"
- file="site_settings/constants.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_SETTINGS_PAGE_HTML"
- file="site_settings_page/site_settings_page.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_SETTINGS_PAGE_JS"
- file="site_settings_page/site_settings_page.js"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_SITE_SETTINGS_PREFS_BROWSER_PROXY_HTML"
- file="site_settings/site_settings_prefs_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_SETTINGS_PREFS_BROWSER_PROXY_JS"
- file="site_settings/site_settings_prefs_browser_proxy.js"
- preprocess="true"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_DETAILS_HTML"
- file="site_settings/site_details.html"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_SITE_DETAILS_JS"
- file="site_settings/site_details.js"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_SITE_DETAILS_PERMISSION_HTML"
- file="site_settings/site_details_permission.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SITE_DETAILS_PERMISSION_JS"
- file="site_settings/site_details_permission.js"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_DIALOG_JS"
- file="search_engines_page/search_engine_dialog.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_DIALOG_HTML"
- file="search_engines_page/search_engine_dialog.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_ENTRY_JS"
- file="search_engines_page/search_engine_entry.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_ENTRY_HTML"
- file="search_engines_page/search_engine_entry.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_ENTRY_CSS_HTML"
- file="search_engines_page/search_engine_entry_css.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_OMNIBOX_EXTENSION_ENTRY_JS"
- file="search_engines_page/omnibox_extension_entry.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_OMNIBOX_EXTENSION_ENTRY_HTML"
- file="search_engines_page/omnibox_extension_entry.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_LIST_JS"
- file="search_engines_page/search_engines_list.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_LIST_HTML"
- file="search_engines_page/search_engines_list.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_PAGE_JS"
- file="search_engines_page/search_engines_page.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_PAGE_HTML"
- file="search_engines_page/search_engines_page.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
<structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_BROWSER_PROXY_JS"
file="search_engines_page/search_engines_browser_proxy.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_SEARCH_ENGINES_BROWSER_PROXY_HTML"
file="search_engines_page/search_engines_browser_proxy.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_GOOGLE_ASSISTANT_PAGE_GOOGLE_ASSISTANT_PAGE_JS"
- file="google_assistant_page/google_assistant_page.js"
- type="chrome_html"
- allowexternalscript="true"/>
+ file="chromeos/google_assistant_page/google_assistant_page.js"
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_GOOGLE_ASSISTANT_PAGE_GOOGLE_ASSISTANT_PAGE_HTML"
- file="google_assistant_page/google_assistant_page.html"
- type="chrome_html"
- allowexternalscript="true" />
+ file="chromeos/google_assistant_page/google_assistant_page.html"
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_GOOGLE_ASSISTANT_PAGE_GOOGLE_ASSISTANT_BROWSER_PROXY_JS"
- file="google_assistant_page/google_assistant_browser_proxy.js"
- type="chrome_html"
- allowexternalscript="true" />
+ file="chromeos/google_assistant_page/google_assistant_browser_proxy.js"
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_GOOGLE_ASSISTANT_PAGE_GOOGLE_ASSISTANT_BROWSER_PROXY_HTML"
- file="google_assistant_page/google_assistant_browser_proxy.html"
- type="chrome_html"
- allowexternalscript="true" />
+ file="chromeos/google_assistant_page/google_assistant_browser_proxy.html"
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_SEARCH_PAGE_JS"
file="chromeos/os_search_page/os_search_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_SEARCH_PAGE_HTML"
file="chromeos/os_search_page/os_search_page.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_SYNC_CONTROLS_JS"
file="people_page/sync_controls.js"
type="chrome_html"
@@ -1099,8 +867,14 @@
<structure name="IDR_OS_SETTINGS_SYNC_CONTROLS_HTML"
file="people_page/sync_controls.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
+ <!-- TODO(jamescook): Remove when SplitSettingsSync is the default. -->
+ <structure name="IDR_OS_SETTINGS_SYNC_ENCRYPTION_OPTIONS_JS"
+ file="people_page/sync_encryption_options.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_SYNC_ENCRYPTION_OPTIONS_HTML"
+ file="people_page/sync_encryption_options.html"
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_SYNC_PAGE_JS"
file="people_page/sync_page.js"
type="chrome_html"
@@ -1108,21 +882,16 @@
<structure name="IDR_OS_SETTINGS_SYNC_PAGE_HTML"
file="people_page/sync_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_OS_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY_HTML"
- file="system_page/system_page_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY"
- file="system_page/system_page_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SYSTEM_PAGE_HTML"
- file="system_page/system_page.html"
- preprocess="true"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_SYSTEM_PAGE_JS"
- file="system_page/system_page.js"
- type="chrome_html" />
+ preprocess="true" />
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_ACCOUNT_CONTROL_HTML"
+ file="people_page/sync_account_control.html"
+ type="chrome_html"
+ flattenhtml="true"
+ allowexternalscript="true" />
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_ACCOUNT_CONTROL_JS"
+ file="people_page/sync_account_control.js"
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_SETTINGS_HTML"
file="chromeos/os_settings.html"
preprocess="true"
@@ -1130,280 +899,282 @@
<structure name="IDR_OS_SETTINGS_LAZY_LOAD_HTML"
file="chromeos/lazy_load.html"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_WEBSITE_USAGE_PRIVATE_API_HTML"
- file="site_settings/website_usage_private_api.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_WEBSITE_USAGE_PRIVATE_API_JS"
- file="site_settings/website_usage_private_api.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ZOOM_LEVELS_HTML"
- file="site_settings/zoom_levels.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ZOOM_LEVELS_JS"
- file="site_settings/zoom_levels.js"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ANDROID_APPS_PAGE_HTML"
- file="android_apps_page/android_apps_page.html"
- type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_ANDROID_APPS_PAGE_JS"
- file="android_apps_page/android_apps_page.js"
- type="chrome_html" />
<structure name="IDR_OS_SETTINGS_ANDROID_APPS_SUBPAGE_HTML"
- file="android_apps_page/android_apps_subpage.html"
+ file="chromeos/os_apps_page/android_apps_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_ANDROID_APPS_SUBPAGE_JS"
- file="android_apps_page/android_apps_subpage.js"
+ file="chromeos/os_apps_page/android_apps_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_ANDROID_APPS_BROWSER_PROXY_JS"
- file="android_apps_page/android_apps_browser_proxy.js"
+ file="chromeos/os_apps_page/android_apps_browser_proxy.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_ANDROID_APPS_BROWSER_PROXY_HTML"
- file="android_apps_page/android_apps_browser_proxy.html"
+ file="chromeos/os_apps_page/android_apps_browser_proxy.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_CROSTINI_PAGE_HTML"
- file="crostini_page/crostini_page.html"
+ file="chromeos/crostini_page/crostini_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_PAGE_JS"
- file="crostini_page/crostini_page.js"
+ file="chromeos/crostini_page/crostini_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_SUBPAGE_HTML"
- file="crostini_page/crostini_subpage.html"
+ file="chromeos/crostini_page/crostini_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_SUBPAGE_JS"
- file="crostini_page/crostini_subpage.js"
+ file="chromeos/crostini_page/crostini_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_ARC_ADB_HTML"
- file="crostini_page/crostini_arc_adb.html"
+ file="chromeos/crostini_page/crostini_arc_adb.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_ARC_ADB_JS"
- file="crostini_page/crostini_arc_adb.js"
+ file="chromeos/crostini_page/crostini_arc_adb.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_DIALOG_HTML"
- file="crostini_page/crostini_arc_adb_confirmation_dialog.html"
+ file="chromeos/crostini_page/crostini_arc_adb_confirmation_dialog.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_DIALOG_JS"
- file="crostini_page/crostini_arc_adb_confirmation_dialog.js"
+ file="chromeos/crostini_page/crostini_arc_adb_confirmation_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_CROSTINI_DISK_RESIZE_DIALOG_HTML"
+ file="chromeos/crostini_page/crostini_disk_resize_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_CROSTINI_DISK_RESIZE_DIALOG_JS"
+ file="chromeos/crostini_page/crostini_disk_resize_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_EXPORT_IMPORT_HTML"
- file="crostini_page/crostini_export_import.html"
+ file="chromeos/crostini_page/crostini_export_import.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_EXPORT_IMPORT_JS"
- file="crostini_page/crostini_export_import.js"
+ file="chromeos/crostini_page/crostini_export_import.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_CROSTINI_PORT_FORWARDING_HTML"
+ file="chromeos/crostini_page/crostini_port_forwarding.html"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_DIALOG_HTML"
+ file="chromeos/crostini_page/crostini_port_forwarding_add_port_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_DIALOG_JS"
+ file="chromeos/crostini_page/crostini_port_forwarding_add_port_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_CROSTINI_PORT_FORWARDING_JS"
+ file="chromeos/crostini_page/crostini_port_forwarding.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_CROSTINI_MIC_SHARING_DIALOG_HTML"
+ file="chromeos/crostini_page/crostini_mic_sharing_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_CROSTINI_MIC_SHARING_DIALOG_JS"
+ file="chromeos/crostini_page/crostini_mic_sharing_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_SHARED_PATHS_HTML"
- file="crostini_page/crostini_shared_paths.html"
+ file="chromeos/crostini_page/crostini_shared_paths.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_SHARED_PATHS_JS"
- file="crostini_page/crostini_shared_paths.js"
+ file="chromeos/crostini_page/crostini_shared_paths.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_HTML"
- file="crostini_page/crostini_shared_usb_devices.html"
+ file="chromeos/crostini_page/crostini_shared_usb_devices.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_JS"
- file="crostini_page/crostini_shared_usb_devices.js"
+ file="chromeos/crostini_page/crostini_shared_usb_devices.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_CROSTINI_BROWSER_PROXY_JS"
- file="crostini_page/crostini_browser_proxy.js"
+ file="chromeos/crostini_page/crostini_browser_proxy.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_CROSTINI_BROWSER_PROXY_HTML"
- file="crostini_page/crostini_browser_proxy.html"
+ file="chromeos/crostini_page/crostini_browser_proxy.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_CROSTINI_IMPORT_CONFIRMATION_DIALOG_HTML"
- file="crostini_page/crostini_import_confirmation_dialog.html"
+ file="chromeos/crostini_page/crostini_import_confirmation_dialog.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_CROSTINI_IMPORT_CONFIRMATION_DIALOG_JS"
- file="crostini_page/crostini_import_confirmation_dialog.js"
+ file="chromeos/crostini_page/crostini_import_confirmation_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_BLUETOOTH_DEVICE_LIST_ITEM_HTML"
- file="bluetooth_page/bluetooth_device_list_item.html"
+ file="chromeos/bluetooth_page/bluetooth_device_list_item.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_BLUETOOTH_DEVICE_LIST_ITEM_JS"
- file="bluetooth_page/bluetooth_device_list_item.js"
+ file="chromeos/bluetooth_page/bluetooth_device_list_item.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_BLUETOOTH_PAGE_HTML"
- file="bluetooth_page/bluetooth_page.html"
+ file="chromeos/bluetooth_page/bluetooth_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_BLUETOOTH_PAGE_JS"
- file="bluetooth_page/bluetooth_page.js"
+ file="chromeos/bluetooth_page/bluetooth_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_BLUETOOTH_SUBPAGE_HTML"
- file="bluetooth_page/bluetooth_subpage.html"
+ file="chromeos/bluetooth_page/bluetooth_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_BLUETOOTH_SUBPAGE_JS"
- file="bluetooth_page/bluetooth_subpage.js"
+ file="chromeos/bluetooth_page/bluetooth_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DATE_TIME_PAGE_HTML"
- file="date_time_page/date_time_page.html"
+ file="chromeos/date_time_page/date_time_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DATE_TIME_PAGE_JS"
- file="date_time_page/date_time_page.js"
+ file="chromeos/date_time_page/date_time_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DATE_TIME_TYPES_HTML"
- file="date_time_page/date_time_types.html"
+ file="chromeos/date_time_page/date_time_types.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_DATE_TIME_TYPES_JS"
- file="date_time_page/date_time_types.js"
+ file="chromeos/date_time_page/date_time_types.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_TIMEZONE_SELECTOR_HTML"
- file="date_time_page/timezone_selector.html"
+ file="chromeos/date_time_page/timezone_selector.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_TIMEZONE_SELECTOR_JS"
- file="date_time_page/timezone_selector.js"
+ file="chromeos/date_time_page/timezone_selector.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_TIMEZONE_SUBPAGE_HTML"
- file="date_time_page/timezone_subpage.html"
+ file="chromeos/date_time_page/timezone_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_TIMEZONE_SUBPAGE_JS"
- file="date_time_page/timezone_subpage.js"
+ file="chromeos/date_time_page/timezone_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_CONFIG_HTML"
- file="internet_page/internet_config.html"
+ file="chromeos/internet_page/internet_config.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_CONFIG_JS"
- file="internet_page/internet_config.js"
+ file="chromeos/internet_page/internet_config.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_DETAIL_PAGE_HTML"
- file="internet_page/internet_detail_page.html"
+ file="chromeos/internet_page/internet_detail_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_DETAIL_PAGE_JS"
- file="internet_page/internet_detail_page.js"
+ file="chromeos/internet_page/internet_detail_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_KNOWN_NETWORKS_PAGE_HTML"
- file="internet_page/internet_known_networks_page.html"
+ file="chromeos/internet_page/internet_known_networks_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_KNOWN_NETWORKS_PAGE_JS"
- file="internet_page/internet_known_networks_page.js"
+ file="chromeos/internet_page/internet_known_networks_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_PAGE_BROWSER_PROXY_HTML"
- file="internet_page/internet_page_browser_proxy.html"
+ file="chromeos/internet_page/internet_page_browser_proxy.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_PAGE_BROWSER_PROXY_JS"
- file="internet_page/internet_page_browser_proxy.js"
+ file="chromeos/internet_page/internet_page_browser_proxy.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_PAGE_HTML"
- file="internet_page/internet_page.html"
+ file="chromeos/internet_page/internet_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_PAGE_JS"
- file="internet_page/internet_page.js"
+ file="chromeos/internet_page/internet_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_SHARED_CSS_HTML"
- file="internet_page/internet_shared_css.html"
+ file="chromeos/internet_page/internet_shared_css.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_SUBPAGE_HTML"
- file="internet_page/internet_subpage.html"
+ file="chromeos/internet_page/internet_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_INTERNET_SUBPAGE_JS"
- file="internet_page/internet_subpage.js"
+ file="chromeos/internet_page/internet_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_BROWSER_PROXY_HTML"
- file="multidevice_page/multidevice_browser_proxy.html"
+ file="chromeos/multidevice_page/multidevice_browser_proxy.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_BROWSER_PROXY_JS"
- file="multidevice_page/multidevice_browser_proxy.js"
+ file="chromeos/multidevice_page/multidevice_browser_proxy.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_CONSTANTS_HTML"
- file="multidevice_page/multidevice_constants.html"
+ file="chromeos/multidevice_page/multidevice_constants.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_CONSTANTS_JS"
- file="multidevice_page/multidevice_constants.js"
+ file="chromeos/multidevice_page/multidevice_constants.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_FEATURE_BEHAVIOR_HTML"
- file="multidevice_page/multidevice_feature_behavior.html"
+ file="chromeos/multidevice_page/multidevice_feature_behavior.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_FEATURE_BEHAVIOR_JS"
- file="multidevice_page/multidevice_feature_behavior.js"
+ file="chromeos/multidevice_page/multidevice_feature_behavior.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_FEATURE_ITEM_HTML"
- file="multidevice_page/multidevice_feature_item.html"
+ file="chromeos/multidevice_page/multidevice_feature_item.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_FEATURE_ITEM_JS"
- file="multidevice_page/multidevice_feature_item.js"
+ file="chromeos/multidevice_page/multidevice_feature_item.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_FEATURE_TOGGLE_HTML"
- file="multidevice_page/multidevice_feature_toggle.html"
+ file="chromeos/multidevice_page/multidevice_feature_toggle.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_FEATURE_TOGGLE_JS"
- file="multidevice_page/multidevice_feature_toggle.js"
+ file="chromeos/multidevice_page/multidevice_feature_toggle.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_PAGE_HTML"
- file="multidevice_page/multidevice_page.html"
+ file="chromeos/multidevice_page/multidevice_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_PAGE_JS"
- file="multidevice_page/multidevice_page.js"
+ file="chromeos/multidevice_page/multidevice_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_RADIO_BUTTON_HTML"
- file="multidevice_page/multidevice_radio_button.html"
+ file="chromeos/multidevice_page/multidevice_radio_button.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_RADIO_BUTTON_JS"
- file="multidevice_page/multidevice_radio_button.js"
+ file="chromeos/multidevice_page/multidevice_radio_button.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_SMARTLOCK_SUBPAGE_HTML"
- file="multidevice_page/multidevice_smartlock_subpage.html"
+ file="chromeos/multidevice_page/multidevice_smartlock_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_SMARTLOCK_SUBPAGE_JS"
- file="multidevice_page/multidevice_smartlock_subpage.js"
+ file="chromeos/multidevice_page/multidevice_smartlock_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_SUBPAGE_HTML"
- file="multidevice_page/multidevice_subpage.html"
+ file="chromeos/multidevice_page/multidevice_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_SUBPAGE_JS"
- file="multidevice_page/multidevice_subpage.js"
+ file="chromeos/multidevice_page/multidevice_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_TETHER_ITEM_HTML"
- file="multidevice_page/multidevice_tether_item.html"
+ file="chromeos/multidevice_page/multidevice_tether_item.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_MULTIDEVICE_TETHER_ITEM_JS"
- file="multidevice_page/multidevice_tether_item.js"
+ file="chromeos/multidevice_page/multidevice_tether_item.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_NETWORK_PROXY_SECTION_HTML"
- file="internet_page/network_proxy_section.html"
+ file="chromeos/internet_page/network_proxy_section.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_NETWORK_PROXY_SECTION_JS"
- file="internet_page/network_proxy_section.js"
+ file="chromeos/internet_page/network_proxy_section.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_NETWORK_SUMMARY_HTML"
- file="internet_page/network_summary.html"
+ file="chromeos/internet_page/network_summary.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_NETWORK_SUMMARY_JS"
- file="internet_page/network_summary.js"
+ file="chromeos/internet_page/network_summary.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_NETWORK_SUMMARY_ITEM_HTML"
- file="internet_page/network_summary_item.html"
+ file="chromeos/internet_page/network_summary_item.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_NETWORK_SUMMARY_ITEM_JS"
- file="internet_page/network_summary_item.js"
+ file="chromeos/internet_page/network_summary_item.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_TETHER_CONNECTION_DIALOG_HTML"
- file="internet_page/tether_connection_dialog.html"
+ file="chromeos/internet_page/tether_connection_dialog.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_TETHER_CONNECTION_DIALOG_JS"
- file="internet_page/tether_connection_dialog.js"
+ file="chromeos/internet_page/tether_connection_dialog.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_PARENTAL_CONTROLS_BROWSER_PROXY_HTML"
- file="parental_controls_page/parental_controls_browser_proxy.html"
+ <structure name="IDR_OS_SETTINGS_PARENTAL_CONTROLS_BROWSER_PROXY_HTML"
+ file="chromeos/parental_controls_page/parental_controls_browser_proxy.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_PARENTAL_CONTROLS_BROWSER_PROXY_JS"
- file="parental_controls_page/parental_controls_browser_proxy.js"
+ <structure name="IDR_OS_SETTINGS_PARENTAL_CONTROLS_BROWSER_PROXY_JS"
+ file="chromeos/parental_controls_page/parental_controls_browser_proxy.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PARENTAL_CONTROLS_PAGE_HTML"
- file="parental_controls_page/parental_controls_page.html"
+ file="chromeos/parental_controls_page/parental_controls_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PARENTAL_CONTROLS_PAGE_JS"
- file="parental_controls_page/parental_controls_page.js"
+ file="chromeos/parental_controls_page/parental_controls_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_HTML"
- file="people_page/account_manager.html"
+ file="chromeos/os_people_page/account_manager.html"
type="chrome_html"/>
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_JS"
- file="people_page/account_manager.js"
+ file="chromeos/os_people_page/account_manager.js"
type="chrome_html"/>
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_BROWSER_PROXY_HTML"
file="people_page/account_manager_browser_proxy.html"
@@ -1411,145 +1182,146 @@
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_BROWSER_PROXY_JS"
file="people_page/account_manager_browser_proxy.js"
type="chrome_html"/>
- <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_CHANGE_PICTURE_HTML"
- file="people_page/change_picture.html"
+ <structure name="IDR_OS_SETTINGS_PERSONALIZATION_PAGE_CHANGE_PICTURE_HTML"
+ file="chromeos/personalization_page/change_picture.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_CHANGE_PICTURE_JS"
- file="people_page/change_picture.js"
+ preprocess="true" />
+ <structure name="IDR_OS_SETTINGS_PERSONALIZATION_PAGE_CHANGE_PICTURE_JS"
+ file="chromeos/personalization_page/change_picture.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_PEOPLE_CHANGE_PICTURE_BROWSER_PROXY_JS"
- file="people_page/change_picture_browser_proxy.js"
+ <structure name="IDR_OS_SETTINGS_PERSONALIZATION_PAGE_CHANGE_PICTURE_BROWSER_PROXY_JS"
+ file="chromeos/personalization_page/change_picture_browser_proxy.js"
type="chrome_html" />
- <structure name="IDR_OS_SETTINGS_PEOPLE_CHANGE_PICTURE_BROWSER_PROXY_HTML"
- file="people_page/change_picture_browser_proxy.html"
+ <structure name="IDR_OS_SETTINGS_PERSONALIZATION_PAGE_CHANGE_PICTURE_BROWSER_PROXY_HTML"
+ file="chromeos/personalization_page/change_picture_browser_proxy.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_HTML"
- file="people_page/kerberos_accounts.html"
+ file="chromeos/os_people_page/kerberos_accounts.html"
type="chrome_html"/>
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_JS"
- file="people_page/kerberos_accounts.js"
+ file="chromeos/os_people_page/kerberos_accounts.js"
type="chrome_html"/>
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ADD_ACCOUNT_DIALOG_HTML"
- file="people_page/kerberos_add_account_dialog.html"
+ file="chromeos/os_people_page/kerberos_add_account_dialog.html"
type="chrome_html"/>
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ADD_ACCOUNT_DIALOG_JS"
- file="people_page/kerberos_add_account_dialog.js"
+ file="chromeos/os_people_page/kerberos_add_account_dialog.js"
type="chrome_html"/>
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KEREROS_ACCOUNTS_BROWSER_PROXY_HTML"
- file="people_page/kerberos_accounts_browser_proxy.html"
+ file="chromeos/os_people_page/kerberos_accounts_browser_proxy.html"
type="chrome_html"/>
<structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KEREROS_ACCOUNTS_BROWSER_PROXY_JS"
- file="people_page/kerberos_accounts_browser_proxy.js"
+ file="chromeos/os_people_page/kerberos_accounts_browser_proxy.js"
type="chrome_html"/>
<structure name="IDR_OS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_PROMPT_DIALOG_JS"
- file="people_page/lock_screen_password_prompt_dialog.js"
+ file="chromeos/os_people_page/lock_screen_password_prompt_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_PROMPT_DIALOG_HTML"
- file="people_page/lock_screen_password_prompt_dialog.html"
+ file="chromeos/os_people_page/lock_screen_password_prompt_dialog.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_PEOPLE_LOCK_SCREEN_JS"
- file="people_page/lock_screen.js"
+ file="chromeos/os_people_page/lock_screen.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_LOCK_SCREEN_HTML"
- file="people_page/lock_screen.html"
+ file="chromeos/os_people_page/lock_screen.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_PEOPLE_LOCK_STATE_BEHAVIOR_JS"
- file="people_page/lock_state_behavior.js"
+ file="chromeos/os_people_page/lock_state_behavior.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_LOCK_STATE_BEHAVIOR_HTML"
- file="people_page/lock_state_behavior.html"
+ file="chromeos/os_people_page/lock_state_behavior.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_PEOPLE_SETUP_PIN_DIALOG_JS"
- file="people_page/setup_pin_dialog.js"
+ file="chromeos/os_people_page/setup_pin_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_SETUP_PIN_DIALOG_HTML"
- file="people_page/setup_pin_dialog.html"
+ file="chromeos/os_people_page/setup_pin_dialog.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_PEOPLE_FINGERPRINT_LIST_JS"
- file="people_page/fingerprint_list.js"
+ file="chromeos/os_people_page/fingerprint_list.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_FINGERPRINT_LIST_HTML"
- file="people_page/fingerprint_list.html"
+ file="chromeos/os_people_page/fingerprint_list.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_SETUP_FINGERPRINT_DIALOG_JS"
- file="people_page/setup_fingerprint_dialog.js"
+ file="chromeos/os_people_page/setup_fingerprint_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_SETUP_FINGERPRINT_DIALOG_HTML"
- file="people_page/setup_fingerprint_dialog.html"
+ file="chromeos/os_people_page/setup_fingerprint_dialog.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_FINGERPRINT_BROWSER_PROXY_JS"
- file="people_page/fingerprint_browser_proxy.js"
+ file="chromeos/os_people_page/fingerprint_browser_proxy.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PEOPLE_FINGERPRINT_BROWSER_PROXY_HTML"
- file="people_page/fingerprint_browser_proxy.html"
+ file="chromeos/os_people_page/fingerprint_browser_proxy.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PLUGIN_VM_PAGE_HTML"
- file="plugin_vm_page/plugin_vm_page.html"
+ file="chromeos/plugin_vm_page/plugin_vm_page.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PLUGIN_VM_PAGE_JS"
- file="plugin_vm_page/plugin_vm_page.js"
+ file="chromeos/plugin_vm_page/plugin_vm_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PLUGIN_VM_SHARED_PATHS_HTML"
- file="plugin_vm_page/plugin_vm_shared_paths.html"
+ file="chromeos/plugin_vm_page/plugin_vm_shared_paths.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PLUGIN_VM_SHARED_PATHS_JS"
- file="plugin_vm_page/plugin_vm_shared_paths.js"
+ file="chromeos/plugin_vm_page/plugin_vm_shared_paths.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PLUGIN_VM_SUBPAGE_HTML"
- file="plugin_vm_page/plugin_vm_subpage.html"
+ file="chromeos/plugin_vm_page/plugin_vm_subpage.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PLUGIN_VM_SUBPAGE_JS"
- file="plugin_vm_page/plugin_vm_subpage.js"
+ file="chromeos/plugin_vm_page/plugin_vm_subpage.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PLUGIN_VM_BROWSER_PROXY_JS"
- file="plugin_vm_page/plugin_vm_browser_proxy.js"
- type="chrome_html"
- allowexternalscript="true" />
+ file="chromeos/plugin_vm_page/plugin_vm_browser_proxy.js"
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_PLUGIN_VM_BROWSER_PROXY_HTML"
- file="plugin_vm_page/plugin_vm_browser_proxy.html"
- type="chrome_html"
- allowexternalscript="true" />
+ file="chromeos/plugin_vm_page/plugin_vm_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_PLUGIN_VM_REMOVE_CONFIRMATION_DIALOG_JS"
+ file="chromeos/plugin_vm_page/plugin_vm_remove_confirmation_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_PLUGIN_VM_REMOVE_CONFIRMATION_DIALOG_HTML"
+ file="chromeos/plugin_vm_page/plugin_vm_remove_confirmation_dialog.html"
+ type="chrome_html" />
<structure name="IDR_OS_SETTINGS_USERS_PAGE_ADD_USER_DIALOG_JS"
- file="people_page/users_add_user_dialog.js"
+ file="chromeos/os_people_page/users_add_user_dialog.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_USERS_PAGE_ADD_USER_DIALOG_HTML"
- file="people_page/users_add_user_dialog.html"
+ file="chromeos/os_people_page/users_add_user_dialog.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_USERS_PAGE_USER_LIST_JS"
- file="people_page/user_list.js"
+ file="chromeos/os_people_page/user_list.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_USERS_PAGE_USER_LIST_HTML"
- file="people_page/user_list.html"
+ file="chromeos/os_people_page/user_list.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_USERS_PAGE_JS"
- file="people_page/users_page.js"
+ file="chromeos/os_people_page/users_page.js"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_USERS_PAGE_HTML"
- file="people_page/users_page.html"
+ file="chromeos/os_people_page/users_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_OS_SETTINGS_WALLPAPER_BROWSER_PROXY_HTML"
- file="appearance_page/wallpaper_browser_proxy.html"
+ file="chromeos/personalization_page/wallpaper_browser_proxy.html"
type="chrome_html" />
<structure name="IDR_OS_SETTINGS_WALLPAPER_BROWSER_PROXY_JS"
- file="appearance_page/wallpaper_browser_proxy.js"
+ file="chromeos/personalization_page/wallpaper_browser_proxy.js"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_METRICS_RECORDER_HTML"
+ file="chromeos/metrics_recorder.html"
+ type="chrome_html" />
+ <structure name="IDR_OS_SETTINGS_METRICS_RECORDER_JS"
+ file="chromeos/metrics_recorder.js"
type="chrome_html" />
</structures>
</release>
diff --git a/chromium/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd b/chromium/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd
index 24bcdcc3e4e..4518589cb40 100644
--- a/chromium/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd
+++ b/chromium/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd
@@ -42,6 +42,55 @@
file="os_settings_manifest.json"
type="BINDATA"
compress="gzip" />
+
+ <!-- App Management -->
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_BITMAP_MOJO_LITE_JS"
+ file="${root_gen_dir}\skia\public\mojom\bitmap.mojom-lite.js"
+ compress="gzip"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_FILE_PATH_MOJO_LITE_JS"
+ file="${root_gen_dir}\mojo\public\mojom\base\file_path.mojom-lite.js"
+ compress="gzip"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS"
+ file="${root_gen_dir}\skia\public\mojom\image_info.mojom-lite.js"
+ compress="gzip"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_MOJO_LITE_JS"
+ file="${root_gen_dir}\ui\gfx\image\mojom\image.mojom-lite.js"
+ compress="gzip"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_MOJO_LITE_JS"
+ file="${root_gen_dir}\chrome\browser\ui\webui\app_management\app_management.mojom-lite.js"
+ compress="gzip"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_APP_MANAGEMENT_TYPES_MOJO_LITE_JS"
+ file="${root_gen_dir}\chrome\services\app_service\public\mojom\types.mojom-lite.js"
+ compress="gzip"
+ use_base_dir="false"
+ type="BINDATA" />
+
+ <!-- Search -->
+ <include name="IDR_OS_SETTINGS_SEARCH_MOJOM_LITE_JS"
+ file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\search.mojom-lite.js"
+ compress="gzip"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_SEARCH_RESULT_ICON_MOJOM_LITE_JS"
+ file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\search_result_icon.mojom-lite.js"
+ compress="gzip"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_OS_SETTINGS_USER_ACTION_RECORDER_MOJOM_LITE_JS"
+ file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\user_action_recorder.mojom-lite.js"
+ compress="gzip"
+ use_base_dir="false"
+ type="BINDATA" />
</includes>
</release>
</grit>
diff --git a/chromium/chrome/browser/resources/settings/people_page/BUILD.gn b/chromium/chrome/browser/resources/settings/people_page/BUILD.gn
index 4d652622d07..526c7543251 100644
--- a/chromium/chrome/browser/resources/settings/people_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/people_page/BUILD.gn
@@ -3,13 +3,19 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
":people_page",
":profile_info_browser_proxy",
":signout_dialog",
+ ":sync_account_control",
":sync_browser_proxy",
+ ":sync_controls",
+ ":sync_encryption_options",
":sync_page",
]
@@ -19,149 +25,20 @@ js_type_check("closure_compile") {
":import_data_dialog",
":manage_profile",
":manage_profile_browser_proxy",
- ":sync_account_control",
]
}
if (is_chromeos) {
- deps += [
- ":account_manager",
- ":account_manager_browser_proxy",
- ":change_picture",
- ":change_picture_browser_proxy",
- ":fingerprint_browser_proxy",
- ":fingerprint_list",
- ":kerberos_accounts",
- ":kerberos_accounts_browser_proxy",
- ":kerberos_add_account_dialog",
- ":lock_screen",
- ":lock_screen_password_prompt_dialog",
- ":lock_state_behavior",
- ":setup_fingerprint_dialog",
- ":setup_pin_dialog",
- ":user_list",
- ":users_add_user_dialog",
- ":users_page",
- ]
+ deps += [ ":account_manager_browser_proxy" ]
}
}
-js_library("account_manager") {
- deps = [
- ":account_manager_browser_proxy",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:icon",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
-}
-
js_library("account_manager_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
-}
-
-js_library("change_picture") {
- deps = [
- ":change_picture_browser_proxy",
- "..:route",
- "//third_party/polymer/v1_0/components-chromium/iron-selector:iron-selector-extracted",
- "//ui/webui/resources/cr_elements/chromeos/cr_picture:cr_picture_list",
- "//ui/webui/resources/cr_elements/chromeos/cr_picture:cr_picture_pane",
- "//ui/webui/resources/cr_elements/chromeos/cr_picture:cr_picture_types",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:util",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
-}
-
-js_library("change_picture_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
-}
-
-js_library("fingerprint_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
-}
-
-js_library("fingerprint_list") {
- deps = [
- ":fingerprint_browser_proxy",
- "..:route",
- "//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted",
- "//third_party/polymer/v1_0/components-chromium/paper-ripple:paper-ripple-extracted",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- "//ui/webui/resources/js/cr/ui:focus_without_ink",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("import_data_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
-}
-
-js_library("kerberos_accounts") {
- deps = [
- ":kerberos_accounts_browser_proxy",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:icon",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
-}
-
-js_library("kerberos_accounts_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
-}
-
-js_library("kerberos_add_account_dialog") {
- deps = [
- ":kerberos_accounts_browser_proxy",
- "//chrome/browser/resources/settings/controls:settings_textarea",
- "//ui/webui/resources/cr_elements/cr_input:cr_input",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
-}
-
-js_library("lock_screen") {
- deps = [
- ":fingerprint_browser_proxy",
- ":lock_screen_password_prompt_dialog",
- ":lock_state_behavior",
- "..:route",
- "../controls:settings_dropdown_menu",
- "../controls:settings_toggle_button",
- "//ui/webui/resources/cr_components/chromeos/quick_unlock:lock_screen_constants",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- "//ui/webui/resources/js/cr/ui:focus_without_ink",
- ]
-}
-
-js_library("lock_state_behavior") {
- deps = [
- "..:route",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
- externs_list = [ "$externs_path/quick_unlock_private.js" ]
- extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("manage_profile") {
@@ -169,6 +46,7 @@ js_library("manage_profile") {
":manage_profile_browser_proxy",
":sync_browser_proxy",
"..:route",
+ "..:router",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
@@ -181,27 +59,18 @@ js_library("manage_profile_browser_proxy") {
]
}
-js_library("lock_screen_password_prompt_dialog") {
- deps = [
- ":lock_state_behavior",
- "../controls:password_prompt_dialog",
- "//ui/webui/resources/cr_components/chromeos/quick_unlock:lock_screen_constants",
- ]
-}
-
js_library("people_page") {
deps = [
- ":lock_screen",
- ":lock_state_behavior",
":profile_info_browser_proxy",
":signout_dialog",
":sync_browser_proxy",
"..:open_window_proxy",
"..:page_visibility",
"..:route",
+ "..:router",
"../settings_page:settings_animated_pages",
"//ui/webui/resources/cr_components/chromeos/quick_unlock:lock_screen_constants",
- "//ui/webui/resources/cr_elements/chromeos/cr_picture:cr_png_behavior",
+ "//ui/webui/resources/cr_elements/chromeos/cr_picture:png",
"//ui/webui/resources/cr_elements/cr_toast:cr_toast",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
@@ -213,28 +82,7 @@ js_library("people_page") {
}
js_library("profile_info_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
-}
-
-js_library("setup_fingerprint_dialog") {
- deps = [
- ":fingerprint_browser_proxy",
- "//ui/webui/resources/cr_elements/chromeos/cr_lottie:cr_lottie",
- "//ui/webui/resources/cr_elements/cr_fingerprint:cr_fingerprint_progress_arc",
- "//ui/webui/resources/js:i18n_behavior",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
-}
-
-js_library("setup_pin_dialog") {
- deps = [
- ":lock_screen_password_prompt_dialog",
- "..:route",
- "//ui/webui/resources/cr_components/chromeos/quick_unlock:setup_pin_keyboard",
- "//ui/webui/resources/js:i18n_behavior",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("signout_dialog") {
@@ -254,8 +102,9 @@ js_library("sync_page") {
deps = [
":sync_account_control",
":sync_browser_proxy",
+ ":sync_encryption_options",
"..:page_visibility",
- "..:route",
+ "..:router",
"../settings_page:settings_animated_pages",
"//ui/webui/resources/cr_elements/cr_expand_button:cr_expand_button",
"//ui/webui/resources/cr_elements/cr_input:cr_input",
@@ -275,37 +124,14 @@ js_library("sync_browser_proxy") {
externs_list = [ "$externs_path/metrics_private.js" ]
}
-js_library("user_list") {
- deps = [
- "..:route",
- "//ui/webui/resources/cr_elements:cr_scrollable_behavior",
- "//ui/webui/resources/js:i18n_behavior",
- ]
- externs_list = [
- "$externs_path/settings_private.js",
- "$externs_path/users_private.js",
- ]
-}
-
-js_library("users_add_user_dialog") {
- deps = [
- "//ui/webui/resources/js:assert",
- ]
- externs_list = [ "$externs_path/users_private.js" ]
-}
-
-js_library("users_page") {
- deps = [
- ":user_list",
- ":users_add_user_dialog",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js/cr/ui:focus_without_ink",
- ]
+js_library("sync_controls") {
+ deps = [ "..:router" ]
}
js_library("import_data_dialog") {
deps = [
":import_data_browser_proxy",
+ "../controls:settings_checkbox",
"../prefs:prefs_behavior",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
@@ -316,7 +142,7 @@ js_library("sync_account_control") {
deps = [
":profile_info_browser_proxy",
":sync_browser_proxy",
- "..:route",
+ "..:router",
"../prefs:prefs_behavior",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/js:icon",
@@ -324,3 +150,322 @@ js_library("sync_account_control") {
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
+
+js_library("sync_encryption_options") {
+ deps = [
+ ":sync_browser_proxy",
+ "//ui/webui/resources/cr_elements/cr_input",
+ "//ui/webui/resources/cr_elements/cr_radio_group",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":account_manager_browser_proxy.m",
+ ":people_page.m",
+ ":profile_info_browser_proxy.m",
+ ":signout_dialog.m",
+ ":sync_account_control.m",
+ ":sync_browser_proxy.m",
+ ":sync_controls.m",
+ ":sync_encryption_options.m",
+ ":sync_page.m",
+ ]
+
+ if (!is_chromeos) {
+ deps += [
+ ":import_data_browser_proxy.m",
+ ":import_data_dialog.m",
+ ":manage_profile.m",
+ ":manage_profile_browser_proxy.m",
+ ]
+ }
+}
+
+js_library("account_manager_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+if (!is_chromeos) {
+ js_library("import_data_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/import_data_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ externs_list = [ "$externs_path/metrics_private.js" ]
+ extra_deps = [ ":modulize" ]
+ }
+
+ js_library("import_data_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/import_data_dialog.m.js" ]
+ deps = [
+ ":import_data_browser_proxy.m",
+ "../controls:settings_checkbox.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":import_data_dialog_module" ]
+ }
+
+ js_library("manage_profile.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/manage_profile.m.js" ]
+ deps = [
+ ":manage_profile_browser_proxy.m",
+ ":sync_browser_proxy.m",
+ "..:i18n_setup.m",
+ "..:route.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":manage_profile_module" ]
+ }
+
+ js_library("manage_profile_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/manage_profile_browser_proxy.m.js" ]
+ deps = [
+ "//ui/webui/resources/cr_elements/cr_profile_avatar_selector:cr_profile_avatar_selector.m",
+ "//ui/webui/resources/js:cr.m",
+ ]
+ extra_deps = [ ":modulize" ]
+ }
+}
+
+js_library("people_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/people_page.m.js" ]
+ deps = [
+ ":account_manager_browser_proxy.m",
+ ":profile_info_browser_proxy.m",
+ ":sync_browser_proxy.m",
+ "..:i18n_setup.m",
+ "..:open_window_proxy.m",
+ "..:page_visibility.m",
+ "..:route.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/chromeos/cr_picture:png.m",
+ "//ui/webui/resources/cr_elements/cr_toast:cr_toast.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:icon.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":people_page_module" ]
+}
+
+js_library("profile_info_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("signout_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/signout_dialog.m.js" ]
+ deps = [
+ ":profile_info_browser_proxy.m",
+ ":sync_browser_proxy.m",
+ "..:i18n_setup.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":signout_dialog_module" ]
+}
+
+js_library("sync_account_control.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/sync_account_control.m.js" ]
+ deps = [
+ ":sync_browser_proxy.m",
+ "..:i18n_setup.m",
+ "..:router.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/js:assert.m",
+ ]
+ extra_deps = [ ":sync_account_control_module" ]
+}
+
+js_library("sync_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/sync_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ externs_list = [ "$externs_path/metrics_private.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("sync_controls.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/sync_controls.m.js" ]
+ deps = [
+ ":sync_browser_proxy.m",
+ "..:i18n_setup.m",
+ "..:router.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":sync_controls_module" ]
+}
+
+js_library("sync_encryption_options.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/sync_encryption_options.m.js" ]
+ deps = [
+ ":sync_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ ]
+ extra_deps = [ ":sync_encryption_options_module" ]
+}
+
+js_library("sync_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/people_page/sync_page.m.js" ]
+ deps = [
+ ":sync_browser_proxy.m",
+ "..:i18n_setup.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
+ "//ui/webui/resources/js:assert.m",
+ ]
+ extra_deps = [ ":sync_page_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":modulize",
+ ":people_page_module",
+ ":signout_dialog_module",
+ ":sync_account_control_module",
+ ":sync_controls_module",
+ ":sync_encryption_options_module",
+ ":sync_page_module",
+ ]
+
+ if (!is_chromeos) {
+ public_deps += [
+ ":import_data_dialog_module",
+ ":manage_profile_module",
+ ]
+ }
+}
+
+polymer_modulizer("import_data_dialog") {
+ js_file = "import_data_dialog.js"
+ html_file = "import_data_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/people_page/import_data_browser_proxy.html|ImportDataBrowserProxy,ImportDataBrowserProxyImpl,ImportDataStatus,BrowserProfile" ]
+}
+
+polymer_modulizer("manage_profile") {
+ js_file = "manage_profile.js"
+ html_file = "manage_profile.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/people_page/manage_profile_browser_proxy.html|ManageProfileBrowserProxy,ManageProfileBrowserProxyImpl,ProfileShortcutStatus",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncStatus",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router,RouteObserverBehavior",
+ "ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html|AvatarIcon",
+ ]
+}
+
+polymer_modulizer("people_page") {
+ js_file = "people_page.js"
+ html_file = "people_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/open_window_proxy.html|OpenWindowProxyImpl",
+ "chrome/browser/resources/settings/router.html|Router,RouteObserverBehavior",
+ "ui/webui/resources/cr_elements/chromeos/cr_picture/png.html|convertImageSequenceToPng",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/cr.html|isChromeOS",
+ "ui/webui/resources/html/icon.html|getImage",
+ "chrome/browser/resources/settings/page_visibility.html|PageVisibility",
+ "chrome/browser/resources/settings/people_page/account_manager_browser_proxy.html|AccountManagerBrowserProxyImpl",
+ "chrome/browser/resources/settings/people_page/profile_info_browser_proxy.html|ProfileInfoBrowserProxyImpl,ProfileInfoBrowserProxy,ProfileInfo",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxyImpl,SyncBrowserProxy,SyncStatus,StoredAccount",
+ ]
+}
+
+polymer_modulizer("signout_dialog") {
+ js_file = "signout_dialog.js"
+ html_file = "signout_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/people_page/profile_info_browser_proxy.html|ProfileInfoBrowserProxyImpl",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxyImpl,SyncStatus",
+ ]
+}
+
+polymer_modulizer("sync_account_control") {
+ js_file = "sync_account_control.js"
+ html_file = "sync_account_control.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxy,SyncBrowserProxyImpl,SyncStatus,StatusAction,StoredAccount",
+ "chrome/browser/resources/settings/router.html|Router",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+}
+
+polymer_modulizer("sync_controls") {
+ js_file = "sync_controls.js"
+ html_file = "sync_controls.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/router.html|Router,RouteObserverBehavior",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxy,SyncBrowserProxyImpl,StatusAction,SyncStatus,SyncPrefs",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+}
+
+polymer_modulizer("sync_encryption_options") {
+ js_file = "sync_encryption_options.js"
+ html_file = "sync_encryption_options.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxyImpl,SyncPrefs,SyncStatus",
+ "ui/webui/resources/html/assert.html|assert,assertNotReached",
+ ]
+}
+
+polymer_modulizer("sync_page") {
+ js_file = "sync_page.js"
+ html_file = "sync_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/html/polymer.html|Polymer,html,flush",
+ "chrome/browser/resources/settings/router.html|Router,RouteObserverBehavior",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxy,SyncBrowserProxyImpl,PageStatus,StatusAction,SyncStatus,SyncPrefs",
+ "ui/webui/resources/html/assert.html|assert,assertNotReached",
+ ]
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "account_manager_browser_proxy.js",
+ "profile_info_browser_proxy.js",
+ "sync_browser_proxy.js",
+ ]
+
+ if (!is_chromeos) {
+ input_files += [
+ "import_data_browser_proxy.js",
+ "manage_profile_browser_proxy.js",
+ ]
+ }
+
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/prefs/BUILD.gn b/chromium/chrome/browser/resources/settings/prefs/BUILD.gn
index 6f61f794d71..5caf67cafc3 100644
--- a/chromium/chrome/browser/resources/settings/prefs/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/prefs/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -14,9 +17,7 @@ js_type_check("closure_compile") {
}
js_library("pref_util") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [ "$externs_path/settings_private.js" ]
}
@@ -25,18 +26,85 @@ js_library("prefs") {
":pref_util",
":prefs_behavior",
":prefs_types",
- "//ui/webui/resources/js:cr",
]
externs_list = [ "$externs_path/settings_private.js" ]
extra_sources = [ "$interfaces_path/settings_private_interface.js" ]
}
js_library("prefs_behavior") {
+ deps = [ "//ui/webui/resources/js:assert" ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+}
+
+js_library("prefs_types") {
+}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
deps = [
- "//ui/webui/resources/js:assert",
+ ":pref_util.m",
+ ":prefs.m",
+ ":prefs_behavior.m",
+ ":prefs_types.m",
]
+}
+
+js_library("pref_util.m") {
+ sources =
+ [ "$root_gen_dir/chrome/browser/resources/settings/prefs/pref_util.m.js" ]
+ deps = [ "//ui/webui/resources/js:assert.m" ]
externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":modulize" ]
}
-js_library("prefs_types") {
+js_library("prefs.m") {
+ sources =
+ [ "$root_gen_dir/chrome/browser/resources/settings/prefs/prefs.m.js" ]
+ deps = [
+ ":pref_util.m",
+ ":prefs_types.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":prefs_module" ]
+ extra_sources = [ "$interfaces_path/settings_private_interface.js" ]
+}
+
+js_library("prefs_behavior.m") {
+ sources = [
+ "$root_gen_dir/chrome/browser/resources/settings/prefs/prefs_behavior.m.js",
+ ]
+ deps = [ "//ui/webui/resources/js:assert.m" ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("prefs_types.m") {
+ sources = [
+ "$root_gen_dir/chrome/browser/resources/settings/prefs/prefs_types.m.js",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":modulize",
+ ":prefs_module",
+ ]
+}
+
+polymer_modulizer("prefs") {
+ js_file = "prefs.js"
+ html_file = "prefs.html"
+ html_type = "dom-module"
+ auto_imports =
+ settings_auto_imports + [ "ui/webui/resources/html/assert.html|assert" ]
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "prefs_behavior.js",
+ "prefs_types.js",
+ "pref_util.js",
+ ]
}
diff --git a/chromium/chrome/browser/resources/settings/printing_page/BUILD.gn b/chromium/chrome/browser/resources/settings/printing_page/BUILD.gn
index 600bba23f47..751b4e43c85 100644
--- a/chromium/chrome/browser/resources/settings/printing_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/printing_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -10,165 +13,94 @@ js_type_check("closure_compile") {
":printing_page",
]
- if (is_chromeos) {
- deps += [
- ":cups_add_printer_dialog",
- ":cups_add_printer_dialog_elements",
- ":cups_edit_printer_dialog",
- ":cups_nearby_printers",
- ":cups_printer_dialog_util",
- ":cups_printer_types",
- ":cups_printers",
- ":cups_printers_browser_proxy",
- ":cups_printers_entry",
- ":cups_printers_entry_list_behavior",
- ":cups_printers_entry_manager",
- ":cups_printers_list",
- ":cups_saved_printers",
- ":printing_browser_proxy",
- ]
+ if (!is_chromeos) {
+ deps += [ ":printing_browser_proxy" ]
}
}
js_library("cloud_printers") {
- deps = [
- "//ui/webui/resources/js:load_time_data",
- ]
}
js_library("printing_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("printing_page") {
deps = [
":printing_browser_proxy",
"..:route",
+ "..:router",
"../settings_page:settings_animated_pages",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:load_time_data",
]
- if (is_chromeos) {
- deps += [ ":cups_printers_browser_proxy" ]
- }
}
-if (is_chromeos) {
- js_library("cups_add_printer_dialog") {
- deps = [
- ":cups_printers_browser_proxy",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
- }
-
- js_library("cups_add_printer_dialog_elements") {
- deps = [
- ":cups_printers_browser_proxy",
- ]
- }
-
- js_library("cups_edit_printer_dialog") {
- deps = [
- "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider",
- "//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
- "//ui/webui/resources/cr_components/chromeos/network:onc_mojo",
- "//ui/webui/resources/cr_elements:cr_scrollable_behavior",
- ]
- }
-
- js_library("cups_nearby_printers") {
- deps = [
- ":cups_printer_types",
- ":cups_printers_browser_proxy",
- ":cups_printers_entry",
- ":cups_printers_entry_list_behavior",
- ":cups_printers_entry_manager",
- "//ui/webui/resources/js:list_property_update_behavior",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
- }
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":cloud_printers.m",
+ ":printing_page.m",
+ ]
- js_library("cups_printer_types") {
- deps = [
- ":cups_printers_browser_proxy",
- ]
+ if (!is_chromeos) {
+ deps += [ ":printing_browser_proxy.m" ]
}
+}
- js_library("cups_printer_dialog_util") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
- }
+js_library("cloud_printers.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/printing_page/cloud_printers.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":cloud_printers_module" ]
+}
- js_library("cups_printers") {
- deps = [
- ":cups_nearby_printers",
- ":cups_printers_browser_proxy",
- ":cups_printers_entry_manager",
- ":cups_saved_printers",
- "..:route",
- "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider",
- "//ui/webui/resources/cr_components/chromeos/network:network_listener_behavior",
- "//ui/webui/resources/cr_components/chromeos/network:onc_mojo",
- "//ui/webui/resources/cr_elements/cr_toast:cr_toast",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:load_time_data",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- "//ui/webui/resources/js/cr/ui:focus_without_ink",
- ]
- }
+js_library("printing_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/printing_page/printing_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
- js_library("cups_printers_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
- }
+js_library("printing_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/printing_page/printing_page.m.js" ]
+ deps = [
+ ":printing_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "../settings_page:settings_animated_pages.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":printing_page_module" ]
+}
- js_library("cups_printers_entry") {
- deps = [
- ":cups_printer_types",
- ":cups_printers_browser_proxy",
- ]
- }
+group("polymer3_elements") {
+ public_deps = [
+ ":cloud_printers_module",
+ ":printing_page_module",
+ ]
- js_library("cups_printers_entry_list_behavior") {
- deps = [
- ":cups_printer_types",
- "//ui/webui/resources/js:list_property_update_behavior",
- ]
+ if (!is_chromeos) {
+ public_deps += [ ":modulize" ]
}
+}
- js_library("cups_printers_entry_manager") {
- deps = [
- ":cups_printer_types",
- ":cups_printers_browser_proxy",
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:cr",
- ]
- }
+polymer_modulizer("cloud_printers") {
+ js_file = "cloud_printers.js"
+ html_file = "cloud_printers.html"
+ html_type = "dom-module"
+}
- js_library("cups_printers_list") {
- deps = [
- ":cups_printers_browser_proxy",
- "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:icon",
- ]
- }
+polymer_modulizer("printing_page") {
+ js_file = "printing_page.js"
+ html_file = "printing_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ ]
+}
- js_library("cups_saved_printers") {
- deps = [
- ":cups_printer_types",
- ":cups_printers_browser_proxy",
- ":cups_printers_entry",
- ":cups_printers_entry_list_behavior",
- ":cups_printers_entry_manager",
- "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
- "//ui/webui/resources/js:list_property_update_behavior",
- "//ui/webui/resources/js:web_ui_listener_behavior",
- ]
- }
+js_modulizer("modulize") {
+ input_files = [ "printing_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
}
diff --git a/chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn b/chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn
index 5dab83f251b..414008552b4 100644
--- a/chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/privacy_page/BUILD.gn
@@ -3,18 +3,63 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
+ ":collapse_radio_button",
+ ":cookies_page",
+ ":disable_safebrowsing_dialog",
+ ":do_not_track_toggle",
":passwords_leak_detection_toggle",
":personalization_options",
":privacy_page",
":privacy_page_browser_proxy",
+ ":safe_browsing_browser_proxy",
+ ":secure_dns",
+ ":secure_dns_input",
":security_keys_bio_enroll_dialog",
":security_keys_credential_management_dialog",
":security_keys_reset_dialog",
":security_keys_set_pin_dialog",
":security_keys_subpage",
+ ":security_page",
+ ]
+}
+
+js_library("collapse_radio_button") {
+ deps = [
+ "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button_behavior",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_indicator",
+ ]
+}
+
+js_library("cookies_page") {
+ deps = [
+ "..:metrics_browser_proxy",
+ "..:route",
+ "..:router",
+ "../prefs:prefs_behavior",
+ "../site_settings:constants",
+ "../site_settings:site_settings_prefs_browser_proxy",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ]
+}
+
+js_library("disable_safebrowsing_dialog") {
+ deps = [ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog" ]
+}
+
+js_library("do_not_track_toggle") {
+ deps = [
+ "..:metrics_browser_proxy",
+ "../controls:settings_toggle_button",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
]
}
@@ -22,7 +67,7 @@ js_library("personalization_options") {
deps = [
":privacy_page_browser_proxy",
"..:page_visibility",
- "..:route",
+ "..:router",
"../controls:settings_toggle_button",
"../people_page:sync_browser_proxy",
"../prefs:prefs_behavior",
@@ -53,14 +98,18 @@ js_library("privacy_page_browser_proxy") {
js_library("privacy_page") {
deps = [
":privacy_page_browser_proxy",
+ "..:hats_browser_proxy",
+ "..:metrics_browser_proxy",
"..:page_visibility",
"..:route",
+ "..:router",
"../controls:settings_toggle_button",
"../people_page:signout_dialog",
"../people_page:sync_browser_proxy",
"../settings_page:settings_animated_pages",
"../site_settings:constants",
"../site_settings:site_data_details_subpage",
+ "../site_settings:site_settings_prefs_browser_proxy",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
@@ -69,17 +118,42 @@ js_library("privacy_page") {
externs_list = [ "$externs_path/settings_private.js" ]
}
-js_library("security_keys_browser_proxy") {
+js_library("safe_browsing_browser_proxy") {
deps = [
+ "../site_settings:site_settings_prefs_browser_proxy",
"//ui/webui/resources/js:cr",
]
externs_list = [ "$externs_path/chrome_send.js" ]
}
+js_library("secure_dns") {
+ deps = [
+ ":privacy_page_browser_proxy",
+ "../prefs:prefs_behavior",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+}
+
+js_library("secure_dns_input") {
+ deps = [
+ ":privacy_page_browser_proxy",
+ "//ui/webui/resources/js:load_time_data",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+}
+
+js_library("security_keys_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+}
+
js_library("security_keys_subpage") {
deps = [
":security_keys_browser_proxy",
- "..:route",
+ "..:router",
"../settings_page:settings_animated_pages",
"//ui/webui/resources/js:i18n_behavior",
]
@@ -96,9 +170,7 @@ js_library("security_keys_set_pin_dialog") {
}
js_library("security_keys_pin_field") {
- deps = [
- "//ui/webui/resources/js:i18n_behavior",
- ]
+ deps = [ "//ui/webui/resources/js:i18n_behavior" ]
}
js_library("security_keys_credential_management_dialog") {
@@ -128,3 +200,487 @@ js_library("security_keys_bio_enroll_dialog") {
]
externs_list = [ "$externs_path/settings_private.js" ]
}
+
+js_library("security_page") {
+ deps = [
+ ":disable_safebrowsing_dialog",
+ ":privacy_page_browser_proxy",
+ ":safe_browsing_browser_proxy",
+ "..:metrics_browser_proxy",
+ "..:route",
+ "..:router",
+ "../people_page:sync_browser_proxy",
+ "../prefs:prefs_behavior",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ]
+}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":collapse_radio_button.m",
+ ":cookies_page.m",
+ ":disable_safebrowsing_dialog.m",
+ ":do_not_track_toggle.m",
+ ":passwords_leak_detection_toggle.m",
+ ":personalization_options.m",
+ ":privacy_page.m",
+ ":privacy_page_browser_proxy.m",
+ ":safe_browsing_browser_proxy.m",
+ ":secure_dns.m",
+ ":secure_dns_input.m",
+ ":security_keys_bio_enroll_dialog.m",
+ ":security_keys_browser_proxy.m",
+ ":security_keys_credential_management_dialog.m",
+ ":security_keys_pin_field.m",
+ ":security_keys_reset_dialog.m",
+ ":security_keys_set_pin_dialog.m",
+ ":security_keys_subpage.m",
+ ":security_page.m",
+ ]
+}
+
+js_library("cookies_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/cookies_page.m.js" ]
+ deps = [
+ "..:metrics_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "../prefs:prefs_behavior.m",
+ "../site_settings:site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":cookies_page_module" ]
+}
+
+js_library("collapse_radio_button.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/collapse_radio_button.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button_behavior.m",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior.m",
+ ]
+ extra_deps = [ ":collapse_radio_button_module" ]
+}
+
+js_library("secure_dns.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/secure_dns.m.js" ]
+ deps = [
+ ":privacy_page_browser_proxy.m",
+ "..:i18n_setup.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":secure_dns_module" ]
+}
+
+js_library("secure_dns_input.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/secure_dns_input.m.js" ]
+ deps = [
+ ":privacy_page_browser_proxy.m",
+ "..:i18n_setup.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":secure_dns_input_module" ]
+}
+
+js_library("disable_safebrowsing_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/disable_safebrowsing_dialog.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ ]
+ extra_deps = [ ":disable_safebrowsing_dialog_module" ]
+}
+
+js_library("do_not_track_toggle.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.m.js" ]
+ deps = [
+ "..:metrics_browser_proxy.m",
+ "../controls:settings_toggle_button.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ extra_deps = [ ":do_not_track_toggle_module" ]
+}
+
+js_library("passwords_leak_detection_toggle.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/passwords_leak_detection_toggle.m.js" ]
+ deps = [
+ "..:metrics_browser_proxy.m",
+ "../people_page:sync_browser_proxy.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":passwords_leak_detection_toggle_module" ]
+}
+
+js_library("personalization_options.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/personalization_options.m.js" ]
+ deps = [
+ ":privacy_page_browser_proxy.m",
+ "..:i18n_setup.m",
+ "..:lifetime_browser_proxy.m",
+ "../controls:settings_toggle_button.m",
+ "../people_page:signout_dialog.m",
+ "../people_page:sync_browser_proxy.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":personalization_options_module" ]
+}
+
+js_library("privacy_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/privacy_page.m.js" ]
+ deps = [
+ ":privacy_page_browser_proxy.m",
+ "..:hats_browser_proxy.m",
+ "..:i18n_setup.m",
+ "..:metrics_browser_proxy.m",
+ "..:page_visibility.m",
+ "..:route.m",
+ "..:router.m",
+ "../controls:settings_toggle_button.m",
+ "../people_page:sync_browser_proxy.m",
+ "../prefs:prefs_behavior.m",
+ "../site_settings:constants.m",
+ "../site_settings:site_data_details_subpage.m",
+ "../site_settings:site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ extra_deps = [ ":privacy_page_module" ]
+}
+
+js_library("privacy_page_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("safe_browsing_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/safe_browsing_browser_proxy.m.js" ]
+ deps = [
+ "../site_settings:site_settings_prefs_browser_proxy.m",
+ "//ui/webui/resources/js:cr.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("security_keys_bio_enroll_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.m.js" ]
+ deps = [
+ ":security_keys_browser_proxy.m",
+ ":security_keys_pin_field.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_fingerprint:cr_fingerprint_progress_arc.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":security_keys_bio_enroll_dialog_module" ]
+}
+
+js_library("security_keys_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("security_keys_credential_management_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.m.js" ]
+ deps = [
+ ":security_keys_browser_proxy.m",
+ ":security_keys_pin_field.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":security_keys_credential_management_dialog_module" ]
+}
+
+js_library("security_keys_pin_field.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ extra_deps = [ ":security_keys_pin_field_module" ]
+}
+
+js_library("security_keys_reset_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.m.js" ]
+ deps = [
+ ":security_keys_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ extra_deps = [ ":security_keys_reset_dialog_module" ]
+}
+
+js_library("security_keys_set_pin_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.m.js" ]
+ deps = [
+ ":security_keys_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ ]
+ extra_deps = [ ":security_keys_set_pin_dialog_module" ]
+}
+
+js_library("security_keys_subpage.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/security_keys_subpage.m.js" ]
+ deps = [
+ "..:i18n_setup.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ ]
+ extra_deps = [ ":security_keys_subpage_module" ]
+}
+
+js_library("security_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/privacy_page/security_page.m.js" ]
+ deps = [
+ ":disable_safebrowsing_dialog.m",
+ ":privacy_page_browser_proxy.m",
+ ":safe_browsing_browser_proxy.m",
+ "..:i18n_setup.m",
+ "..:metrics_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "../people_page:sync_browser_proxy.m",
+ "../prefs:prefs_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ extra_deps = [ ":security_page_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":collapse_radio_button_module",
+ ":cookies_page_module",
+ ":disable_safebrowsing_dialog_module",
+ ":do_not_track_toggle_module",
+ ":modulize",
+ ":passwords_leak_detection_toggle_module",
+ ":personalization_options_module",
+ ":privacy_page_module",
+ ":secure_dns_input_module",
+ ":secure_dns_module",
+ ":security_keys_bio_enroll_dialog_module",
+ ":security_keys_credential_management_dialog_module",
+ ":security_keys_pin_field_module",
+ ":security_keys_reset_dialog_module",
+ ":security_keys_set_pin_dialog_module",
+ ":security_keys_subpage_module",
+ ":security_page_module",
+ ]
+}
+
+polymer_modulizer("cookies_page") {
+ js_file = "cookies_page.js"
+ html_file = "cookies_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|SiteSettingsPrefsBrowserProxy,SiteSettingsPrefsBrowserProxyImpl,ContentSettingProvider,CookieControlsManagedState,DefaultContentSetting",
+ "chrome/browser/resources/settings/site_settings/constants.html|ContentSettingsTypes,SiteSettingSource,CookieControlsMode,ContentSetting",
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/metrics_browser_proxy.html|PrivacyElementInteractions,MetricsBrowserProxy,MetricsBrowserProxyImpl",
+ ]
+}
+
+polymer_modulizer("collapse_radio_button") {
+ js_file = "collapse_radio_button.js"
+ html_file = "collapse_radio_button.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.html|CrPolicyIndicatorType",
+ "ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button_behavior.html|CrRadioButtonBehavior",
+ ]
+}
+
+polymer_modulizer("disable_safebrowsing_dialog") {
+ js_file = "disable_safebrowsing_dialog.js"
+ html_file = "disable_safebrowsing_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports
+}
+
+polymer_modulizer("secure_dns") {
+ js_file = "secure_dns.js"
+ html_file = "secure_dns.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.html|PrivacyPageBrowserProxy,PrivacyPageBrowserProxyImpl,SecureDnsUiManagementMode,SecureDnsMode,ResolverOption,SecureDnsSetting",
+ "ui/webui/resources/html/assert.html|assertNotReached",
+ ]
+}
+
+polymer_modulizer("secure_dns_input") {
+ js_file = "secure_dns_input.js"
+ html_file = "secure_dns_input.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.html|PrivacyPageBrowserProxy,PrivacyPageBrowserProxyImpl" ]
+}
+
+polymer_modulizer("do_not_track_toggle") {
+ js_file = "do_not_track_toggle.js"
+ html_file = "do_not_track_toggle.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/metrics_browser_proxy.html|PrivacyElementInteractions,MetricsBrowserProxyImpl" ]
+}
+
+polymer_modulizer("passwords_leak_detection_toggle") {
+ js_file = "passwords_leak_detection_toggle.js"
+ html_file = "passwords_leak_detection_toggle.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxyImpl,SyncStatus,StoredAccount",
+ "chrome/browser/resources/settings/metrics_browser_proxy.html|PrivacyElementInteractions,MetricsBrowserProxyImpl",
+ ]
+}
+
+polymer_modulizer("personalization_options") {
+ js_file = "personalization_options.js"
+ html_file = "personalization_options.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.html|PrivacyPageBrowserProxy,PrivacyPageBrowserProxyImpl,MetricsReporting",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|StatusAction,SyncStatus",
+ "chrome/browser/resources/settings/lifetime_browser_proxy.html|LifetimeBrowserProxyImpl",
+ ]
+}
+
+polymer_modulizer("privacy_page") {
+ js_file = "privacy_page.js"
+ html_file = "privacy_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/metrics_browser_proxy.html|PrivacyElementInteractions,MetricsBrowserProxyImpl",
+ "chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.html|PrivacyPageBrowserProxy,PrivacyPageBrowserProxyImpl",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|SiteSettingsPrefsBrowserProxyImpl",
+ "chrome/browser/resources/settings/site_settings/constants.html|ContentSettingsTypes,CookieControlsMode,ChooserType",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncBrowserProxyImpl,SyncStatus",
+ "chrome/browser/resources/settings/hats_browser_proxy.html|HatsBrowserProxyImpl",
+ "chrome/browser/resources/settings/page_visibility.html|PrivacyPageVisibility",
+ "chrome/browser/resources/settings/router.html|RouteObserverBehavior,Router",
+ ]
+}
+
+polymer_modulizer("security_keys_bio_enroll_dialog") {
+ js_file = "security_keys_bio_enroll_dialog.js"
+ html_file = "security_keys_bio_enroll_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.html|SecurityKeysBioEnrollProxy,SecurityKeysBioEnrollProxyImpl,Ctap2Status,SampleStatus,Enrollment,EnrollmentResponse,SampleResponse,",
+ "ui/webui/resources/html/assert.html|assert,assertNotReached",
+ "ui/webui/resources/html/polymer.html|afterNextRender,html,Polymer",
+ ]
+}
+
+polymer_modulizer("security_keys_credential_management_dialog") {
+ js_file = "security_keys_credential_management_dialog.js"
+ html_file = "security_keys_credential_management_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.html|SecurityKeysCredentialBrowserProxy,SecurityKeysCredentialBrowserProxyImpl,Credential",
+ "ui/webui/resources/html/assert.html|assert,assertNotReached",
+ ]
+}
+
+polymer_modulizer("security_keys_pin_field") {
+ js_file = "security_keys_pin_field.js"
+ html_file = "security_keys_pin_field.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports =
+ settings_auto_imports +
+ [ "ui/webui/resources/html/polymer.html|afterNextRender,html,Polymer" ]
+}
+
+polymer_modulizer("security_keys_reset_dialog") {
+ js_file = "security_keys_reset_dialog.js"
+ html_file = "security_keys_reset_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.html|SecurityKeysResetBrowserProxy,SecurityKeysResetBrowserProxyImpl" ]
+}
+
+polymer_modulizer("security_keys_set_pin_dialog") {
+ js_file = "security_keys_set_pin_dialog.js"
+ html_file = "security_keys_set_pin_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.html|SecurityKeysPINBrowserProxy,SecurityKeysPINBrowserProxyImpl",
+ "ui/webui/resources/html/polymer.html|afterNextRender,html,Polymer",
+ ]
+}
+
+polymer_modulizer("security_keys_subpage") {
+ js_file = "security_keys_subpage.js"
+ html_file = "security_keys_subpage.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports =
+ settings_auto_imports + [ "ui/webui/resources/html/assert.html|assert" ]
+}
+
+polymer_modulizer("security_page") {
+ js_file = "security_page.js"
+ html_file = "security_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/router.html|Router",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/metrics_browser_proxy.html|PrivacyElementInteractions,MetricsBrowserProxy,MetricsBrowserProxyImpl",
+ "chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.html|PrivacyPageBrowserProxy,PrivacyPageBrowserProxyImpl",
+ "chrome/browser/resources/settings/privacy_page/safe_browsing_browser_proxy.html|SafeBrowsingBrowserProxy,SafeBrowsingBrowserProxyImpl,SafeBrowsingRadioManagedState",
+ "chrome/browser/resources/settings/people_page/sync_browser_proxy.html|SyncStatus",
+ ]
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "privacy_page_browser_proxy.js",
+ "safe_browsing_browser_proxy.js",
+ "security_keys_browser_proxy.js",
+ ]
+
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/reset_page/BUILD.gn b/chromium/chrome/browser/resources/settings/reset_page/BUILD.gn
index 0e0d76b780d..31c4ec6700d 100644
--- a/chromium/chrome/browser/resources/settings/reset_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/reset_page/BUILD.gn
@@ -3,31 +3,24 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
":reset_browser_proxy",
":reset_page",
+ ":reset_profile_banner",
":reset_profile_dialog",
]
-
- if (is_chromeos) {
- deps += [ ":powerwash_dialog" ]
- }
-}
-
-js_library("powerwash_dialog") {
- deps = [
- ":reset_browser_proxy",
- "..:lifetime_browser_proxy",
- ]
}
js_library("reset_page") {
deps = [
":reset_profile_dialog",
- "..:page_visibility",
"..:route",
+ "..:router",
"//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
@@ -37,9 +30,7 @@ js_library("reset_page") {
}
js_library("reset_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [ "$externs_path/chrome_send.js" ]
}
@@ -51,3 +42,120 @@ js_library("reset_profile_dialog") {
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
+
+js_library("reset_profile_banner") {
+ deps = [
+ ":reset_browser_proxy",
+ "..:route",
+ "..:router",
+ "//ui/webui/resources/cr_elements/cr_dialog",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":reset_browser_proxy.m",
+ ":reset_page.m",
+ ":reset_profile_banner.m",
+ ":reset_profile_dialog.m",
+ ]
+}
+
+js_library("reset_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/reset_page/reset_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("reset_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/reset_page/reset_page.m.js" ]
+ deps = [
+ ":reset_profile_dialog.m",
+ "..:route.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":reset_page_module" ]
+}
+
+js_library("reset_profile_banner.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/reset_page/reset_profile_banner.m.js" ]
+ deps = [
+ ":reset_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ ]
+ extra_deps = [ ":reset_profile_banner_module" ]
+}
+
+js_library("reset_profile_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/reset_page/reset_profile_dialog.m.js" ]
+ deps = [
+ ":reset_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":reset_profile_dialog_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":modulize",
+ ":reset_page_module",
+ ":reset_profile_banner_module",
+ ":reset_profile_dialog_module",
+ ]
+}
+
+polymer_modulizer("reset_page") {
+ js_file = "reset_page.js"
+ html_file = "reset_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "ui/webui/resources/html/assert.html|assert",
+ "chrome/browser/resources/settings/reset_page/reset_browser_proxy.html|ResetBrowserProxyImpl",
+ "chrome/browser/resources/settings/router.html|Router,Route,RouteObserverBehavior",
+ "chrome/browser/resources/settings/route.html|routes",
+ ]
+}
+
+polymer_modulizer("reset_profile_banner") {
+ js_file = "reset_profile_banner.js"
+ html_file = "reset_profile_banner.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/reset_page/reset_browser_proxy.html|ResetBrowserProxyImpl",
+ "chrome/browser/resources/settings/router.html|Router",
+ "chrome/browser/resources/settings/route.html|routes",
+ ]
+}
+
+polymer_modulizer("reset_profile_dialog") {
+ js_file = "reset_profile_dialog.js"
+ html_file = "reset_profile_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/reset_page/reset_browser_proxy.html|ResetBrowserProxyImpl,ResetBrowserProxy",
+ "chrome/browser/resources/settings/router.html|Router",
+ "chrome/browser/resources/settings/route.html|routes",
+ ]
+}
+
+js_modulizer("modulize") {
+ input_files = [ "reset_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/safety_check_page/BUILD.gn b/chromium/chrome/browser/resources/settings/safety_check_page/BUILD.gn
new file mode 100644
index 00000000000..539f64fd088
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/safety_check_page/BUILD.gn
@@ -0,0 +1,105 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
+
+js_type_check("closure_compile") {
+ deps = [
+ ":safety_check_browser_proxy",
+ ":safety_check_page",
+ "..:lifetime_browser_proxy",
+ "..:metrics_browser_proxy",
+ "../autofill_page:password_manager_proxy",
+ ]
+}
+
+js_library("safety_check_page") {
+ deps = [
+ ":safety_check_browser_proxy",
+ "..:hats_browser_proxy",
+ "..:lifetime_browser_proxy",
+ "..:metrics_browser_proxy",
+ "..:open_window_proxy",
+ "..:route",
+ "..:router",
+ "../autofill_page:password_manager_proxy",
+ "//third_party/polymer/v1_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer-extracted",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+}
+
+js_library("safety_check_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":safety_check_browser_proxy.m",
+ ":safety_check_page.m",
+ ]
+}
+
+js_library("safety_check_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/safety_check_page/safety_check_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("safety_check_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/safety_check_page/safety_check_page.m.js" ]
+ deps = [
+ ":safety_check_browser_proxy.m",
+ "..:hats_browser_proxy.m",
+ "..:lifetime_browser_proxy.m",
+ "..:metrics_browser_proxy.m",
+ "..:open_window_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "../autofill_page:password_manager_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":safety_check_page_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":modulize",
+ ":safety_check_page_module",
+ ]
+}
+
+polymer_modulizer("safety_check_page") {
+ js_file = "safety_check_page.js"
+ html_file = "safety_check_page.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ "chrome/browser/resources/settings/autofill_page/password_manager_proxy.html|PasswordManagerImpl,PasswordManagerProxy",
+ "chrome/browser/resources/settings/lifetime_browser_proxy.html|LifetimeBrowserProxy,LifetimeBrowserProxyImpl",
+ "chrome/browser/resources/settings/hats_browser_proxy.html|HatsBrowserProxyImpl",
+ "chrome/browser/resources/settings/metrics_browser_proxy.html|SafetyCheckInteractions,MetricsBrowserProxy,MetricsBrowserProxyImpl",
+ "chrome/browser/resources/settings/open_window_proxy.html|OpenWindowProxyImpl",
+ "chrome/browser/resources/settings/safety_check_page/safety_check_browser_proxy.html|SafetyCheckBrowserProxy,SafetyCheckBrowserProxyImpl,SafetyCheckExtensionsStatus,SafetyCheckPasswordsStatus,SafetyCheckUpdatesStatus,SafetyCheckSafeBrowsingStatus,SafetyCheckCallbackConstants",
+ "ui/webui/resources/html/assert.html|assertNotReached",
+ "ui/webui/resources/html/polymer.html|Polymer,html,flush",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+js_modulizer("modulize") {
+ input_files = [ "safety_check_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/search_engines_page/BUILD.gn b/chromium/chrome/browser/resources/settings/search_engines_page/BUILD.gn
index 623691241cc..95e4d6c114e 100644
--- a/chromium/chrome/browser/resources/settings/search_engines_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/search_engines_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -18,6 +21,7 @@ js_type_check("closure_compile") {
js_library("search_engine_dialog") {
deps = [
":search_engines_browser_proxy",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:web_ui_listener_behavior",
@@ -66,6 +70,8 @@ js_library("search_engines_page") {
deps = [
":search_engines_browser_proxy",
"..:global_scroll_target_behavior",
+ "..:route",
+ "//third_party/polymer/v1_0/components-chromium/iron-list:iron-list-extracted",
"//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
@@ -73,3 +79,156 @@ js_library("search_engines_page") {
"//ui/webui/resources/js/cr/ui:focus_without_ink",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":omnibox_extension_entry.m",
+ ":search_engine_dialog.m",
+ ":search_engine_entry.m",
+ ":search_engines_browser_proxy.m",
+ ":search_engines_list.m",
+ ":search_engines_page.m",
+ ]
+}
+
+js_library("omnibox_extension_entry.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.m.js" ]
+ deps = [
+ ":search_engines_browser_proxy.m",
+ "..:extension_control_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
+ ]
+ extra_deps = [ ":omnibox_extension_entry_module" ]
+}
+
+js_library("search_engine_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.m.js" ]
+ deps = [
+ ":search_engines_browser_proxy.m",
+ "..:i18n_setup.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":search_engine_dialog_module" ]
+}
+
+js_library("search_engine_entry.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/search_engines_page/search_engine_entry.m.js" ]
+ deps = [
+ ":search_engines_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
+ ]
+ extra_deps = [ ":search_engine_entry_module" ]
+}
+
+js_library("search_engines_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("search_engines_list.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/search_engines_page/search_engines_list.m.js" ]
+ deps = [
+ ":search_engines_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":search_engines_list_module" ]
+}
+
+js_library("search_engines_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/search_engines_page/search_engines_page.m.js" ]
+ deps = [
+ ":search_engines_browser_proxy.m",
+ "..:global_scroll_target_behavior.m",
+ "..:settings_routes.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-list",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":search_engines_page_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":modulize",
+ ":omnibox_extension_entry_module",
+ ":search_engine_dialog_module",
+ ":search_engine_entry_css_module",
+ ":search_engine_entry_module",
+ ":search_engines_list_module",
+ ":search_engines_page_module",
+ ]
+}
+
+polymer_modulizer("omnibox_extension_entry") {
+ js_file = "omnibox_extension_entry.js"
+ html_file = "omnibox_extension_entry.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.html|SearchEngine",
+ "ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html|AnchorAlignment",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+}
+
+polymer_modulizer("search_engine_dialog") {
+ js_file = "search_engine_dialog.js"
+ html_file = "search_engine_dialog.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.html|SearchEnginesBrowserProxyImpl,SearchEnginesBrowserProxy,SearchEngine,SearchEnginesInfo" ]
+}
+
+polymer_modulizer("search_engine_entry") {
+ js_file = "search_engine_entry.js"
+ html_file = "search_engine_entry.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.html|SearchEnginesBrowserProxyImpl,SearchEnginesBrowserProxy,SearchEngine",
+ "ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html|AnchorAlignment",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+}
+
+polymer_modulizer("search_engine_entry_css") {
+ js_file = "search_engine_entry_css.m.js"
+ html_file = "search_engine_entry_css.html"
+ html_type = "style-module"
+}
+
+polymer_modulizer("search_engines_list") {
+ js_file = "search_engines_list.js"
+ html_file = "search_engines_list.html"
+ html_type = "dom-module"
+ auto_imports = [ "chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.html|SearchEngine" ]
+}
+
+polymer_modulizer("search_engines_page") {
+ js_file = "search_engines_page.js"
+ html_file = "search_engines_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.html|SearchEnginesBrowserProxyImpl,SearchEngine,SearchEnginesInfo",
+ "chrome/browser/resources/settings/route.html|routes",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/polymer.html|afterNextRender,html,Polymer",
+ ]
+}
+
+js_modulizer("modulize") {
+ input_files = [ "search_engines_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/search_page/BUILD.gn b/chromium/chrome/browser/resources/settings/search_page/BUILD.gn
index 48ae8f7353f..8f902780a4d 100644
--- a/chromium/chrome/browser/resources/settings/search_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/search_page/BUILD.gn
@@ -3,20 +3,55 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
- deps = [
- ":search_page",
- ]
+ deps = [ ":search_page" ]
}
js_library("search_page") {
deps = [
"..:route",
+ "..:router",
"../prefs",
"../search_engines_page:search_engines_browser_proxy",
"../settings_page:settings_animated_pages",
"//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:i18n_behavior",
+ ]
+}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [ ":search_page.m" ]
+}
+
+js_library("search_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/search_page/search_page.m.js" ]
+ deps = [
+ "..:route.m",
+ "..:router.m",
+ "../search_engines_page:search_engines_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:cr.m",
+ ]
+ extra_deps = [ ":search_page_module" ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [ ":search_page_module" ]
+}
+
+polymer_modulizer("search_page") {
+ js_file = "search_page.js"
+ html_file = "search_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ "chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.html|SearchEnginesBrowserProxyImpl,SearchEnginesBrowserProxy,SearchEngine",
+ "ui/webui/resources/html/cr.html|addWebUIListener",
]
}
diff --git a/chromium/chrome/browser/resources/settings/settings.gni b/chromium/chrome/browser/resources/settings/settings.gni
new file mode 100644
index 00000000000..e3ba931f4fc
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/settings.gni
@@ -0,0 +1,136 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Common namespace rewrites for all polymer_modulizer() or js_modulizer()
+# targets in Settings.
+settings_namespace_rewrites = [
+ "// #polymer3 |",
+ "cr_slider.SliderTick|SliderTick",
+ "settings.address.CountryDetailManager|CountryDetailManager",
+ "settings.AboutPageBrowserProxy|AboutPageBrowserProxy",
+ "settings.AccountManagerBrowserProxy|AccountManagerBrowserProxy",
+ "settings.Account|Account",
+ "settings.ALL_SITES_DIALOG|ALL_SITES_DIALOG",
+ "settings.AllSitesAction|AllSitesAction",
+ "settings.AllSitesAction2|AllSitesAction2",
+ "settings.AndroidInfoBrowserProxy|AndroidInfoBrowserProxy",
+ "settings.AndroidSmsInfo|AndroidSmsInfo",
+ "settings.AppearanceBrowserProxy|AppearanceBrowserProxy",
+ "settings.AutofillManager|AutofillManager",
+ "settings.BioEnrollDialogPage|BioEnrollDialogPage",
+ "settings.BlockingRequestManager|BlockingRequestManager",
+ "settings.BlockAutoplayStatus|BlockAutoplayStatus",
+ "settings.CaptionsBrowserProxy|CaptionsBrowserProxy",
+ "settings.CategoryListItem|CategoryListItem",
+ "settings.ChooserType|ChooserType",
+ "settings.ChromeCleanupProxy|ChromeCleanupProxy",
+ "settings.ChromeCleanupRemovalListItem|ChromeCleanupRemovalListItem",
+ "settings.ClearBrowsingDataBrowserProxy|ClearBrowsingDataBrowserProxy",
+ "settings.ContentSetting|ContentSetting",
+ "settings.CookieControlsMode|CookieControlsMode",
+ "settings.CreditCardEntry|CreditCardEntry",
+ "settings.BrowserProfile|BrowserProfile",
+ "settings.DefaultBrowserBrowserProxy|DefaultBrowserBrowserProxy",
+ "settings.DownloadsBrowserProxy|DownloadsBrowserProxy",
+ "settings.EDIT_STARTUP_URL_EVENT|EDIT_STARTUP_URL_EVENT",
+ "settings.ExtensionControlBrowserProxy|ExtensionControlBrowserProxy",
+ "settings.FontsBrowserProxy|FontsBrowserProxy",
+ "settings.GlobalScrollTargetBehavior|GlobalScrollTargetBehavior",
+ "settings.getSearchManager|getSearchManager",
+ "settings.HatsBrowserProxy|HatsBrowserProxy",
+ "settings.ImportDataStatus|ImportDataStatus",
+ "settings.ImportDataBrowserProxy|ImportDataBrowserProxy",
+ "settings.IncompatibleApplicationsBrowserProxy|IncompatibleApplicationsBrowserProxy",
+ "settings.IncompatibleApplication|IncompatibleApplication",
+ "settings.INVALID_CATEGORY_SUBTYPE|INVALID_CATEGORY_SUBTYPE",
+ "settings.LanguagesBrowserProxy|LanguagesBrowserProxy",
+ "settings.LifetimeBrowserProxy|LifetimeBrowserProxy",
+ "settings.LocalDataBrowserProxy|LocalDataBrowserProxy",
+ "settings.MainPageBehavior|MainPageBehavior",
+ "settings.ManageProfileBrowserProxy|ManageProfileBrowserProxy",
+ "settings.MetricsBrowserProxy|MetricsBrowserProxy",
+ "settings.MinimumRoutes|MinimumRoutes",
+ "settings.OnStartupBrowserProxy|OnStartupBrowserProxy",
+ "settings.OpenWindowProxy|OpenWindowProxy",
+ "settings.PageStatus|PageStatus",
+ "settings.PaymentsManager|PaymentsManager",
+ "settings.pageVisibility|pageVisibility",
+ "settings.PINFieldSubmitFunc|PINFieldSubmitFunc",
+ "settings.PluralStringProxy|PluralStringProxy",
+ "Settings.PrefUtil.prefToString|prefToString",
+ "Settings.PrefUtil.stringToPrefValue|stringToPrefValue",
+ "settings.PrintingBrowserProxy|PrintingBrowserProxy",
+ "settings.PrivacyElementInteractions|PrivacyElementInteractions",
+ "settings.PrivacyPageBrowserProxy|PrivacyPageBrowserProxy",
+ "settings.ProfileInfoBrowserProxy|ProfileInfoBrowserProxy",
+ "settings.ProfileInfo|ProfileInfo",
+ "settings.ProfileShortcutStatus|ProfileShortcutStatus",
+ "settings.ResetBrowserProxy|ResetBrowserProxy",
+ "settings.ResetDialogPage|ResetDialogPage",
+ "settings.ResolverOption|ResolverOption",
+ "settings.Route|Route",
+ "settings.routes|routes",
+ "settings.SafeBrowsingBrowserProxy|SafeBrowsingBrowserProxy",
+ "settings.SafeBrowsingRadioManagedState|SafeBrowsingRadioManagedState",
+ "settings.SafetyCheckInteractions|SafetyCheckInteractions",
+ "settings.SearchEnginesBrowserProxy|SearchEnginesBrowserProxy",
+ "settings.SearchRequest|SearchRequest",
+ "settings.SearchResult|SearchResult",
+ "settings.SecureDnsMode|SecureDnsMode",
+ "settings.SecureDnsSetting|SecureDnsSetting",
+ "settings.SecureDnsUiManagementMode|SecureDnsUiManagementMode",
+ "settings.SecurityKeysBioEnrollProxy|SecurityKeysBioEnrollProxy",
+ "settings.SecurityKeysCredentialBrowserProxy|SecurityKeysCredentialBrowserProxy",
+ "settings.SecurityKeysResetBrowserProxy|SecurityKeysResetBrowserProxy",
+ "settings.Enrollment|Enrollment",
+ "settings.SecurityKeysPINBrowserProxy|SecurityKeysPINBrowserProxy",
+ "settings.EnrollmentResponse|EnrollmentResponse",
+ "settings.SetPINDialogPage|SetPINDialogPage",
+ "settings.CredentialManagementDialogPage|CredentialManagementDialogPage",
+ "settings.SampleStatus|SampleStatus",
+ "settings.SampleResponse|SampleResponse",
+ "settings.Ctap2Status|Ctap2Status",
+ "settings.Credential|Credential",
+ "settings.MetricsReporting|MetricsReporting",
+ "settings.SafetyCheckBrowserProxy|SafetyCheckBrowserProxy",
+ "settings.SafetyCheckCallbackConstants|SafetyCheckCallbackConstants",
+ "settings.SafetyCheckExtensionsStatus|SafetyCheckExtensionsStatus",
+ "settings.SafetyCheckPasswordsStatus|SafetyCheckPasswordsStatus",
+ "settings.SafetyCheckSafeBrowsingStatus|SafetyCheckSafeBrowsingStatus",
+ "settings.SafetyCheckUpdatesStatus|SafetyCheckUpdatesStatus",
+ "settings.SITE_EXCEPTION_WILDCARD|SITE_EXCEPTION_WILDCARD",
+ "settings.SiteSettingSource|SiteSettingSource",
+ "settings.SiteSettingsPrefsBrowserProxy|SiteSettingsPrefsBrowserProxy",
+ "settings.SortMethod|SortMethod",
+ "settings.StartupUrlsPageBrowserProxy|StartupUrlsPageBrowserProxy",
+ "settings.StatusAction|StatusAction",
+ "settings.StoredAccount|StoredAccount",
+ "settings.SyncBrowserProxy|SyncBrowserProxy",
+ "settings.SyncPrefs|SyncPrefs",
+ "settings.SyncStatus|SyncStatus",
+ "settings.SystemPageBrowserProxy|SystemPageBrowserProxy",
+ "settings.RouteObserverBehavior|RouteObserverBehavior",
+ "settings.WebsiteUsageBrowserProxy|WebsiteUsageBrowserProxy",
+
+ "action_link.m.js|action_link.js",
+
+ # TODO(1026426): Add more entries above as needed.
+]
+
+settings_auto_imports = [
+ "chrome/browser/resources/settings/autofill_page/blocking_request_manager.html|BlockingRequestManager",
+ "chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html|CreditCardEntry",
+ "chrome/browser/resources/settings/autofill_page/password_check_behavior.html|PasswordCheckBehavior",
+ "chrome/browser/resources/settings/autofill_page/show_password_behavior.html|ShowPasswordBehavior",
+ "chrome/browser/resources/settings/controls/pref_control_behavior.html|PrefControlBehavior",
+ "chrome/browser/resources/settings/controls/settings_boolean_control_behavior.html|SettingsBooleanControlBehavior",
+ "chrome/browser/resources/settings/downloads_page/downloads_browser_proxy.html|DownloadsBrowserProxy,DownloadsBrowserProxyImpl",
+ "chrome/browser/resources/settings/extension_control_browser_proxy.html|ExtensionControlBrowserProxyImpl,ExtensionControlBrowserProxy",
+ "chrome/browser/resources/settings/global_scroll_target_behavior.html|GlobalScrollTargetBehavior",
+ "chrome/browser/resources/settings/i18n_setup.html|loadTimeData",
+ "chrome/browser/resources/settings/prefs/prefs_behavior.html|PrefsBehavior",
+ "chrome/browser/resources/settings/prefs/prefs_types.html|CrSettingsPrefs",
+ "chrome/browser/resources/settings/printing_page/printing_browser_proxy.html|PrintingBrowserProxyImpl",
+ "chrome/browser/resources/settings/site_settings/site_settings_behavior.html|SiteSettingsBehavior",
+]
diff --git a/chromium/chrome/browser/resources/settings/settings_main/BUILD.gn b/chromium/chrome/browser/resources/settings/settings_main/BUILD.gn
index c4eddc9c214..19101578cb4 100644
--- a/chromium/chrome/browser/resources/settings/settings_main/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/settings_main/BUILD.gn
@@ -3,17 +3,18 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
- deps = [
- ":settings_main",
- ]
+ deps = [ ":settings_main" ]
}
js_library("settings_main") {
deps = [
"..:page_visibility",
"..:route",
+ "..:router",
"..:search_settings",
"../about_page",
"../basic_page:basic_page",
@@ -23,3 +24,44 @@ js_library("settings_main") {
"//ui/webui/resources/js:load_time_data",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [ ":settings_main.m" ]
+}
+
+js_library("settings_main.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/settings_main/settings_main.m.js" ]
+ deps = [
+ "..:page_visibility.m",
+ "..:route.m",
+ "..:router.m",
+ "..:search_settings.m",
+ "../about_page:about_page.m",
+ "../about_page:about_page_browser_proxy.m",
+ "../basic_page:basic_page.m",
+ "../settings_page:main_page_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":settings_main_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [ ":settings_main_module" ]
+}
+
+polymer_modulizer("settings_main") {
+ js_file = "settings_main.js"
+ html_file = "settings_main.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/about_page/about_page_browser_proxy.html|AboutPageBrowserProxyImpl",
+ "chrome/browser/resources/settings/page_visibility.html|PageVisibility",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route,Router,RouteObserverBehavior",
+ "ui/webui/resources/html/assert.html|assert,assertNotReached",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/settings_menu/BUILD.gn b/chromium/chrome/browser/resources/settings/settings_menu/BUILD.gn
index d138e4484cc..94d054eae0c 100644
--- a/chromium/chrome/browser/resources/settings/settings_menu/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/settings_menu/BUILD.gn
@@ -3,17 +3,50 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
- deps = [
- ":settings_menu",
- ]
+ deps = [ ":settings_menu" ]
}
js_library("settings_menu") {
deps = [
"..:page_visibility",
- "..:route",
+ "..:router",
"//third_party/polymer/v1_0/components-chromium/paper-ripple:paper-ripple-extracted",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [ ":settings_menu.m" ]
+}
+
+js_library("settings_menu.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/settings_menu/settings_menu.m.js" ]
+ deps = [
+ "..:page_visibility.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":settings_menu_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [ ":settings_menu_module" ]
+}
+
+polymer_modulizer("settings_menu") {
+ js_file = "settings_menu.js"
+ html_file = "settings_menu.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = [
+ "chrome/browser/resources/settings/page_visibility.html|PageVisibility",
+ "chrome/browser/resources/settings/router.html|RouteObserverBehavior,Router,Route",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn b/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn
index 3479cc1ccc8..e8a15f26d84 100644
--- a/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/settings_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -16,7 +19,7 @@ js_type_check("closure_compile") {
js_library("main_page_behavior") {
deps = [
":settings_section",
- "..:route",
+ "..:router",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:util",
]
@@ -26,7 +29,7 @@ js_library("main_page_behavior") {
js_library("settings_animated_pages") {
deps = [
":settings_subpage",
- "..:route",
+ "..:router",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js/cr/ui:focus_without_ink",
]
@@ -38,11 +41,122 @@ js_library("settings_section") {
js_library("settings_subpage") {
deps = [
- "..:route",
+ "..:router",
"//third_party/polymer/v1_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior-extracted",
"//ui/webui/resources/cr_elements/cr_search_field:cr_search_field",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:find_shortcut_behavior",
+ "//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js/cr/ui:focus_without_ink",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":main_page_behavior.m",
+ ":settings_animated_pages.m",
+ ":settings_section.m",
+ ":settings_subpage.m",
+ ]
+}
+
+js_library("main_page_behavior.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/settings_page/main_page_behavior.m.js" ]
+ deps = [
+ ":settings_section.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:util.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("settings_animated_pages.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/settings_page/settings_animated_pages.m.js" ]
+ deps = [
+ ":settings_subpage.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ extra_deps = [ ":settings_animated_pages_module" ]
+}
+
+js_library("settings_section.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/settings_page/settings_section.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":settings_section_module" ]
+}
+
+js_library("settings_subpage.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/settings_page/settings_subpage.m.js" ]
+ deps = [
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-resizable-behavior:iron-resizable-behavior",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_search_field:cr_search_field.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:find_shortcut_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ extra_deps = [ ":settings_subpage_module" ]
+}
+
+import("//tools/polymer/polymer.gni")
+
+group("polymer3_elements") {
+ public_deps = [
+ ":modulize",
+ ":settings_animated_pages_module",
+ ":settings_section_module",
+ ":settings_subpage_module",
+ ]
+}
+
+polymer_modulizer("settings_animated_pages") {
+ js_file = "settings_animated_pages.js"
+ html_file = "settings_animated_pages.html"
+ html_type = "dom-module"
+ auto_imports = [
+ "chrome/browser/resources/settings/router.html|Route, Router, RouteObserverBehavior",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/polymer.html|afterNextRender, dom, DomIf, html, Polymer",
+ ]
+ namespace_rewrites = settings_namespace_rewrites + [
+ "Polymer.dom|dom",
+ "Polymer.DomIf|DomIf",
+ ]
+}
+
+polymer_modulizer("settings_section") {
+ js_file = "settings_section.js"
+ html_file = "settings_section.html"
+ html_type = "dom-module"
+}
+
+polymer_modulizer("settings_subpage") {
+ js_file = "settings_subpage.js"
+ html_file = "settings_subpage.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/router.html|RouteObserverBehavior,Router",
+ "third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/iron-resizable-behavior.html|IronResizableBehavior",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/polymer.html|html, Polymer, afterNextRender",
+ ]
+ namespace_rewrites = settings_namespace_rewrites +
+ [ "Polymer.IronResizableBehavior|IronResizableBehavior" ]
+}
+
+import("//ui/webui/resources/tools/js_modulizer.gni")
+
+js_modulizer("modulize") {
+ input_files = [ "main_page_behavior.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/settings_resources.grd b/chromium/chrome/browser/resources/settings/settings_resources.grd
index 58976f6eeb7..27b17e0fb2a 100644
--- a/chromium/chrome/browser/resources/settings/settings_resources.grd
+++ b/chromium/chrome/browser/resources/settings/settings_resources.grd
@@ -11,6 +11,9 @@
<output filename="settings_resources.pak" type="data_package" />
</outputs>
<release seq="1">
+ <includes>
+ <part file="settings_resources_v3.grdp" />
+ </includes>
<structures>
<structure name="IDR_SETTINGS_A11Y_PAGE_JS"
file="a11y_page/a11y_page.js"
@@ -19,43 +22,23 @@
<structure name="IDR_SETTINGS_A11Y_PAGE_HTML"
file="a11y_page/a11y_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_CAPTIONS_SUBPAGE_HTML"
- file="a11y_page/captions_subpage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CAPTIONS_SUBPAGE_JS"
- file="a11y_page/captions_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CAPTIONS_BROWSER_PROXY_HTML"
- file="a11y_page/captions_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CAPTIONS_BROWSER_PROXY_JS"
- file="a11y_page/captions_browser_proxy.js"
- type="chrome_html" />
- <if expr="chromeos">
- <structure name="IDR_SETTINGS_MANAGE_A11Y_PAGE_JS"
- file="a11y_page/manage_a11y_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MANAGE_A11Y_PAGE_HTML"
- file="a11y_page/manage_a11y_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_SWITCH_ACCESS_SUBPAGE_JS"
- file="a11y_page/switch_access_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_SWITCH_ACCESS_SUBPAGE_HTML"
- file="a11y_page/switch_access_subpage.html"
+ preprocess="true" />
+
+ <if expr="not is_macosx and not chromeos">
+ <structure name="IDR_SETTINGS_CAPTIONS_SUBPAGE_HTML"
+ file="a11y_page/captions_subpage.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_TTS_SUBPAGE_JS"
- file="a11y_page/tts_subpage.js"
+ <structure name="IDR_SETTINGS_CAPTIONS_SUBPAGE_JS"
+ file="a11y_page/captions_subpage.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_TTS_SUBPAGE_HTML"
- file="a11y_page/tts_subpage.html"
+ </if>
+ <if expr="is_win or is_macosx">
+ <structure name="IDR_SETTINGS_CAPTIONS_BROWSER_PROXY_HTML"
+ file="a11y_page/captions_browser_proxy.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_MANIFEST"
- file="manifest.json"
+ <structure name="IDR_SETTINGS_CAPTIONS_BROWSER_PROXY_JS"
+ file="a11y_page/captions_browser_proxy.js"
type="chrome_html" />
-
</if>
<structure name="IDR_SETTINGS_ABOUT_PAGE_BROWSER_PROXY_HTML"
file="about_page/about_page_browser_proxy.html"
@@ -71,28 +54,7 @@
<structure name="IDR_SETTINGS_ABOUT_PAGE_HTML"
file="about_page/about_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <if expr="chromeos">
- <structure name="IDR_SETTINGS_CHANNEL_SWITCHER_DIALOG_HTML"
- file="about_page/channel_switcher_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CHANNEL_SWITCHER_DIALOG_JS"
- file="about_page/channel_switcher_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DETAILED_BUILD_INFO_JS"
- file="about_page/detailed_build_info.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DETAILED_BUILD_INFO_HTML"
- file="about_page/detailed_build_info.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_UPDATE_WARNING_DIALOG_HTML"
- file="about_page/update_warning_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_UPDATE_WARNING_DIALOG_JS"
- file="about_page/update_warning_dialog.js"
- type="chrome_html" />
- </if>
+ preprocess="true" />
<structure name="IDR_SETTINGS_ADD_SITE_DIALOG_HTML"
file="site_settings/add_site_dialog.html"
type="chrome_html" />
@@ -157,26 +119,16 @@
file="appearance_page/appearance_browser_proxy.js"
type="chrome_html"
preprocess="true" />
- <if expr="chromeos">
- <structure name="IDR_SETTINGS_WALLPAPER_BROWSER_PROXY_HTML"
- file="appearance_page/wallpaper_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_WALLPAPER_BROWSER_PROXY_JS"
- file="appearance_page/wallpaper_browser_proxy.js"
- type="chrome_html" />
- </if>
<structure name="IDR_SETTINGS_APPEARANCE_FONTS_PAGE_HTML"
file="appearance_page/appearance_fonts_page.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_APPEARANCE_FONTS_PAGE_JS"
file="appearance_page/appearance_fonts_page.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_APPEARANCE_PAGE_HTML"
file="appearance_page/appearance_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_APPEARANCE_PAGE_JS"
file="appearance_page/appearance_page.js"
type="chrome_html"
@@ -194,8 +146,7 @@
<structure name="IDR_SETTINGS_BASIC_PAGE_HTML"
file="basic_page/basic_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_EDIT_EXCEPTION_DIALOG_HTML"
file="site_settings/edit_exception_dialog.html"
type="chrome_html" />
@@ -233,6 +184,9 @@
<structure name="IDR_SETTINGS_ON_STARTUP_PAGE_JS"
file="on_startup_page/on_startup_page.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_SEARCH_SETTINGS_HTML"
+ file="search_settings.html"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_SEARCH_SETTINGS_JS"
file="search_settings.js"
type="chrome_html" />
@@ -253,28 +207,24 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_STARTUP_URL_DIALOG_HTML"
file="on_startup_page/startup_url_dialog.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_STARTUP_URL_ENTRY_JS"
file="on_startup_page/startup_url_entry.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_STARTUP_URL_ENTRY_HTML"
file="on_startup_page/startup_url_entry.html"
- type="chrome_html"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_CR_SETTINGS_MAIN_HTML"
file="settings_main/settings_main.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_CR_SETTINGS_MAIN_JS"
file="settings_main/settings_main.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_CR_SETTINGS_MENU_HTML"
file="settings_menu/settings_menu.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_CR_SETTINGS_MENU_JS"
file="settings_menu/settings_menu.js"
type="chrome_html" />
@@ -309,8 +259,7 @@
<structure name="IDR_SETTINGS_CR_SETTINGS_UI_HTML"
file="settings_ui/settings_ui.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_CR_SETTINGS_UI_JS"
file="settings_ui/settings_ui.js"
type="chrome_html"
@@ -321,20 +270,6 @@
<structure name="IDR_SETTINGS_GLOBAL_SCROLL_TARGET_BEHAVIOR_JS"
file="global_scroll_target_behavior.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_CHANGE_PASSWORD_BROWSER_PROXY_HTML"
- file="change_password_page/change_password_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CHANGE_PASSWORD_BROWSER_PROXY_JS"
- file="change_password_page/change_password_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CHANGE_PASSWORD_PAGE_HTML"
- file="change_password_page/change_password_page.html"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_SETTINGS_CHANGE_PASSWORD_PAGE_JS"
- file="change_password_page/change_password_page.js"
- type="chrome_html"
- preprocess="true" />
<if expr="is_win">
<structure name="IDR_SETTINGS_CHROME_CLEANUP_PROXY_HTML"
file="chrome_cleanup_page/chrome_cleanup_proxy.html"
@@ -348,8 +283,7 @@
preprocess="true" />
<structure name="IDR_SETTINGS_CHROME_CLEANUP_PAGE_JS"
file="chrome_cleanup_page/chrome_cleanup_page.js"
- type="chrome_html"
- preprocess="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_CHROME_CLEANUP_ITEMS_TO_REMOVE_LIST_HTML"
file="chrome_cleanup_page/items_to_remove_list.html"
type="chrome_html"/>
@@ -390,16 +324,22 @@
file="clear_browsing_data_dialog/clear_browsing_data_dialog.js"
type="chrome_html"
preprocess="true" />
+ <structure name="IDR_SETTINGS_CLEAR_BROWSING_DATA_INSTALLED_APP_CHECKBOX_HTML"
+ file="clear_browsing_data_dialog/installed_app_checkbox.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_CLEAR_BROWSING_DATA_INSTALLED_APP_CHECKBOX_JS"
+ file="clear_browsing_data_dialog/installed_app_checkbox.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_HISTORY_DELETION_DIALOG_HTML"
file="clear_browsing_data_dialog/history_deletion_dialog.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_HISTORY_DELETION_DIALOG_JS"
file="clear_browsing_data_dialog/history_deletion_dialog.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_SECURITY_KEYS_PAGE_HTML"
+ <structure name="IDR_SETTINGS_SECURITY_KEYS_SUBPAGE_HTML"
file="privacy_page/security_keys_subpage.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_SECURITY_KEYS_PAGE_JS"
+ <structure name="IDR_SETTINGS_SECURITY_KEYS_SUBPAGE_JS"
file="privacy_page/security_keys_subpage.js"
type="chrome_html"/>
<structure name="IDR_SETTINGS_SECURITY_KEYS_SET_PIN_DIALOG_HTML"
@@ -432,10 +372,10 @@
<structure name="IDR_SETTINGS_SECURITY_KEYS_BIO_ENROLL_DIALOG_JS"
file="privacy_page/security_keys_bio_enroll_dialog.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_SECURITY_KEYS_DIALOG_BROWSER_PROXY_HTML"
+ <structure name="IDR_SETTINGS_SECURITY_KEYS_BROWSER_PROXY_HTML"
file="privacy_page/security_keys_browser_proxy.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_SECURITY_KEYS_DIALOG_BROWSER_PROXY_JS"
+ <structure name="IDR_SETTINGS_SECURITY_KEYS_BROWSER_PROXY_JS"
file="privacy_page/security_keys_browser_proxy.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_CONTROLS_BOOLEAN_CONTROL_BEHAVIOR_HTML"
@@ -480,8 +420,7 @@
<structure name="IDR_SETTINGS_CONTROLS_PASSWORD_PROMPT_DIALOG_HTML"
file="controls/password_prompt_dialog.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_CONTROLS_PREF_CONTROL_BEHAVIOR_HTML"
file="controls/pref_control_behavior.html"
type="chrome_html" />
@@ -534,104 +473,11 @@
<structure name="IDR_SETTINGS_DEFAULT_BROWSER_PAGE_HTML"
file="default_browser_page/default_browser_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_DEFAULT_BROWSER_PAGE_JS"
file="default_browser_page/default_browser_page.js"
type="chrome_html" />
</if>
- <if expr="chromeos">
- <structure name="IDR_SETTINGS_DEVICE_BROWSER_PROXY_HTML"
- file="device_page/device_page_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_BROWSER_PROXY_JS"
- file="device_page/device_page_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_DISPLAY_HTML"
- file="device_page/display.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_DISPLAY_JS"
- file="device_page/display.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_DISPLAY_LAYOUT_HTML"
- file="device_page/display_layout.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_DISPLAY_LAYOUT_JS"
- file="device_page/display_layout.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_DISPLAY_OVERSCAN_DIALOG_HTML"
- file="device_page/display_overscan_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_DISPLAY_OVERSCAN_DIALOG_JS"
- file="device_page/display_overscan_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_KEYBOARD_HTML"
- file="device_page/keyboard.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_KEYBOARD_JS"
- file="device_page/keyboard.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_POWER_HTML"
- file="device_page/power.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_POWER_JS"
- file="device_page/power.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_STORAGE_HTML"
- file="device_page/storage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_STORAGE_JS"
- file="device_page/storage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_STORAGE_EXTERNAL_ENTRY_HTML"
- file="device_page/storage_external_entry.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_STORAGE_EXTERNAL_ENTRY_JS"
- file="device_page/storage_external_entry.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_STORAGE_EXTERNAL_HTML"
- file="device_page/storage_external.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_STORAGE_EXTERNAL_JS"
- file="device_page/storage_external.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_STYLUS_HTML"
- file="device_page/stylus.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_STYLUS_JS"
- file="device_page/stylus.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_PAGE_HTML"
- file="device_page/device_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_PAGE_JS"
- file="device_page/device_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_POINTERS_HTML"
- file="device_page/pointers.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_POINTERS_JS"
- file="device_page/pointers.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_DRAG_BEHAVIOR_HTML"
- file="device_page/drag_behavior.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_DRAG_BEHAVIOR_JS"
- file="device_page/drag_behavior.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_LAYOUT_BEHAVIOR_HTML"
- file="device_page/layout_behavior.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_LAYOUT_BEHAVIOR_JS"
- file="device_page/layout_behavior.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_NIGHT_LIGHT_SLIDER_HTML"
- file="device_page/night_light_slider.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DEVICE_NIGHT_LIGHT_SLIDER_JS"
- file="device_page/night_light_slider.js"
- type="chrome_html" />
- </if>
<structure name="IDR_SETTINGS_DOWNLOADS_BROWSER_PROXY_HTML"
file="downloads_page/downloads_browser_proxy.html"
type="chrome_html" />
@@ -642,20 +488,11 @@
<structure name="IDR_SETTINGS_DOWNLOADS_PAGE_HTML"
file="downloads_page/downloads_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_DOWNLOADS_PAGE_JS"
file="downloads_page/downloads_page.js"
type="chrome_html"
preprocess="true" />
- <if expr="chromeos">
- <structure name="IDR_SETTINGS_SMB_SHARES_PAGE_HTML"
- file="downloads_page/smb_shares_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_SMB_SHARES_PAGE_JS"
- file="downloads_page/smb_shares_page.js"
- type="chrome_html" />
- </if>
<structure name="IDR_SETTINGS_I18n_SETUP_HTML"
file="i18n_setup.html"
type="chrome_html" />
@@ -663,23 +500,29 @@
file="icons.html"
type="chrome_html"
preprocess="true" />
- <if expr="chromeos">
- <!-- TODO(crbug.com/986596): Remove OS icons when SplitSettings
- is complete. -->
- <structure name="IDR_SETTINGS_CHROMEOS_OS_ICONS"
- file="chromeos/os_icons.html"
- type="chrome_html"
- preprocess="true" />
- <structure name="IDR_OS_SETTINGS_OS_SETTINGS_ICONS_CSS_HTML"
- file="chromeos/os_settings_icons_css.html"
- flattenhtml="true"
- type="chrome_html" />
- </if>
- <structure name="IDR_SETTINGS_POWERWASH_DIALOG_HTML"
- file="reset_page/powerwash_dialog.html"
+ <structure name="IDR_SETTINGS_IMAGES_COOKIES_BANNER_SVG"
+ file="images/cookies_banner.svg"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_COOKIES_BANNER_DARK_SVG"
+ file="images/cookies_banner_dark.svg"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_PERMISSIONS_BANNER_SVG"
+ file="images/permissions_banner.svg"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_PERMISSIONS_BANNER_DARK_SVG"
+ file="images/permissions_banner_dark.svg"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_SAFE_BROWSING_BANNER_SVG"
+ file="images/safe_browsing_banner.svg"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_SAFE_BROWSING_BANNER_DARK_SVG"
+ file="images/safe_browsing_banner_dark.svg"
type="chrome_html" />
- <structure name="IDR_SETTINGS_POWERWASH_DIALOG_JS"
- file="reset_page/powerwash_dialog.js"
+ <structure name="IDR_SETTINGS_IMAGES_SYNC_BANNER_SVG"
+ file="images/sync_banner.svg"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_SYNC_BANNER_DARK_SVG"
+ file="images/sync_banner_dark.svg"
type="chrome_html" />
<structure name="IDR_SETTINGS_RESET_PAGE_HTML"
file="reset_page/reset_page.html"
@@ -714,8 +557,7 @@
<structure name="IDR_SETTINGS_LANGUAGES_JS"
file="languages_page/languages.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_LANGUAGES_BROWSER_PROXY_HTML"
file="languages_page/languages_browser_proxy.html"
type="chrome_html" />
@@ -732,21 +574,11 @@
<structure name="IDR_SETTINGS_LANGUAGES_PAGE_HTML"
file="languages_page/languages_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_LANGUAGES_PAGE_JS"
file="languages_page/languages_page.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <if expr="chromeos">
- <structure name="IDR_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_PAGE_HTML"
- file="languages_page/manage_input_methods_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_PAGE_JS"
- file="languages_page/manage_input_methods_page.js"
- type="chrome_html" />
- </if>
+ preprocess="true" />
<if expr="not is_macosx">
<structure name="IDR_SETTINGS_LANGUAGES_EDIT_DICTIONARY_PAGE_HTML"
file="languages_page/edit_dictionary_page.html"
@@ -767,11 +599,11 @@
<structure name="IDR_SETTINGS_AUTOFILL_PAGE_JS"
file="autofill_page/autofill_page.js"
type="chrome_html" />
- <structure name="IDR_SETTINGS_CREDIT_CARD_LIST_HTML"
- file="autofill_page/credit_card_list.html"
+ <structure name="IDR_SETTINGS_PAYMENTS_LIST_HTML"
+ file="autofill_page/payments_list.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_CREDIT_CARD_LIST_JS"
- file="autofill_page/credit_card_list.js"
+ <structure name="IDR_SETTINGS_PAYMENTS_LIST_JS"
+ file="autofill_page/payments_list.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_CREDIT_CARD_LIST_ENTRY_HTML"
file="autofill_page/credit_card_list_entry.html"
@@ -779,9 +611,16 @@
<structure name="IDR_SETTINGS_CREDIT_CARD_LIST_ENTRY_JS"
file="autofill_page/credit_card_list_entry.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_UPI_ID_LIST_ENTRY_HTML"
+ file="autofill_page/upi_id_list_entry.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_UPI_ID_LIST_ENTRY_JS"
+ file="autofill_page/upi_id_list_entry.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PASSWORDS_SHARED_CSS_HTML"
file="autofill_page/passwords_shared_css.html"
- type="chrome_html" />
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_CREDIT_CARD_EDIT_DIALOG_HTML"
file="autofill_page/credit_card_edit_dialog.html"
type="chrome_html" />
@@ -816,6 +655,34 @@
file="autofill_page/show_password_behavior.js"
type="chrome_html"
preprocess="true" />
+ <structure name="IDR_SETTINGS_PASSWORD_CHECK_HTML"
+ file="autofill_page/password_check.html"
+ type="chrome_html"
+ preprocess="true" />
+ <structure name="IDR_SETTINGS_PASSWORD_CHECK_JS"
+ file="autofill_page/password_check.js"
+ type="chrome_html"
+ preprocess="true" />
+ <structure name="IDR_SETTINGS_PASSWORD_CHECK_BEHAVIOR_HTML"
+ file="autofill_page/password_check_behavior.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PASSWORD_CHECK_BEHAVIOR_JS"
+ file="autofill_page/password_check_behavior.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PASSWORD_CHECK_EDIT_DIALOG_HTML"
+ file="autofill_page/password_check_edit_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PASSWORD_CHECK_EDIT_DIALOG_JS"
+ file="autofill_page/password_check_edit_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PASSWORD_CHECK_LIST_ITEM_HTML"
+ file="autofill_page/password_check_list_item.html"
+ type="chrome_html"
+ preprocess="true" />
+ <structure name="IDR_SETTINGS_PASSWORD_CHECK_LIST_ITEM_JS"
+ file="autofill_page/password_check_list_item.js"
+ type="chrome_html"
+ preprocess="true" />
<structure name="IDR_SETTINGS_PASSWORD_LIST_ITEM_HTML"
file="autofill_page/password_list_item.html"
type="chrome_html"
@@ -829,6 +696,18 @@
<structure name="IDR_SETTINGS_PASSWORD_MANAGER_PROXY_JS"
file="autofill_page/password_manager_proxy.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_NEUTRAL_SVG"
+ file="images/password_check_neutral.svg"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_NEUTRAL_DARK_SVG"
+ file="images/password_check_neutral_dark.svg"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_POSITIVE_SVG"
+ file="images/password_check_positive.svg"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_POSITIVE_DARK_SVG"
+ file="images/password_check_positive_dark.svg"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PASSWORDS_SECTION_HTML"
file="autofill_page/passwords_section.html"
type="chrome_html"
@@ -852,6 +731,12 @@
file="autofill_page/passwords_export_dialog.js"
type="chrome_html"
preprocess="true" />
+ <structure name="IDR_SETTINGS_PASSWORD_REMOVE_CONFIRMATION_DIALOG_HTML"
+ file="autofill_page/password_remove_confirmation_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PASSWORD_REMOVE_CONFIRMATION_DIALOG_JS"
+ file="autofill_page/password_remove_confirmation_dialog.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PAYMENTS_SECTION_HTML"
file="autofill_page/payments_section.html"
type="chrome_html" />
@@ -861,22 +746,20 @@
<structure name="IDR_SETTINGS_PEOPLE_PAGE_HTML"
file="people_page/people_page.html"
type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_PEOPLE_PAGE_JS"
file="people_page/people_page.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_ACCOUNT_CONTROL_HTML"
+ file="people_page/sync_account_control.html"
+ type="chrome_html"
+ preprocess="true" />
+ <structure name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_ACCOUNT_CONTROL_JS"
+ file="people_page/sync_account_control.js"
+ type="chrome_html"
+ preprocess="true" />
<if expr="not chromeos">
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_ACCOUNT_CONTROL_HTML"
- file="people_page/sync_account_control.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_ACCOUNT_CONTROL_JS"
- file="people_page/sync_account_control.js"
- type="chrome_html" />
<structure name="IDR_SETTINGS_PEOPLE_PAGE_IMPORT_DATA_DIALOG_HTML"
file="people_page/import_data_dialog.html"
type="chrome_html" />
@@ -891,9 +774,7 @@
type="chrome_html" />
<structure name="IDR_SETTINGS_PEOPLE_PAGE_MANAGE_PROFILE_HTML"
file="people_page/manage_profile.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PEOPLE_PAGE_MANAGE_PROFILE_JS"
file="people_page/manage_profile.js"
type="chrome_html" />
@@ -924,8 +805,7 @@
<structure name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_BROWSER_PROXY_JS"
file="people_page/sync_browser_proxy.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_PREF_UTIL_HTML"
file="prefs/pref_util.html"
type="chrome_html" />
@@ -953,95 +833,11 @@
<structure name="IDR_SETTINGS_PRINTING_PAGE_HTML"
file="printing_page/printing_page.html"
preprocess="true"
- allowexternalscript="true"
type="chrome_html" />
<structure name="IDR_SETTINGS_PRINTING_PAGE_JS"
file="printing_page/printing_page.js"
preprocess="true"
type="chrome_html" />
- <if expr="chromeos">
- <structure name="IDR_SETTINGS_CUPS_PRINTER_TYPES_HTML"
- file="printing_page/cups_printer_types.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTER_TYPES_JS"
- file="printing_page/cups_printer_types.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTER_SHARED_CSS_HTML"
- file="printing_page/cups_printer_shared_css.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTING_PAGE_HTML"
- file="printing_page/cups_printers.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTING_PAGE_JS"
- file="printing_page/cups_printers.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_BROWSER_PROXY_HTML"
- file="printing_page/cups_printers_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_BROWSER_PROXY_JS"
- file="printing_page/cups_printers_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_ENTRY_HTML"
- file="printing_page/cups_printers_entry.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_ENTRY_JS"
- file="printing_page/cups_printers_entry.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_ENTRY_LIST_BEHAVIOR_HTML"
- file="printing_page/cups_printers_entry_list_behavior.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_ENTRY_LIST_BEHAVIOR_JS"
- file="printing_page/cups_printers_entry_list_behavior.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_ENTRY_MANAGER_HTML"
- file="printing_page/cups_printers_entry_manager.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_ENTRY_MANAGER_JS"
- file="printing_page/cups_printers_entry_manager.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_LIST_HTML"
- file="printing_page/cups_printers_list.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTERS_LIST_JS"
- file="printing_page/cups_printers_list.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_SAVED_PRINTERS_HTML"
- file="printing_page/cups_saved_printers.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_SAVED_PRINTERS_JS"
- file="printing_page/cups_saved_printers.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_NEARBY_PRINTERS_HTML"
- file="printing_page/cups_nearby_printers.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_NEARBY_PRINTERS_JS"
- file="printing_page/cups_nearby_printers.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_EDIT_PRINTER_DIALOG_HTML"
- file="printing_page/cups_edit_printer_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_EDIT_PRINTER_DIALOG_JS"
- file="printing_page/cups_edit_printer_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_HTML"
- file="printing_page/cups_add_printer_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_JS"
- file="printing_page/cups_add_printer_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_ELEMENTS_HTML"
- file="printing_page/cups_add_printer_dialog_elements.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_ADD_PRINTER_DIALOG_ELEMENTS_JS"
- file="printing_page/cups_add_printer_dialog_elements.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTER_DIALOG_UTIL_HTML"
- file="printing_page/cups_printer_dialog_util.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CUPS_PRINTER_DIALOG_UTIL_JS"
- file="printing_page/cups_printer_dialog_util.js"
- type="chrome_html" />
- </if>
<if expr="not chromeos">
<structure name="IDR_SETTINGS_PRINTING_BROWSER_PROXY_HTML"
file="printing_page/printing_browser_proxy.html"
@@ -1068,6 +864,12 @@
<structure name="IDR_SETTINGS_OPEN_WINDOW_PROXY_JS"
file="open_window_proxy.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_PLURAL_STRING_PROXY_HTML"
+ file="plural_string_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_PLURAL_STRING_PROXY_JS"
+ file="plural_string_proxy.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PAGE_VISIBILITY_HTML"
file="page_visibility.html"
type="chrome_html" />
@@ -1081,11 +883,22 @@
<structure name="IDR_SETTINGS_PDF_DOCUMENTS_JS"
file="site_settings/pdf_documents.js"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_COOKIES_PAGE_HTML"
+ file="privacy_page/cookies_page.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_COOKIES_PAGE_JS"
+ file="privacy_page/cookies_page.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_DO_NOT_TRACK_TOGGLE_HTML"
+ file="privacy_page/do_not_track_toggle.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_DO_NOT_TRACK_TOGGLE_JS"
+ file="privacy_page/do_not_track_toggle.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PERSONALIZATION_OPTIONS_HTML"
file="privacy_page/personalization_options.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_PERSONALIZATION_OPTIONS_JS"
file="privacy_page/personalization_options.js"
preprocess="true"
@@ -1097,11 +910,42 @@
file="privacy_page/passwords_leak_detection_toggle.js"
type="chrome_html"
preprocess="true" />
+ <structure name="IDR_SETTINGS_COLLAPSE_RADIO_BUTTON_HTML"
+ file="privacy_page/collapse_radio_button.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_COLLAPSE_RADIO_BUTTON_JS"
+ file="privacy_page/collapse_radio_button.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SECURE_DNS_HTML"
+ file="privacy_page/secure_dns.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SECURE_DNS_JS"
+ file="privacy_page/secure_dns.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SECURE_DNS_INPUT_HTML"
+ file="privacy_page/secure_dns_input.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SECURE_DNS_INPUT_JS"
+ file="privacy_page/secure_dns_input.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SECURITY_PAGE_HTML"
+ file="privacy_page/security_page.html"
+ preprocess="true"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SECURITY_PAGE_JS"
+ file="privacy_page/security_page.js"
+ type="chrome_html"
+ preprocess="true" />
+ <structure name="IDR_SETTINGS_DISABLE_SAFEBROWSING_DIALOG_HTML"
+ file="privacy_page/disable_safebrowsing_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_DISABLE_SAFEBROWSING_DIALOG_JS"
+ file="privacy_page/disable_safebrowsing_dialog.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PRIVACY_PAGE_HTML"
file="privacy_page/privacy_page.html"
- type="chrome_html"
- flattenhtml="true"
- allowexternalscript="true" />
+ preprocess="true"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PRIVACY_PAGE_JS"
file="privacy_page/privacy_page.js"
preprocess="true"
@@ -1113,6 +957,24 @@
file="privacy_page/privacy_page_browser_proxy.js"
preprocess="true"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_SAFE_BROWSING_BROWSER_PROXY_HTML"
+ file="privacy_page/safe_browsing_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SAFE_BROWSING_BROWSER_PROXY_JS"
+ file="privacy_page/safe_browsing_browser_proxy.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SAFETY_CHECK_PAGE_HTML"
+ file="safety_check_page/safety_check_page.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SAFETY_CHECK_PAGE_JS"
+ file="safety_check_page/safety_check_page.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SAFETY_CHECK_BROWSER_PROXY_HTML"
+ file="safety_check_page/safety_check_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SAFETY_CHECK_BROWSER_PROXY_JS"
+ file="safety_check_page/safety_check_browser_proxy.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_PROTOCOL_HANDLERS_HTML"
file="site_settings/protocol_handlers.html"
preprocess="true"
@@ -1121,6 +983,26 @@
file="site_settings/protocol_handlers.js"
preprocess="true"
type="chrome_html" />
+ <structure name="IDR_SETTINGS_HATS_BROWSER_PROXY_HTML"
+ file="hats_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_HATS_BROWSER_PROXY_JS"
+ file="hats_browser_proxy.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_METRICS_BROWSER_PROXY_HTML"
+ file="metrics_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_METRICS_BROWSER_PROXY_JS"
+ file="metrics_browser_proxy.js"
+ type="chrome_html"
+ preprocess="true" />
+ <structure name="IDR_SETTINGS_RECENT_SITE_PERMISSIONS_HTML"
+ file="site_settings_page/recent_site_permissions.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_RECENT_SITE_PERMISSIONS_JS"
+ file="site_settings_page/recent_site_permissions.js"
+ preprocess="true"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_ROUTE_HTML"
file="route.html"
type="chrome_html" />
@@ -1128,20 +1010,26 @@
file="route.js"
type="chrome_html"
preprocess="true" />
- <if expr="chromeos">
- <structure name="IDR_SETTINGS_ROUTE_ORIGIN_BEHAVIOR_HTML"
- file="route_origin_behavior.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_ROUTE_ORIGIN_BEHAVIOR_JS"
- file="route_origin_behavior.js"
- type="chrome_html" />
- </if>
+ <structure name="IDR_SETTINGS_ROUTER_HTML"
+ file="router.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ROUTER_JS"
+ file="router.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_SITE_FAVICON_HTML"
file="site_favicon.html"
type="chrome_html" />
<structure name="IDR_SETTINGS_SITE_FAVICON_JS"
file="site_favicon.js"
type="chrome_html" />
+ <if expr="chromeos">
+ <structure name="IDR_SETTINGS_ANDROID_INFO_BROWSER_PROXY_HTML"
+ file="site_settings/android_info_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_ANDROID_INFO_BROWSER_PROXY_JS"
+ file="site_settings/android_info_browser_proxy.js"
+ type="chrome_html" />
+ </if>
<structure name="IDR_SETTINGS_SITE_DATA_HTML"
file="site_settings/site_data.html"
type="chrome_html" />
@@ -1195,6 +1083,12 @@
file="site_settings_page/site_settings_page.js"
type="chrome_html"
preprocess="true" />
+ <structure name="IDR_SETTINGS_SITE_SETTINGS_LIST_HTML"
+ file="site_settings_page/site_settings_list.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SITE_SETTINGS_LIST_JS"
+ file="site_settings_page/site_settings_list.js"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_SITE_SETTINGS_PREFS_BROWSER_PROXY_HTML"
file="site_settings/site_settings_prefs_browser_proxy.html"
type="chrome_html" />
@@ -1223,16 +1117,14 @@
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_DIALOG_HTML"
file="search_engines_page/search_engine_dialog.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_ENTRY_JS"
file="search_engines_page/search_engine_entry.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_ENTRY_HTML"
file="search_engines_page/search_engine_entry.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_ENTRY_CSS_HTML"
file="search_engines_page/search_engine_entry_css.html"
type="chrome_html" />
@@ -1242,70 +1134,47 @@
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_OMNIBOX_EXTENSION_ENTRY_HTML"
file="search_engines_page/omnibox_extension_entry.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_LIST_JS"
file="search_engines_page/search_engines_list.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_LIST_HTML"
file="search_engines_page/search_engines_list.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_PAGE_JS"
file="search_engines_page/search_engines_page.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_PAGE_HTML"
file="search_engines_page/search_engines_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_BROWSER_PROXY_JS"
file="search_engines_page/search_engines_browser_proxy.js"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ preprocess="true" />
<structure name="IDR_SETTINGS_SEARCH_ENGINES_BROWSER_PROXY_HTML"
file="search_engines_page/search_engines_browser_proxy.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <if expr="chromeos">
- <structure name="IDR_SETTINGS_GOOGLE_ASSISTANT_PAGE_GOOGLE_ASSISTANT_PAGE_JS"
- file="google_assistant_page/google_assistant_page.js"
- type="chrome_html"
- allowexternalscript="true"/>
- <structure name="IDR_SETTINGS_GOOGLE_ASSISTANT_PAGE_GOOGLE_ASSISTANT_PAGE_HTML"
- file="google_assistant_page/google_assistant_page.html"
- type="chrome_html"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_GOOGLE_ASSISTANT_PAGE_GOOGLE_ASSISTANT_BROWSER_PROXY_JS"
- file="google_assistant_page/google_assistant_browser_proxy.js"
- type="chrome_html"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_GOOGLE_ASSISTANT_PAGE_GOOGLE_ASSISTANT_BROWSER_PROXY_HTML"
- file="google_assistant_page/google_assistant_browser_proxy.html"
- type="chrome_html"
- allowexternalscript="true" />
- </if>
+ preprocess="true" />
<structure name="IDR_SETTINGS_SEARCH_PAGE_JS"
file="search_page/search_page.js"
- type="chrome_html"
- preprocess="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_SEARCH_PAGE_HTML"
file="search_page/search_page.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_SYNC_CONTROLS_JS"
file="people_page/sync_controls.js"
- type="chrome_html"
- preprocess="true" />
+ type="chrome_html" />
<structure name="IDR_SETTINGS_SYNC_CONTROLS_HTML"
file="people_page/sync_controls.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SYNC_ENCRYPTION_OPTIONS_JS"
+ file="people_page/sync_encryption_options.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SYNC_ENCRYPTION_OPTIONS_HTML"
+ file="people_page/sync_encryption_options.html"
+ type="chrome_html" />
<structure name="IDR_SETTINGS_SYNC_PAGE_JS"
file="people_page/sync_page.js"
type="chrome_html"
@@ -1313,21 +1182,22 @@
<structure name="IDR_SETTINGS_SYNC_PAGE_HTML"
file="people_page/sync_page.html"
type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY_HTML"
- file="system_page/system_page_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY"
- file="system_page/system_page_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_SYSTEM_PAGE_HTML"
- file="system_page/system_page.html"
- preprocess="true"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_SYSTEM_PAGE_JS"
- file="system_page/system_page.js"
- type="chrome_html" />
+ preprocess="true" />
+ <if expr="not chromeos">
+ <structure name="IDR_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY_HTML"
+ file="system_page/system_page_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY"
+ file="system_page/system_page_browser_proxy.js"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SYSTEM_PAGE_HTML"
+ file="system_page/system_page.html"
+ preprocess="true"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_SYSTEM_PAGE_JS"
+ file="system_page/system_page.js"
+ type="chrome_html" />
+ </if>
<structure name="IDR_SETTINGS_SETTINGS_HTML"
preprocess="true"
file="settings.html"
@@ -1336,11 +1206,14 @@
preprocess="true"
file="lazy_load.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_WEBSITE_USAGE_PRIVATE_API_HTML"
- file="site_settings/website_usage_private_api.html"
+ <structure name="IDR_SETTINGS_ENSURE_LAZY_LOADED_HTML"
+ file="ensure_lazy_loaded.html"
type="chrome_html" />
- <structure name="IDR_SETTINGS_WEBSITE_USAGE_PRIVATE_API_JS"
- file="site_settings/website_usage_private_api.js"
+ <structure name="IDR_SETTINGS_WEBSITE_USAGE_BROWSER_PROXY_HTML"
+ file="site_settings/website_usage_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_SETTINGS_WEBSITE_USAGE_BROWSER_PROXY_JS"
+ file="site_settings/website_usage_browser_proxy.js"
type="chrome_html" />
<structure name="IDR_SETTINGS_ZOOM_LEVELS_HTML"
file="site_settings/zoom_levels.html"
@@ -1349,411 +1222,12 @@
file="site_settings/zoom_levels.js"
type="chrome_html" />
<if expr="chromeos">
- <structure name="IDR_SETTINGS_ANDROID_APPS_PAGE_HTML"
- file="android_apps_page/android_apps_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_ANDROID_APPS_PAGE_JS"
- file="android_apps_page/android_apps_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_ANDROID_APPS_SUBPAGE_HTML"
- file="android_apps_page/android_apps_subpage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_ANDROID_APPS_SUBPAGE_JS"
- file="android_apps_page/android_apps_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_ANDROID_APPS_BROWSER_PROXY_JS"
- file="android_apps_page/android_apps_browser_proxy.js"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_ANDROID_APPS_BROWSER_PROXY_HTML"
- file="android_apps_page/android_apps_browser_proxy.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_CROSTINI_PAGE_HTML"
- file="crostini_page/crostini_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_PAGE_JS"
- file="crostini_page/crostini_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_SUBPAGE_HTML"
- file="crostini_page/crostini_subpage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_SUBPAGE_JS"
- file="crostini_page/crostini_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_ARC_ADB_HTML"
- file="crostini_page/crostini_arc_adb.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_ARC_ADB_JS"
- file="crostini_page/crostini_arc_adb.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_DIALOG_HTML"
- file="crostini_page/crostini_arc_adb_confirmation_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_DIALOG_JS"
- file="crostini_page/crostini_arc_adb_confirmation_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_EXPORT_IMPORT_HTML"
- file="crostini_page/crostini_export_import.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_EXPORT_IMPORT_JS"
- file="crostini_page/crostini_export_import.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_SHARED_PATHS_HTML"
- file="crostini_page/crostini_shared_paths.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_SHARED_PATHS_JS"
- file="crostini_page/crostini_shared_paths.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_SHARED_USB_DEVICES_HTML"
- file="crostini_page/crostini_shared_usb_devices.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_SHARED_USB_DEVICES_JS"
- file="crostini_page/crostini_shared_usb_devices.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_BROWSER_PROXY_JS"
- file="crostini_page/crostini_browser_proxy.js"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_CROSTINI_BROWSER_PROXY_HTML"
- file="crostini_page/crostini_browser_proxy.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_CROSTINI_IMPORT_CONFIRMATION_DIALOG_HTML"
- file="crostini_page/crostini_import_confirmation_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_CROSTINI_IMPORT_CONFIRMATION_DIALOG_JS"
- file="crostini_page/crostini_import_confirmation_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_LIST_ITEM_HTML"
- file="bluetooth_page/bluetooth_device_list_item.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_DEVICE_LIST_ITEM_JS"
- file="bluetooth_page/bluetooth_device_list_item.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_PAGE_HTML"
- file="bluetooth_page/bluetooth_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_PAGE_JS"
- file="bluetooth_page/bluetooth_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_SUBPAGE_HTML"
- file="bluetooth_page/bluetooth_subpage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_BLUETOOTH_SUBPAGE_JS"
- file="bluetooth_page/bluetooth_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DATE_TIME_PAGE_HTML"
- file="date_time_page/date_time_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DATE_TIME_PAGE_JS"
- file="date_time_page/date_time_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DATE_TIME_TYPES_HTML"
- file="date_time_page/date_time_types.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_DATE_TIME_TYPES_JS"
- file="date_time_page/date_time_types.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_TIMEZONE_SELECTOR_HTML"
- file="date_time_page/timezone_selector.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_TIMEZONE_SELECTOR_JS"
- file="date_time_page/timezone_selector.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_TIMEZONE_SUBPAGE_HTML"
- file="date_time_page/timezone_subpage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_TIMEZONE_SUBPAGE_JS"
- file="date_time_page/timezone_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_CONFIG_HTML"
- file="internet_page/internet_config.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_CONFIG_JS"
- file="internet_page/internet_config.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_DETAIL_PAGE_HTML"
- file="internet_page/internet_detail_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_DETAIL_PAGE_JS"
- file="internet_page/internet_detail_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_KNOWN_NETWORKS_PAGE_HTML"
- file="internet_page/internet_known_networks_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_KNOWN_NETWORKS_PAGE_JS"
- file="internet_page/internet_known_networks_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_PAGE_BROWSER_PROXY_HTML"
- file="internet_page/internet_page_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_PAGE_BROWSER_PROXY_JS"
- file="internet_page/internet_page_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_PAGE_HTML"
- file="internet_page/internet_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_PAGE_JS"
- file="internet_page/internet_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_SHARED_CSS_HTML"
- file="internet_page/internet_shared_css.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_SUBPAGE_HTML"
- file="internet_page/internet_subpage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_INTERNET_SUBPAGE_JS"
- file="internet_page/internet_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_BROWSER_PROXY_HTML"
- file="multidevice_page/multidevice_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_BROWSER_PROXY_JS"
- file="multidevice_page/multidevice_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_CONSTANTS_HTML"
- file="multidevice_page/multidevice_constants.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_CONSTANTS_JS"
- file="multidevice_page/multidevice_constants.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_BEHAVIOR_HTML"
- file="multidevice_page/multidevice_feature_behavior.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_BEHAVIOR_JS"
- file="multidevice_page/multidevice_feature_behavior.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_ITEM_HTML"
- file="multidevice_page/multidevice_feature_item.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_ITEM_JS"
- file="multidevice_page/multidevice_feature_item.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_TOGGLE_HTML"
- file="multidevice_page/multidevice_feature_toggle.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_FEATURE_TOGGLE_JS"
- file="multidevice_page/multidevice_feature_toggle.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_PAGE_HTML"
- file="multidevice_page/multidevice_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_PAGE_JS"
- file="multidevice_page/multidevice_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_RADIO_BUTTON_HTML"
- file="multidevice_page/multidevice_radio_button.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_RADIO_BUTTON_JS"
- file="multidevice_page/multidevice_radio_button.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_SMARTLOCK_SUBPAGE_HTML"
- file="multidevice_page/multidevice_smartlock_subpage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_SMARTLOCK_SUBPAGE_JS"
- file="multidevice_page/multidevice_smartlock_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_SUBPAGE_HTML"
- file="multidevice_page/multidevice_subpage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_SUBPAGE_JS"
- file="multidevice_page/multidevice_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_TETHER_ITEM_HTML"
- file="multidevice_page/multidevice_tether_item.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_MULTIDEVICE_TETHER_ITEM_JS"
- file="multidevice_page/multidevice_tether_item.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_PROXY_SECTION_HTML"
- file="internet_page/network_proxy_section.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_PROXY_SECTION_JS"
- file="internet_page/network_proxy_section.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_SUMMARY_HTML"
- file="internet_page/network_summary.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_SUMMARY_JS"
- file="internet_page/network_summary.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_SUMMARY_ITEM_HTML"
- file="internet_page/network_summary_item.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_NETWORK_SUMMARY_ITEM_JS"
- file="internet_page/network_summary_item.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PARENTAL_CONTROLS_BROWSER_PROXY_HTML"
- file="parental_controls_page/parental_controls_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PARENTAL_CONTROLS_BROWSER_PROXY_JS"
- file="parental_controls_page/parental_controls_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PARENTAL_CONTROLS_HTML"
- file="parental_controls_page/parental_controls_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PARENTAL_CONTROLS_PAGE_JS"
- file="parental_controls_page/parental_controls_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_TETHER_CONNECTION_DIALOG_HTML"
- file="internet_page/tether_connection_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_TETHER_CONNECTION_DIALOG_JS"
- file="internet_page/tether_connection_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_HTML"
- file="people_page/account_manager.html"
- type="chrome_html"/>
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_JS"
- file="people_page/account_manager.js"
- type="chrome_html"/>
<structure name="IDR_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_BROWSER_PROXY_HTML"
file="people_page/account_manager_browser_proxy.html"
type="chrome_html"/>
<structure name="IDR_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_BROWSER_PROXY_JS"
file="people_page/account_manager_browser_proxy.js"
type="chrome_html"/>
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_CHANGE_PICTURE_HTML"
- file="people_page/change_picture.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_CHANGE_PICTURE_JS"
- file="people_page/change_picture.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_CHANGE_PICTURE_BROWSER_PROXY_JS"
- file="people_page/change_picture_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_CHANGE_PICTURE_BROWSER_PROXY_HTML"
- file="people_page/change_picture_browser_proxy.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_HTML"
- file="people_page/kerberos_accounts.html"
- type="chrome_html"/>
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_JS"
- file="people_page/kerberos_accounts.js"
- type="chrome_html"/>
- <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ADD_ACCOUNT_DIALOG_HTML"
- file="people_page/kerberos_add_account_dialog.html"
- type="chrome_html"/>
- <structure name="IDR_OS_SETTINGS_PEOPLE_PAGE_KERBEROS_ADD_ACCOUNT_DIALOG_JS"
- file="people_page/kerberos_add_account_dialog.js"
- type="chrome_html"/>
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_BROWSER_PROXY_HTML"
- file="people_page/kerberos_accounts_browser_proxy.html"
- type="chrome_html"/>
- <structure name="IDR_SETTINGS_PEOPLE_PAGE_KERBEROS_ACCOUNTS_BROWSER_PROXY_JS"
- file="people_page/kerberos_accounts_browser_proxy.js"
- type="chrome_html"/>
- <structure name="IDR_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_PROMPT_DIALOG_JS"
- file="people_page/lock_screen_password_prompt_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_PROMPT_DIALOG_HTML"
- file="people_page/lock_screen_password_prompt_dialog.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_PEOPLE_LOCK_SCREEN_JS"
- file="people_page/lock_screen.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_LOCK_SCREEN_HTML"
- file="people_page/lock_screen.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_PEOPLE_LOCK_STATE_BEHAVIOR_JS"
- file="people_page/lock_state_behavior.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_LOCK_STATE_BEHAVIOR_HTML"
- file="people_page/lock_state_behavior.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_PEOPLE_SETUP_PIN_DIALOG_JS"
- file="people_page/setup_pin_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_SETUP_PIN_DIALOG_HTML"
- file="people_page/setup_pin_dialog.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_PEOPLE_FINGERPRINT_LIST_JS"
- file="people_page/fingerprint_list.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_FINGERPRINT_LIST_HTML"
- file="people_page/fingerprint_list.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_SETUP_FINGERPRINT_DIALOG_JS"
- file="people_page/setup_fingerprint_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_SETUP_FINGERPRINT_DIALOG_HTML"
- file="people_page/setup_fingerprint_dialog.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_FINGERPRINT_BROWSER_PROXY_JS"
- file="people_page/fingerprint_browser_proxy.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PEOPLE_FINGERPRINT_BROWSER_PROXY_HTML"
- file="people_page/fingerprint_browser_proxy.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PLUGIN_VM_PAGE_HTML"
- file="plugin_vm_page/plugin_vm_page.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PLUGIN_VM_PAGE_JS"
- file="plugin_vm_page/plugin_vm_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PLUGIN_VM_SHARED_PATHS_HTML"
- file="plugin_vm_page/plugin_vm_shared_paths.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PLUGIN_VM_SHARED_PATHS_JS"
- file="plugin_vm_page/plugin_vm_shared_paths.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PLUGIN_VM_SUBPAGE_HTML"
- file="plugin_vm_page/plugin_vm_subpage.html"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PLUGIN_VM_SUBPAGE_JS"
- file="plugin_vm_page/plugin_vm_subpage.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_PLUGIN_VM_BROWSER_PROXY_JS"
- file="plugin_vm_page/plugin_vm_browser_proxy.js"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_PLUGIN_VM_BROWSER_PROXY_HTML"
- file="plugin_vm_page/plugin_vm_browser_proxy.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_USERS_PAGE_ADD_USER_DIALOG_JS"
- file="people_page/users_add_user_dialog.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_USERS_PAGE_ADD_USER_DIALOG_HTML"
- file="people_page/users_add_user_dialog.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_USERS_PAGE_USER_LIST_JS"
- file="people_page/user_list.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_USERS_PAGE_USER_LIST_HTML"
- file="people_page/user_list.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
- <structure name="IDR_SETTINGS_USERS_PAGE_JS"
- file="people_page/users_page.js"
- type="chrome_html" />
- <structure name="IDR_SETTINGS_USERS_PAGE_HTML"
- file="people_page/users_page.html"
- type="chrome_html"
- preprocess="true"
- allowexternalscript="true" />
</if>
</structures>
</release>
diff --git a/chromium/chrome/browser/resources/settings/settings_resources_v3.grdp b/chromium/chrome/browser/resources/settings/settings_resources_v3.grdp
new file mode 100644
index 00000000000..c519226f257
--- /dev/null
+++ b/chromium/chrome/browser/resources/settings/settings_resources_v3.grdp
@@ -0,0 +1,815 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <!-- Polymer 3.0 Elements -->
+ <include name="IDR_SETTINGS_A11Y_PAGE_A11Y_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/a11y_page/a11y_page.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <if expr="not is_macosx and not chromeos">
+ <include name="IDR_SETTINGS_A11Y_PAGE_CAPTIONS_SUBPAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/a11y_page/captions_subpage.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <if expr="is_win or is_macosx">
+ <include name="IDR_SETTINGS_A11Y_PAGE_CAPTIONS_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/a11y_page/captions_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <include name="IDR_SETTINGS_ABOUT_PAGE_ABOUT_PAGE_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/about_page/about_page_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_ABOUT_PAGE_ABOUT_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/about_page/about_page.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_APPEARANCE_PAGE_APPEARANCE_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/appearance_page/appearance_browser_proxy.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_APPEARANCE_PAGE_APPEARANCE_FONTS_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_APPEARANCE_PAGE_APPEARANCE_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/appearance_page/appearance_page.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_APPEARANCE_PAGE_FONTS_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/appearance_page/fonts_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_APPEARANCE_PAGE_HOME_URL_INPUT_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/appearance_page/home_url_input.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_AUTOFILL_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/autofill_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PAYMENTS_LIST_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/payments_list.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_CREDIT_CARD_LIST_ENTRY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_UPI_ID_LIST_ENTRY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORDS_SHARED_CSS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/passwords_shared_css.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_CREDIT_CARD_EDIT_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_AUTOFILL_SECTION_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/autofill_section.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_ADDRESS_EDIT_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/address_edit_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <if expr="chromeos">
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_BLOCKING_REQUEST_MANAGER_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/blocking_request_manager.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_SHOW_PASSWORD_BEHAVIOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/show_password_behavior.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_CHECK_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_check.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true"/>
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_CHECK_BEHAVIOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_check_behavior.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_CHECK_EDIT_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_CHECK_LIST_ITEM_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_check_list_item.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_LIST_ITEM_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_list_item.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_MANAGER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_manager_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_REMOVE_CONFIRMATION_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORDS_SECTION_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/passwords_section.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORD_EDIT_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/password_edit_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PASSWORDS_EXPORT_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_AUTOFILL_PAGE_PAYMENTS_SECTION_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/autofill_page/payments_section.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_BASIC_PAGE_BASIC_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/basic_page/basic_page.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <if expr="is_win">
+ <include name="IDR_SETTINGS_CHROME_CLEANUP_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CHROME_CLEANUP_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_CHROME_CLEANUP_ITEMS_TO_REMOVE_LIST_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <include name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_CLEAR_BROWSING_DATA_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_CLEAR_BROWSING_DATA_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_HISTORY_DELETION_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CLEAR_BROWSING_DATA_DIALOG_INSTALLED_APP_CHECKBOX_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_CONTROLLED_BUTTON_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/controlled_button.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_CONTROLLED_RADIO_BUTTON_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/controlled_radio_button.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_EXTENSION_CONTROLLED_INDICATOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/extension_controlled_indicator.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_PASSWORD_PROMPT_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/password_prompt_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_SETTINGS_BOOLEAN_CONTROL_BEHAVIOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_boolean_control_behavior.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_SETTINGS_CHECKBOX_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_checkbox.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_SETTINGS_DROPDOWN_MENU_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_dropdown_menu.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_SETTINGS_IDLE_LOAD_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_idle_load.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_PREF_CONTROL_BEHAVIOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/pref_control_behavior.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_SETTINGS_RADIO_GROUP_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_radio_group.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_SETTINGS_SLIDER_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_slider.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_SETTINGS_TEXTAREA_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_textarea.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_CONTROLS_SETTINGS_TOGGLE_BUTTON_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/controls/settings_toggle_button.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <if expr="not chromeos">
+ <include name="IDR_SETTINGS_DEFAULT_BROWSER_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/default_browser_page/default_browser_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_DEFAULT_BROWSER_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/default_browser_page/default_browser_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <include name="IDR_SETTINGS_DOWNLOADS_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/downloads_page/downloads_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_DOWNLOADS_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/downloads_page/downloads_page.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_ENSURE_LAZY_LOADED_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/ensure_lazy_loaded.m.js"
+ preprocess="true"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_EXTENSION_CONTROL_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/extension_control_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_GLOBAL_SCROLL_TARGET_BEHAVIOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/global_scroll_target_behavior.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_HATS_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/hats_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_I18N_SETUP_M_JS"
+ file="i18n_setup.m.js"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_ICONS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/icons.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <if expr="is_win and _google_chrome">
+ <include name="IDR_SETTINGS_INCOMPATIBLE_APPLICATIONS_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_INCOMPATIBLE_APPLICATIONS_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_INCOMPATIBLE_APPLICATIONS_INCOMPATIBLE_APPLICATION_ITEM_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <include name="IDR_SETTINGS_LANGUAGES_PAGE_LANGUAGES_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/languages_page/languages.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_LANGUAGES_PAGE_LANGUAGES_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/languages_page/languages_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_LANGUAGES_PAGE_ADD_LANGUAGES_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/languages_page/add_languages_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_LANGUAGES_PAGE_LANGUAGES_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/languages_page/languages_page.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <if expr="not is_macosx">
+ <include name="IDR_SETTINGS_LANGUAGES_PAGE_EDIT_DICTIONARY_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/languages_page/edit_dictionary_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <include name="IDR_SETTINGS_LAZY_LOAD_V3_JS"
+ file="lazy_load.js"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_LIFETIME_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/lifetime_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_MENU_SETTINGS_MENU_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_menu/settings_menu.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_METRICS_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/metrics_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_ON_STARTUP_PAGE_ON_STARTUP_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/on_startup_page/on_startup_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_ON_STARTUP_PAGE_ON_STARTUP_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/on_startup_page/on_startup_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_ON_STARTUP_PAGE_STARTUP_URL_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_ON_STARTUP_PAGE_STARTUP_URL_ENTRY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/on_startup_page/startup_url_entry.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_ON_STARTUP_PAGE_STARTUP_URLS_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/on_startup_page/startup_urls_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_ON_STARTUP_PAGE_STARTUP_URLS_PAGE_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/on_startup_page/startup_urls_page_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_OPEN_WINDOW_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/open_window_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PAGE_VISIBILITY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/page_visibility.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <if expr="not chromeos">
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_IMPORT_DATA_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/import_data_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_IMPORT_DATA_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/import_data_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_MANAGE_PROFILE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/manage_profile.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_MANAGE_PROFILE_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/manage_profile_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <if expr="chromeos">
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_ACCOUNT_MANAGER_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/account_manager_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_ACCOUNT_CONTROL_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_account_control.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_ENCRYPTION_OPTIONS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_encryption_options.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_PEOPLE_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/people_page.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_PROFILE_INFO_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/profile_info_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_SIGNOUT_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/signout_dialog.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_CONTROLS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_controls.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PEOPLE_PAGE_SYNC_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/people_page/sync_page.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PLURAL_STRING_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/plural_string_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PREFS_PREFS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/prefs/prefs.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PREFS_PREFS_BEHAVIOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/prefs/prefs_behavior.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PREFS_PREFS_TYPES_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/prefs/prefs_types.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PREFS_PREF_UTIL_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/prefs/pref_util.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRINTING_PAGE_CLOUD_PRINTERS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/printing_page/cloud_printers.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRINTING_PAGE_PRINTING_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/printing_page/printing_page.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_COLLAPSE_RADIO_BUTTON_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/collapse_radio_button.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_COOKIES_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/cookies_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_DO_NOT_TRACK_TOGGLE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_PRIVACY_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/privacy_page.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_PASSWORDS_LEAK_DETECTION_TOGGLE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/passwords_leak_detection_toggle.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_PERSONALIZATION_OPTIONS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/personalization_options.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/privacy_page_browser_proxy.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SAFE_BROWSING_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/safe_browsing_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURE_DNS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/secure_dns.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURE_DNS_INPUT_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/secure_dns_input.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURITY_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/security_page.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_DISABLE_SAFEBROWSING_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/disable_safebrowsing_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURITY_KEYS_BIO_ENROLL_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURITY_KEYS_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/security_keys_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURITY_KEYS_CREDENTIAL_MANAGEMENT_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURITY_KEYS_PIN_FIELD_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURITY_KEYS_RESET_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURITY_KEYS_SET_PIN_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_PRIVACY_PAGE_SECURITY_KEYS_SUBPAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/privacy_page/security_keys_subpage.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_RESET_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/reset_page/reset_page.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_RESET_PROFILE_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/reset_page/reset_profile_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_RESET_PROFILE_BANNER_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/reset_page/reset_profile_banner.m.js"
+ use_base_dir="false"
+ type="BINDATA"/>
+ <include name="IDR_SETTINGS_RESET_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/reset_page/reset_browser_proxy.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_ROUTE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/route.m.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_ROUTER_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/router.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SEARCH_ENGINES_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_OMNIBOX_EXTENSION_ENTRY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/search_engines_page/search_engine_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_ENTRY_CSS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/search_engines_page/search_engine_entry_css.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINE_ENTRY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/search_engines_page/search_engine_entry.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_LIST_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/search_engines_page/search_engines_list.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SEARCH_ENGINES_PAGE_SEARCH_ENGINES_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/search_engines_page/search_engines_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SEARCH_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/search_page/search_page.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SEARCH_SETTINGS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/search_settings.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SETTINGS_MAIN_SETTINGS_MAIN_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_main/settings_main.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SETTINGS_PAGE_MAIN_PAGE_BEHAVIOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_page/main_page_behavior.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SETTINGS_PAGE_SETTINGS_ANIMATED_PAGES_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_page/settings_animated_pages.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SETTINGS_PAGE_SETTINGS_SECTION_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_page/settings_section.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SETTINGS_PAGE_SETTINGS_SUBPAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_page/settings_subpage.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SETTINGS_UI_SETTINGS_UI_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_ui/settings_ui.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SETTINGS_ROUTES_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_routes.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SETTINGS_PAGE_CSS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_page_css.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SETTINGS_SHARED_CSS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_shared_css.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SETTINGS_VARS_CSS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/settings_vars_css.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SETTINGS_V3_HTML"
+ file="settings_v3.html"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SETTINGS_V3_JS"
+ file="settings.js"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SITE_FAVICON_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_favicon.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_ADD_SITE_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/add_site_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_ALL_SITES_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/all_sites.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_ALL_SITES_ICONS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/all_sites_icons.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <if expr="chromeos">
+ <include name="IDR_SETTINGS_SITE_SETTINGS_ANDROID_INFO_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/android_info_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ </if>
+ <include name="IDR_SETTINGS_SITE_SETTINGS_CATEGORY_DEFAULT_SETTING_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/category_default_setting.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_CATEGORY_SETTING_EXCEPTIONS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/category_setting_exceptions.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_CHOOSER_EXCEPTION_LIST_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/chooser_exception_list.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_CHOOSER_EXCEPTION_LIST_ENTRY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_CLEAR_STORAGE_DIALOG_CSS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/clear_storage_dialog_css.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_CONSTANTS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/constants.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_COOKIE_INFO_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/cookie_info.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_EDIT_EXCEPTION_DIALOG_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/edit_exception_dialog.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_LOCAL_DATA_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_MEDIA_PICKER_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/media_picker.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_PDF_DOCUMENTS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/pdf_documents.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_PROTOCOL_HANDLERS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/protocol_handlers.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_DATA_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_data.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_DATA_DETAILS_SUBPAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_data_details_subpage.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_DATA_ENTRY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_data_entry.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_DETAILS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_details.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_DETAILS_PERMISSION_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_details_permission.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_ENTRY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_entry.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_LIST_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_list.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_LIST_ENTRY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_list_entry.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_SETTINGS_BEHAVIOR_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_settings_behavior.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_SITE_SETTINGS_PREFS_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_WEBSITE_USAGE_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/website_usage_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_ZOOM_LEVELS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings/zoom_levels.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_PAGE_RECENT_SITE_PERMISSIONS_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_PAGE_SITE_SETTINGS_LIST_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings_page/site_settings_list.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SITE_SETTINGS_PAGE_SITE_SETTINGS_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/site_settings_page/site_settings_page.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ <if expr="not chromeos">
+ <include name="IDR_SETTINGS_PRINTING_PAGE_PRINTING_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/printing_page/printing_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SYSTEM_PAGE_BROWSER_PROXY_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/system_page/system_page_browser_proxy.m.js"
+ use_base_dir="false"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_SYSTEM_PAGE_M_JS"
+ file="${root_gen_dir}/chrome/browser/resources/settings/system_page/system_page.m.js"
+ use_base_dir="false"
+ type="BINDATA"
+ preprocess="true" />
+ </if>
+</grit-part>
diff --git a/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd b/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd
index 61b333fad32..5c4b44a2c1b 100644
--- a/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd
+++ b/chromium/chrome/browser/resources/settings/settings_resources_vulcanized.grd
@@ -12,11 +12,101 @@
</outputs>
<release seq="1">
<includes>
- <include name="IDR_SETTINGS_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_SETTINGS_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\settings\crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" />
- <include name="IDR_SETTINGS_LAZY_LOAD_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.vulcanized.html" use_base_dir="false" flattenhtml="true" allowexternalscript="true" type="BINDATA" compress="gzip" />
- <include name="IDR_SETTINGS_LAZY_LOAD_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.crisper.js" use_base_dir="false" flattenhtml="true" type="BINDATA" compress="gzip" />
- <include name="IDR_SETTINGS_MANIFEST" file="manifest.json" type="BINDATA" compress="gzip" />
+ <include name="IDR_SETTINGS_VULCANIZED_HTML"
+ file="${root_gen_dir}\chrome\browser\resources\settings\vulcanized.html"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_CRISPER_JS"
+ file="${root_gen_dir}\chrome\browser\resources\settings\crisper.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_LAZY_LOAD_VULCANIZED_HTML"
+ file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.vulcanized.html"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_LAZY_LOAD_CRISPER_JS"
+ file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.crisper.js"
+ use_base_dir="false"
+ preprocess="true"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_COOKIES_BANNER_SVG"
+ file="images/cookies_banner.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_COOKIES_BANNER_DARK_SVG"
+ file="images/cookies_banner_dark.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_PERMISSIONS_BANNER_SVG"
+ file="images/permissions_banner.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_PERMISSIONS_BANNER_DARK_SVG"
+ file="images/permissions_banner_dark.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_SAFE_BROWSING_BANNER_SVG"
+ file="images/safe_browsing_banner.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_SAFE_BROWSING_BANNER_DARK_SVG"
+ file="images/safe_browsing_banner_dark.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_SYNC_BANNER_SVG"
+ file="images/sync_banner.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_SYNC_BANNER_DARK_SVG"
+ file="images/sync_banner_dark.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_NEUTRAL_SVG"
+ file="images/password_check_neutral.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_NEUTRAL_DARK_SVG"
+ file="images/password_check_neutral_dark.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_POSITIVE_SVG"
+ file="images/password_check_positive.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_IMAGES_PASSWORD_CHECK_POSITIVE_DARK_SVG"
+ file="images/password_check_positive_dark.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <!-- Polymer 3 related files -->
+ <include name="IDR_SETTINGS_SETTINGS_V3_HTML"
+ file="settings_v3.html"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_SETTINGS_SETTINGS_ROLLUP_JS"
+ file="${root_gen_dir}\chrome\browser\resources\settings\settings.rollup.js"
+ use_base_dir="false"
+ preprocess="true"
+ compress="gzip"
+ type="BINDATA" />
+ <include name="IDR_SETTINGS_LAZY_LOAD_ROLLUP_JS"
+ file="${root_gen_dir}\chrome\browser\resources\settings\lazy_load.rollup.js"
+ preprocess="true"
+ type="BINDATA"
+ compress="gzip"
+ use_base_dir="false" />
+ <include name="IDR_SETTINGS_SHARED_ROLLUP_JS"
+ file="${root_gen_dir}\chrome\browser\resources\settings\shared.rollup.js"
+ preprocess="true"
+ type="BINDATA"
+ compress="gzip"
+ use_base_dir="false" />
</includes>
</release>
</grit>
diff --git a/chromium/chrome/browser/resources/settings/settings_ui/BUILD.gn b/chromium/chrome/browser/resources/settings/settings_ui/BUILD.gn
index 5352040d9b2..92a83108aa8 100644
--- a/chromium/chrome/browser/resources/settings/settings_ui/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/settings_ui/BUILD.gn
@@ -3,17 +3,19 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
- deps = [
- ":settings_ui",
- ]
+ deps = [ ":settings_ui" ]
}
js_library("settings_ui") {
deps = [
"..:global_scroll_target_behavior",
"..:page_visibility",
+ "..:route",
+ "..:router",
"../prefs",
"../settings_main:settings_main",
"//ui/webui/resources/cr_elements:cr_container_shadow_behavior",
@@ -24,3 +26,55 @@ js_library("settings_ui") {
"//ui/webui/resources/js:find_shortcut_behavior",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [ ":settings_ui.m" ]
+}
+
+js_library("settings_ui.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/settings_ui/settings_ui.m.js" ]
+ deps = [
+ "..:global_scroll_target_behavior.m",
+ "..:page_visibility.m",
+ "..:route.m",
+ "..:router.m",
+ "../prefs:prefs.m",
+ "../settings_main:settings_main.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements:cr_container_shadow_behavior.m",
+ "//ui/webui/resources/cr_elements/cr_drawer:cr_drawer.m",
+ "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar.m",
+ "//ui/webui/resources/cr_elements/cr_toolbar:cr_toolbar_search_field.m",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:find_shortcut_behavior.m",
+ "//ui/webui/resources/js:util.m",
+ ]
+ extra_deps = [ ":settings_ui_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [ ":settings_ui_module" ]
+}
+
+polymer_modulizer("settings_ui") {
+ js_file = "settings_ui.js"
+ html_file = "settings_ui.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/global_scroll_target_behavior.html|setGlobalScrollTarget,resetGlobalScrollTargetForTesting",
+ "chrome/browser/resources/settings/page_visibility.html|PageVisibility,pageVisibility",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route,Router,RouteObserverBehavior",
+ "ui/webui/resources/html/assert.html|assert",
+ "ui/webui/resources/html/cr.html|isChromeOS",
+ "ui/webui/resources/html/util.html|listenOnce",
+ "ui/webui/resources/cr_elements/cr_container_shadow_behavior.html|CrContainerShadowBehavior",
+ ]
+ namespace_rewrites = settings_namespace_rewrites + [
+ "settings.setGlobalScrollTarget|setGlobalScrollTarget",
+ "settings.resetGlobalScrollTargetForTesting|resetGlobalScrollTargetForTesting",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/settings/site_settings/BUILD.gn b/chromium/chrome/browser/resources/settings/site_settings/BUILD.gn
index 527f2ceb5a8..e72d5093127 100644
--- a/chromium/chrome/browser/resources/settings/site_settings/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/site_settings/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -27,7 +30,7 @@ js_type_check("closure_compile") {
":site_list_entry",
":site_settings_behavior",
":site_settings_prefs_browser_proxy",
- ":website_usage_private_api",
+ ":website_usage_browser_proxy",
":zoom_levels",
]
}
@@ -47,16 +50,23 @@ js_library("all_sites") {
"//ui/webui/resources/cr_elements/cr_search_field:cr_search_field",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
externs_list = [ "$externs_path/settings_private.js" ]
}
+js_library("android_info_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+ externs_list = [ "$externs_path/chrome_send.js" ]
+}
+
js_library("category_default_setting") {
deps = [
":constants",
":site_settings_behavior",
+ "..:route",
"../settings_page:settings_animated_pages",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
@@ -98,9 +108,7 @@ js_library("chooser_exception_list_entry") {
}
js_library("constants") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("local_data_browser_proxy") {
@@ -123,15 +131,15 @@ js_library("media_picker") {
}
js_library("cookie_info") {
- deps = [
- "//ui/webui/resources/js:load_time_data",
- ]
+ deps = [ "//ui/webui/resources/js:load_time_data" ]
}
js_library("protocol_handlers") {
deps = [
":site_settings_behavior",
- "../android_apps_page:android_apps_browser_proxy",
+
+ # Must be included on all platforms to satisfy closure compiler.
+ ":android_info_browser_proxy",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/js:web_ui_listener_behavior",
]
@@ -144,6 +152,7 @@ js_library("site_data") {
":site_data_entry",
":site_settings_behavior",
"..:global_scroll_target_behavior",
+ "..:route",
"//ui/webui/resources/cr_elements/cr_search_field:cr_search_field",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
@@ -158,6 +167,7 @@ js_library("site_data_details_subpage") {
deps = [
":local_data_browser_proxy",
"..:route",
+ "..:router",
"//third_party/polymer/v1_0/components-chromium/iron-list:iron-list-extracted",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:web_ui_listener_behavior",
@@ -180,8 +190,8 @@ js_library("site_details") {
":constants",
":site_details_permission",
":site_settings_behavior",
- ":website_usage_private_api",
- "..:route",
+ ":website_usage_browser_proxy",
+ "..:router",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:i18n_behavior",
@@ -209,6 +219,7 @@ js_library("site_entry") {
":site_settings_behavior",
":site_settings_prefs_browser_proxy",
"..:route",
+ "..:router",
"//third_party/polymer/v1_0/components-chromium/iron-collapse:iron-collapse-extracted",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render",
@@ -220,10 +231,10 @@ js_library("site_entry") {
js_library("site_list") {
deps = [
+ ":android_info_browser_proxy",
":constants",
":site_list_entry",
":site_settings_behavior",
- "../multidevice_page:multidevice_browser_proxy",
"//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
@@ -238,7 +249,7 @@ js_library("site_list_entry") {
deps = [
":constants",
":site_settings_behavior",
- "..:route",
+ "..:router",
"//ui/webui/resources/cr_elements/policy:cr_policy_pref_indicator",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js/cr/ui:focus_row_behavior",
@@ -249,7 +260,7 @@ js_library("site_settings_behavior") {
deps = [
":constants",
":site_settings_prefs_browser_proxy",
- "..:route",
+ "..:router",
"//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior",
"//ui/webui/resources/cr_elements/policy:cr_policy_pref_behavior",
"//ui/webui/resources/js:assert",
@@ -270,10 +281,8 @@ js_library("site_settings_prefs_browser_proxy") {
]
}
-js_library("website_usage_private_api") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+js_library("website_usage_browser_proxy") {
+ deps = [ "//ui/webui/resources/js:cr" ]
externs_list = [ "$externs_path/chrome_send.js" ]
}
@@ -284,3 +293,624 @@ js_library("zoom_levels") {
"//ui/webui/resources/js:web_ui_listener_behavior",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":add_site_dialog.m",
+ ":all_sites.m",
+ ":android_info_browser_proxy.m",
+ ":category_default_setting.m",
+ ":category_setting_exceptions.m",
+ ":chooser_exception_list.m",
+ ":chooser_exception_list_entry.m",
+ ":constants.m",
+ ":cookie_info.m",
+ ":edit_exception_dialog.m",
+ ":local_data_browser_proxy.m",
+ ":media_picker.m",
+ ":pdf_documents.m",
+ ":protocol_handlers.m",
+ ":site_data.m",
+ ":site_data_details_subpage.m",
+ ":site_data_entry.m",
+ ":site_details.m",
+ ":site_details_permission.m",
+ ":site_entry.m",
+ ":site_list.m",
+ ":site_list_entry.m",
+ ":site_settings_behavior.m",
+ ":site_settings_prefs_browser_proxy.m",
+ ":website_usage_browser_proxy.m",
+ ":zoom_levels.m",
+ ]
+}
+
+js_library("add_site_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/add_site_dialog.m.js" ]
+ deps = [
+ ":constants.m",
+ ":site_settings_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":add_site_dialog_module" ]
+}
+
+js_library("all_sites.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/all_sites.m.js" ]
+ deps = [
+ ":constants.m",
+ ":local_data_browser_proxy.m",
+ ":site_settings_behavior.m",
+ ":site_settings_prefs_browser_proxy.m",
+ "..:global_scroll_target_behavior.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":all_sites_module" ]
+}
+
+js_library("android_info_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/android_info_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("category_default_setting.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/category_default_setting.m.js" ]
+ deps = [
+ ":constants.m",
+ ":site_settings_behavior.m",
+ "..:route.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":category_default_setting_module" ]
+}
+
+js_library("category_setting_exceptions.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/category_setting_exceptions.m.js" ]
+ deps = [
+ ":constants.m",
+ ":site_settings_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":category_setting_exceptions_module" ]
+}
+
+js_library("chooser_exception_list.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/chooser_exception_list.m.js" ]
+ deps = [
+ ":chooser_exception_list_entry.m",
+ ":site_settings_behavior.m",
+ ":site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:list_property_update_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":chooser_exception_list_module" ]
+}
+
+js_library("chooser_exception_list_entry.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.m.js" ]
+ deps = [
+ ":site_list_entry.m",
+ ":site_settings_behavior.m",
+ ":site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":chooser_exception_list_entry_module" ]
+}
+
+js_library("constants.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/constants.m.js" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("cookie_info.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/cookie_info.m.js" ]
+ deps = [ "//ui/webui/resources/js:load_time_data.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("edit_exception_dialog.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/edit_exception_dialog.m.js" ]
+ deps = [
+ ":constants.m",
+ ":site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
+ ]
+ extra_deps = [ ":edit_exception_dialog_module" ]
+}
+
+js_library("local_data_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.m.js" ]
+ deps = [
+ ":cookie_info.m",
+ "//ui/webui/resources/js:cr.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("media_picker.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/media_picker.m.js" ]
+ deps = [
+ ":site_settings_behavior.m",
+ ":site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":media_picker_module" ]
+}
+
+js_library("pdf_documents.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/pdf_documents.m.js" ]
+ deps = [
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ extra_deps = [ ":pdf_documents_module" ]
+}
+
+js_library("protocol_handlers.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/protocol_handlers.m.js" ]
+ deps = [
+ ":site_settings_behavior.m",
+
+ # Must be included on all platforms to satisfy closure compiler.
+ ":android_info_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":protocol_handlers_module" ]
+}
+
+js_library("site_data.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_data.m.js" ]
+ deps = [
+ ":cookie_info.m",
+ ":local_data_browser_proxy.m",
+ ":site_data_entry.m",
+ ":site_settings_behavior.m",
+ "..:global_scroll_target_behavior.m",
+ "..:route.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_search_field:cr_search_field.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:list_property_update_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ extra_deps = [ ":site_data_module" ]
+}
+
+js_library("site_data_details_subpage.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_data_details_subpage.m.js" ]
+ deps = [
+ ":local_data_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-list:iron-list",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":site_data_details_subpage_module" ]
+}
+
+js_library("site_data_entry.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_data_entry.m.js" ]
+ deps = [
+ ":cookie_info.m",
+ ":local_data_browser_proxy.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:icon.m",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
+ ]
+ extra_deps = [ ":site_data_entry_module" ]
+}
+
+js_library("site_details.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_details.m.js" ]
+ deps = [
+ ":constants.m",
+ ":site_details_permission.m",
+ ":site_settings_behavior.m",
+ ":website_usage_browser_proxy.m",
+ "..:router.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":site_details_module" ]
+}
+
+js_library("site_details_permission.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_details_permission.m.js" ]
+ deps = [
+ ":constants.m",
+ ":site_settings_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":site_details_permission_module" ]
+}
+
+js_library("site_entry.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_entry.m.js" ]
+ deps = [
+ ":constants.m",
+ ":local_data_browser_proxy.m",
+ ":site_settings_behavior.m",
+ ":site_settings_prefs_browser_proxy.m",
+ "..:route.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/iron-collapse:iron-collapse",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
+ ]
+ extra_deps = [ ":site_entry_module" ]
+}
+
+js_library("site_list.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_list.m.js" ]
+ deps = [
+ ":android_info_browser_proxy.m",
+ ":constants.m",
+ ":site_list_entry.m",
+ ":site_settings_behavior.m",
+ ":site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/paper-tooltip:paper-tooltip",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:list_property_update_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":site_list_module" ]
+}
+
+js_library("site_list_entry.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_list_entry.m.js" ]
+ deps = [
+ ":constants.m",
+ ":site_settings_behavior.m",
+ "..:route.m",
+ "..:router.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_pref_indicator",
+ "//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
+ ]
+ extra_deps = [ ":site_list_entry_module" ]
+}
+
+js_library("site_settings_behavior.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_settings_behavior.m.js" ]
+ deps = [
+ ":constants.m",
+ ":site_settings_prefs_browser_proxy.m",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:icon.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("site_settings_prefs_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.m.js" ]
+ deps = [
+ ":constants.m",
+ "//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior.m",
+ "//ui/webui/resources/js:cr.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("website_usage_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/website_usage_browser_proxy.m.js" ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ extra_deps = [ ":modulize" ]
+}
+
+js_library("zoom_levels.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings/zoom_levels.m.js" ]
+ deps = [
+ ":site_settings_behavior.m",
+ ":site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:list_property_update_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":zoom_levels_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":add_site_dialog_module",
+ ":all_sites_icons_module",
+ ":all_sites_module",
+ ":category_default_setting_module",
+ ":category_setting_exceptions_module",
+ ":chooser_exception_list_entry_module",
+ ":chooser_exception_list_module",
+ ":clear_storage_dialog_css_module",
+ ":edit_exception_dialog_module",
+ ":media_picker_module",
+ ":modulize",
+ ":pdf_documents_module",
+ ":protocol_handlers_module",
+ ":site_data_details_subpage_module",
+ ":site_data_entry_module",
+ ":site_data_module",
+ ":site_details_module",
+ ":site_details_permission_module",
+ ":site_entry_module",
+ ":site_list_entry_module",
+ ":site_list_module",
+ ":zoom_levels_module",
+ ]
+}
+
+polymer_modulizer("add_site_dialog") {
+ js_file = "add_site_dialog.js"
+ html_file = "add_site_dialog.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/site_settings/constants.html|ContentSetting,ContentSettingsTypes,SITE_EXCEPTION_WILDCARD",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("all_sites") {
+ js_file = "all_sites.js"
+ html_file = "all_sites.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/global_scroll_target_behavior.html|GlobalScrollTargetBehavior,GlobalScrollTargetBehaviorImpl",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route,Router,RouteObserverBehavior",
+ "chrome/browser/resources/settings/site_settings/constants.html|ALL_SITES_DIALOG,AllSitesAction2,ContentSetting,ContentSettingsTypes,SortMethod",
+ "chrome/browser/resources/settings/site_settings/local_data_browser_proxy.html|LocalDataBrowserProxy,LocalDataBrowserProxyImpl",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|SiteGroup",
+ "ui/webui/resources/html/polymer.html|afterNextRender,html,Polymer",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("all_sites_icons") {
+ js_file = "all_sites_icons.m.js"
+ html_file = "all_sites_icons.html"
+ html_type = "iron-iconset"
+}
+
+polymer_modulizer("category_default_setting") {
+ js_file = "category_default_setting.js"
+ html_file = "category_default_setting.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/site_settings/constants.html|ContentSetting,ContentSettingsTypes",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|ContentSettingProvider,DefaultContentSetting",
+ "ui/webui/resources/html/assert.html|assert,assertNotReached",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("category_setting_exceptions") {
+ js_file = "category_setting_exceptions.js"
+ html_file = "category_setting_exceptions.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/site_settings/constants.html|ContentSetting,ContentSettingsTypes,SiteSettingSource" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("chooser_exception_list") {
+ js_file = "chooser_exception_list.js"
+ html_file = "chooser_exception_list.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/site_settings/constants.html|ChooserType,ContentSettingsTypes",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|ChooserException,RawChooserException",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("chooser_exception_list_entry") {
+ js_file = "chooser_exception_list_entry.js"
+ html_file = "chooser_exception_list_entry.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|ChooserException" ]
+}
+
+polymer_modulizer("clear_storage_dialog_css") {
+ js_file = "clear_storage_dialog_css.m.js"
+ html_file = "clear_storage_dialog_css.html"
+ html_type = "style-module"
+}
+
+polymer_modulizer("edit_exception_dialog") {
+ js_file = "edit_exception_dialog.js"
+ html_file = "edit_exception_dialog.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/site_settings/constants.html|SITE_EXCEPTION_WILDCARD",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|SiteException,SiteSettingsPrefsBrowserProxy,SiteSettingsPrefsBrowserProxyImpl",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("media_picker") {
+ js_file = "media_picker.js"
+ html_file = "media_picker.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|MediaPickerEntry" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("pdf_documents") {
+ js_file = "pdf_documents.js"
+ html_file = "pdf_documents.html"
+ html_type = "dom-module"
+}
+
+polymer_modulizer("protocol_handlers") {
+ js_file = "protocol_handlers.js"
+ html_file = "protocol_handlers.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/site_settings/android_info_browser_proxy.html|AndroidInfoBrowserProxyImpl,AndroidAppsInfo" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_data") {
+ js_file = "site_data.js"
+ html_file = "site_data.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/global_scroll_target_behavior.html|GlobalScrollTargetBehavior,GlobalScrollTargetBehaviorImpl",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route,Router,RouteObserverBehavior",
+ "chrome/browser/resources/settings/site_settings/local_data_browser_proxy.html|LocalDataBrowserProxy,LocalDataBrowserProxyImpl",
+ "chrome/browser/resources/settings/site_settings/site_data_entry.html|CookieDataSummaryItem",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_data_details_subpage") {
+ js_file = "site_data_details_subpage.js"
+ html_file = "site_data_details_subpage.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route,Router,RouteObserverBehavior",
+ "chrome/browser/resources/settings/site_settings/cookie_info.html|CookieDataForDisplay,CookieDetails,getCookieData",
+ "chrome/browser/resources/settings/site_settings/local_data_browser_proxy.html|CookieList,LocalDataBrowserProxy,LocalDataBrowserProxyImpl",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_data_entry") {
+ js_file = "site_data_entry.js"
+ html_file = "site_data_entry.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/site_settings/local_data_browser_proxy.html|LocalDataBrowserProxy,LocalDataBrowserProxyImpl" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_details") {
+ js_file = "site_details.js"
+ html_file = "site_details.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route,Router,RouteObserverBehavior",
+ "chrome/browser/resources/settings/site_settings/constants.html|ContentSetting,ContentSettingsTypes",
+ "chrome/browser/resources/settings/site_settings/website_usage_browser_proxy.html|WebsiteUsageBrowserProxy,WebsiteUsageBrowserProxyImpl",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_details_permission") {
+ js_file = "site_details_permission.js"
+ html_file = "site_details_permission.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/site_settings/constants.html|ContentSetting,ContentSettingsTypes,SiteSettingSource",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|RawSiteException",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_entry") {
+ js_file = "site_entry.js"
+ html_file = "site_entry.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/site_settings/constants.html|AllSitesAction2,SortMethod",
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ "chrome/browser/resources/settings/site_settings/local_data_browser_proxy.html|LocalDataBrowserProxy,LocalDataBrowserProxyImpl",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|OriginInfo,SiteGroup",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_list") {
+ js_file = "site_list.js"
+ html_file = "site_list.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/site_settings/android_info_browser_proxy.html|AndroidInfoBrowserProxyImpl,AndroidSmsInfo",
+ "chrome/browser/resources/settings/site_settings/constants.html|ContentSetting,ContentSettingsTypes,INVALID_CATEGORY_SUBTYPE",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|RawSiteException,SiteException,SiteSettingsPrefsBrowserProxyImpl",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_list_entry") {
+ js_file = "site_list_entry.js"
+ html_file = "site_list_entry.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Router",
+ "chrome/browser/resources/settings/site_settings/constants.html|ChooserType,ContentSettingsTypes,SITE_EXCEPTION_WILDCARD",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|SiteException",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("zoom_levels") {
+ js_file = "zoom_levels.js"
+ html_file = "zoom_levels.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|ZoomLevelEntry" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+js_modulizer("modulize") {
+ input_files = [
+ "constants.js",
+ "cookie_info.js",
+ "android_info_browser_proxy.js",
+ "local_data_browser_proxy.js",
+ "site_settings_behavior.js",
+ "site_settings_prefs_browser_proxy.js",
+ "website_usage_browser_proxy.js",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn b/chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn
index 7467e9e011e..2cb8a6e32bf 100644
--- a/chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/site_settings_page/BUILD.gn
@@ -3,23 +3,160 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
+ ":recent_site_permissions",
+ ":site_settings_list",
":site_settings_page",
]
}
+js_library("recent_site_permissions") {
+ deps = [
+ "..:route",
+ "..:router",
+ "../people_page:sync_browser_proxy",
+ "../prefs:prefs_behavior",
+ "../site_settings:site_settings_behavior",
+ "//ui/webui/resources/js:i18n_behavior",
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
js_library("site_settings_page") {
deps = [
+ ":recent_site_permissions",
+ ":site_settings_list",
"..:route",
+ "..:router",
"../site_settings:constants",
- "../site_settings:site_settings_behavior",
"../site_settings:site_settings_prefs_browser_proxy",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js:cr",
"//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink",
+ ]
+}
+
+js_library("site_settings_list") {
+ deps = [
+ "..:router",
+ "../site_settings:constants",
+ "../site_settings:site_settings_prefs_browser_proxy",
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:i18n_behavior",
"//ui/webui/resources/js:web_ui_listener_behavior",
"//ui/webui/resources/js/cr/ui:focus_without_ink",
]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":recent_site_permissions.m",
+ ":site_settings_list.m",
+ ":site_settings_page.m",
+ ]
+}
+
+js_library("recent_site_permissions.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.m.js" ]
+ deps = [
+ "..:route.m",
+ "..:router.m",
+ "../people_page:sync_browser_proxy.m",
+ "../prefs:prefs_behavior.m",
+ "../site_settings:constants.m",
+ "../site_settings:site_settings_behavior.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ ]
+ extra_deps = [ ":recent_site_permissions_module" ]
+}
+
+js_library("site_settings_list.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings_page/site_settings_list.m.js" ]
+ deps = [
+ "..:router.m",
+ "../site_settings:constants.m",
+ "../site_settings:site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:i18n_behavior.m",
+ "//ui/webui/resources/js:web_ui_listener_behavior.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ extra_deps = [ ":site_settings_list_module" ]
+}
+
+js_library("site_settings_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/site_settings_page/site_settings_page.m.js" ]
+ deps = [
+ ":recent_site_permissions.m",
+ ":site_settings_list.m",
+ "..:route.m",
+ "..:router.m",
+ "../site_settings:constants.m",
+ "../site_settings:site_settings_prefs_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
+ ]
+ extra_deps = [ ":site_settings_page_module" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":recent_site_permissions_module",
+ ":site_settings_list_module",
+ ":site_settings_page_module",
+ ]
+}
+
+polymer_modulizer("recent_site_permissions") {
+ js_file = "recent_site_permissions.js"
+ html_file = "recent_site_permissions.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route,Router,RouteObserverBehavior",
+ "chrome/browser/resources/settings/site_settings/constants.html|AllSitesAction,ContentSetting,SiteSettingSource",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|RawSiteException,RecentSitePermissions",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_settings_list") {
+ js_file = "site_settings_list.js"
+ html_file = "site_settings_list.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/router.html|Route,Router",
+ "chrome/browser/resources/settings/site_settings/constants.html|ContentSetting,ContentSettingsTypes",
+ "chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.html|SiteSettingsPrefsBrowserProxy,SiteSettingsPrefsBrowserProxyImpl",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
+
+polymer_modulizer("site_settings_page") {
+ js_file = "site_settings_page.js"
+ html_file = "site_settings_page.html"
+ html_type = "dom-module"
+ auto_imports = settings_auto_imports + [
+ "chrome/browser/resources/settings/route.html|routes",
+ "chrome/browser/resources/settings/router.html|Route,Router",
+ "chrome/browser/resources/settings/site_settings/constants.html|ContentSettingsTypes",
+ "chrome/browser/resources/settings/site_settings_page/site_settings_list.html|CategoryListItem",
+ "ui/webui/resources/html/assert.html|assert",
+ ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/settings/system_page/BUILD.gn b/chromium/chrome/browser/resources/settings/system_page/BUILD.gn
index 10b912a94c3..63950561901 100644
--- a/chromium/chrome/browser/resources/settings/system_page/BUILD.gn
+++ b/chromium/chrome/browser/resources/settings/system_page/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/polymer.gni")
+import("//ui/webui/resources/tools/js_modulizer.gni")
+import("../settings.gni")
js_type_check("closure_compile") {
deps = [
@@ -26,3 +29,54 @@ js_library("system_page") {
]
externs_list = [ "$externs_path/settings_private.js" ]
}
+
+js_type_check("closure_compile_module") {
+ is_polymer3 = true
+ deps = [
+ ":system_page.m",
+ ":system_page_browser_proxy.m",
+ ]
+}
+
+js_library("system_page.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/system_page/system_page.m.js" ]
+ deps = [
+ ":system_page_browser_proxy.m",
+ "..:lifetime_browser_proxy.m",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ ]
+ externs_list = [ "$externs_path/settings_private.js" ]
+ extra_deps = [ ":system_page_module" ]
+}
+
+js_library("system_page_browser_proxy.m") {
+ sources = [ "$root_gen_dir/chrome/browser/resources/settings/system_page/system_page_browser_proxy.m.js" ]
+ deps = [
+ "//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+ extra_deps = [ ":modulize" ]
+}
+
+group("polymer3_elements") {
+ public_deps = [
+ ":modulize",
+ ":system_page_module",
+ ]
+}
+
+polymer_modulizer("system_page") {
+ js_file = "system_page.js"
+ html_file = "system_page.html"
+ html_type = "dom-module"
+ namespace_rewrites = settings_namespace_rewrites
+ auto_imports = [
+ "chrome/browser/resources/settings/lifetime_browser_proxy.html|LifetimeBrowserProxyImpl",
+ "chrome/browser/resources/settings/system_page/system_page_browser_proxy.html|SystemPageBrowserProxyImpl",
+ ]
+}
+
+js_modulizer("modulize") {
+ input_files = [ "system_page_browser_proxy.js" ]
+ namespace_rewrites = settings_namespace_rewrites
+}
diff --git a/chromium/chrome/browser/resources/signin/BUILD.gn b/chromium/chrome/browser/resources/signin/BUILD.gn
index be812e866ab..0fb2cd86ca8 100644
--- a/chromium/chrome/browser/resources/signin/BUILD.gn
+++ b/chromium/chrome/browser/resources/signin/BUILD.gn
@@ -5,21 +5,22 @@
import("//tools/polymer/polymer.gni")
group("closure_compile") {
- deps = [
- "sync_confirmation:closure_compile",
- ]
+ deps = [ "sync_confirmation:closure_compile" ]
if (!is_chromeos) {
- deps += [ "signin_email_confirmation:closure_compile" ]
+ deps += [
+ "signin_email_confirmation:closure_compile",
+ "signin_error:closure_compile",
+ ]
}
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":signin_shared_css_module",
"sync_confirmation:polymer3_elements",
]
if (!is_chromeos) {
- deps += [ "signin_email_confirmation:polymer3_elements" ]
+ public_deps += [ "signin_email_confirmation:polymer3_elements" ]
}
}
diff --git a/chromium/chrome/browser/resources/signin/signin_email_confirmation/BUILD.gn b/chromium/chrome/browser/resources/signin/signin_email_confirmation/BUILD.gn
index 436f8ea6157..8f802a44ce6 100644
--- a/chromium/chrome/browser/resources/signin/signin_email_confirmation/BUILD.gn
+++ b/chromium/chrome/browser/resources/signin/signin_email_confirmation/BUILD.gn
@@ -7,9 +7,7 @@ import("//tools/polymer/polymer.gni")
js_type_check("closure_compile") {
is_polymer3 = true
- deps = [
- ":signin_email_confirmation_app",
- ]
+ deps = [ ":signin_email_confirmation_app" ]
}
js_library("signin_email_confirmation_app") {
@@ -21,9 +19,7 @@ js_library("signin_email_confirmation_app") {
}
group("polymer3_elements") {
- deps = [
- ":signin_email_confirmation_app_module",
- ]
+ public_deps = [ ":signin_email_confirmation_app_module" ]
}
polymer_modulizer("signin_email_confirmation_app") {
diff --git a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html
index 074d130a266..29b6aedb425 100644
--- a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html
+++ b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation.html
@@ -2,12 +2,18 @@
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
+ <link rel="stylesheet" href="chrome://resources/css/md_colors.css">
<link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
<style>
body {
margin: 0;
padding: 0;
}
+ @media (prefers-color-scheme: dark) {
+ body {
+ background-color: var(--md-background-color);
+ }
+ }
</style>
</head>
<body>
diff --git a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.html b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.html
index 908ab216d4c..b5d7e465d99 100644
--- a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.html
+++ b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.html
@@ -32,6 +32,11 @@
line-height: 22px;
padding: 16px 24px;
}
+ @media (prefers-color-scheme: dark) {
+ .top-title-bar {
+ color: var(--cr-primary-text-color);
+ }
+ }
#closeButton {
margin-inline-start: 8px;
diff --git a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.js b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.js
index 94eb54b8af5..f9756526a7f 100644
--- a/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.js
+++ b/chromium/chrome/browser/resources/signin/signin_email_confirmation/signin_email_confirmation_app.js
@@ -5,6 +5,7 @@
import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js';
import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
import './signin_shared_css.js';
import './strings.m.js';
@@ -18,7 +19,7 @@ Polymer({
_template: html`{__html_template__}`,
/** @override */
- ready: function() {
+ ready() {
const args = /** @type {{lastEmail: string, newEmail: string}} */
(JSON.parse(chrome.getVariableValue('dialogArguments')));
const {lastEmail, newEmail} = args;
@@ -33,7 +34,7 @@ Polymer({
document.addEventListener('keydown', this.onKeyDown_.bind(this));
},
- onKeyDown_: function(e) {
+ onKeyDown_(e) {
// If the currently focused element isn't something that performs an action
// on "enter" being pressed and the user hits "enter", perform the default
// action of the dialog, which is "OK".
@@ -45,13 +46,13 @@ Polymer({
},
/** @private */
- onConfirm_: function() {
+ onConfirm_() {
const action = this.$$('cr-radio-group').selected;
chrome.send('dialogClose', [JSON.stringify({'action': action})]);
},
/** @private */
- onCancel_: function() {
+ onCancel_() {
chrome.send('dialogClose', [JSON.stringify({'action': 'cancel'})]);
},
});
diff --git a/chromium/chrome/browser/resources/signin/signin_error/BUILD.gn b/chromium/chrome/browser/resources/signin/signin_error/BUILD.gn
new file mode 100644
index 00000000000..14ad99a38ff
--- /dev/null
+++ b/chromium/chrome/browser/resources/signin/signin_error/BUILD.gn
@@ -0,0 +1,23 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+
+js_type_check("closure_compile") {
+ deps = [
+ ":signin_error",
+ ":signin_error_app",
+ ]
+}
+
+js_library("signin_error") {
+ deps = [ "//ui/webui/resources/js:cr" ]
+}
+
+js_library("signin_error_app") {
+ deps = [
+ "//ui/webui/resources/js:load_time_data",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
diff --git a/chromium/chrome/browser/resources/signin/signin_error/signin_error.html b/chromium/chrome/browser/resources/signin/signin_error/signin_error.html
index 6c9d1c10483..a17d6283850 100644
--- a/chromium/chrome/browser/resources/signin/signin_error/signin_error.html
+++ b/chromium/chrome/browser/resources/signin/signin_error/signin_error.html
@@ -2,107 +2,26 @@
<html dir="$i18n{textdirection}" lang="$i18n{language}">
<head>
<meta charset="utf-8">
- <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
- <link rel="import" href="chrome://resources/html/polymer.html">
- <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
- <link rel="import" href="signin_shared_old_css.html">
<link rel="stylesheet" href="chrome://resources/css/md_colors.css">
- <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
- <link rel="import" href="chrome://resources/html/cr.html">
<link rel="import" href="chrome://resources/html/load_time_data.html">
- <link rel="import" href="chrome://resources/html/util.html">
- <custom-style>
- <style include="signin-dialog-shared">
- @media (prefers-color-scheme: dark) {
- html {
- background: var(--md-background-color);
- }
- }
-
- .details {
- line-height: 20px;
- margin-bottom: 8px;
- margin-top: 16px;
- padding: 0 24px;
- }
-
- .details p {
- margin-bottom: 0;
- }
-
- #closeButton {
- margin-inline-start: 8px;
- }
-
- #normal-error-message p:empty,
- #normal-error-message a:empty {
- display: none;
- }
-
- #profile-blocking-error-message {
- margin-top: 30px;
- }
-
- #profile-blocking-error-message p {
- background-position: 0 3px;
- background-repeat: no-repeat;
- background-size: 20px;
- line-height: 18px;
- padding-inline-start: 35px;
- }
-
- html[dir=rtl] #profile-blocking-error-message p {
- background-position: right 3px;
- }
-
- #profile-blocking-error-message p:empty {
- display: none;
- }
-
- #profile-blocking-error-message p:nth-child(1) {
- background-image:
- url(../../../../../ui/webui/resources/images/business.svg);
- }
-
- #profile-blocking-error-message p:nth-child(2) {
- background-image:
- url(../../../../../ui/webui/resources/images/info.svg);
- }
-
-<if expr="is_macosx or is_linux">
- #closeButton {
- margin-inline-end: 8px;
- margin-inline-start: 0;
- }
-</if>
- </style>
- </custom-style>
+ <script src="strings.js"></script>
+ <link rel="import" href="signin_error_app.html">
+ <style>
+ body {
+ margin: 0;
+ }
+
+ @media (prefers-color-scheme: dark) {
+ html {
+ background: var(--md-background-color);
+ }
+ }
+ </style>
</head>
<body>
- <div class="container">
- <div class="top-title-bar">$i18n{signinErrorTitle}</div>
- <div id="normal-error-message" class="details">
- <p>$i18nRaw{signinErrorMessage}</p>
- <a id="learnMoreLink" href="#">$i18nRaw{signinErrorLearnMore}</a>
- </div>
- <div id="profile-blocking-error-message" class="details">
- <p>$i18n{profileBlockedMessage}</p>
- <p>$i18n{profileBlockedAddPersonSuggestion}</p>
- <p>$i18n{profileBlockedRemoveProfileSuggestion}</p>
- </div>
- <div class="action-container">
- <cr-button class="action-button" id="switchButton">
- $i18n{signinErrorSwitchLabel}
- </cr-button>
- <cr-button id="closeButton">
- $i18n{signinErrorCloseLabel}
- </cr-button>
- <cr-button id="confirmButton" hidden>
- $i18n{signinErrorOkLabel}
- </cr-button>
- </div>
- </div>
+ <signin-error-app></signin-error-app>
</body>
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+ <link rel="import" href="chrome://resources/html/cr.html">
<script src="signin_error.js"></script>
- <script src="chrome://signin-error/strings.js"></script>
</html>
diff --git a/chromium/chrome/browser/resources/signin/signin_error/signin_error.js b/chromium/chrome/browser/resources/signin/signin_error/signin_error.js
index 71d654cafcb..f264d64e9ac 100644
--- a/chromium/chrome/browser/resources/signin/signin_error/signin_error.js
+++ b/chromium/chrome/browser/resources/signin/signin_error/signin_error.js
@@ -2,63 +2,19 @@
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file. */
-cr.define('signin.error', function() {
- 'use strict';
-
- function initialize() {
- document.addEventListener('keydown', onKeyDown);
- $('confirmButton').addEventListener('click', onConfirm);
- $('closeButton').addEventListener('click', onConfirm);
- $('switchButton').addEventListener('click', onSwitchToExistingProfile);
- $('learnMoreLink').addEventListener('click', onLearnMore);
- if (loadTimeData.getBoolean('isSystemProfile')) {
- $('learnMoreLink').hidden = true;
- }
-
- // Prefer using |document.body.offsetHeight| instead of
- // |document.body.scrollHeight| as it returns the correct height of the
- // even when the page zoom in Chrome is different than 100%.
- chrome.send('initializedWithSize', [document.body.offsetHeight]);
- }
-
- function onKeyDown(e) {
- // If the currently focused element isn't something that performs an action
- // on "enter" being pressed and the user hits "enter", perform the default
- // action of the dialog, which is "OK".
- if (e.key == 'Enter' &&
- !/^(A|CR-BUTTON)$/.test(document.activeElement.tagName)) {
- $('confirmButton').click();
- e.preventDefault();
- }
- }
-
- function onConfirm(e) {
- chrome.send('confirm');
- }
-
- function onSwitchToExistingProfile(e) {
- chrome.send('switchToExistingProfile');
- }
-
- function onLearnMore(e) {
- chrome.send('learnMore');
- }
-
- function clearFocus() {
- document.activeElement.blur();
- }
-
- function removeSwitchButton() {
- $('switchButton').hidden = true;
- $('closeButton').hidden = true;
- $('confirmButton').hidden = false;
- }
-
- return {
- initialize: initialize,
- clearFocus: clearFocus,
- removeSwitchButton: removeSwitchButton
- };
-});
-
-document.addEventListener('DOMContentLoaded', signin.error.initialize);
+(function() {
+function initialize() {
+ cr.addWebUIListener('clear-focus', clearFocus);
+
+ // Prefer using |document.body.offsetHeight| instead of
+ // |document.body.scrollHeight| as it returns the correct height of the
+ // even when the page zoom in Chrome is different than 100%.
+ chrome.send('initializedWithSize', [document.body.offsetHeight]);
+}
+
+function clearFocus() {
+ document.activeElement.blur();
+}
+
+document.addEventListener('DOMContentLoaded', initialize);
+})();
diff --git a/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.html b/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.html
new file mode 100644
index 00000000000..1178a949ec5
--- /dev/null
+++ b/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.html
@@ -0,0 +1,98 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/load_time_data.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="signin_shared_old_css.html">
+
+<dom-module id="signin-error-app">
+ <template>
+ <style include="signin-dialog-shared">
+ .details {
+ line-height: 20px;
+ margin-bottom: 8px;
+ margin-top: 16px;
+ padding: 0 24px;
+ }
+
+ #normal-error-message > p {
+ margin-bottom: 0;
+ }
+
+ #closeButton {
+ margin-inline-start: 8px;
+ }
+
+ #profile-blocking-error-message {
+ margin-top: 30px;
+ }
+
+ #profile-blocking-error-message > div {
+ align-items: center;
+ display: flex;
+ margin-top: 1em;
+ }
+
+ iron-icon {
+ color: var(--cr-secondary-text-color);
+ flex-shrink: 0;
+ height: var(--cr-icon-size);
+ margin-inline-end: 16px;
+ width: var(--cr-icon-size);
+ }
+
+<if expr="is_macosx or is_linux">
+ #closeButton {
+ margin-inline-end: 8px;
+ margin-inline-start: 0;
+ }
+</if>
+ </style>
+ <div class="container">
+ <div class="top-title-bar">$i18n{signinErrorTitle}</div>
+ <div id="normal-error-message" class="details"
+ hidden="[[hideNormalError_]]">
+ <p>$i18nRaw{signinErrorMessage}</p>
+ <a id="learnMoreLink" href="#" on-click="onLearnMore_"
+ hidden="[[isSystemProfile_]]">
+ $i18nRaw{signinErrorLearnMore}
+ </a>
+ </div>
+ <div id="profile-blocking-error-message" class="details"
+ hidden="[[hideProfileBlockingErrors_.0]]">
+ <div hidden="[[hideProfileBlockingErrors_.1]]">
+ <iron-icon icon="cr:domain"></iron-icon>
+ <span>$i18n{profileBlockedMessage}</span>
+ </div>
+ <div hidden="[[hideProfileBlockingErrors_.2]]">
+ <iron-icon icon="cr:info"></iron-icon>
+ <span>$i18n{profileBlockedAddPersonSuggestion}</span>
+ </div>
+ <div hidden="[[hideProfileBlockingErrors_.3]]">
+ <iron-icon icon="cr:info"></iron-icon>
+ <span>$i18n{profileBlockedRemoveProfileSuggestion}</span>
+ </div>
+ </div>
+ <div class="action-container">
+ <cr-button class="action-button" id="switchButton"
+ hidden="[[switchButtonUnavailable_]]"
+ on-click="onSwitchToExistingProfile_">
+ $i18n{signinErrorSwitchLabel}
+ </cr-button>
+ <cr-button id="closeButton"
+ hidden="[[switchButtonUnavailable_]]"
+ on-click="onConfirm_">
+ $i18n{signinErrorCloseLabel}
+ </cr-button>
+ <cr-button id="confirmButton" hidden="[[!switchButtonUnavailable_]]"
+ on-click="onConfirm_">
+ $i18n{signinErrorOkLabel}
+ </cr-button>
+ </div>
+ </div>
+ </template>
+ <script src="signin_error_app.js"></script>
+</dom-module>
diff --git a/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.js b/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.js
new file mode 100644
index 00000000000..a5782fdc518
--- /dev/null
+++ b/chromium/chrome/browser/resources/signin/signin_error/signin_error_app.js
@@ -0,0 +1,100 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer({
+ is: 'signin-error-app',
+
+ behaviors: [
+ WebUIListenerBehavior,
+ ],
+
+ properties: {
+ /** @private {boolean} */
+ isSystemProfile_: {
+ type: Boolean,
+ value: () => loadTimeData.getBoolean('isSystemProfile'),
+ },
+
+ /** @private {boolean} */
+ switchButtonUnavailable_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /** @private */
+ hideNormalError_: {
+ type: Boolean,
+ value: () => loadTimeData.getString('signinErrorMessage').length === 0,
+ },
+
+ /**
+ * An array of booleans indicating whether profile blocking messages should
+ * be hidden. Position 0 corresponds to the #profile-blocking-error-message
+ * container, and subsequent positions correspond to each of the 3 related
+ * messages respectively.
+ * @private {!Array<boolean>}
+ */
+ hideProfileBlockingErrors_: {
+ type: Array,
+ value: function() {
+ const hide = [
+ 'profileBlockedMessage',
+ 'profileBlockedAddPersonSuggestion',
+ 'profileBlockedRemoveProfileSuggestion',
+ ].map(id => loadTimeData.getString(id).length === 0);
+
+ // Hide the container itself if all of each children are also hidden.
+ hide.unshift(hide.every(hideEntry => hideEntry));
+
+ return hide;
+ },
+ },
+ },
+
+ /** @private {?function(!Event)} */
+ boundKeyDownHandler_: null,
+
+ /** @override */
+ attached() {
+ this.boundKeyDownHandler_ = this.onKeyDown_.bind(this);
+ document.addEventListener('keydown', this.boundKeyDownHandler_);
+
+ this.addWebUIListener('switch-button-unavailable', () => {
+ this.switchButtonUnavailable_ = true;
+ });
+ },
+
+ /** @override */
+ detached() {
+ document.removeEventListener('keydown', this.boundKeyDownHandler_);
+ this.boundKeyDownHandler_ = null;
+ },
+
+ /** @private */
+ onConfirm_() {
+ chrome.send('confirm');
+ },
+
+ /** @private */
+ onSwitchToExistingProfile_() {
+ chrome.send('switchToExistingProfile');
+ },
+
+ /** @private */
+ onLearnMore_() {
+ chrome.send('learnMore');
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onKeyDown_(e) {
+ if (e.key == 'Enter' &&
+ !/^(A|CR-BUTTON)$/.test(e.composedPath()[0].tagName)) {
+ this.onConfirm_();
+ e.preventDefault();
+ }
+ },
+});
diff --git a/chromium/chrome/browser/resources/signin/signin_shared_css.html b/chromium/chrome/browser/resources/signin/signin_shared_css.html
index 79227224ba7..c7de5b75449 100644
--- a/chromium/chrome/browser/resources/signin/signin_shared_css.html
+++ b/chromium/chrome/browser/resources/signin/signin_shared_css.html
@@ -6,11 +6,6 @@
text-decoration: none;
}
- body {
- margin: 0;
- padding: 0;
- }
-
.container {
color: var(--cr-primary-text-color);
width: 448px;
diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/BUILD.gn b/chromium/chrome/browser/resources/signin/sync_confirmation/BUILD.gn
index 4492e543319..b0de948da72 100644
--- a/chromium/chrome/browser/resources/signin/sync_confirmation/BUILD.gn
+++ b/chromium/chrome/browser/resources/signin/sync_confirmation/BUILD.gn
@@ -5,25 +5,13 @@
import("//third_party/closure_compiler/compile_js.gni")
import("//tools/polymer/polymer.gni")
-group("closure_compile") {
- deps = [
- ":closure_compile_polymer2",
- ":closure_compile_polymer3",
- ]
-}
-
-js_type_check("closure_compile_polymer2") {
- deps = [
- ":sync_disabled_confirmation",
- ]
-}
-
-js_type_check("closure_compile_polymer3") {
+js_type_check("closure_compile") {
is_polymer3 = true
deps = [
":sync_confirmation",
":sync_confirmation_app",
":sync_confirmation_browser_proxy",
+ ":sync_disabled_confirmation_app",
]
}
@@ -45,26 +33,25 @@ js_library("sync_confirmation_app") {
}
js_library("sync_confirmation_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
externs_list = [
"$externs_path/chrome_send.js",
"$externs_path/metrics_private.js",
]
}
-js_library("sync_disabled_confirmation") {
+js_library("sync_disabled_confirmation_app") {
deps = [
- "//ui/webui/resources/js:assert",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js:util",
+ ":sync_confirmation_browser_proxy",
+ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+ "//ui/webui/resources/js:assert.m",
]
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":sync_confirmation_app_module",
+ ":sync_disabled_confirmation_app_module",
]
}
@@ -73,3 +60,9 @@ polymer_modulizer("sync_confirmation_app") {
js_file = "sync_confirmation_app.js"
html_type = "v3-ready"
}
+
+polymer_modulizer("sync_disabled_confirmation_app") {
+ html_file = "sync_disabled_confirmation_app.html"
+ js_file = "sync_disabled_confirmation_app.js"
+ html_type = "v3-ready"
+}
diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js
index 2e9c4aa7af8..1557d13bc78 100644
--- a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js
+++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_confirmation_app.js
@@ -27,7 +27,7 @@ Polymer({
/** @private */
accountImageSrc_: {
type: String,
- value: function() {
+ value() {
return loadTimeData.getString('accountPictureUrl');
},
},
@@ -40,7 +40,7 @@ Polymer({
boundKeyDownHandler_: null,
/** @override */
- attached: function() {
+ attached() {
this.syncConfirmationBrowserProxy_ =
SyncConfirmationBrowserProxyImpl.getInstance();
this.boundKeyDownHandler_ = this.onKeyDown_.bind(this);
@@ -54,29 +54,29 @@ Polymer({
},
/** @override */
- detached: function() {
+ detached() {
document.removeEventListener('keydown', this.boundKeyDownHandler_);
},
/** @private */
- onConfirm_: function(e) {
+ onConfirm_(e) {
this.syncConfirmationBrowserProxy_.confirm(
this.getConsentDescription_(), this.getConsentConfirmation_(e.path));
},
/** @private */
- onUndo_: function() {
+ onUndo_() {
this.syncConfirmationBrowserProxy_.undo();
},
/** @private */
- onGoToSettings_: function(e) {
+ onGoToSettings_(e) {
this.syncConfirmationBrowserProxy_.goToSettings(
this.getConsentDescription_(), this.getConsentConfirmation_(e.path));
},
/** @private */
- onKeyDown_: function(e) {
+ onKeyDown_(e) {
if (e.key == 'Enter' && !/^(A|CR-BUTTON)$/.test(e.path[0].tagName)) {
this.onConfirm_(e);
e.preventDefault();
@@ -89,7 +89,7 @@ Polymer({
* @return {string} The text of the consent confirmation element.
* @private
*/
- getConsentConfirmation_: function(path) {
+ getConsentConfirmation_(path) {
for (const element of path) {
if (element.nodeType !== Node.DOCUMENT_FRAGMENT_NODE &&
element.hasAttribute('consent-confirmation')) {
@@ -101,7 +101,7 @@ Polymer({
},
/** @return {!Array<string>} Text of the consent description elements. */
- getConsentDescription_: function() {
+ getConsentDescription_() {
const consentDescription =
Array.from(this.shadowRoot.querySelectorAll('[consent-description]'))
.filter(element => element.clientWidth * element.clientHeight > 0)
@@ -115,7 +115,7 @@ Polymer({
* @param {string} imageSrc
* @private
*/
- handleAccountImageChanged_: function(imageSrc) {
+ handleAccountImageChanged_(imageSrc) {
this.accountImageSrc_ = imageSrc;
},
diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.html b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.html
index 059bc92e3b9..b4ca728741f 100644
--- a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.html
+++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.html
@@ -3,70 +3,16 @@
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="chrome://resources/css/md_colors.css">
+ <script type="module" src="sync_disabled_confirmation_app.js"></script>
<style>
html {
background-color: var(--md-background-color);
}
</style>
- <link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html">
- <link rel="import" href="chrome://resources/html/polymer.html">
- <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
- <link rel="import" href="signin_shared_old_css.html">
- <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
- <custom-style>
- <style include="signin-dialog-shared">
- .details {
- padding: 0 24px;
- }
- #undoButton {
-<if expr="is_macosx or is_linux">
- margin-inline-end: 8px;
-</if>
-<if expr="not is_macosx and not is_linux">
- margin-inline-start: 8px;
-</if>
- }
-
- #syncDisabledDetails {
- line-height: 20px;
- margin-bottom: 8px;
- margin-top: 16px;
- padding: 0 24px;
- }
-
- </style>
- </custom-style>
</head>
<body>
- <!--
- Use the 'consent-description' attribute to annotate all the UI elements
- that are part of the text the user reads before consenting to the Sync
- data collection . Similarly, use 'consent-confirmation' on UI elements on
- which user clicks to indicate consent.
- -->
- <div class="container">
- <div class="top-title-bar" consent-description>
- $i18n{syncDisabledConfirmationTitle}
- </div>
- <div class="details" id="syncDisabledDetails">
- <div class="body text" consent-description>
- $i18n{syncDisabledConfirmationDetails}
- </div>
- </div>
- <div class="action-container">
- <cr-button class="action-button" id="confirmButton"
- consent-confirmation>
- $i18n{syncDisabledConfirmationConfirmLabel}
- </cr-button>
- <cr-button id="undoButton">
- $i18n{syncDisabledConfirmationUndoLabel}
- </cr-button>
- </div>
- </div>
+ <sync-disabled-confirmation-app></sync-disabled-confirmation-app>
</body>
- <link rel="import" href="chrome://resources/html/cr.html">
- <link rel="import" href="chrome://resources/html/load_time_data.html">
- <link rel="import" href="chrome://resources/html/util.html">
- <script src="sync_disabled_confirmation.js"></script>
- <script src="chrome://sync-confirmation/strings.js"></script>
+ <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css">
+ <script type="module" src="sync_confirmation.js"></script>
</html>
diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.js b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.js
deleted file mode 100644
index 97f494ac9b6..00000000000
--- a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation.js
+++ /dev/null
@@ -1,74 +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. */
-
-cr.define('sync.confirmation', function() {
- 'use strict';
-
- /**
- * @param {!Array<!HTMLElement>} path Path of the click event. Must contain
- * a consent confirmation element.
- * @return {string} The text of the consent confirmation element.
- * @private
- */
- function getConsentConfirmation(path) {
- let consentConfirmation;
- for (const element of path) {
- if (element.nodeType !== Node.DOCUMENT_FRAGMENT_NODE &&
- element.hasAttribute('consent-confirmation')) {
- return element.innerHTML.trim();
- }
- }
- assertNotReached('No consent confirmation element found.');
- return '';
- }
-
- /** @return {!Array<string>} Text of the consent description elements. */
- function getConsentDescription() {
- const consentDescription =
- Array.from(document.querySelectorAll('[consent-description]'))
- .filter(element => element.clientWidth * element.clientHeight > 0)
- .map(element => element.innerHTML.trim());
- assert(consentDescription);
- return consentDescription;
- }
-
- function onConfirm(e) {
- chrome.send(
- 'confirm', [getConsentDescription(), getConsentConfirmation(e.path)]);
- }
-
- function onUndo(e) {
- chrome.send('undo');
- }
-
- function initialize() {
- cr.addWebUIListener('clear-focus', clearFocus);
- document.addEventListener('keydown', onKeyDown);
- $('confirmButton').addEventListener('click', onConfirm);
- $('undoButton').addEventListener('click', onUndo);
- // Prefer using |document.body.offsetHeight| instead of
- // |document.body.scrollHeight| as it returns the correct height of the
- // even when the page zoom in Chrome is different than 100%.
- chrome.send('initializedWithSize', [document.body.offsetHeight]);
- }
-
- function clearFocus() {
- document.activeElement.blur();
- }
-
- function onKeyDown(e) {
- // If the currently focused element isn't something that performs an action
- // on "enter" being pressed and the user hits "enter", perform the default
- // action of the dialog, which is "OK, Got It".
- if (e.key == 'Enter' &&
- !/^(A|PAPER-(BUTTON|CHECKBOX))$/.test(document.activeElement.tagName)) {
- $('confirmButton').click();
- e.preventDefault();
- }
- }
-
- return {initialize: initialize};
-});
-
-document.addEventListener('DOMContentLoaded', sync.confirmation.initialize);
diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.html b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.html
new file mode 100644
index 00000000000..4ec21e8f6d3
--- /dev/null
+++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.html
@@ -0,0 +1,45 @@
+<style include="signin-dialog-shared">
+ .details {
+ padding: 0 24px;
+ }
+ #undoButton {
+<if expr="is_macosx or is_linux">
+ margin-inline-end: 8px;
+</if>
+<if expr="not is_macosx and not is_linux">
+ margin-inline-start: 8px;
+</if>
+ }
+
+ #syncDisabledDetails {
+ line-height: 20px;
+ margin-bottom: 8px;
+ margin-top: 16px;
+ padding: 0 24px;
+ }
+</style>
+<!--
+ Use the 'consent-description' attribute to annotate all the UI elements
+ that are part of the text the user reads before consenting to the Sync
+ data collection . Similarly, use 'consent-confirmation' on UI elements on
+ which user clicks to indicate consent.
+-->
+<div class="container">
+ <div class="top-title-bar" consent-description>
+ $i18n{syncDisabledConfirmationTitle}
+ </div>
+ <div class="details" id="syncDisabledDetails">
+ <div class="body text" consent-description>
+ $i18n{syncDisabledConfirmationDetails}
+ </div>
+ </div>
+ <div class="action-container">
+ <cr-button class="action-button" id="confirmButton"
+ consent-confirmation on-click="onConfirm_">
+ $i18n{syncDisabledConfirmationConfirmLabel}
+ </cr-button>
+ <cr-button id="undoButton" on-click="onUndo_">
+ $i18n{syncDisabledConfirmationUndoLabel}
+ </cr-button>
+ </div>
+</div>
diff --git a/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.js b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.js
new file mode 100644
index 00000000000..83cafe54f91
--- /dev/null
+++ b/chromium/chrome/browser/resources/signin/sync_confirmation/sync_disabled_confirmation_app.js
@@ -0,0 +1,90 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import './signin_shared_css.js';
+import './strings.m.js';
+
+import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
+import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {SyncConfirmationBrowserProxy, SyncConfirmationBrowserProxyImpl} from './sync_confirmation_browser_proxy.js';
+
+Polymer({
+ is: 'sync-disabled-confirmation-app',
+
+ _template: html`{__html_template__}`,
+
+ /** @private {?SyncConfirmationBrowserProxy} */
+ syncConfirmationBrowserProxy_: null,
+
+ /** @override */
+ attached() {
+ this.syncConfirmationBrowserProxy_ =
+ SyncConfirmationBrowserProxyImpl.getInstance();
+
+ document.addEventListener(
+ 'keydown', e => this.onKeyDown_(/** @type {!KeyboardEvent} */ (e)));
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onConfirm_(e) {
+ this.syncConfirmationBrowserProxy_.confirm(
+ this.getConsentDescription_(),
+ this.getConsentConfirmation_(e.composedPath()));
+ },
+
+ /**
+ * @param {!Array<!HTMLElement>} path Path of the click event. Must contain
+ * a consent confirmation element.
+ * @return {string} The text of the consent confirmation element.
+ * @private
+ */
+ getConsentConfirmation_(path) {
+ for (const element of path) {
+ if (element.nodeType !== Node.DOCUMENT_FRAGMENT_NODE &&
+ element.hasAttribute('consent-confirmation')) {
+ return element.innerHTML.trim();
+ }
+ }
+ assertNotReached('No consent confirmation element found.');
+ return '';
+ },
+
+ /**
+ * @return {!Array<string>} Text of the consent description elements.
+ * @private
+ */
+ getConsentDescription_() {
+ const consentDescription =
+ Array.from(this.shadowRoot.querySelectorAll('[consent-description]'))
+ .filter(element => element.clientWidth * element.clientHeight > 0)
+ .map(element => element.innerHTML.trim());
+ assert(consentDescription);
+ return consentDescription;
+ },
+
+ /**
+ * @param {!KeyboardEvent} e
+ * @private
+ */
+ onKeyDown_(e) {
+ // If the currently focused element isn't something that performs an action
+ // on "enter" being pressed and the user hits "enter", perform the default
+ // action of the dialog, which is "OK, Got It".
+ if (e.key == 'Enter' &&
+ !/^(A|PAPER-(BUTTON|CHECKBOX))$/.test(document.activeElement.tagName)) {
+ this.$.confirmButton.click();
+ e.preventDefault();
+ }
+ },
+
+ /** @private */
+ onUndo_() {
+ this.syncConfirmationBrowserProxy_.undo();
+ },
+});
diff --git a/chromium/chrome/browser/resources/snippets_internals/BUILD.gn b/chromium/chrome/browser/resources/snippets_internals/BUILD.gn
index fbb8573744a..d31aa271b58 100644
--- a/chromium/chrome/browser/resources/snippets_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/snippets_internals/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
- deps = [
- ":snippets_internals",
- ]
+ deps = [ ":snippets_internals" ]
}
js_library("snippets_internals") {
diff --git a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/BUILD.gn b/chromium/chrome/browser/resources/ssl/ssl_error_assistant/BUILD.gn
deleted file mode 100644
index 1867e4ca52a..00000000000
--- a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/BUILD.gn
+++ /dev/null
@@ -1,44 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Generate the binary proto form of "ssl_error_assistant" from the ascii proto.
-action("make_ssl_error_assistant_protobuf") {
- script = "gen_ssl_error_assistant_proto.py"
-
- # The output goes in $target_gen_dir since that's where
- # chrome/browser/browser_resources.grd will look for it.
-
- input_filename = "ssl_error_assistant.asciipb"
- output_dir = target_gen_dir
- output_basename = "ssl_error_assistant.pb"
- python_path_root = "$root_out_dir/pyproto"
- python_path_ssl = "$python_path_root/chrome/browser/ssl/"
-
- inputs = [
- input_filename,
- ]
-
- deps = [
- "//chrome/browser/ssl:proto",
- "//third_party/protobuf:py_proto",
- ]
-
- outputs = [
- "$output_dir/$output_basename",
- ]
-
- args = [
- "-w",
- "-i",
- rebase_path(input_filename, root_build_dir),
- "-d",
- rebase_path(output_dir, root_build_dir),
- "-o",
- output_basename,
- "-p",
- rebase_path(python_path_root, root_build_dir),
- "-p",
- rebase_path(python_path_ssl, root_build_dir),
- ]
-}
diff --git a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/PRESUBMIT.py b/chromium/chrome/browser/resources/ssl/ssl_error_assistant/PRESUBMIT.py
deleted file mode 100644
index 16a0f328f8a..00000000000
--- a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/PRESUBMIT.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Presubmit checks for ssl_error_assistant.asciipb.
-
- This is taken from chrome/browser/resources/safe_browsing/PRESUBMIT.py.
-"""
-
-# TODO(meacer): Refactor and reuse shared code with
-# chrome/browser/resources/safe_browsing/PRESUBMIT.py
-def CheckVersionUpdatedInSSLErrorAssistantProto(input_api, output_api):
- def IsSSLErrorAssistantProto(x):
- return (input_api.os_path.basename(x.LocalPath()) ==
- 'ssl_error_assistant.asciipb')
-
- ssl_error_assistant_proto = input_api.AffectedFiles(
- file_filter=IsSSLErrorAssistantProto)
- if not ssl_error_assistant_proto:
- return []
-
- for _, line in ssl_error_assistant_proto[0].ChangedContents():
- if line.strip().startswith('version_id: '):
- return []
-
- # It's enticing to do something fancy like checking whether the ID was in fact
- # incremented or whether this is a whitespace-only or comment-only change.
- # However, currently deleted lines don't show up in ChangedContents() and
- # attempting to parse the asciipb file any more than we are doing above is
- # likely not worth the trouble.
- #
- # At worst, the submitter can skip the presubmit check on upload if it isn't
- # correct.
- return [output_api.PresubmitError(
- 'Increment |version_id| in ssl_error_assistant.asciipb if you are '
- 'updating the SSL Error Assistant proto.')]
-
-def CheckChangeOnUpload(input_api, output_api):
- # TODO(asanka): Add a PRESUBMIT check for verifying that the
- # ssl_error_assistant.asciipb file is valid.
- return CheckVersionUpdatedInSSLErrorAssistantProto(input_api, output_api)
diff --git a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py b/chromium/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py
deleted file mode 100755
index 46aeced3a3e..00000000000
--- a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/gen_ssl_error_assistant_proto.py
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/usr/bin/python
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""
- Convert the ASCII ssl_error_assistant.asciipb proto into a binary resource.
-"""
-
-import base64
-import os
-import sys
-
-# Subdirectory to be copied to Google Cloud Storage. Contains a copy of the
-# generated proto under a versioned directory.
-GS_COPY_DIR = "gs_copy"
-
-# Import the binary proto generator. Walks up to the root of the source tree
-# which is six directories above, and finds the protobufs directory from there.
-proto_generator_path = os.path.normpath(os.path.join(os.path.abspath(__file__),
- *[os.path.pardir] * 6 + ['chrome/browser/resources/protobufs']))
-sys.path.insert(0, proto_generator_path)
-from binary_proto_generator import BinaryProtoGenerator
-
-def MakeSubDirs(outfile):
- """ Make the subdirectories needed to create file |outfile| """
- dirname = os.path.dirname(outfile)
- if not os.path.exists(dirname):
- os.makedirs(dirname)
-
-class SSLErrorAssistantProtoGenerator(BinaryProtoGenerator):
- def ImportProtoModule(self):
- import ssl_error_assistant_pb2
- globals()['ssl_error_assistant_pb2'] = ssl_error_assistant_pb2
-
- def EmptyProtoInstance(self):
- return ssl_error_assistant_pb2.SSLErrorAssistantConfig()
-
- def ValidatePb(self, opts, pb):
- assert pb.version_id > 0
- assert len(pb.captive_portal_cert) > 0
- for cert in pb.captive_portal_cert:
- assert(cert.sha256_hash.startswith("sha256/"))
- decoded_hash = base64.b64decode(cert.sha256_hash[len("sha256/"):])
- assert(len(decoded_hash) == 32)
-
- def ProcessPb(self, opts, pb):
- binary_pb_str = pb.SerializeToString()
- outfile = os.path.join(opts.outdir, opts.outbasename)
-
- # Write two copies of the proto:
- # 1. Under the root of the gen directory for .grd files to refer to
- # (./ssl_error_assistant/ssl_error_assistant.pb)
- # 2. Under a versioned directory for the proto pusher to refer to
- # (./ssl_error_assistant/gs_copy/<version>/all/ssl_error_assistant.pb)
- outfile = os.path.join(opts.outdir, opts.outbasename)
- with open(outfile, 'wb') as f:
- f.write(binary_pb_str)
-
- outfile_copy = os.path.join(opts.outdir, GS_COPY_DIR, str(pb.version_id),
- "all", opts.outbasename)
- MakeSubDirs(outfile_copy)
- with open(outfile_copy, 'wb') as f:
- f.write(binary_pb_str)
-
-
-def main():
- return SSLErrorAssistantProtoGenerator().Run()
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/push_proto.py b/chromium/chrome/browser/resources/ssl/ssl_error_assistant/push_proto.py
deleted file mode 100755
index b7727eec3af..00000000000
--- a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/push_proto.py
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/python
-# Copyright 2018 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# Build and push the {vers}/all/ssl_error_assistant.pb file to GCS so
-# that the component update system will pick it up and push it to users.
-# See README.md before running this.
-#
-# Requires ninja and gsutil to be in the user's path.
-
-import optparse
-import os
-import shutil
-import subprocess
-import sys
-
-
-DEST_BUCKET = 'gs://chrome-components-ssl-error-assistant'
-RESOURCE_SUBDIR = 'chrome/browser/resources/ssl/ssl_error_assistant'
-
-# Subdirectory to be copied to Google Cloud Storage. Contains a copy of the
-# generated proto under a versioned directory.
-GS_COPY_DIR = "gs_copy"
-
-# TODO(meacer): This is pretty much a duplicate of
-# chrome/browser/safe_browsing/push_file_type_proto.py. Consider
-# refactoring and reusing code.
-def main():
- parser = optparse.OptionParser()
- parser.add_option('-d', '--dir',
- help='An up-to-date GN/Ninja build directory, '
- 'such as ./out/Debug')
-
- (opts, _) = parser.parse_args()
- if opts.dir is None:
- parser.print_help()
- return 1
-
- # Clear out the target dir before we build so we can be sure we've got
- # the freshest version.
- target_dir = os.path.join(opts.dir, "gen", RESOURCE_SUBDIR)
- if os.path.isdir(target_dir):
- shutil.rmtree(target_dir)
-
- gn_command = ['ninja',
- '-C', opts.dir,
- RESOURCE_SUBDIR + ':make_ssl_error_assistant_protobuf']
- print "Running the following"
- print " " + (' '.join(gn_command))
- if subprocess.call(gn_command):
- print "Ninja failed."
- return 1
-
- # Use the versioned files under the copy directory to push to the GCS bucket.
- copy_dir = os.path.join(target_dir, GS_COPY_DIR)
- os.chdir(copy_dir)
-
- # Sanity check that there is a versioned copy under the directory.
- dirs = os.listdir('.')
- assert len(dirs) == 1 and dirs[0].isdigit(), (
- "There must be a single versioned dir under " + copy_dir)
-
- # Push the files with their directories, in the form
- # {vers}/{platform}/download_file_types.pb
- # Don't overwrite existing files, in case we forgot to increment the
- # version.
- version_dir = dirs[0]
- command = ['gsutil', 'cp', '-Rn', version_dir, DEST_BUCKET]
-
- print '\nGoing to run the following command'
- print ' ', ' '.join(command)
- print '\nIn directory'
- print ' ', copy_dir
- print '\nWhich should push the following files'
- expected_files = [os.path.join(dp, f) for dp, _, fn in
- os.walk(version_dir) for f in fn]
- for f in expected_files:
- print ' ', f
-
- shall = raw_input('\nAre you sure (y/N) ').lower() == 'y'
- if not shall:
- print 'aborting'
- return 1
- return subprocess.call(command)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.asciipb b/chromium/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.asciipb
deleted file mode 100644
index be32c3b963f..00000000000
--- a/chromium/chrome/browser/resources/ssl/ssl_error_assistant/ssl_error_assistant.asciipb
+++ /dev/null
@@ -1,356 +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.
-
-version_id: 7
-
-# List of SPKI hashes of certificates that are treated as captive portal
-# certificates. See chrome/browser/ssl/ssl_error_assistant.proto for the full
-# format.
-
-# https://captive-portal.badssl.com leaf.
-# This is a test certificate, always keep it at the top.
-captive_portal_cert {
- sha256_hash: "sha256/fjZPHewEHTrMDX3I1ecEIeoy3WFxHyGplOLv28kIbtI="
-}
-
-################################################################################
-# The rest of the certificates are case-insensitive sorted by the first line of
-# their comments.
-# See http://go/chrome-captive-portal-list for instructions to update this list.
-
-# Always On
-# Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited,
-# CN=COMODO High-Assurance Secure Server CA
-# Subject: C=ZA/postalCode=0157, ST=Gauteng,
-# L=CENTURION/street=1020 SASBY AVENUE ELDORAIGNE,
-# O=Always On Broadband Wireless Solutions, OU=InstantSSL,
-# CN=gateway.alwayson.co.za
-captive_portal_cert {
- sha256_hash: "sha256/m/nBiLhStttu1YmOz7Y3D2u1iB1dV2CbIfFa3R2YW5M="
-}
-
-# auth.impulse.com
-# https://crt.sh/?q=d92d97e4d17ce28a7c844f58b0d1cda44e604b959cff998435e01777777ce715
-captive_portal_cert {
- sha256_hash: "sha256/8Iuf4xRbVCmCMQTJn3rxlglIO1IOKoyuSUgmXyfaIKs="
-}
-# https://crt.sh/?q=AB+DF+09+66+47+46+2D+B6+D1+4F+AC+B8+13+7B+D6+8C+8B+B7+26+A9
-captive_portal_cert {
- sha256_hash: "sha256/8IHdrS+r6IWzSMcRcD/GA6mBxk1ECX8tGRW0rtGWILE="
-}
-
-# beeline.ru
-# https://crt.sh/?q=e64aa319a108ce49931ac19bf32f838f8db7427150cf7a781af7d9ff76f75cac
-captive_portal_cert {
- sha256_hash: "sha256/k/2eeJTznE32mblA/du19wpVDSIReFX44M8wXa2JY30="
-}
-
-# BT Wi-fi
-# https://crt.sh/?q=9e6bc5f9ecc52460e8edc02c644d1be1cb9f2316f41daf3b616a0b2058294b31
-captive_portal_cert {
- sha256_hash: "sha256/urWd7jMwR6DJgvWhp6xfRHF5b/cba3iG0ggXtTR6AfM="
-}
-
-# controller.access.network
-# https://crt.sh/?q=1544e807f17771b98a382b6b7faf2f2faf45eda44f460c4f8054b9eab845b860
-captive_portal_cert {
- sha256_hash: "sha256/IJPCDSE5tM9H3nuD5m6RU2i9KDdPXVn4qmC/ULlcZzc="
-}
-
-# hotelwifi.com
-# https://crt.sh/?q=f9dca04c4ac67f346c505c6a9bdc931c5272547dbb512a138c4459a903b023c7
-captive_portal_cert {
- sha256_hash: "sha256/0Gy8RMdbxHNWR2GQJ62QKDXORYf5JmMmnr1FJFPYpzM="
-}
-
-# Innflux
-# Issuer: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc.,
-# OU=http://certs.godaddy.com/repository/,
-# CN=Go Daddy Secure Certificate Authority - G2
-# Subject: OU=Domain Control Validated, CN=gateway.innflux.com
-captive_portal_cert {
- sha256_hash: "sha256/8tTICtyaxIQrdbYYDdgZhTN0OpM9kYndvoImtw1Ys5E="
-}
-
-# kewiko.mn
-# Issuer: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc.,
-# OU=http://certs.godaddy.com/repository/,
-# CN=Go Daddy Secure Certificate Authority - G2
-# Subject: OU=Domain Control Validated, CN=wireless.kewiko.mn
-captive_portal_cert {
- sha256_hash: "sha256/F7HIlsaG0bpJW8CzYekRbtFqLVTTGqwvuwPDqnlLct0="
-}
-
-# login.globalsuite.net
-# https://crt.sh/?q=ed4119e407aa22f507617226bbf2009fdbca55079a2c2f8eebda84e3173006a6
-captive_portal_cert {
- sha256_hash: "sha256/zaV2Aw1A742R1+WpXWvL5atsJbGmeSS6dzZOfe6f1Yw="
-}
-
-# login.netinary.net
-# Issuer: C=US, O=thawte, Inc., CN=thawte SSL CA - G2
-# Subject: C=FR, ST=Bouches-du-Rh\xC3\xB4ne, L=MARSEILLE, O=NETINARY,
-# OU=Security, CN=login.netinary.net
-captive_portal_cert {
- sha256_hash: "sha256/UwOkRGMlP0K/mKNJdpQ0sTg2ean9Tje8UTOvFYzt1GE="
-}
-
-# mobicare.com.br
-# https://crt.sh/?q=bf9a13fc64b18221a6f0360e95ba54714d8ebf70a0291b7ea5f357be30436a7a
-captive_portal_cert {
- sha256_hash: "sha256/w7KUXE4/BAo1YVZdO3mBsrMpu4IQuN0mhUXUI//agVU="
-}
-
-# ombord.info
-# https://crt.sh/?q=f849586eedb4c754fc53e4352948d36097ae7fec50abc5f93c08239719c8184a
-captive_portal_cert {
- sha256_hash: "sha256/JnPvGqEn36FjHQlBXtG1uWwNtdMj1o2ojR/asqyypNk="
-}
-
-# Orange France
-# Issuer: C=US, O=Symantec Corporation, OU=Symantec Trust Network,
-# CN=Symantec Class 3 Secure Server CA - G4
-# Subject: C=FR, ST=Paris, L=Paris, O=Orange, OU=Orange France,
-# CN=hautdebitmobile.orange.fr
-captive_portal_cert {
- sha256_hash: "sha256/AUSXlKDCf1X30WhWeAWbjToABfBkJrKWPL6KwEi5VH0="
-}
-
-# virginwifi.io
-# Issuer: O=GeoTrust Inc., CN=RapidSSL SHA256 CA - G2, C=US
-# Subject: CN=*.virginwifi.io
-captive_portal_cert {
- sha256_hash: "sha256/zSyVjjFJMIeXK0ktVTIjewwr6U5OePRqyY/nEXTI4P8="
-}
-
-# wifipass.org
-# https://crt.sh/?q=1cce212718a7cf65ce33acde91b5bc66863d14ae259fbaf841f83bf89748f5fd
-captive_portal_cert {
- sha256_hash: "sha256/9dcHlrXN2WV/ehbEdMxMZ8IV4qvGejCtNC5r6nfTviM="
-}
-
-# wifisignon.shaw.ca
-# Issuer: C=US, O=Symantec Corporation, OU=Symantec Trust Network,
-# CN=Symantec Class 3 Secure Server CA - G4
-# Subject: C=CA, ST=Alberta, L=Calgary, O=Shaw Cablesystems G.P., OU=TNO,
-# CN=wifisignon.shaw.ca
-captive_portal_cert {
- sha256_hash: "sha256/E+0WZLGSIe5nddlVKZ5fYzaNHHCE3hNqi/OWZD3iKgA="
-}
-
-# wifree.voo.be
-# Issuer: C=US, O=DigiCert Inc, OU=www.digicert.com,
-# CN=DigiCert SHA2 High Assurance Server CA
-# Subject: C=BE, ST=Liege, L=Liege, O=Tecteo Group, CN=wifree.voo.be
-captive_portal_cert {
- sha256_hash: "sha256/QJ/69CTHYPRa0I3UVlwD6N4MtToxpQ1+0izyGnqEHQo="
-}
-
-# wireless.wifirst.net
-# Issuer: C=FR, ST=Paris, L=Paris, O=Gandi, CN=Gandi Standard SSL CA 2
-# Subject: OU=Domain Control Validated, OU=Gandi Standard SSL,
-# CN=wireless.wifirst.net
-captive_portal_cert {
- sha256_hash: "sha256/LKtpdq9q7F7msGK0w1+b/gKoDHaQcZKTHIf9PTz2u+U="
-}
-
-# https://mitm-software.badssl.com leaf.
-# This is a test certificate, keep it at the top of the MITM software list.
-mitm_software {
- name: "BadSSL Antivirus",
- issuer_common_name_regex: "BadSSL MITM Software Test"
-}
-
-################################################################################
-# The rest of the MITM software certificates are sorted alphabetically by name.
-
-mitm_software {
- name: "Avast Antivirus",
- issuer_common_name_regex: "avast! Web/Mail Shield Root",
- issuer_organization_regex: "avast! Web/Mail Shield"
-}
-
-mitm_software {
- name: "Bitdefender Antivirus",
- issuer_common_name_regex: "Bitdefender Personal CA\.Net-Defender",
- issuer_organization_regex: "Bitdefender"
-}
-
-mitm_software {
- name: "Cisco Umbrella",
- issuer_common_name_regex: "Cisco Umbrella Root CA",
- issuer_organization_regex: "Cisco"
-}
-
-mitm_software {
- name: "Cisco Umbrella",
- issuer_common_name_regex: "Cisco Umbrella Primary SubCA",
- issuer_organization_regex: "Cisco"
-}
-
-mitm_software {
- name: "ContentKeeper",
- issuer_common_name_regex: "ContentKeeper Appliance CA \(\d+\)",
- issuer_organization_regex: "ContentKeeper Technologies"
-}
-
-mitm_software {
- name: "Cyberoam Firewall",
- issuer_organization_regex: "Cyberoam Certificate Authority"
-}
-
-mitm_software {
- name: "ForcePoint",
- issuer_common_name_regex: "Forcepoint Cloud CA",
- issuer_organization_regex: "Forcepoint LLC"
-}
-
-mitm_software {
- name: "Fortigate",
- issuer_common_name_regex: "FortiGate CA",
- issuer_organization_regex: "Fortinet"
-}
-
-mitm_software {
- name: "Fortinet",
- issuer_organization_regex: "Fortinet( Ltd\.)?"
-}
-
-mitm_software {
- name: "Kaspersky Internet Security",
- issuer_common_name_regex: "Kaspersky Anti-Virus Personal Root Certificate"
-}
-
-mitm_software {
- name: "McAfee Web Gateway",
- issuer_common_name_regex: "McAfee Web Gateway"
-}
-
-mitm_software {
- name: "NetSpark",
- issuer_common_name_regex: "www\.netspark\.com",
- issuer_organization_regex: "NetSpark"
-}
-
-mitm_software {
- name: "SmoothWall Firewall",
- issuer_common_name_regex: "Smoothwall-default-root-certificate-authority"
-}
-
-mitm_software {
- name: "SonicWall Firewall",
- issuer_organization_regex: "HTTPS Management Certificate for SonicWALL"
-}
-
-mitm_software {
- name: "Sophos",
- issuer_common_name_regex: "Sophos SSL CA_[A-Z0-9\-]+",
- issuer_organization_regex: "Sophos"
-}
-
-mitm_software {
- name: "Sophos",
- issuer_common_name_regex: "Sophos_CA_[A-Z0-9]+"
-}
-
-mitm_software {
- name: "Sophos UTM",
- issuer_common_name_regex: "sophosutm Proxy CA",
- issuer_organization_regex: "sophosutm"
-}
-
-mitm_software {
- name: "Sophos Web Appliance",
- issuer_common_name_regex: "Sophos Web Appliance",
- issuer_organization_regex: "Sophos Plc"
-}
-
-mitm_software {
- name: "Symantec Blue Coat",
- issuer_organization_regex: "Blue Coat.*"
-}
-
-mitm_software {
- name: "Trend Micro InterScan Web Security Suite (IWSS)",
- issuer_common_name_regex: "IWSS\.TREND"
-}
-
-mitm_software {
- name: "Zscaler",
- issuer_organization_regex: "Zscaler Inc\."
-}
-
-################################################################################
-# Dynamic interstitials
-
-# Potentially compromised Mitel keys.
-# https://www.mitel.com/support/security-advisories/mitel-product-security-advisory-17-0001
-#
-# These keys have been blacklisted but some of them are also weak signature
-# algorithms so may have already stopped working in Chrome. We trigger the MITM
-# interstitial for ERR_CERT_REVOKED and also for
-# ERR_CERT_WEAK_SIGNATURE_ALGORITHM when appropriate. (We're not guaranteed to
-# receive one error code or the other.)
-#
-# All fields for these entries should match except |cert_error| and
-# |sha256_hash|.
-
-dynamic_interstitial {
- cert_error: ERR_CERT_REVOKED,
- sha256_hash: "sha256/cH02TnKuUhQx3ZU4l/nEhG1bjDJCmP5T+9StofLRFX8=",
- mitm_software_name: "Mitel",
- interstitial_type: INTERSTITIAL_PAGE_MITM_SOFTWARE
-}
-
-dynamic_interstitial {
- cert_error: ERR_CERT_WEAK_SIGNATURE_ALGORITHM,
- sha256_hash: "sha256/cH02TnKuUhQx3ZU4l/nEhG1bjDJCmP5T+9StofLRFX8=",
- mitm_software_name: "Mitel",
- interstitial_type: INTERSTITIAL_PAGE_MITM_SOFTWARE
-}
-
-dynamic_interstitial {
- cert_error: ERR_CERT_REVOKED,
- sha256_hash: "sha256/atuOPgVUYJItFQHLl/lMagLjnI8ndMpAiCW3tYN53BQ=",
- mitm_software_name: "Mitel",
- interstitial_type: INTERSTITIAL_PAGE_MITM_SOFTWARE
-}
-
-dynamic_interstitial {
- cert_error: ERR_CERT_REVOKED,
- sha256_hash: "sha256/SQtuxr6y1gNHILUUm2spzTVRWYjMFq+FQUiwe5sfihE=",
- mitm_software_name: "Mitel",
- interstitial_type: INTERSTITIAL_PAGE_MITM_SOFTWARE
-}
-
-dynamic_interstitial {
- cert_error: ERR_CERT_REVOKED,
- sha256_hash: "sha256/71UShHFSMt6S4kbDIzKTYrEySTuxa1ieR3VSC+uHGlY=",
- mitm_software_name: "Mitel",
- interstitial_type: INTERSTITIAL_PAGE_MITM_SOFTWARE
-}
-
-dynamic_interstitial {
- cert_error: ERR_CERT_WEAK_SIGNATURE_ALGORITHM,
- sha256_hash: "sha256/71UShHFSMt6S4kbDIzKTYrEySTuxa1ieR3VSC+uHGlY=",
- mitm_software_name: "Mitel",
- interstitial_type: INTERSTITIAL_PAGE_MITM_SOFTWARE
-}
-
-# Potentially compromised Sennheiser HeadSetup and Sennheiser HeadSetup Pro
-# certs.
-# https://nvd.nist.gov/vuln/detail/CVE-2018-17612
-dynamic_interstitial {
- cert_error: ERR_CERT_REVOKED,
- sha256_hash: "sha256/DEPqi83p/DvKFlZkrIIVVn40idU5OgyB4aeRQZkuGVM=",
- mitm_software_name: "Sennheiser HeadSetup",
- interstitial_type: INTERSTITIAL_PAGE_MITM_SOFTWARE
-}
-
-dynamic_interstitial {
- cert_error: ERR_CERT_REVOKED,
- sha256_hash: "sha256/j1kfeqTcPv6UkMOKRpLJAR7RKPHeWVVpQG13tvofa0w=",
- mitm_software_name: "Sennheiser HeadSetup",
- interstitial_type: INTERSTITIAL_PAGE_MITM_SOFTWARE
-}
diff --git a/chromium/chrome/browser/resources/tab_strip/.eslintrc.js b/chromium/chrome/browser/resources/tab_strip/.eslintrc.js
new file mode 100644
index 00000000000..18f6e9550ca
--- /dev/null
+++ b/chromium/chrome/browser/resources/tab_strip/.eslintrc.js
@@ -0,0 +1,11 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/tab_strip/BUILD.gn b/chromium/chrome/browser/resources/tab_strip/BUILD.gn
index fcdcc6cabf5..2e3220be9ae 100644
--- a/chromium/chrome/browser/resources/tab_strip/BUILD.gn
+++ b/chromium/chrome/browser/resources/tab_strip/BUILD.gn
@@ -11,7 +11,9 @@ js_type_check("closure_compile") {
":alert_indicator",
":alert_indicators",
":custom_element",
+ ":drag_manager",
":tab",
+ ":tab_group",
":tab_list",
":tab_strip_embedder_proxy",
":tab_strip_options",
@@ -21,41 +23,86 @@ js_type_check("closure_compile") {
}
js_library("alert_indicator") {
+ deps = [
+ ":custom_element",
+ ":tabs_api_proxy",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
}
js_library("alert_indicators") {
+ deps = [
+ ":alert_indicator",
+ ":custom_element",
+ ":tabs_api_proxy",
+ ]
}
js_library("custom_element") {
}
-js_library("tabs_api_proxy") {
+js_library("drag_manager") {
deps = [
- "//ui/webui/resources/js:cr.m",
+ ":tab",
+ ":tab_group",
+ ":tabs_api_proxy",
+ "//ui/webui/resources/js:assert.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ ]
+}
+
+js_library("tabs_api_proxy") {
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+ externs_list = [
+ "$externs_path/chrome_extensions.js",
+ "$externs_path/metrics_private.js",
]
- externs_list = [ "$externs_path/chrome_extensions.js" ]
}
js_library("tab") {
deps = [
+ ":alert_indicators",
+ ":custom_element",
+ ":tab_strip_embedder_proxy",
+ ":tab_strip_options",
+ ":tab_swiper",
+ ":tabs_api_proxy",
"//ui/webui/resources/js:icon.m",
"//ui/webui/resources/js:load_time_data.m",
"//ui/webui/resources/js:util.m",
]
+ externs_list = [ "$externs_path/metrics_private.js" ]
}
-js_library("tab_list") {
+js_library("tab_group") {
deps = [
- "//ui/webui/resources/js/cr/ui:focus_outline_manager.m",
+ ":custom_element",
+ ":tab_strip_embedder_proxy",
+ ":tabs_api_proxy",
+ "//ui/webui/resources/js:load_time_data.m",
]
}
-js_library("tab_strip_embedder_proxy") {
+js_library("tab_list") {
deps = [
+ ":custom_element",
+ ":drag_manager",
+ ":tab",
+ ":tab_group",
+ ":tab_strip_embedder_proxy",
+ ":tab_strip_options",
+ ":tabs_api_proxy",
"//ui/webui/resources/js:cr.m",
+ "//ui/webui/resources/js:load_time_data.m",
+ "//ui/webui/resources/js:util.m",
+ "//ui/webui/resources/js/cr/ui:focus_outline_manager.m",
]
}
+js_library("tab_strip_embedder_proxy") {
+ deps = [ "//ui/webui/resources/js:cr.m" ]
+}
+
js_library("tab_strip_options") {
}
@@ -63,9 +110,10 @@ js_library("tab_swiper") {
}
group("tab_strip_modules") {
- deps = [
+ public_deps = [
":alert_indicator_module",
":alert_indicators_module",
+ ":tab_group_module",
":tab_list_module",
":tab_module",
]
@@ -89,6 +137,12 @@ polymer_modulizer("tab") {
html_type = "v3-ready"
}
+polymer_modulizer("tab_group") {
+ js_file = "tab_group.js"
+ html_file = "tab_group.html"
+ html_type = "v3-ready"
+}
+
polymer_modulizer("tab_list") {
js_file = "tab_list.js"
html_file = "tab_list.html"
diff --git a/chromium/chrome/browser/resources/tab_strip/alert_indicator.html b/chromium/chrome/browser/resources/tab_strip/alert_indicator.html
index a69550f5dc9..eff3a70c61a 100644
--- a/chromium/chrome/browser/resources/tab_strip/alert_indicator.html
+++ b/chromium/chrome/browser/resources/tab_strip/alert_indicator.html
@@ -9,7 +9,7 @@
}
:host([alert-state_='0']),
- :host([alert-state_='8']) {
+ :host([alert-state_='9']) {
-webkit-mask-image: url(alert_indicators/tab_media_recording.svg);
background-color: var(--tabstrip-indicator-recording-color);
}
@@ -38,15 +38,19 @@
}
:host([alert-state_='6']) {
- -webkit-mask-image: url(alert_indicators/serial_port.svg);
+ -webkit-mask-image: url(alert_indicators/tab_hid_connected.svg);
}
:host([alert-state_='7']) {
+ -webkit-mask-image: url(alert_indicators/serial_port.svg);
+ }
+
+ :host([alert-state_='8']) {
-webkit-mask-image: url(alert_indicators/picture_in_picture_alt.svg);
background-color: var(--tabstrip-indicator-pip-color);
}
- :host([alert-state_='9']) {
+ :host([alert-state_='10']) {
-webkit-mask-image: url(alert_indicators/vr_headset.svg);
}
</style>
diff --git a/chromium/chrome/browser/resources/tab_strip/alert_indicator.js b/chromium/chrome/browser/resources/tab_strip/alert_indicator.js
index f2120ba7ec1..480b42812e6 100644
--- a/chromium/chrome/browser/resources/tab_strip/alert_indicator.js
+++ b/chromium/chrome/browser/resources/tab_strip/alert_indicator.js
@@ -35,6 +35,8 @@ function getAriaLabel(alertState) {
return loadTimeData.getStringF('bluetoothConnected', '');
case TabAlertState.USB_CONNECTED:
return loadTimeData.getStringF('usbConnected', '');
+ case TabAlertState.HID_CONNECTED:
+ return loadTimeData.getStringF('hidConnected', '');
case TabAlertState.SERIAL_CONNECTED:
return loadTimeData.getStringF('serialConnected', '');
case TabAlertState.PIP_PLAYING:
diff --git a/chromium/chrome/browser/resources/tab_strip/alert_indicators.js b/chromium/chrome/browser/resources/tab_strip/alert_indicators.js
index f83b5e6dc52..e3dd5dcd0be 100644
--- a/chromium/chrome/browser/resources/tab_strip/alert_indicators.js
+++ b/chromium/chrome/browser/resources/tab_strip/alert_indicators.js
@@ -15,8 +15,7 @@ export class AlertIndicatorsElement extends CustomElement {
super();
/** @private {!HTMLElement} */
- this.containerEl_ = /** @type {!HTMLElement} */ (
- this.shadowRoot.querySelector('#container'));
+ this.containerEl_ = /** @type {!HTMLElement} */ (this.$('#container'));
const audioIndicator = new AlertIndicatorElement();
const recordingIndicator = new AlertIndicatorElement();
@@ -29,6 +28,7 @@ export class AlertIndicatorsElement extends CustomElement {
[TabAlertState.AUDIO_MUTING, audioIndicator],
[TabAlertState.BLUETOOTH_CONNECTED, new AlertIndicatorElement()],
[TabAlertState.USB_CONNECTED, new AlertIndicatorElement()],
+ [TabAlertState.HID_CONNECTED, new AlertIndicatorElement()],
[TabAlertState.SERIAL_CONNECTED, new AlertIndicatorElement()],
[TabAlertState.PIP_PLAYING, new AlertIndicatorElement()],
[TabAlertState.DESKTOP_CAPTURING, recordingIndicator],
diff --git a/chromium/chrome/browser/resources/tab_strip/alert_indicators/tab_hid_connected.svg b/chromium/chrome/browser/resources/tab_strip/alert_indicators/tab_hid_connected.svg
new file mode 100644
index 00000000000..1176e627ada
--- /dev/null
+++ b/chromium/chrome/browser/resources/tab_strip/alert_indicators/tab_hid_connected.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill-rule="evenodd"><path d="M 21 6 H 3 c -1.1 0 -2 0.9 -2 2 v 8 c 0 1.1 0.9 2 2 2 h 18 c 1.1 0 2 -0.9 2 -2 V 8 c 0 -1.1 -0.9 -2 -2 -2 Z m -10 7 H 8 v 3 H 6 v -3 H 3 v -2 h 3 V 8 h 2 v 3 h 3 v 2 Z m 4.5 2 c -0.83 0 -1.5 -0.67 -1.5 -1.5 c 0 -0.83 0.67 -1.5 1.5 -1.5 c 0.83 0 1.5 0.67 1.5 1.5 c 0 0.83 -0.67 1.5 -1.5 1.5 Z m 4 -3 c -0.83 0 -1.5 -0.67 -1.5 -1.5 S 18.67 9 19.5 9 c 0.83 0 1.5 0.67 1.5 1.5 c 0 0.83 -0.67 1.5 -1.5 1.5 Z"/></svg>
diff --git a/chromium/chrome/browser/resources/tab_strip/custom_element.js b/chromium/chrome/browser/resources/tab_strip/custom_element.js
index 2d8e4e91937..50e2bdae652 100644
--- a/chromium/chrome/browser/resources/tab_strip/custom_element.js
+++ b/chromium/chrome/browser/resources/tab_strip/custom_element.js
@@ -14,4 +14,20 @@ export class CustomElement extends HTMLElement {
template.innerHTML = this.constructor.template || '';
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
+
+ /**
+ * @param {string} query
+ * @return {?Element}
+ */
+ $(query) {
+ return this.shadowRoot.querySelector(query);
+ }
+
+ /**
+ * @param {string} query
+ * @return {!NodeList<!Element>}
+ */
+ $all(query) {
+ return this.shadowRoot.querySelectorAll(query);
+ }
}
diff --git a/chromium/chrome/browser/resources/tab_strip/drag_manager.js b/chromium/chrome/browser/resources/tab_strip/drag_manager.js
new file mode 100644
index 00000000000..69b836bf742
--- /dev/null
+++ b/chromium/chrome/browser/resources/tab_strip/drag_manager.js
@@ -0,0 +1,519 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import './strings.m.js';
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+
+import {isTabElement, TabElement} from './tab.js';
+import {isTabGroupElement, TabGroupElement} from './tab_group.js';
+import {TabData, TabNetworkState, TabsApiProxy} from './tabs_api_proxy.js';
+
+/** @const {number} */
+export const PLACEHOLDER_TAB_ID = -1;
+
+/** @const {string} */
+export const PLACEHOLDER_GROUP_ID = 'placeholder';
+
+/**
+ * The data type key for pinned state of a tab. Since drag events only expose
+ * whether or not a data type exists (not the actual value), presence of this
+ * data type means that the tab is pinned.
+ * @const {string}
+ */
+const PINNED_DATA_TYPE = 'pinned';
+
+/**
+ * Gets the data type of tab IDs on DataTransfer objects in drag events. This
+ * is a function so that loadTimeData can get overridden by tests.
+ * @return {string}
+ */
+function getTabIdDataType() {
+ return loadTimeData.getString('tabIdDataType');
+}
+
+/** @return {string} */
+function getGroupIdDataType() {
+ return loadTimeData.getString('tabGroupIdDataType');
+}
+
+/** @return {!TabData} */
+function getDefaultTabData() {
+ return {
+ active: false,
+ alertStates: [],
+ blocked: false,
+ crashed: false,
+ id: -1,
+ index: -1,
+ isDefaultFavicon: false,
+ networkState: TabNetworkState.NONE,
+ pinned: false,
+ shouldHideThrobber: false,
+ showIcon: true,
+ title: '',
+ url: '',
+ };
+}
+
+/**
+ * @interface
+ */
+export class DragManagerDelegate {
+ /**
+ * @param {!TabElement} tabElement
+ * @return {number}
+ */
+ getIndexOfTab(tabElement) {}
+
+ /**
+ * @param {!TabElement} element
+ * @param {number} index
+ * @param {boolean} pinned
+ * @param {string=} groupId
+ */
+ placeTabElement(element, index, pinned, groupId) {}
+
+ /**
+ * @param {!TabGroupElement} element
+ * @param {number} index
+ */
+ placeTabGroupElement(element, index) {}
+}
+
+/** @typedef {!DragManagerDelegate|!HTMLElement} */
+let DragManagerDelegateElement;
+
+class DragSession {
+ /**
+ * @param {!DragManagerDelegateElement} delegate
+ * @param {!TabElement|!TabGroupElement} element
+ * @param {number} srcIndex
+ * @param {string=} srcGroup
+ */
+ constructor(delegate, element, srcIndex, srcGroup) {
+ /** @const @private {!DragManagerDelegateElement} */
+ this.delegate_ = delegate;
+
+ /** @const {!TabElement|!TabGroupElement} */
+ this.element_ = element;
+
+ /** @const {number} */
+ this.srcIndex = srcIndex;
+
+ /** @const {string|undefined} */
+ this.srcGroup = srcGroup;
+
+ /** @private @const {!TabsApiProxy} */
+ this.tabsProxy_ = TabsApiProxy.getInstance();
+ }
+
+ /**
+ * @param {!DragManagerDelegateElement} delegate
+ * @param {!TabElement|!TabGroupElement} element
+ * @return {!DragSession}
+ */
+ static createFromElement(delegate, element) {
+ if (isTabGroupElement(element)) {
+ return new DragSession(
+ delegate, element,
+ delegate.getIndexOfTab(
+ /** @type {!TabElement} */ (element.firstElementChild)));
+ }
+
+ const srcIndex = delegate.getIndexOfTab(
+ /** @type {!TabElement} */ (element));
+ const srcGroup =
+ (element.parentElement && isTabGroupElement(element.parentElement)) ?
+ element.parentElement.dataset.groupId :
+ undefined;
+ return new DragSession(delegate, element, srcIndex, srcGroup);
+ }
+
+ /**
+ * @param {!DragManagerDelegateElement} delegate
+ * @param {!DragEvent} event
+ * @return {?DragSession}
+ */
+ static createFromEvent(delegate, event) {
+ if (event.dataTransfer.types.includes(getTabIdDataType())) {
+ const isPinned = event.dataTransfer.types.includes('pinned');
+ const placeholderTabElement =
+ /** @type {!TabElement} */ (document.createElement('tabstrip-tab'));
+ placeholderTabElement.tab = /** @type {!TabData} */ (Object.assign(
+ getDefaultTabData(), {id: PLACEHOLDER_TAB_ID, pinned: isPinned}));
+ placeholderTabElement.setDragging(true);
+ delegate.placeTabElement(placeholderTabElement, -1, isPinned);
+ return DragSession.createFromElement(delegate, placeholderTabElement);
+ }
+
+ if (event.dataTransfer.types.includes(getGroupIdDataType())) {
+ const placeholderGroupElement = /** @type {!TabGroupElement} */
+ (document.createElement('tabstrip-tab-group'));
+ placeholderGroupElement.dataset.groupId = PLACEHOLDER_GROUP_ID;
+ placeholderGroupElement.setDragging(true);
+ delegate.placeTabGroupElement(placeholderGroupElement, -1);
+ return DragSession.createFromElement(delegate, placeholderGroupElement);
+ }
+
+ return null;
+ }
+
+ /** @return {string|undefined} */
+ get dstGroup() {
+ if (isTabElement(this.element_) && this.element_.parentElement &&
+ isTabGroupElement(this.element_.parentElement)) {
+ return this.element_.parentElement.dataset.groupId;
+ }
+
+ return undefined;
+ }
+
+ /** @return {number} */
+ get dstIndex() {
+ if (isTabElement(this.element_)) {
+ return this.delegate_.getIndexOfTab(
+ /** @type {!TabElement} */ (this.element_));
+ }
+
+ if (this.element_.children.length === 0) {
+ // If this group element has no children, it was a placeholder element
+ // being dragged. Find out the destination index by finding the index of
+ // the tab closest to it and incrementing it by 1.
+ const previousElement = this.element_.previousElementSibling;
+ if (!previousElement) {
+ return 0;
+ }
+ if (isTabElement(previousElement)) {
+ return this.delegate_.getIndexOfTab(
+ /** @private {!TabElement} */ (previousElement)) +
+ 1;
+ }
+
+ assert(isTabGroupElement(previousElement));
+ return this.delegate_.getIndexOfTab(/** @private {!TabElement} */ (
+ previousElement.lastElementChild)) +
+ 1;
+ }
+
+ // If a tab group is moving backwards (to the front of the tab strip), the
+ // new index is the index of the first tab in that group. If a tab group is
+ // moving forwards (to the end of the tab strip), the new index is the index
+ // of the last tab in that group.
+ let dstIndex = this.delegate_.getIndexOfTab(
+ /** @type {!TabElement} */ (this.element_.firstElementChild));
+ if (this.srcIndex <= dstIndex) {
+ dstIndex += this.element_.childElementCount - 1;
+ }
+ return dstIndex;
+ }
+
+ cancel() {
+ if (this.isDraggingPlaceholder()) {
+ this.element_.remove();
+ return;
+ }
+
+ if (isTabGroupElement(this.element_)) {
+ this.delegate_.placeTabGroupElement(
+ /** @type {!TabGroupElement} */ (this.element_), this.srcIndex);
+ } else if (isTabElement(this.element_)) {
+ this.delegate_.placeTabElement(
+ /** @type {!TabElement} */ (this.element_), this.srcIndex,
+ this.element_.tab.pinned, this.srcGroup);
+ }
+
+ this.element_.setDragging(false);
+ }
+
+ /** @return {boolean} */
+ isDraggingPlaceholder() {
+ return this.isDraggingPlaceholderTab_() ||
+ this.isDraggingPlaceholderGroup_();
+ }
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isDraggingPlaceholderTab_() {
+ return isTabElement(this.element_) &&
+ this.element_.tab.id === PLACEHOLDER_TAB_ID;
+ }
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isDraggingPlaceholderGroup_() {
+ return isTabGroupElement(this.element_) &&
+ this.element_.dataset.groupId === PLACEHOLDER_GROUP_ID;
+ }
+
+ /** @param {!DragEvent} event */
+ finish(event) {
+ if (this.isDraggingPlaceholderTab_()) {
+ const id = Number(event.dataTransfer.getData(getTabIdDataType()));
+ this.element_.tab = Object.assign({}, this.element_.tab, {id});
+ } else if (this.isDraggingPlaceholderGroup_()) {
+ this.element_.dataset.groupId =
+ event.dataTransfer.getData(getGroupIdDataType());
+ }
+
+ const dstIndex = this.dstIndex;
+ if (isTabElement(this.element_)) {
+ this.tabsProxy_.moveTab(this.element_.tab.id, dstIndex);
+ } else if (isTabGroupElement(this.element_)) {
+ this.tabsProxy_.moveGroup(this.element_.dataset.groupId, dstIndex);
+ }
+
+ const dstGroup = this.dstGroup;
+ if (dstGroup && dstGroup !== this.srcGroup) {
+ this.tabsProxy_.groupTab(this.element_.tab.id, dstGroup);
+ } else if (!dstGroup && this.srcGroup) {
+ this.tabsProxy_.ungroupTab(this.element_.tab.id);
+ }
+
+ this.element_.setDragging(false);
+ }
+
+ /**
+ * @param {!TabElement|!TabGroupElement} dragOverElement
+ * @return {boolean}
+ */
+ shouldOffsetIndexForGroup_(dragOverElement) {
+ // Since TabGroupElements do not have any TabElements, they need to offset
+ // the index for any elements that come after it as if there is at least
+ // one element inside of it.
+ return this.isDraggingPlaceholder() &&
+ !!(dragOverElement.compareDocumentPosition(this.element_) &
+ Node.DOCUMENT_POSITION_PRECEDING);
+ }
+
+ /** @param {!DragEvent} event */
+ start(event) {
+ event.dataTransfer.effectAllowed = 'move';
+ const draggedItemRect = this.element_.getBoundingClientRect();
+ this.element_.setDragging(true);
+
+ const dragImage = this.element_.getDragImage();
+ const dragImageRect = dragImage.getBoundingClientRect();
+
+ let scaleFactor = 1;
+ let verticalOffset = 0;
+
+ // <if expr="chromeos">
+ // Touch on ChromeOS automatically scales drag images by 1.2 and adds a
+ // vertical offset of 25px. See //ash/drag_drop/drag_drop_controller.cc.
+ scaleFactor = 1.2;
+ verticalOffset = 25;
+ // </if>
+
+ const xDiffFromCenter =
+ event.clientX - draggedItemRect.left - (draggedItemRect.width / 2);
+ const yDiffFromCenter = event.clientY - draggedItemRect.top -
+ verticalOffset - (draggedItemRect.height / 2);
+
+ event.dataTransfer.setDragImage(
+ dragImage, (dragImageRect.width / 2 + xDiffFromCenter / scaleFactor),
+ (dragImageRect.height / 2 + yDiffFromCenter / scaleFactor));
+
+ if (isTabElement(this.element_)) {
+ event.dataTransfer.setData(
+ getTabIdDataType(), this.element_.tab.id.toString());
+
+ if (this.element_.tab.pinned) {
+ event.dataTransfer.setData(
+ 'pinned', this.element_.tab.pinned.toString());
+ }
+ } else if (isTabGroupElement(this.element_)) {
+ event.dataTransfer.setData(
+ getGroupIdDataType(), this.element_.dataset.groupId);
+ }
+ }
+
+ /** @param {!DragEvent} event */
+ update(event) {
+ event.dataTransfer.dropEffect = 'move';
+ if (isTabGroupElement(this.element_)) {
+ this.updateForTabGroupElement_(event);
+ } else if (isTabElement(this.element_)) {
+ this.updateForTabElement_(event);
+ }
+ }
+
+ /**
+ * @param {!DragEvent} event
+ * @private
+ */
+ updateForTabGroupElement_(event) {
+ const tabGroupElement =
+ /** @type {!TabGroupElement} */ (this.element_);
+ const composedPath = /** @type {!Array<!Element>} */ (event.composedPath());
+ if (composedPath.includes(assert(this.element_))) {
+ // Dragging over itself or a child of itself.
+ return;
+ }
+
+ const dragOverTabElement =
+ /** @type {!TabElement|undefined} */ (composedPath.find(isTabElement));
+ if (dragOverTabElement && !dragOverTabElement.tab.pinned) {
+ let dragOverIndex = this.delegate_.getIndexOfTab(dragOverTabElement);
+ dragOverIndex +=
+ this.shouldOffsetIndexForGroup_(dragOverTabElement) ? 1 : 0;
+ this.delegate_.placeTabGroupElement(tabGroupElement, dragOverIndex);
+ return;
+ }
+
+ const dragOverGroupElement = /** @type {!TabGroupElement|undefined} */ (
+ composedPath.find(isTabGroupElement));
+ if (dragOverGroupElement) {
+ let dragOverIndex = this.delegate_.getIndexOfTab(
+ /** @type {!TabElement} */ (dragOverGroupElement.firstElementChild));
+ dragOverIndex +=
+ this.shouldOffsetIndexForGroup_(dragOverGroupElement) ? 1 : 0;
+ this.delegate_.placeTabGroupElement(tabGroupElement, dragOverIndex);
+ }
+ }
+
+ /**
+ * @param {!DragEvent} event
+ * @private
+ */
+ updateForTabElement_(event) {
+ const tabElement = /** @type {!TabElement} */ (this.element_);
+ const composedPath = /** @type {!Array<!Element>} */ (event.composedPath());
+ const dragOverTabElement =
+ /** @type {?TabElement} */ (composedPath.find(isTabElement));
+ if (dragOverTabElement &&
+ dragOverTabElement.tab.pinned !== tabElement.tab.pinned) {
+ // Can only drag between the same pinned states.
+ return;
+ }
+
+ const previousGroupId = (tabElement.parentElement &&
+ isTabGroupElement(tabElement.parentElement)) ?
+ tabElement.parentElement.dataset.groupId :
+ undefined;
+
+ const dragOverTabGroup =
+ /** @type {?TabGroupElement} */ (composedPath.find(isTabGroupElement));
+ if (dragOverTabGroup &&
+ dragOverTabGroup.dataset.groupId !== previousGroupId) {
+ this.delegate_.placeTabElement(
+ tabElement, this.dstIndex, false, dragOverTabGroup.dataset.groupId);
+ return;
+ }
+
+ if (!dragOverTabGroup && previousGroupId) {
+ this.delegate_.placeTabElement(
+ tabElement, this.dstIndex, false, undefined);
+ return;
+ }
+
+ if (!dragOverTabElement) {
+ return;
+ }
+
+ const dragOverIndex = this.delegate_.getIndexOfTab(dragOverTabElement);
+ this.delegate_.placeTabElement(
+ tabElement, dragOverIndex, tabElement.tab.pinned, previousGroupId);
+ }
+}
+
+export class DragManager {
+ /** @param {!DragManagerDelegateElement} delegate */
+ constructor(delegate) {
+ /** @private {!DragManagerDelegateElement} */
+ this.delegate_ = delegate;
+
+ /** @type {?DragSession} */
+ this.dragSession_ = null;
+
+ /** @private {!TabsApiProxy} */
+ this.tabsProxy_ = TabsApiProxy.getInstance();
+ }
+
+ /** @private */
+ onDragLeave_() {
+ if (this.dragSession_ && !this.dragSession_.isDraggingPlaceholder()) {
+ return;
+ }
+
+ this.dragSession_.cancel();
+ this.dragSession_ = null;
+ }
+
+ /** @param {!DragEvent} event */
+ onDragOver_(event) {
+ event.preventDefault();
+ if (!this.dragSession_) {
+ return;
+ }
+
+ this.dragSession_.update(event);
+ }
+
+ /** @param {!DragEvent} event */
+ onDragStart_(event) {
+ const draggedItem =
+ /** @type {!Array<!Element>} */ (event.composedPath()).find(item => {
+ return isTabElement(item) || isTabGroupElement(item);
+ });
+ if (!draggedItem) {
+ return;
+ }
+
+ this.dragSession_ = DragSession.createFromElement(
+ this.delegate_,
+ /** @type {!TabElement|!TabGroupElement} */ (draggedItem));
+ this.dragSession_.start(event);
+ }
+
+ /** @param {!DragEvent} event */
+ onDragEnd_(event) {
+ if (!this.dragSession_) {
+ return;
+ }
+
+ this.dragSession_.cancel();
+ this.dragSession_ = null;
+ }
+
+ /** @param {!DragEvent} event */
+ onDragEnter_(event) {
+ if (this.dragSession_) {
+ return;
+ }
+
+ this.dragSession_ = DragSession.createFromEvent(this.delegate_, event);
+ }
+
+ /**
+ * @param {!DragEvent} event
+ */
+ onDrop_(event) {
+ if (!this.dragSession_) {
+ return;
+ }
+
+ this.dragSession_.finish(event);
+ this.dragSession_ = null;
+ }
+
+ startObserving() {
+ this.delegate_.addEventListener(
+ 'dragstart', e => this.onDragStart_(/** @type {!DragEvent} */ (e)));
+ this.delegate_.addEventListener(
+ 'dragend', e => this.onDragEnd_(/** @type {!DragEvent} */ (e)));
+ this.delegate_.addEventListener(
+ 'dragenter', (e) => this.onDragEnter_(/** @type {!DragEvent} */ (e)));
+ this.delegate_.addEventListener('dragleave', () => this.onDragLeave_());
+ this.delegate_.addEventListener(
+ 'dragover', e => this.onDragOver_(/** @type {!DragEvent} */ (e)));
+ this.delegate_.addEventListener(
+ 'drop', e => this.onDrop_(/** @type {!DragEvent} */ (e)));
+ }
+}
diff --git a/chromium/chrome/browser/resources/tab_strip/tab.html b/chromium/chrome/browser/resources/tab_strip/tab.html
index 567c24be4f6..7bb542efb9b 100644
--- a/chromium/chrome/browser/resources/tab_strip/tab.html
+++ b/chromium/chrome/browser/resources/tab_strip/tab.html
@@ -2,6 +2,7 @@
:host {
--tabstrip-tab-transition-duration: 250ms;
+ display: block;
height: var(--tabstrip-tab-height);
padding-inline-end: var(--tabstrip-tab-spacing);
position: relative;
@@ -287,33 +288,58 @@
/* When being dragged, the contents of the drag image needs to be off-screen
* with nothing else on top or below obscuring it. */
- :host([dragging_]) #tab {
- box-shadow: none;
+ :host([dragging_]) #dragImage {
+ /* Enough padding to not crop the box shadow set on #tab below. */
+ --drag-image-padding: 25px;
+ align-items: center;
+ display: flex;
+ height: 100%;
+ justify-content: center;
+ padding-block-end: var(--drag-image-padding);
+ padding-block-start: var(--drag-image-padding);
+ padding-inline-end: calc(
+ var(--tabstrip-tab-spacing) + var(--drag-image-padding));
+ padding-inline-start: var(--drag-image-padding);
position: absolute;
- top: -999px;
+ top: 100vh;
+ width: 100%;
+ }
+
+ :host([dragging_]) #tab {
+ box-shadow: var(--tabstrip-tab-dragging-shadow);
+ transform: scale(var(--tabstrip-tab-drag-image-scale));
}
</style>
<div id="dragPlaceholder"></div>
-<div id="tab" role="tab" tabindex="0"
- aria-labelledby="titleText alertIndicators">
- <header id="title">
- <div id="faviconContainer" aria-hidden="true">
- <div id="progressSpinner"></div>
- <div id="favicon"></div>
- <div id="crashedIcon"></div>
- <div id="blocked"></div>
+<!--
+ #dragImage is a wrapper that wraps the entire #tab contents so that #tab can
+ be styled with properties, such as box-shadow, that extend beyond #tab's
+ boundaries and #dragImage can add padding to itself to contain all of #tab's
+ styles. When the tab is not being dragged, the #dragImage parent has no use.
+-->
+<div id="dragImage">
+ <div id="tab" role="tab" tabindex="0"
+ aria-labelledby="titleText alertIndicators">
+ <header id="title">
+ <div id="faviconContainer" aria-hidden="true">
+ <div id="progressSpinner"></div>
+ <div id="favicon"></div>
+ <div id="crashedIcon"></div>
+ <div id="blocked"></div>
+ </div>
+ <h2 id="titleText"></h2>
+ <tabstrip-alert-indicators id="alertIndicators">
+ </tabstrip-alert-indicators>
+ <button id="close" aria-describedby="titleText">
+ <span id="closeIconFocus"></span>
+ <span id="closeIcon"></span>
+ </button>
+ </header>
+
+ <div id="thumbnail">
+ <img id="thumbnailImg">
</div>
- <h2 id="titleText"></h2>
- <tabstrip-alert-indicators id="alertIndicators"></tabstrip-alert-indicators>
- <button id="close" aria-describedby="titleText">
- <span id="closeIconFocus"></span>
- <span id="closeIcon"></span>
- </button>
- </header>
-
- <div id="thumbnail">
- <img id="thumbnailImg">
</div>
</div>
diff --git a/chromium/chrome/browser/resources/tab_strip/tab.js b/chromium/chrome/browser/resources/tab_strip/tab.js
index d64f93c4db5..4c6fbb904e1 100644
--- a/chromium/chrome/browser/resources/tab_strip/tab.js
+++ b/chromium/chrome/browser/resources/tab_strip/tab.js
@@ -14,7 +14,7 @@ import {CustomElement} from './custom_element.js';
import {TabStripEmbedderProxy} from './tab_strip_embedder_proxy.js';
import {tabStripOptions} from './tab_strip_options.js';
import {TabSwiper} from './tab_swiper.js';
-import {TabData, TabNetworkState, TabsApiProxy} from './tabs_api_proxy.js';
+import {CloseTabAction, TabData, TabNetworkState, TabsApiProxy} from './tabs_api_proxy.js';
const DEFAULT_ANIMATION_DURATION = 125;
@@ -53,34 +53,32 @@ export class TabElement extends CustomElement {
super();
this.alertIndicatorsEl_ = /** @type {!AlertIndicatorsElement} */
- (this.shadowRoot.querySelector('tabstrip-alert-indicators'));
+ (this.$('tabstrip-alert-indicators'));
// Normally, custom elements will get upgraded automatically once added to
// the DOM, but TabElement may need to update properties on
// AlertIndicatorElement before this happens, so upgrade it manually.
customElements.upgrade(this.alertIndicatorsEl_);
/** @private {!HTMLElement} */
- this.closeButtonEl_ =
- /** @type {!HTMLElement} */ (this.shadowRoot.querySelector('#close'));
+ this.closeButtonEl_ = /** @type {!HTMLElement} */ (this.$('#close'));
this.closeButtonEl_.setAttribute(
'aria-label', loadTimeData.getString('closeTab'));
/** @private {!HTMLElement} */
- this.tabEl_ =
- /** @type {!HTMLElement} */ (this.shadowRoot.querySelector('#tab'));
+ this.dragImageEl_ = /** @type {!HTMLElement} */ (this.$('#dragImage'));
/** @private {!HTMLElement} */
- this.faviconEl_ =
- /** @type {!HTMLElement} */ (this.shadowRoot.querySelector('#favicon'));
+ this.tabEl_ = /** @type {!HTMLElement} */ (this.$('#tab'));
+
+ /** @private {!HTMLElement} */
+ this.faviconEl_ = /** @type {!HTMLElement} */ (this.$('#favicon'));
/** @private {!HTMLElement} */
this.thumbnailContainer_ =
- /** @type {!HTMLElement} */ (
- this.shadowRoot.querySelector('#thumbnail'));
+ /** @type {!HTMLElement} */ (this.$('#thumbnail'));
/** @private {!Image} */
- this.thumbnail_ =
- /** @type {!Image} */ (this.shadowRoot.querySelector('#thumbnailImg'));
+ this.thumbnail_ = /** @type {!Image} */ (this.$('#thumbnailImg'));
/** @private {!TabData} */
this.tab_;
@@ -92,8 +90,7 @@ export class TabElement extends CustomElement {
this.embedderApi_ = TabStripEmbedderProxy.getInstance();
/** @private {!HTMLElement} */
- this.titleTextEl_ = /** @type {!HTMLElement} */ (
- this.shadowRoot.querySelector('#titleText'));
+ this.titleTextEl_ = /** @type {!HTMLElement} */ (this.$('#titleText'));
this.tabEl_.addEventListener('click', () => this.onClick_());
this.tabEl_.addEventListener('contextmenu', e => this.onContextMenu_(e));
@@ -183,7 +180,7 @@ export class TabElement extends CustomElement {
/** @return {!HTMLElement} */
getDragImage() {
- return this.tabEl_;
+ return this.dragImageEl_;
}
/**
@@ -229,19 +226,15 @@ export class TabElement extends CustomElement {
* @private
*/
onClose_(event) {
- if (!this.tab_) {
- return;
- }
-
+ assert(this.tab_);
event.stopPropagation();
- this.tabsApi_.closeTab(this.tab_.id);
+ this.tabsApi_.closeTab(this.tab_.id, CloseTabAction.CLOSE_BUTTON);
}
/** @private */
onSwipe_() {
- // Prevent slideOut animation from playing.
- this.remove();
- this.tabsApi_.closeTab(this.tab_.id);
+ assert(this.tab_);
+ this.tabsApi_.closeTab(this.tab_.id, CloseTabAction.SWIPED_TO_CLOSE);
}
/**
@@ -254,11 +247,15 @@ export class TabElement extends CustomElement {
}
}
+ resetSwipe() {
+ this.tabSwiper_.reset();
+ }
+
/**
- * @param {boolean} dragging
+ * @param {boolean} isDragging
*/
- setDragging(dragging) {
- this.toggleAttribute('dragging_', dragging);
+ setDragging(isDragging) {
+ this.toggleAttribute('dragging_', isDragging);
}
/**
@@ -293,6 +290,18 @@ export class TabElement extends CustomElement {
animation.onfinish = () => {
resolve();
};
+
+ // TODO(crbug.com/1035678) By the next animation frame, the animation
+ // should start playing. By the time another animation frame happens,
+ // force play the animation if the animation has not yet begun. Remove
+ // if/when the Blink issue has been fixed.
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ if (animation.pending) {
+ animation.play();
+ }
+ });
+ });
});
}
@@ -300,8 +309,8 @@ export class TabElement extends CustomElement {
* @return {!Promise}
*/
slideOut() {
- if (!this.embedderApi_.isVisible() || this.tab_.pinned) {
- // There is no point in animating if the tab strip is hidden.
+ if (!this.embedderApi_.isVisible() || this.tab_.pinned ||
+ this.tabSwiper_.wasSwiping()) {
this.remove();
return Promise.resolve();
}
@@ -370,3 +379,11 @@ export class TabElement extends CustomElement {
}
customElements.define('tabstrip-tab', TabElement);
+
+/**
+ * @param {!Element} element
+ * @return {boolean}
+ */
+export function isTabElement(element) {
+ return element.tagName === 'TABSTRIP-TAB';
+}
diff --git a/chromium/chrome/browser/resources/tab_strip/tab_group.html b/chromium/chrome/browser/resources/tab_strip/tab_group.html
new file mode 100644
index 00000000000..77809c82201
--- /dev/null
+++ b/chromium/chrome/browser/resources/tab_strip/tab_group.html
@@ -0,0 +1,181 @@
+<style>
+:host {
+ --tabstrip-tab-group-title-height: 22px;
+ --tabstrip-tab-group-title-margin: var(--tabstrip-tab-spacing);
+}
+
+:host(:empty:not([dragging])) {
+ /* A tab group can temporarily become empty as a tab is being dragged out. */
+ display: none;
+}
+
+#tabGroup {
+ border-radius: 8px;
+ box-shadow: 0 0 0 1px rgb(var(--tabstrip-tab-group-color-rgb));
+ padding: var(--tabstrip-tab-spacing);
+}
+
+#chipContainer {
+ min-width: 100%;
+ width: 0;
+}
+
+#chip {
+ display: inline-block;
+ height: var(--tabstrip-tab-group-title-height);
+ margin-bottom: var(--tabstrip-tab-group-title-margin);
+ max-width: 100%;
+}
+
+#chip:focus {
+ outline: none;
+}
+
+#title {
+ background: rgb(var(--tabstrip-tab-group-color-rgb));
+ border-radius: 4px;
+ box-sizing: border-box;
+ color: rgb(var(--tabstrip-tab-group-text-color-rgb));
+ display: inline-block;
+ height: var(--tabstrip-tab-group-title-height);
+ line-height: var(--tabstrip-tab-group-title-height);
+ max-width: 100%;
+ overflow: hidden;
+ padding: 0 6px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+#title:empty {
+ border-radius: 50%;
+ height: 16px;
+ margin-top: 4px;
+ width: 16px;
+}
+
+#chip:focus #title {
+ box-shadow: 0 0 0 2px var(--tabstrip-focus-outline-color);
+ outline: none;
+}
+
+#tabs {
+ /* Cached CSS variable so the children could use them and override the
+ * original values. */
+ --ungrouped-tab-thumbnail-height: var(--tabstrip-tab-thumbnail-height);
+
+ display: flex;
+ min-width: fit-content;
+}
+
+:host ::slotted(tabstrip-tab) {
+ --tabstrip-tab-thumbnail-height: calc(
+ var(--ungrouped-tab-thumbnail-height) -
+ var(--tabstrip-tab-group-title-height) -
+ var(--tabstrip-tab-group-title-margin));
+ --tabstrip-tab-thumbnail-width: calc(
+ var(--tabstrip-tab-thumbnail-height) *
+ var(--tabstrip-tab-thumbnail-aspect-ratio));
+
+ /* Recalculate tab heights and widths off new thumbnail sizes. */
+ --tabstrip-tab-height: calc(var(--tabstrip-tab-title-height) +
+ var(--tabstrip-tab-thumbnail-height));
+ --tabstrip-tab-width: var(--tabstrip-tab-thumbnail-width);
+}
+
+:host([getting-drag-image_]) #dragImage {
+ /* Enough padding for the drop shadow on #tabGroup. The position of the
+ drag image is translated with the same value as the padding, to ensure
+ that the drag image stays in the same position as it would be without
+ padding. This is to ensure drag events do not get canceled as drag targets
+ move around. */
+ --drag-image-padding: 25px;
+ padding: var(--drag-image-padding);
+ transform: translate(
+ calc(var(--drag-image-x-direction, -1) * var(--drag-image-padding)),
+ calc(-1 * var(--drag-image-padding)));
+}
+
+:host-context([dir='rtl']):host([getting-drag-image_]) #dragImage {
+ --drag-image-x-direction: 1;
+}
+
+:host([getting-drag-image_]) #tabGroup {
+ background: var(--tabstrip-background-color);
+ border-radius: var(--tabstrip-tab-border-radius);
+ box-shadow: var(--tabstrip-tab-dragging-shadow);
+ height: var(--tabstrip-tab-height);
+ overflow: hidden;
+ transform: scale(var(--tabstrip-tab-drag-image-scale));
+}
+
+:host([getting-drag-image_]) ::slotted(tabstrip-tab) {
+ --tabstrip-tab-active-border-color: var(--tabstrip-tab-separator-color);
+}
+
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:first-child) {
+ /* Make sure the first tab is always above the other tabs. */
+ z-index: 4;
+}
+
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:nth-child(2)),
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:nth-child(3)),
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:nth-child(4)),
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:nth-child(5)) {
+ /* Add a negative margin to the 2nd - 5th tab to move them behind the first
+ tab to give an impression that they are a stacked group of tabs.
+ Transform cannot be used here since we also want the space the tabs
+ take up to be moved. */
+ margin-inline-start: calc(-1 * var(--tabstrip-tab-width));
+}
+
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:nth-child(2)) {
+ z-index: 3;
+}
+
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:nth-child(3)) {
+ z-index: 2;
+}
+
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:nth-child(4)) {
+ z-index: 1;
+}
+
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:nth-child(5)) {
+ padding: 0;
+ z-index: 0;
+}
+
+:host([getting-drag-image_]) ::slotted(tabstrip-tab:nth-child(n + 6)) {
+ display: none;
+}
+
+:host([dragging]) #dragPlaceholder {
+ background: var(--tabstrip-tab-background-color);
+ border-radius: var(--tabstrip-tab-border-radius);
+ height: var(--tabstrip-tab-height);
+ opacity: 0.5;
+ width: var(--tabstrip-tab-width);
+}
+
+:host([dragging]) #dragImage {
+ /* Position the actual drag image out of view so it is not visible. */
+ position: absolute;
+ top: 100vh;
+}
+</style>
+
+<div id="dragPlaceholder"></div>
+
+<div id="dragImage">
+ <div id="tabGroup">
+ <div id="chipContainer">
+ <div id="chip" draggable="true" tabindex="0" role="button"
+ aria-describedby="tabs">
+ <div id="title"></div>
+ </div>
+ </div>
+ <div id="tabs">
+ <slot></slot>
+ </div>
+ </div>
+</div>
diff --git a/chromium/chrome/browser/resources/tab_strip/tab_group.js b/chromium/chrome/browser/resources/tab_strip/tab_group.js
new file mode 100644
index 00000000000..e50abdbf55a
--- /dev/null
+++ b/chromium/chrome/browser/resources/tab_strip/tab_group.js
@@ -0,0 +1,101 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+
+import {CustomElement} from './custom_element.js';
+import {TabStripEmbedderProxy} from './tab_strip_embedder_proxy.js';
+import {TabGroupVisualData} from './tabs_api_proxy.js';
+
+export class TabGroupElement extends CustomElement {
+ static get template() {
+ return `{__html_template__}`;
+ }
+
+ constructor() {
+ super();
+
+ /** @private @const {!TabStripEmbedderProxy} */
+ this.embedderApi_ = TabStripEmbedderProxy.getInstance();
+
+ /** @private @const {!HTMLElement} */
+ this.chip_ = /** @type {!HTMLElement} */ (this.$('#chip'));
+ this.chip_.addEventListener('click', () => this.onClickChip_());
+ this.chip_.addEventListener(
+ 'keydown', e => this.onKeydownChip_(/** @type {!KeyboardEvent} */ (e)));
+ }
+
+ /** @return {!HTMLElement} */
+ getDragImage() {
+ return /** @type {!HTMLElement} */ (this.$('#dragImage'));
+ }
+
+ /** @private */
+ onClickChip_() {
+ if (!this.dataset.groupId) {
+ return;
+ }
+
+ const boundingBox = this.$('#chip').getBoundingClientRect();
+ this.embedderApi_.showEditDialogForGroup(
+ this.dataset.groupId, boundingBox.left, boundingBox.top,
+ boundingBox.width, boundingBox.height);
+ }
+
+ /**
+ * @param {!KeyboardEvent} event
+ * @private
+ */
+ onKeydownChip_(event) {
+ if (event.key === 'Enter' || event.key === ' ') {
+ this.onClickChip_();
+ }
+ }
+
+ /** @param {boolean} enabled */
+ setDragging(enabled) {
+ // Since the draggable target is the #chip, if the #chip moves and is no
+ // longer under the pointer while the dragstart event is happening, the drag
+ // will get canceled. This is unfortunately the behavior of the native drag
+ // and drop API. The workaround is to have two different attributes: one
+ // to get the drag image and start the drag event while keeping #chip in
+ // place, and another to update the placeholder to take the place of where
+ // the #chip would be.
+ this.toggleAttribute('getting-drag-image_', enabled);
+ requestAnimationFrame(() => {
+ this.toggleAttribute('dragging', enabled);
+ });
+ }
+
+ /**
+ * @param {!TabGroupVisualData} visualData
+ */
+ updateVisuals(visualData) {
+ this.$('#title').innerText = visualData.title;
+ this.style.setProperty('--tabstrip-tab-group-color-rgb', visualData.color);
+ this.style.setProperty(
+ '--tabstrip-tab-group-text-color-rgb', visualData.textColor);
+
+ // Content strings are empty for the label and are instead replaced by
+ // the aria-describedby attribute on the chip.
+ if (visualData.title) {
+ this.chip_.setAttribute(
+ 'aria-label',
+ loadTimeData.getStringF('namedGroupLabel', visualData.title, ''));
+ } else {
+ this.chip_.setAttribute(
+ 'aria-label', loadTimeData.getStringF('unnamedGroupLabel', ''));
+ }
+ }
+}
+
+customElements.define('tabstrip-tab-group', TabGroupElement);
+
+/**
+ * @param {!Element} element
+ * @return {boolean}
+ */
+export function isTabGroupElement(element) {
+ return element.tagName === 'TABSTRIP-TAB-GROUP';
+}
diff --git a/chromium/chrome/browser/resources/tab_strip/tab_list.html b/chromium/chrome/browser/resources/tab_strip/tab_list.html
index 3d256ce11f2..12be60a5f39 100644
--- a/chromium/chrome/browser/resources/tab_strip/tab_list.html
+++ b/chromium/chrome/browser/resources/tab_strip/tab_list.html
@@ -4,6 +4,18 @@
var(--tabstrip-tab-thumbnail-height));
--tabstrip-tab-width: var(--tabstrip-tab-thumbnail-width);
--tabstrip-tab-spacing: 16px;
+ --tabstrip-tab-dragging-shadow:
+ 0 2px 3px 0 rgba(var(--google-grey-800-rgb), .3),
+ 0 6px 10px 4px rgba(var(--google-grey-800-rgb), .15);
+
+<if expr="not chromeos">
+ --tabstrip-tab-drag-image-scale: 1.1;
+</if>
+<if expr="chromeos">
+ /* ChromeOS scales drag images by 1.2, so this variable multiplied by
+ * 1.2 should be around 1.1. */
+ --tabstrip-tab-drag-image-scale: calc(1.1 / 1.2);
+</if>
background: var(--tabstrip-background-color);
box-sizing: border-box;
@@ -14,7 +26,17 @@
width: 100%;
}
- #pinnedTabsContainer {
+ #tabs {
+ display: flex;
+ min-width: fit-content;
+ overflow: hidden;
+ padding-inline-end: calc(
+ var(--tabstrip-new-tab-button-width) +
+ var(--tabstrip-new-tab-button-margin));
+ width: 100%;
+ }
+
+ #pinnedTabs {
/* 3 pinned tabs should fit in the same space vertically as 1 unpinned
* tab. 20px is subtracted from the height of an unpinned tab as there
* are two 10px gaps to separate each of the 3 pinned tabs. */
@@ -25,21 +47,83 @@
grid-auto-flow: column;
grid-gap: 10px;
grid-template-rows: repeat(3, var(--tabstrip-pinned-tab-size));
- padding: var(--tabstrip-tab-spacing);
+ padding-block-end: var(--tabstrip-tab-list-vertical-padding);
+ padding-block-start: var(--tabstrip-tab-list-vertical-padding);
padding-inline-end: 0;
+ padding-inline-start: var(--tabstrip-tab-spacing);
}
- #pinnedTabsContainer:empty {
+ #pinnedTabs:empty {
display: none;
}
- #tabsContainer {
+ #unpinnedTabs {
display: flex;
min-width: fit-content;
- overflow: hidden;
- padding: var(--tabstrip-tab-spacing);
+ padding-block-end: var(--tabstrip-tab-list-vertical-padding);
+ padding-block-start: var(--tabstrip-tab-list-vertical-padding);
padding-inline-end: 0;
- width: 100%;
+ padding-inline-start: var(--tabstrip-tab-spacing);
+ }
+
+ tabstrip-tab-group {
+ --tabstrip-tab-spacing: 8px;
+ }
+
+ tabstrip-tab-group:not([dragging]) {
+ margin-block-end: calc(-1 * var(--tabstrip-tab-spacing));
+ margin-block-start: calc(-1 * var(--tabstrip-tab-spacing));
+ margin-inline-end: var(--tabstrip-tab-spacing);
+ margin-inline-start: 0;
+ }
+
+ tabstrip-tab-group tabstrip-tab:last-child {
+ --tabstrip-tab-spacing: 0px;
+ }
+
+ tabstrip-tab + tabstrip-tab-group:not([dragging]) {
+ margin-inline-start: calc(-1 * var(--tabstrip-tab-spacing));
+ }
+
+ tabstrip-tab-group[dragging] {
+ margin-block-end: 0;
+ margin-block-start: 0;
+ margin-inline-end: 16px;
+ margin-inline-start: 0;
+ }
+
+ #newTabButton {
+ --cr-icon-button-size: var(--tabstrip-new-tab-button-width);
+ --cr-icon-button-icon-size: 32px;
+ --cr-icon-button-fill-color: var(--tabstrip-tab-text-color);
+ --cr-icon-button-margin-end: var(--tabstrip-new-tab-button-margin);
+ --cr-icon-button-margin-start: 0px;
+ background: var(--tabstrip-tab-background-color);
+ border-radius: 50%;
+ box-shadow: 0 1px 3px 0 rgba(var(--google-grey-800-rgb), .3),
+ 0 4px 8px 3px rgba(var(--google-grey-800-rgb), .15);
+ height: var(--tabstrip-new-tab-button-width);
+ margin: 0;
+ position: fixed;
+ right: var(--tabstrip-new-tab-button-margin);
+ top: calc((var(--tabstrip-tab-height) / 2)
+ + var(--tabstrip-tab-list-vertical-padding));
+ transform: translateY(-50%);
+ width: var(--tabstrip-new-tab-button-width);
+ }
+
+ :host-context([dir='rtl']) #newTabButton {
+ left: var(--tabstrip-new-tab-button-margin);
+ right: auto;
+ }
+
+ #dropPlaceholder {
+ background: var(--tabstrip-tab-background-color);
+ border-radius: var(--tabstrip-tab-border-radius);
+ height: var(--tabstrip-tab-height);
+ margin-inline-end: var(--tabstrip-tab-spacing);
+ opacity: 0.5;
+ width: var(--tabstrip-tab-width);
}
#demoOptions {
@@ -51,8 +135,14 @@
}
</style>
-<div id="pinnedTabsContainer"></div>
-<div id="tabsContainer"></div>
+<div id="tabs">
+ <div id="pinnedTabs"></div>
+ <div id="unpinnedTabs"></div>
+</div>
+<cr-icon-button aria-label="$i18n{newTab}"
+ id="newTabButton"
+ iron-icon="cr:add">
+</cr-icon-button>
<div id="demoOptions">
<label>
diff --git a/chromium/chrome/browser/resources/tab_strip/tab_list.js b/chromium/chrome/browser/resources/tab_strip/tab_list.js
index 15169e66d42..08ac72db837 100644
--- a/chromium/chrome/browser/resources/tab_strip/tab_list.js
+++ b/chromium/chrome/browser/resources/tab_strip/tab_list.js
@@ -4,17 +4,22 @@
import './strings.m.js';
import './tab.js';
+import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
+import 'chrome://resources/cr_elements/icons.m.js';
import {assert} from 'chrome://resources/js/assert.m.js';
-import {addWebUIListener} from 'chrome://resources/js/cr.m.js';
+import {addWebUIListener, removeWebUIListener, WebUIListener} from 'chrome://resources/js/cr.m.js';
import {FocusOutlineManager} from 'chrome://resources/js/cr/ui/focus_outline_manager.m.js';
import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {isRTL} from 'chrome://resources/js/util.m.js';
import {CustomElement} from './custom_element.js';
+import {DragManager, DragManagerDelegate} from './drag_manager.js';
import {TabElement} from './tab.js';
+import {isTabGroupElement, TabGroupElement} from './tab_group.js';
import {TabStripEmbedderProxy} from './tab_strip_embedder_proxy.js';
import {tabStripOptions} from './tab_strip_options.js';
-import {TabData, TabsApiProxy} from './tabs_api_proxy.js';
+import {TabData, TabGroupVisualData, TabsApiProxy} from './tabs_api_proxy.js';
/**
* The amount of padding to leave between the edge of the screen and the active
@@ -37,17 +42,12 @@ export function setScrollAnimationEnabledForTesting(enabled) {
*/
const LayoutVariable = {
VIEWPORT_WIDTH: '--tabstrip-viewport-width',
+ NEW_TAB_BUTTON_MARGIN: '--tabstrip-new-tab-button-margin',
+ NEW_TAB_BUTTON_WIDTH: '--tabstrip-new-tab-button-width',
TAB_WIDTH: '--tabstrip-tab-thumbnail-width',
};
-/**
- * @param {!Element} element
- * @return {boolean}
- */
-function isTabElement(element) {
- return element.tagName === 'TABSTRIP-TAB';
-}
-
+/** @implements {DragManagerDelegate} */
class TabListElement extends CustomElement {
static get template() {
return `{__html_template__}`;
@@ -77,11 +77,15 @@ class TabListElement extends CustomElement {
this.onDocumentVisibilityChange_();
/**
- * The TabElement that is currently being dragged.
- * @private {!TabElement|undefined}
+ * The element that is currently being dragged.
+ * @private {!TabElement|!TabGroupElement|undefined}
*/
this.draggedItem_;
+ /** @private {!Element} */
+ this.dropPlaceholder_ = document.createElement('div');
+ this.dropPlaceholder_.id = 'dropPlaceholder';
+
/** @private @const {!FocusOutlineManager} */
this.focusOutlineManager_ = FocusOutlineManager.forDocument(document);
@@ -111,9 +115,11 @@ class TabListElement extends CustomElement {
this.activatingTabIdTimestamp_;
/** @private {!Element} */
- this.pinnedTabsContainerElement_ =
- /** @type {!Element} */ (
- this.shadowRoot.querySelector('#pinnedTabsContainer'));
+ this.newTabButtonElement_ =
+ /** @type {!Element} */ (this.$('#newTabButton'));
+
+ /** @private {!Element} */
+ this.pinnedTabsElement_ = /** @type {!Element} */ (this.$('#pinnedTabs'));
/** @private {!TabStripEmbedderProxy} */
this.tabStripEmbedderProxy_ = TabStripEmbedderProxy.getInstance();
@@ -122,9 +128,11 @@ class TabListElement extends CustomElement {
this.tabsApi_ = TabsApiProxy.getInstance();
/** @private {!Element} */
- this.tabsContainerElement_ =
- /** @type {!Element} */ (
- this.shadowRoot.querySelector('#tabsContainer'));
+ this.unpinnedTabsElement_ =
+ /** @type {!Element} */ (this.$('#unpinnedTabs'));
+
+ /** @private {!Array<!WebUIListener>} */
+ this.webUIListeners_ = [];
/** @private {!Function} */
this.windowBlurListener_ = () => this.onWindowBlur_();
@@ -132,33 +140,35 @@ class TabListElement extends CustomElement {
/** @private {!Function} */
this.contextMenuListener_ = e => this.onContextMenu_(e);
- addWebUIListener(
+ this.addWebUIListener_(
'layout-changed', layout => this.applyCSSDictionary_(layout));
- addWebUIListener('theme-changed', () => this.fetchAndUpdateColors_());
+ this.addWebUIListener_('theme-changed', () => {
+ this.fetchAndUpdateColors_();
+ this.fetchAndUpdateGroupData_();
+ });
this.tabStripEmbedderProxy_.observeThemeChanges();
- addWebUIListener(
+ this.addWebUIListener_(
'tab-thumbnail-updated', this.tabThumbnailUpdated_.bind(this));
- this.addEventListener(
- 'dragstart', (e) => this.onDragStart_(/** @type {!DragEvent} */ (e)));
- this.addEventListener(
- 'dragend', (e) => this.onDragEnd_(/** @type {!DragEvent} */ (e)));
- this.addEventListener(
- 'dragover', (e) => this.onDragOver_(/** @type {!DragEvent} */ (e)));
-
document.addEventListener('contextmenu', this.contextMenuListener_);
document.addEventListener(
'visibilitychange', this.documentVisibilityChangeListener_);
- addWebUIListener(
+ this.addWebUIListener_(
'received-keyboard-focus', () => this.onReceivedKeyboardFocus_());
window.addEventListener('blur', this.windowBlurListener_);
+ this.newTabButtonElement_.addEventListener('click', () => {
+ this.tabsApi_.createNewTab();
+ });
+
+ const dragManager = new DragManager(this);
+ dragManager.startObserving();
+
if (loadTimeData.getBoolean('showDemoOptions')) {
- this.shadowRoot.querySelector('#demoOptions').style.display = 'block';
+ this.$('#demoOptions').style.display = 'block';
- const autoCloseCheckbox =
- this.shadowRoot.querySelector('#autoCloseCheckbox');
+ const autoCloseCheckbox = this.$('#autoCloseCheckbox');
autoCloseCheckbox.checked = tabStripOptions.autoCloseEnabled;
autoCloseCheckbox.addEventListener('change', () => {
tabStripOptions.autoCloseEnabled = autoCloseCheckbox.checked;
@@ -175,6 +185,15 @@ class TabListElement extends CustomElement {
}
/**
+ * @param {string} eventName
+ * @param {!Function} callback
+ * @private
+ */
+ addWebUIListener_(eventName, callback) {
+ this.webUIListeners_.push(addWebUIListener(eventName, callback));
+ }
+
+ /**
* @param {number} scrollBy
* @private
*/
@@ -240,18 +259,37 @@ class TabListElement extends CustomElement {
const createTabsStartTimestamp = Date.now();
tabs.forEach(tab => this.onTabCreated_(tab));
+ this.fetchAndUpdateGroupData_();
this.tabStripEmbedderProxy_.reportTabCreationDuration(
tabs.length, Date.now() - createTabsStartTimestamp);
- addWebUIListener('tab-created', tab => this.onTabCreated_(tab));
- addWebUIListener(
+ this.addWebUIListener_('tab-created', tab => this.onTabCreated_(tab));
+ this.addWebUIListener_(
'tab-moved', (tabId, newIndex) => this.onTabMoved_(tabId, newIndex));
- addWebUIListener('tab-removed', tabId => this.onTabRemoved_(tabId));
- addWebUIListener(
+ this.addWebUIListener_('tab-removed', tabId => this.onTabRemoved_(tabId));
+ this.addWebUIListener_(
'tab-replaced', (oldId, newId) => this.onTabReplaced_(oldId, newId));
- addWebUIListener('tab-updated', tab => this.onTabUpdated_(tab));
- addWebUIListener(
+ this.addWebUIListener_('tab-updated', tab => this.onTabUpdated_(tab));
+ this.addWebUIListener_(
'tab-active-changed', tabId => this.onTabActivated_(tabId));
+ this.addWebUIListener_(
+ 'tab-close-cancelled', tabId => this.onTabCloseCancelled_(tabId));
+ this.addWebUIListener_(
+ 'tab-group-state-changed',
+ (tabId, index, groupId) =>
+ this.onTabGroupStateChanged_(tabId, index, groupId));
+ this.addWebUIListener_(
+ 'tab-group-closed', groupId => this.onTabGroupClosed_(groupId));
+ this.addWebUIListener_(
+ 'tab-group-moved',
+ (groupId, index) => this.onTabGroupMoved_(groupId, index));
+ this.addWebUIListener_(
+ 'tab-group-visuals-changed',
+ (groupId, visualData) =>
+ this.onTabGroupVisualsChanged_(groupId, visualData));
+ this.addWebUIListener_(
+ 'tab-group-id-replaced',
+ (oldId, newId) => this.onTabGroupIdReplaced_(oldId, newId));
});
}
@@ -260,6 +298,7 @@ class TabListElement extends CustomElement {
document.removeEventListener(
'visibilitychange', this.documentVisibilityChangeListener_);
window.removeEventListener('blur', this.windowBlurListener_);
+ this.webUIListeners_.forEach(removeWebUIListener);
}
/**
@@ -283,7 +322,17 @@ class TabListElement extends CustomElement {
*/
findTabElement_(tabId) {
return /** @type {?TabElement} */ (
- this.shadowRoot.querySelector(`tabstrip-tab[data-tab-id="${tabId}"]`));
+ this.$(`tabstrip-tab[data-tab-id="${tabId}"]`));
+ }
+
+ /**
+ * @param {string} groupId
+ * @return {?TabGroupElement}
+ * @private
+ */
+ findTabGroupElement_(groupId) {
+ return /** @type {?TabGroupElement} */ (
+ this.$(`tabstrip-tab-group[data-group-id="${groupId}"]`));
}
/** @private */
@@ -292,49 +341,39 @@ class TabListElement extends CustomElement {
colors => this.applyCSSDictionary_(colors));
}
+ /** @private */
+ fetchAndUpdateGroupData_() {
+ const tabGroupElements = this.$all('tabstrip-tab-group');
+ this.tabsApi_.getGroupVisualData().then(data => {
+ tabGroupElements.forEach(tabGroupElement => {
+ tabGroupElement.updateVisuals(
+ assert(data[tabGroupElement.dataset.groupId]));
+ });
+ });
+ }
+
/**
* @return {?TabElement}
* @private
*/
getActiveTab_() {
- return /** @type {?TabElement} */ (
- this.shadowRoot.querySelector('tabstrip-tab[active]'));
+ return /** @type {?TabElement} */ (this.$('tabstrip-tab[active]'));
}
/**
- * @param {!LayoutVariable} variable
- * @return {number} in pixels
+ * @param {!TabElement} tabElement
+ * @return {number}
*/
- getLayoutVariable_(variable) {
- return parseInt(this.style.getPropertyValue(variable), 10);
+ getIndexOfTab(tabElement) {
+ return Array.prototype.indexOf.call(this.$all('tabstrip-tab'), tabElement);
}
/**
- * @param {!TabElement} tabElement
- * @param {number} index
- * @private
+ * @param {!LayoutVariable} variable
+ * @return {number} in pixels
*/
- insertTabOrMoveTo_(tabElement, index) {
- const isInserting = !tabElement.isConnected;
-
- // Remove the tabElement if it already exists in the DOM
- tabElement.remove();
-
- if (tabElement.tab && tabElement.tab.pinned) {
- this.pinnedTabsContainerElement_.insertBefore(
- tabElement, this.pinnedTabsContainerElement_.childNodes[index]);
- } else {
- // Pinned tabs are in their own container, so the index of non-pinned
- // tabs need to be offset by the number of pinned tabs
- const offsetIndex =
- index - this.pinnedTabsContainerElement_.childElementCount;
- this.tabsContainerElement_.insertBefore(
- tabElement, this.tabsContainerElement_.childNodes[offsetIndex]);
- }
-
- if (isInserting) {
- this.updateThumbnailTrackStatus_(tabElement);
- }
+ getLayoutVariable_(variable) {
+ return parseInt(this.style.getPropertyValue(variable), 10);
}
/**
@@ -352,66 +391,17 @@ class TabListElement extends CustomElement {
if (!this.tabStripEmbedderProxy_.isVisible()) {
this.scrollToActiveTab_();
}
- Array.from(this.tabsContainerElement_.children)
- .forEach((tabElement) => this.updateThumbnailTrackStatus_(tabElement));
- }
-
- /**
- * @param {!DragEvent} event
- * @private
- */
- onDragEnd_(event) {
- if (!this.draggedItem_) {
- return;
- }
- this.draggedItem_.setDragging(false);
- this.draggedItem_ = undefined;
- }
-
- /**
- * @param {!DragEvent} event
- * @private
- */
- onDragOver_(event) {
- event.preventDefault();
- const dragOverItem = event.path.find((pathItem) => {
- return pathItem !== this.draggedItem_ && isTabElement(pathItem);
+ this.unpinnedTabsElement_.childNodes.forEach(element => {
+ if (isTabGroupElement(/** @type {!Element} */ (element))) {
+ element.childNodes.forEach(
+ tabElement => this.updateThumbnailTrackStatus_(
+ /** @type {!TabElement} */ (tabElement)));
+ } else {
+ this.updateThumbnailTrackStatus_(
+ /** @type {!TabElement} */ (element));
+ }
});
-
- if (!dragOverItem || !this.draggedItem_ ||
- dragOverItem.tab.pinned !== this.draggedItem_.tab.pinned) {
- return;
- }
-
- event.dataTransfer.dropEffect = 'move';
-
- let dragOverIndex =
- Array.from(dragOverItem.parentNode.children).indexOf(dragOverItem);
- if (!this.draggedItem_.tab.pinned) {
- dragOverIndex += this.pinnedTabsContainerElement_.childElementCount;
- }
-
- this.tabsApi_.moveTab(this.draggedItem_.tab.id, dragOverIndex);
- }
-
- /**
- * @param {!DragEvent} event
- * @private
- */
- onDragStart_(event) {
- const draggedItem = event.path[0];
- if (!isTabElement(draggedItem)) {
- return;
- }
-
- this.draggedItem_ = /** @type {!TabElement} */ (draggedItem);
- this.draggedItem_.setDragging(true);
- event.dataTransfer.effectAllowed = 'move';
- event.dataTransfer.setDragImage(
- this.draggedItem_.getDragImage(),
- event.pageX - this.draggedItem_.offsetLeft,
- event.pageY - this.draggedItem_.offsetTop);
}
/** @private */
@@ -420,7 +410,7 @@ class TabListElement extends CustomElement {
// document. When the tab strip first gains keyboard focus, no such event
// exists yet, so the outline needs to be explicitly set to visible.
this.focusOutlineManager_.visible = true;
- this.shadowRoot.querySelector('tabstrip-tab').focus();
+ this.$('tabstrip-tab').focus();
}
/**
@@ -439,13 +429,12 @@ class TabListElement extends CustomElement {
// have updated a Tab to have an active state. For example, if a
// tab is created with an already active state, there may be 2 active
// TabElements: the newly created tab and the previously active tab.
- this.shadowRoot.querySelectorAll('tabstrip-tab[active]')
- .forEach((previouslyActiveTab) => {
- if (previouslyActiveTab.tab.id !== tabId) {
- previouslyActiveTab.tab = /** @type {!TabData} */ (
- Object.assign({}, previouslyActiveTab.tab, {active: false}));
- }
- });
+ this.$all('tabstrip-tab[active]').forEach((previouslyActiveTab) => {
+ if (previouslyActiveTab.tab.id !== tabId) {
+ previouslyActiveTab.tab = /** @type {!TabData} */ (
+ Object.assign({}, previouslyActiveTab.tab, {active: false}));
+ }
+ });
const newlyActiveTab = this.findTabElement_(tabId);
if (newlyActiveTab) {
@@ -472,12 +461,32 @@ class TabListElement extends CustomElement {
}
/**
+ * @param {number} id
+ * @private
+ */
+ onTabCloseCancelled_(id) {
+ const tabElement = this.findTabElement_(id);
+ if (!tabElement) {
+ return;
+ }
+ tabElement.resetSwipe();
+ }
+
+ /**
* @param {!TabData} tab
* @private
*/
onTabCreated_(tab) {
+ const droppedTabElement = this.findTabElement_(tab.id);
+ if (droppedTabElement) {
+ droppedTabElement.tab = tab;
+ droppedTabElement.setDragging(false);
+ this.tabsApi_.setThumbnailTracked(tab.id, true);
+ return;
+ }
+
const tabElement = this.createTabElement_(tab);
- this.insertTabOrMoveTo_(tabElement, tab.index);
+ this.placeTabElement(tabElement, tab.index, tab.pinned, tab.groupId);
this.addAnimationPromise_(tabElement.slideIn());
if (tab.active) {
this.scrollToTab_(tabElement);
@@ -485,6 +494,66 @@ class TabListElement extends CustomElement {
}
/**
+ * @param {string} groupId
+ * @private
+ */
+ onTabGroupClosed_(groupId) {
+ const tabGroupElement = this.findTabGroupElement_(groupId);
+ if (!tabGroupElement) {
+ return;
+ }
+ tabGroupElement.remove();
+ }
+
+ /**
+ * @param {string} groupId
+ * @param {number} index
+ * @private
+ */
+ onTabGroupMoved_(groupId, index) {
+ const tabGroupElement = this.findTabGroupElement_(groupId);
+ if (!tabGroupElement) {
+ return;
+ }
+ this.placeTabGroupElement(tabGroupElement, index);
+ }
+
+ /**
+ * @param {string} oldId
+ * @param {string} newId
+ * @private
+ */
+ onTabGroupIdReplaced_(oldId, newId) {
+ const tabGroupElement = this.findTabGroupElement_(oldId);
+ if (tabGroupElement) {
+ tabGroupElement.dataset.groupId = newId;
+ }
+ }
+
+ /**
+ * @param {number} tabId
+ * @param {number} index
+ * @param {string} groupId
+ * @private
+ */
+ onTabGroupStateChanged_(tabId, index, groupId) {
+ const tabElement = this.findTabElement_(tabId);
+ tabElement.tab = /** @type {!TabData} */ (
+ Object.assign({}, tabElement.tab, {groupId: groupId}));
+ this.placeTabElement(tabElement, index, false, groupId);
+ }
+
+ /**
+ * @param {string} groupId
+ * @param {!TabGroupVisualData} visualData
+ * @private
+ */
+ onTabGroupVisualsChanged_(groupId, visualData) {
+ const tabGroupElement = this.findTabGroupElement_(groupId);
+ tabGroupElement.updateVisuals(visualData);
+ }
+
+ /**
* @param {number} tabId
* @param {number} newIndex
* @private
@@ -492,7 +561,8 @@ class TabListElement extends CustomElement {
onTabMoved_(tabId, newIndex) {
const movedTab = this.findTabElement_(tabId);
if (movedTab) {
- this.insertTabOrMoveTo_(movedTab, newIndex);
+ this.placeTabElement(
+ movedTab, newIndex, movedTab.tab.pinned, movedTab.tab.groupId);
if (movedTab.tab.active) {
this.scrollToTab_(movedTab);
}
@@ -541,7 +611,7 @@ class TabListElement extends CustomElement {
if (previousTab.pinned !== tab.pinned) {
// If the tab is being pinned or unpinned, we need to move it to its new
// location
- this.insertTabOrMoveTo_(tabElement, tab.index);
+ this.placeTabElement(tabElement, tab.index, tab.pinned, tab.groupId);
if (tab.active) {
this.scrollToTab_(tabElement);
}
@@ -559,6 +629,82 @@ class TabListElement extends CustomElement {
}
}
+ /**
+ * @param {!TabElement} element
+ * @param {number} index
+ * @param {boolean} pinned
+ * @param {string=} groupId
+ */
+ placeTabElement(element, index, pinned, groupId) {
+ const isInserting = !element.isConnected;
+
+ // Remove the element if it already exists in the DOM.
+ element.remove();
+
+ if (pinned) {
+ this.pinnedTabsElement_.insertBefore(
+ element, this.pinnedTabsElement_.childNodes[index]);
+ } else {
+ let elementToInsert = element;
+ let elementAtIndex = this.$all('tabstrip-tab').item(index);
+ let parentElement = this.unpinnedTabsElement_;
+
+ if (groupId) {
+ let tabGroupElement = this.findTabGroupElement_(groupId);
+ if (tabGroupElement) {
+ // If a TabGroupElement already exists, add the TabElement to it.
+ parentElement = tabGroupElement;
+ } else {
+ // If a TabGroupElement does not exist, create one and add the
+ // TabGroupElement into the DOM.
+ tabGroupElement = document.createElement('tabstrip-tab-group');
+ tabGroupElement.setAttribute('data-group-id', groupId);
+ tabGroupElement.appendChild(element);
+ elementToInsert = tabGroupElement;
+ }
+ }
+
+ if (elementAtIndex && elementAtIndex.parentElement &&
+ isTabGroupElement(elementAtIndex.parentElement) &&
+ (elementAtIndex.previousElementSibling === null &&
+ elementAtIndex.tab.groupId !== groupId)) {
+ // If the element at the model index is in a group, and the group is
+ // different from the new tab's group, and is the first element in its
+ // group, insert the new element before its TabGroupElement. If a
+ // TabElement is being sandwiched between two TabElements in a group, it
+ // can be assumed that the tab will eventually be inserted into the
+ // group as well.
+ elementAtIndex = elementAtIndex.parentElement;
+ }
+
+ if (elementAtIndex && elementAtIndex.parentElement === parentElement) {
+ parentElement.insertBefore(elementToInsert, elementAtIndex);
+ } else {
+ parentElement.appendChild(elementToInsert);
+ }
+ }
+
+ if (isInserting) {
+ this.updateThumbnailTrackStatus_(element);
+ }
+ }
+
+ /**
+ * @param {!TabGroupElement} element
+ * @param {number} index
+ */
+ placeTabGroupElement(element, index) {
+ element.remove();
+
+ let elementAtIndex = this.$all('tabstrip-tab')[index];
+ if (elementAtIndex && elementAtIndex.parentElement &&
+ isTabGroupElement(elementAtIndex.parentElement)) {
+ elementAtIndex = elementAtIndex.parentElement;
+ }
+
+ this.unpinnedTabsElement_.insertBefore(element, elementAtIndex);
+ }
+
/** @private */
scrollToActiveTab_() {
const activeTab = this.getActiveTab_();
@@ -574,24 +720,39 @@ class TabListElement extends CustomElement {
* @private
*/
scrollToTab_(tabElement) {
- const tabElementLeft = tabElement.getBoundingClientRect().left;
+ const tabElementWidth = this.getLayoutVariable_(LayoutVariable.TAB_WIDTH);
+ const tabElementRect = tabElement.getBoundingClientRect();
+ // In RTL languages, the TabElement's scale animation scales from right to
+ // left. Therefore, the value of its getBoundingClientRect().left may not be
+ // accurate of its final rendered size because the element may not have
+ // fully scaled to the left yet.
+ const tabElementLeft =
+ isRTL() ? tabElementRect.right - tabElementWidth : tabElementRect.left;
+
+ const newTabButtonSpace =
+ this.getLayoutVariable_(LayoutVariable.NEW_TAB_BUTTON_WIDTH) +
+ this.getLayoutVariable_(LayoutVariable.NEW_TAB_BUTTON_MARGIN);
+ const leftBoundary =
+ isRTL() ? SCROLL_PADDING + newTabButtonSpace : SCROLL_PADDING;
let scrollBy = 0;
- if (tabElementLeft === SCROLL_PADDING) {
+ if (tabElementLeft === leftBoundary) {
// Perfectly aligned to the left.
return;
- } else if (tabElementLeft < SCROLL_PADDING) {
- // If the element's left is to the left of the visible screen, scroll
- // such that the element's left edge is aligned with the screen's edge.
- scrollBy = tabElementLeft - SCROLL_PADDING;
+ } else if (tabElementLeft < leftBoundary) {
+ // If the element's left is to the left of the left boundary, scroll
+ // such that the element's left edge is aligned with the left boundary.
+ scrollBy = tabElementLeft - leftBoundary;
} else {
- const tabElementWidth = this.getLayoutVariable_(LayoutVariable.TAB_WIDTH);
const tabElementRight = tabElementLeft + tabElementWidth;
- const viewportWidth =
- this.getLayoutVariable_(LayoutVariable.VIEWPORT_WIDTH);
-
- if (tabElementRight + SCROLL_PADDING > viewportWidth) {
- scrollBy = (tabElementRight + SCROLL_PADDING) - viewportWidth;
+ const rightBoundary = isRTL() ?
+ this.getLayoutVariable_(LayoutVariable.VIEWPORT_WIDTH) -
+ SCROLL_PADDING :
+ this.getLayoutVariable_(LayoutVariable.VIEWPORT_WIDTH) -
+ SCROLL_PADDING - newTabButtonSpace;
+
+ if (tabElementRight > rightBoundary) {
+ scrollBy = (tabElementRight) - rightBoundary;
} else {
// Perfectly aligned to the right.
return;
@@ -618,6 +779,10 @@ class TabListElement extends CustomElement {
* @private
*/
updateThumbnailTrackStatus_(tabElement) {
+ if (!tabElement.tab) {
+ return;
+ }
+
if (this.tabStripEmbedderProxy_.isVisible() && !tabElement.tab.pinned) {
// If the tab strip is visible and the tab is not pinned, let the
// IntersectionObserver start observing the TabElement to automatically
diff --git a/chromium/chrome/browser/resources/tab_strip/tab_strip.html b/chromium/chrome/browser/resources/tab_strip/tab_strip.html
index 88977577baf..8b4037b1023 100644
--- a/chromium/chrome/browser/resources/tab_strip/tab_strip.html
+++ b/chromium/chrome/browser/resources/tab_strip/tab_strip.html
@@ -29,10 +29,46 @@
padding: 0;
width: 100%;
}
+
+<if expr="not chromeos">
+ /* ChromeOS is the only platform that can be guaranteed to have overlay
+ * scrollbars, so override the styles of native scrollbars for other
+ * platforms. */
+ html ::-webkit-scrollbar {
+ display: block;
+ height: 4px;
+ }
+
+ ::-webkit-scrollbar-track,
+ ::-webkit-scrollbar,
+ ::-webkit-scrollbar-track-piece {
+ background: var(--tabstrip-background-color);
+ }
+
+ ::-webkit-scrollbar {
+ display: none;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ background: rgba(var(--tabstrip-scrollbar-thumb-color-rgb), .7);
+ border-inline-end: solid 16px var(--tabstrip-background-color);
+ border-inline-start: solid 16px var(--tabstrip-background-color);
+ }
+</if>
</style>
</head>
<body>
- <tabstrip-tab-list role="tablist"></tabstrip-tab-list>
+ <!--
+ The CSS variables defined inside of TabList's style tag are also
+ made available through TabList's class object in JavaScript.
+ -->
+ <tabstrip-tab-list
+ role="tablist"
+ style="
+ --tabstrip-new-tab-button-margin: 24px;
+ --tabstrip-new-tab-button-width: 50px;
+ ">
+ </tabstrip-tab-list>
<script src="tab_list.js" type="module"></script>
</body>
</html>
diff --git a/chromium/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js b/chromium/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js
index 159a688c32e..898858e782c 100644
--- a/chromium/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js
+++ b/chromium/chrome/browser/resources/tab_strip/tab_strip_embedder_proxy.js
@@ -31,6 +31,19 @@ export class TabStripEmbedderProxy {
}
/**
+ * @param {string} groupId
+ * @param {number} locationX
+ * @param {number} locationY
+ * @param {number} width
+ * @param {number} height
+ */
+ showEditDialogForGroup(groupId, locationX, locationY, width, height) {
+ chrome.send(
+ 'showEditDialogForGroup',
+ [groupId, locationX, locationY, width, height]);
+ }
+
+ /**
* @param {number} tabId
* @param {number} locationX
* @param {number} locationY
diff --git a/chromium/chrome/browser/resources/tab_strip/tab_strip_resources.grd b/chromium/chrome/browser/resources/tab_strip/tab_strip_resources.grd
index c125f52a5dd..fe3ddc57f85 100644
--- a/chromium/chrome/browser/resources/tab_strip/tab_strip_resources.grd
+++ b/chromium/chrome/browser/resources/tab_strip/tab_strip_resources.grd
@@ -16,7 +16,8 @@
name="IDR_TAB_STRIP_HTML"
file="tab_strip.html"
type="chrome_html"
- compress="gzip"/>
+ compress="gzip"
+ preprocess="true"/>
<structure
name="IDR_TAB_STRIP_TABS_API_PROXY_JS"
file="tabs_api_proxy.js"
@@ -28,11 +29,18 @@
type="chrome_html"
compress="gzip"/>
<structure
+ name="IDR_TAB_STRIP_TAB_GROUP_JS"
+ file="${root_gen_dir}/chrome/browser/resources/tab_strip/tab_group.js"
+ use_base_dir="false"
+ type="chrome_html"
+ compress="gzip"/>
+ <structure
name="IDR_TAB_STRIP_TAB_LIST_JS"
file="${root_gen_dir}/chrome/browser/resources/tab_strip/tab_list.js"
use_base_dir="false"
type="chrome_html"
- compress="gzip"/>
+ compress="gzip"
+ preprocess="true"/>
<structure
name="IDR_TAB_STRIP_TAB_JS"
file="${root_gen_dir}/chrome/browser/resources/tab_strip/tab.js"
@@ -66,6 +74,12 @@
file="tab_swiper.js"
type="chrome_html"
compress="gzip"/>
+ <structure
+ name="IDR_TAB_STRIP_DRAG_MANAGER_JS"
+ file="drag_manager.js"
+ type="chrome_html"
+ compress="gzip"
+ preprocess="true"/>
</structures>
<includes>
@@ -96,6 +110,11 @@
type="BINDATA"
compress="gzip" />
<include
+ name="IDR_TAB_STRIP_TAB_HID_CONNECTED_SVG"
+ file="alert_indicators/tab_hid_connected.svg"
+ type="BINDATA"
+ compress="gzip" />
+ <include
name="IDR_TAB_STRIP_TAB_MEDIA_CAPTURING_WITH_ARROW_SVG"
file="alert_indicators/tab_media_capturing_with_arrow.svg"
type="BINDATA"
diff --git a/chromium/chrome/browser/resources/tab_strip/tab_swiper.js b/chromium/chrome/browser/resources/tab_strip/tab_swiper.js
index d02f130b3e2..269f16ed8b7 100644
--- a/chromium/chrome/browser/resources/tab_strip/tab_swiper.js
+++ b/chromium/chrome/browser/resources/tab_strip/tab_swiper.js
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import {isRTL} from 'chrome://resources/js/util.m.js';
+
/**
* The minimum amount of pixels needed for the user to swipe for the position
* (controlled by transform property) to start animating to 0.
@@ -81,6 +83,9 @@ export class TabSwiper {
/** @private */
createAnimation_() {
+ // TODO(crbug.com/1025390): padding-inline-end does not work with
+ // animations built using JS.
+ const paddingInlineEnd = isRTL() ? 'paddingLeft' : 'paddingRight';
const animation = new Animation(new KeyframeEffect(
this.element_,
[
@@ -88,6 +93,7 @@ export class TabSwiper {
// Base.
opacity: 1,
maxWidth: 'var(--tabstrip-tab-width)',
+ [paddingInlineEnd]: 'var(--tabstrip-tab-spacing)',
transform: `translateY(0)`
},
{
@@ -100,12 +106,14 @@ export class TabSwiper {
// Start of max-width and opacity animation swiping up.
maxWidth: 'var(--tabstrip-tab-width)',
offset: SWIPE_START_THRESHOLD_PX / SWIPE_FINISH_THRESHOLD_PX,
+ [paddingInlineEnd]: 'var(--tabstrip-tab-spacing)',
opacity: 1,
},
{
// Fully swiped up.
maxWidth: '0px',
opacity: 0,
+ [paddingInlineEnd]: 0,
transform: `translateY(-${SWIPE_FINISH_THRESHOLD_PX}px)`
},
],
@@ -113,7 +121,7 @@ export class TabSwiper {
duration: SWIPE_FINISH_THRESHOLD_PX,
fill: 'both',
}));
- animation.currentTime = 0;
+ animation.cancel();
animation.onfinish = () => {
this.element_.dispatchEvent(new CustomEvent('swipe'));
};
@@ -202,6 +210,10 @@ export class TabSwiper {
this.clearPointerEvents_();
}
+ reset() {
+ this.animation_.cancel();
+ }
+
startObserving() {
this.element_.addEventListener('pointerdown', this.pointerDownListener_);
}
diff --git a/chromium/chrome/browser/resources/tab_strip/tabs_api_proxy.js b/chromium/chrome/browser/resources/tab_strip/tabs_api_proxy.js
index 35a4573808f..ca87356a5d4 100644
--- a/chromium/chrome/browser/resources/tab_strip/tabs_api_proxy.js
+++ b/chromium/chrome/browser/resources/tab_strip/tabs_api_proxy.js
@@ -5,6 +5,16 @@
import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
/**
+ * These values are persisted to logs and should not be renumbered or re-used.
+ * See tools/metrics/histograms/enums.xml.
+ * @enum {number}
+ */
+export const CloseTabAction = {
+ CLOSE_BUTTON: 0,
+ SWIPED_TO_CLOSE: 1,
+};
+
+/**
* Must be kept in sync with TabNetworkState from
* //chrome/browser/ui/tabs/tab_network_state.h.
* @enum {number}
@@ -18,7 +28,7 @@ export const TabNetworkState = {
/**
* Must be kept in sync with TabAlertState from
- * //chrome/browser ui/tabs/tab_utils.h
+ * //chrome/browser/ui/tabs/tab_utils.h
* @enum {number}
*/
export const TabAlertState = {
@@ -28,10 +38,11 @@ export const TabAlertState = {
AUDIO_MUTING: 3,
BLUETOOTH_CONNECTED: 4,
USB_CONNECTED: 5,
- SERIAL_CONNECTED: 6,
- PIP_PLAYING: 7,
- DESKTOP_CAPTURING: 8,
- VR_PRESENTING_IN_HEADSET: 9,
+ HID_CONNECTED: 6,
+ SERIAL_CONNECTED: 7,
+ PIP_PLAYING: 8,
+ DESKTOP_CAPTURING: 9,
+ VR_PRESENTING_IN_HEADSET: 10,
};
/**
@@ -41,6 +52,7 @@ export const TabAlertState = {
* blocked: boolean,
* crashed: boolean,
* favIconUrl: (string|undefined),
+ * groupId: (string|undefined),
* id: number,
* index: number,
* isDefaultFavicon: boolean,
@@ -57,6 +69,15 @@ export let TabData;
/** @typedef {!Tab} */
let ExtensionsApiTab;
+/**
+ * @typedef {{
+ * color: string,
+ * textColor: string,
+ * title: string,
+ * }}
+ */
+export let TabGroupVisualData;
+
export class TabsApiProxy {
/**
* @param {number} tabId
@@ -68,6 +89,18 @@ export class TabsApiProxy {
});
}
+ createNewTab() {
+ chrome.send('createNewTab');
+ }
+
+ /**
+ * @return {!Promise<!Object<!TabGroupVisualData>>} Object of group IDs as
+ * strings mapped to their visual data.
+ */
+ getGroupVisualData() {
+ return sendWithPromise('getGroupVisualData');
+ }
+
/**
* @return {!Promise<!Array<!TabData>>}
*/
@@ -77,25 +110,38 @@ export class TabsApiProxy {
/**
* @param {number} tabId
- * @return {!Promise}
+ * @param {!CloseTabAction} closeTabAction
*/
- closeTab(tabId) {
- return new Promise(resolve => {
- chrome.tabs.remove(tabId, resolve);
- });
+ closeTab(tabId, closeTabAction) {
+ chrome.send(
+ 'closeTab', [tabId, closeTabAction === CloseTabAction.SWIPED_TO_CLOSE]);
+ chrome.metricsPrivate.recordEnumerationValue(
+ 'WebUITabStrip.CloseTabAction', closeTabAction,
+ Object.keys(CloseTabAction).length);
+ }
+
+ /**
+ * @param {number} tabId
+ * @param {string} groupId
+ */
+ groupTab(tabId, groupId) {
+ chrome.send('groupTab', [tabId, groupId]);
+ }
+
+ /**
+ * @param {string} groupId
+ * @param {number} newIndex
+ */
+ moveGroup(groupId, newIndex) {
+ chrome.send('moveGroup', [groupId, newIndex]);
}
/**
* @param {number} tabId
* @param {number} newIndex
- * @return {!Promise<!ExtensionsApiTab>}
*/
moveTab(tabId, newIndex) {
- return new Promise(resolve => {
- chrome.tabs.move(tabId, {index: newIndex}, tab => {
- resolve(tab);
- });
- });
+ chrome.send('moveTab', [tabId, newIndex]);
}
/**
@@ -105,6 +151,11 @@ export class TabsApiProxy {
setThumbnailTracked(tabId, thumbnailTracked) {
chrome.send('setThumbnailTracked', [tabId, thumbnailTracked]);
}
+
+ /** @param {number} tabId */
+ ungroupTab(tabId) {
+ chrome.send('ungroupTab', [tabId]);
+ }
}
addSingletonGetter(TabsApiProxy);
diff --git a/chromium/chrome/browser/resources/tools/rollup_plugin.js b/chromium/chrome/browser/resources/tools/rollup_plugin.js
index e1942718e76..f462ab10cb0 100644
--- a/chromium/chrome/browser/resources/tools/rollup_plugin.js
+++ b/chromium/chrome/browser/resources/tools/rollup_plugin.js
@@ -12,7 +12,7 @@ const polymerUrl = 'chrome://resources/polymer/v3_0/';
// TODO: Determine whether it is worth maintaining this list vs always checking
// both directories for the existence of a file.
-const nonGeneratedFiles = ['cr.m.js', 'action_link.js'];
+const nonGeneratedFiles = ['cr.m.js', 'cr_splitter.js', 'action_link.js'];
function normalizeSlashes(filepath) {
return filepath.replace(/\\/gi, '/');
diff --git a/chromium/chrome/browser/resources/usb_internals/BUILD.gn b/chromium/chrome/browser/resources/usb_internals/BUILD.gn
index f5829ca991f..30f5807a8d0 100644
--- a/chromium/chrome/browser/resources/usb_internals/BUILD.gn
+++ b/chromium/chrome/browser/resources/usb_internals/BUILD.gn
@@ -46,12 +46,9 @@ grit("resources") {
"usb_internals_resources.pak",
]
output_dir = "$root_gen_dir/chrome"
- depfile_dir = target_gen_dir
grit_flags = [
"-E",
"root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
]
- deps = [
- "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js",
- ]
+ deps = [ "//chrome/browser/ui/webui/usb_internals:mojo_bindings_js" ]
}
diff --git a/chromium/chrome/browser/resources/user_manager/BUILD.gn b/chromium/chrome/browser/resources/user_manager/BUILD.gn
index ec9959fe082..6adf635f369 100644
--- a/chromium/chrome/browser/resources/user_manager/BUILD.gn
+++ b/chromium/chrome/browser/resources/user_manager/BUILD.gn
@@ -38,15 +38,11 @@ js_library("error_dialog") {
}
js_library("profile_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr",
- ]
+ deps = [ "//ui/webui/resources/js:cr" ]
}
js_library("user_manager_pages") {
- deps = [
- "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager",
- ]
+ deps = [ "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager" ]
}
js_library("user_manager_tutorial") {
diff --git a/chromium/chrome/browser/resources/user_manager/control_bar.js b/chromium/chrome/browser/resources/user_manager/control_bar.js
index b58e581518a..ae5af0ba7b5 100644
--- a/chromium/chrome/browser/resources/user_manager/control_bar.js
+++ b/chromium/chrome/browser/resources/user_manager/control_bar.js
@@ -35,14 +35,14 @@ Polymer({
*/
isForceSigninEnabled_: {
type: Boolean,
- value: function() {
+ value() {
return loadTimeData.getBoolean('isForceSigninEnabled');
},
}
},
/** @override */
- created: function() {
+ created() {
this.browserProxy_ = signin.ProfileBrowserProxyImpl.getInstance();
},
@@ -51,7 +51,7 @@ Polymer({
* @param {!Event} event
* @private
*/
- onLaunchGuestTap_: function(event) {
+ onLaunchGuestTap_(event) {
this.browserProxy_.areAllProfilesLocked().then(allProfilesLocked => {
if (!allProfilesLocked || this.isForceSigninEnabled_) {
this.browserProxy_.launchGuestUser();
@@ -67,7 +67,7 @@ Polymer({
* @param {!Event} event
* @private
*/
- onAddUserTap_: function(event) {
+ onAddUserTap_(event) {
this.browserProxy_.areAllProfilesLocked().then(allProfilesLocked => {
if (!allProfilesLocked || this.isForceSigninEnabled_) {
// Event is caught by user-manager-pages.
diff --git a/chromium/chrome/browser/resources/user_manager/create_profile.js b/chromium/chrome/browser/resources/user_manager/create_profile.js
index 24aa9d51403..ca0c2d6858b 100644
--- a/chromium/chrome/browser/resources/user_manager/create_profile.js
+++ b/chromium/chrome/browser/resources/user_manager/create_profile.js
@@ -25,7 +25,7 @@ Polymer({
*/
availableIcons_: {
type: Array,
- value: function() {
+ value() {
return [];
}
},
@@ -69,7 +69,7 @@ Polymer({
*/
isProfileShortcutsEnabled_: {
type: Boolean,
- value: function() {
+ value() {
return loadTimeData.getBoolean('profileShortcutsEnabled');
},
readOnly: true
@@ -81,19 +81,19 @@ Polymer({
*/
isForceSigninEnabled_: {
type: Boolean,
- value: function() {
+ value() {
return loadTimeData.getBoolean('isForceSigninEnabled');
},
},
},
/** @override */
- created: function() {
+ created() {
this.browserProxy_ = signin.ProfileBrowserProxyImpl.getInstance();
},
/** @override */
- ready: function() {
+ ready() {
this.addWebUIListener(
'create-profile-success', this.handleSuccess_.bind(this));
this.addWebUIListener(
@@ -108,7 +108,7 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
// cr-input's focusable element isn't defined until after it's attached.
Polymer.RenderStatus.afterNextRender(this, () => this.$.nameInput.focus());
},
@@ -119,7 +119,7 @@ Polymer({
* @param {!Event} event
* @private
*/
- onTap_: function(event) {
+ onTap_(event) {
const element = Polymer.dom(event).rootTarget;
if (element.id == 'sign-in-to-chrome') {
@@ -138,7 +138,7 @@ Polymer({
* @param {!Event} event
* @private
*/
- onSaveTap_: function(event) {
+ onSaveTap_(event) {
this.createProfile_();
},
@@ -146,7 +146,7 @@ Polymer({
* Creates the new profile.
* @private
*/
- createProfile_: function() {
+ createProfile_() {
this.hideMessage_();
this.createInProgress_ = true;
const createShortcut =
@@ -162,7 +162,7 @@ Polymer({
* @param {!Event} event
* @private
*/
- onCancelTap_: function(event) {
+ onCancelTap_(event) {
this.fire('change-page', {page: 'user-pods-page'});
},
@@ -171,7 +171,7 @@ Polymer({
* @param {!ProfileInfo} profileInfo Details of the created/imported profile.
* @private
*/
- handleSuccess_: function(profileInfo) {
+ handleSuccess_(profileInfo) {
this.createInProgress_ = false;
this.fire('change-page', {page: 'user-pods-page'});
},
@@ -180,7 +180,7 @@ Polymer({
* Hides the warning/error message.
* @private
*/
- hideMessage_: function() {
+ hideMessage_() {
this.isMessageVisble_ = false;
},
@@ -189,7 +189,7 @@ Polymer({
* @param {*} message An HTML warning/error message.
* @private
*/
- handleMessage_: function(message) {
+ handleMessage_(message) {
this.createInProgress_ = false;
this.message_ = '' + message;
this.isMessageVisble_ = true;
@@ -201,10 +201,10 @@ Polymer({
* @param {string} id The ID of the string to translate.
* @private
*/
- i18nAllowIDAttr_: function(id) {
+ i18nAllowIDAttr_(id) {
const opts = {
'attrs': {
- 'id': function(node, value) {
+ 'id'(node, value) {
return node.tagName == 'A';
}
}
@@ -219,7 +219,7 @@ Polymer({
* @return {boolean}
* @private
*/
- isSpinnerActive_: function(createInProgress) {
+ isSpinnerActive_(createInProgress) {
return createInProgress;
},
@@ -230,7 +230,7 @@ Polymer({
* @return {boolean}
* @private
*/
- isSaveDisabled_: function(createInProgress, profileName) {
+ isSaveDisabled_(createInProgress, profileName) {
/** @type {CrInputElement} */
const nameInput = this.$.nameInput;
return createInProgress || !profileName || !nameInput.validate();
diff --git a/chromium/chrome/browser/resources/user_manager/error_dialog.js b/chromium/chrome/browser/resources/user_manager/error_dialog.js
index 0b15eb7f4e5..1a0580031b8 100644
--- a/chromium/chrome/browser/resources/user_manager/error_dialog.js
+++ b/chromium/chrome/browser/resources/user_manager/error_dialog.js
@@ -22,7 +22,7 @@ Polymer({
* Displays the dialog populated with the given message.
* @param {string} message Error message to show.
*/
- show: function(message) {
+ show(message) {
this.message_ = message;
this.$.dialog.showModal();
}
diff --git a/chromium/chrome/browser/resources/user_manager/user_manager.html b/chromium/chrome/browser/resources/user_manager/user_manager.html
index 77561990e0d..74127616b46 100644
--- a/chromium/chrome/browser/resources/user_manager/user_manager.html
+++ b/chromium/chrome/browser/resources/user_manager/user_manager.html
@@ -88,9 +88,9 @@
}
.pod {
- @apply --cr-card-elevation;
background-color: var(--cr-card-background-color);
border-radius: var(--cr-card-border-radius);
+ box-shadow: var(--cr-card-shadow);
color: var(--cr-primary-text-color);
cursor: default;
height: auto;
diff --git a/chromium/chrome/browser/resources/user_manager/user_manager_pages.js b/chromium/chrome/browser/resources/user_manager/user_manager_pages.js
index 04761b5b277..41b0a5859f5 100644
--- a/chromium/chrome/browser/resources/user_manager/user_manager_pages.js
+++ b/chromium/chrome/browser/resources/user_manager/user_manager_pages.js
@@ -26,7 +26,7 @@ Polymer({
listeners: {'change-page': 'onChangePage_'},
/** @override */
- attached: function() {
+ attached() {
this.setSelectedPage('user-pods-page');
},
@@ -36,7 +36,7 @@ Polymer({
* and the optional data to be passed to the page.
* @private
*/
- onChangePage_: function(e) {
+ onChangePage_(e) {
this.setSelectedPage(e.detail.page, e.detail.data);
},
@@ -45,7 +45,7 @@ Polymer({
* @param {string} pageId ID of the page that is to be selected.
* @param {Object=} opt_pageData Optional data to be passed to the page.
*/
- setSelectedPage: function(pageId, opt_pageData) {
+ setSelectedPage(pageId, opt_pageData) {
this.pageData_ = opt_pageData || null;
this.selectedPage_ = pageId;
/** @type {CrViewManagerElement} */ (this.$.animatedPages)
@@ -62,12 +62,12 @@ Polymer({
* @param {!Event} e
* @private
*/
- stopPropagation_: function(e) {
+ stopPropagation_(e) {
e.stopPropagation();
},
/** @return {boolean} */
- shouldShowCreateProfile_: function() {
+ shouldShowCreateProfile_() {
return this.selectedPage_ == 'create-user-page';
}
});
diff --git a/chromium/chrome/browser/resources/user_manager/user_manager_tutorial.html b/chromium/chrome/browser/resources/user_manager/user_manager_tutorial.html
index bdffe5546ff..e09abd67ecb 100644
--- a/chromium/chrome/browser/resources/user_manager/user_manager_tutorial.html
+++ b/chromium/chrome/browser/resources/user_manager/user_manager_tutorial.html
@@ -9,11 +9,11 @@
<template>
<style include="shared-styles">
.tutorial-slide {
- @apply --cr-card-elevation;
-webkit-transition: opacity 200ms ease-in-out;
background-color: var(--cr-card-background-color);
border-radius: var(--cr-card-border-radius);
bottom: 0;
+ box-shadow: var(--cr-card-shadow);
height: 408px;
left: 0;
margin: auto;
diff --git a/chromium/chrome/browser/resources/user_manager/user_manager_tutorial.js b/chromium/chrome/browser/resources/user_manager/user_manager_tutorial.js
index 8fb553fc566..6fcde44ead3 100644
--- a/chromium/chrome/browser/resources/user_manager/user_manager_tutorial.js
+++ b/chromium/chrome/browser/resources/user_manager/user_manager_tutorial.js
@@ -46,7 +46,7 @@ Polymer({
* @return {boolean}
* @private
*/
- isStepHidden_: function(currentStep, step) {
+ isStepHidden_(currentStep, step) {
return currentStep != step;
},
@@ -55,7 +55,7 @@ Polymer({
* @param {!Event} event
* @private
*/
- onNextClick_: function(event) {
+ onNextClick_(event) {
this.currentStep_ =
event.composedPath().find(e => e.tagName == 'CR-BUTTON').dataset.next;
},
@@ -66,7 +66,7 @@ Polymer({
* @param {!Event} event
* @private
*/
- onAddUserTap_: function(event) {
+ onAddUserTap_(event) {
this.onDissmissTap_();
// Event is caught by user-manager-pages.
this.fire('change-page', {page: 'create-user-page'});
@@ -75,7 +75,7 @@ Polymer({
/**
* Starts the tutorial.
*/
- startTutorial: function() {
+ startTutorial() {
this.currentStep_ = TutorialSteps.YOUR_CHROME;
this.hidden_ = false;
@@ -95,7 +95,7 @@ Polymer({
* Ends the tutorial.
* @private
*/
- onDissmissTap_: function() {
+ onDissmissTap_() {
$('inner-container').classList.remove('disabled');
this.hidden_ = true;
}
diff --git a/chromium/chrome/browser/resources/vr/OWNERS b/chromium/chrome/browser/resources/vr/OWNERS
index f8d52f36333..49ca9b4b145 100644
--- a/chromium/chrome/browser/resources/vr/OWNERS
+++ b/chromium/chrome/browser/resources/vr/OWNERS
@@ -1,6 +1,5 @@
alcooper@chromium.org
bialpio@chromium.org
-cjgrant@chromium.org
tiborg@chromium.org
# TEAM: xr-dev@chromium.org
diff --git a/chromium/chrome/browser/resources/webapks/BUILD.gn b/chromium/chrome/browser/resources/webapks/BUILD.gn
index 7012bb64db4..8798ad554c7 100644
--- a/chromium/chrome/browser/resources/webapks/BUILD.gn
+++ b/chromium/chrome/browser/resources/webapks/BUILD.gn
@@ -8,9 +8,7 @@ import("//tools/grit/grit_rule.gni")
js_type_check("closure_compile") {
uses_js_modules = true
- deps = [
- ":about_webapks",
- ]
+ deps = [ ":about_webapks" ]
}
js_library("about_webapks") {
diff --git a/chromium/chrome/browser/resources/welcome/.eslintrc.js b/chromium/chrome/browser/resources/welcome/.eslintrc.js
new file mode 100644
index 00000000000..9c84e103640
--- /dev/null
+++ b/chromium/chrome/browser/resources/welcome/.eslintrc.js
@@ -0,0 +1,11 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {'eqeqeq': ['error', 'always', {'null': 'ignore'}]},
+};
diff --git a/chromium/chrome/browser/resources/welcome/BUILD.gn b/chromium/chrome/browser/resources/welcome/BUILD.gn
index f82bd8f077e..dc3f647f2f2 100644
--- a/chromium/chrome/browser/resources/welcome/BUILD.gn
+++ b/chromium/chrome/browser/resources/welcome/BUILD.gn
@@ -38,9 +38,7 @@ js_library("landing_view") {
}
js_library("landing_view_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
externs_list = [ "$externs_path/metrics_private.js" ]
}
@@ -54,9 +52,7 @@ js_library("signin_view") {
}
js_library("signin_view_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
externs_list = [ "$externs_path/metrics_private.js" ]
}
@@ -81,9 +77,7 @@ js_library("welcome_app") {
}
js_library("welcome_browser_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
externs_list = [ "$externs_path/chrome_send.js" ]
}
@@ -106,7 +100,7 @@ polymer_modulizer("signin_view") {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":landing_view_module",
":signin_view_module",
":welcome_app_module",
diff --git a/chromium/chrome/browser/resources/welcome/OWNERS b/chromium/chrome/browser/resources/welcome/OWNERS
index 08ee1a9630e..90c0002b3ab 100644
--- a/chromium/chrome/browser/resources/welcome/OWNERS
+++ b/chromium/chrome/browser/resources/welcome/OWNERS
@@ -1 +1 @@
-hcarmona@chromium.org
+johntlee@chromium.org
diff --git a/chromium/chrome/browser/resources/welcome/google_apps/BUILD.gn b/chromium/chrome/browser/resources/welcome/google_apps/BUILD.gn
index f6f678ed905..5e14c83a05d 100644
--- a/chromium/chrome/browser/resources/welcome/google_apps/BUILD.gn
+++ b/chromium/chrome/browser/resources/welcome/google_apps/BUILD.gn
@@ -35,16 +35,12 @@ js_library("nux_google_apps") {
}
js_library("google_app_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
externs_list = [ "$externs_path/chrome_send.js" ]
}
js_library("google_apps_metrics_proxy") {
- deps = [
- "../shared:module_metrics_proxy",
- ]
+ deps = [ "../shared:module_metrics_proxy" ]
}
polymer_modulizer("nux_google_apps") {
diff --git a/chromium/chrome/browser/resources/welcome/google_apps/nux_google_apps.js b/chromium/chrome/browser/resources/welcome/google_apps/nux_google_apps.js
index fd25a48c78f..c6c6bf36b4a 100644
--- a/chromium/chrome/browser/resources/welcome/google_apps/nux_google_apps.js
+++ b/chromium/chrome/browser/resources/welcome/google_apps/nux_google_apps.js
@@ -91,7 +91,7 @@ Polymer({
wasBookmarkBarShownOnInit_: false,
/** @override */
- ready: function() {
+ ready() {
this.appProxy_ = GoogleAppProxyImpl.getInstance();
this.metricsManager_ = new ModuleMetricsManager(
GoogleAppsMetricsProxyImpl.getInstance());
@@ -100,17 +100,17 @@ Polymer({
},
/** @override */
- attached: function() {
+ attached() {
afterNextRender(this, () => IronA11yAnnouncer.requestAvailability());
},
- onRouteEnter: function() {
+ onRouteEnter() {
this.finalized_ = false;
this.metricsManager_.recordPageInitialized();
this.populateAllBookmarks_();
},
- onRouteExit: function() {
+ onRouteExit() {
if (this.finalized_) {
return;
}
@@ -118,7 +118,7 @@ Polymer({
this.metricsManager_.recordBrowserBackOrForward();
},
- onRouteUnload: function() {
+ onRouteUnload() {
if (this.finalized_) {
return;
}
@@ -131,7 +131,7 @@ Polymer({
* @param {number} direction
* @private
*/
- changeFocus_: function(element, direction) {
+ changeFocus_(element, direction) {
if (isRTL()) {
direction *= -1; // Reverse direction if RTL.
}
@@ -160,7 +160,7 @@ Polymer({
* Called when bookmarks should be removed for all selected apps.
* @private
*/
- cleanUp_: function() {
+ cleanUp_() {
this.finalized_ = true;
if (!this.appList_) {
@@ -189,7 +189,7 @@ Polymer({
* @param {!{model: !AppItemModel}} e
* @private
*/
- onAppClick_: function(e) {
+ onAppClick_(e) {
const item = e.model.item;
e.model.set('item.selected', !item.selected);
@@ -209,10 +209,10 @@ Polymer({
* @param {!Event} e
* @private
*/
- onAppKeyUp_: function(e) {
- if (e.key == 'ArrowRight') {
+ onAppKeyUp_(e) {
+ if (e.key === 'ArrowRight') {
this.changeFocus_(e.currentTarget, 1);
- } else if (e.key == 'ArrowLeft') {
+ } else if (e.key === 'ArrowLeft') {
this.changeFocus_(e.currentTarget, -1);
} else {
e.currentTarget.classList.add(KEYBOARD_FOCUSED);
@@ -223,12 +223,12 @@ Polymer({
* @param {!Event} e
* @private
*/
- onAppPointerDown_: function(e) {
+ onAppPointerDown_(e) {
e.currentTarget.classList.remove(KEYBOARD_FOCUSED);
},
/** @private */
- onGetStartedClicked_: function() {
+ onGetStartedClicked_() {
this.finalized_ = true;
this.appList_.forEach(app => {
if (app.selected) {
@@ -240,7 +240,7 @@ Polymer({
},
/** @private */
- onNoThanksClicked_: function() {
+ onNoThanksClicked_() {
this.cleanUp_();
this.metricsManager_.recordNoThanks();
navigateToNextStep();
@@ -250,7 +250,7 @@ Polymer({
* Called when bookmarks should be created for all selected apps.
* @private
*/
- populateAllBookmarks_: function() {
+ populateAllBookmarks_() {
this.wasBookmarkBarShownOnInit_ = this.bookmarkBarManager_.getShown();
if (this.appList_) {
@@ -273,7 +273,7 @@ Polymer({
* @param {!AppItem} item
* @private
*/
- updateBookmark_: function(item) {
+ updateBookmark_(item) {
if (item.selected && !item.bookmarkId) {
this.bookmarkBarManager_.setShown(true);
this.bookmarkProxy_.addBookmark(
@@ -297,7 +297,7 @@ Polymer({
* Updates the value of hasAppsSelected_.
* @private
*/
- updateHasAppsSelected_: function() {
+ updateHasAppsSelected_() {
this.hasAppsSelected_ =
this.appList_ && this.appList_.some(a => a.selected);
if (!this.hasAppsSelected_) {
@@ -311,7 +311,7 @@ Polymer({
* @return {string}
* @private
*/
- getAriaPressed_: function(value) {
+ getAriaPressed_(value) {
return value ? 'true' : 'false';
}
});
diff --git a/chromium/chrome/browser/resources/welcome/landing_view.js b/chromium/chrome/browser/resources/welcome/landing_view.js
index 785bb5ea99a..8befb08b9cc 100644
--- a/chromium/chrome/browser/resources/welcome/landing_view.js
+++ b/chromium/chrome/browser/resources/welcome/landing_view.js
@@ -42,12 +42,12 @@ Polymer({
this.landingViewProxy_ = LandingViewProxyImpl.getInstance();
},
- onRouteEnter: function() {
+ onRouteEnter() {
this.finalized_ = false;
this.landingViewProxy_.recordPageShown();
},
- onRouteUnload: function() {
+ onRouteUnload() {
// Clicking on 'Returning user' will change the URL.
if (this.finalized_) {
return;
@@ -57,7 +57,7 @@ Polymer({
},
/** @private */
- onExistingUserClick_: function() {
+ onExistingUserClick_() {
this.finalized_ = true;
this.landingViewProxy_.recordExistingUser();
if (this.signinAllowed_) {
@@ -69,7 +69,7 @@ Polymer({
},
/** @private */
- onNewUserClick_: function() {
+ onNewUserClick_() {
this.finalized_ = true;
this.landingViewProxy_.recordNewUser();
navigateTo(Routes.NEW_USER, 1);
diff --git a/chromium/chrome/browser/resources/welcome/navigation_behavior.js b/chromium/chrome/browser/resources/welcome/navigation_behavior.js
index c2c9445216d..72b12866871 100644
--- a/chromium/chrome/browser/resources/welcome/navigation_behavior.js
+++ b/chromium/chrome/browser/resources/welcome/navigation_behavior.js
@@ -72,7 +72,7 @@ function notifyObservers() {
// Modules are only attached to DOM if they're for the current route, so
// as long as the id of an element matches up to the current step, it
// means that element is for the current route.
- if (observer.id == `step-${step}`) {
+ if (observer.id === `step-${step}`) {
currentRouteElement = observer;
}
});
@@ -138,7 +138,7 @@ export function navigateTo(route, step) {
*/
export const NavigationBehavior = {
/** @override */
- attached: function() {
+ attached() {
assert(!routeObservers.has(this));
routeObservers.add(this);
@@ -152,7 +152,7 @@ export const NavigationBehavior = {
// Modules are only attached to DOM if they're for the current route, so
// as long as the id of an element matches up to the current step, it
// means that element is for the current route.
- if (this.id == `step-${step}`) {
+ if (this.id === `step-${step}`) {
currentRouteElement = this;
this.onRouteEnter();
this.updateFocusForA11y();
@@ -160,7 +160,7 @@ export const NavigationBehavior = {
},
/** Called to update focus when progressing through the modules. */
- updateFocusForA11y: function() {
+ updateFocusForA11y() {
const header = this.$$('h1');
if (header) {
afterNextRender(this, () => header.focus());
@@ -168,7 +168,7 @@ export const NavigationBehavior = {
},
/** @override */
- detached: function() {
+ detached() {
assert(routeObservers.delete(this));
},
@@ -176,11 +176,11 @@ export const NavigationBehavior = {
* @param {!Routes} route
* @param {number} step
*/
- onRouteChange: function(route, step) {},
+ onRouteChange(route, step) {},
- onRouteEnter: function() {},
+ onRouteEnter() {},
- onRouteExit: function() {},
+ onRouteExit() {},
- onRouteUnload: function() {},
+ onRouteUnload() {},
};
diff --git a/chromium/chrome/browser/resources/welcome/ntp_background/nux_ntp_background.js b/chromium/chrome/browser/resources/welcome/ntp_background/nux_ntp_background.js
index b255441592f..240b849610e 100644
--- a/chromium/chrome/browser/resources/welcome/ntp_background/nux_ntp_background.js
+++ b/chromium/chrome/browser/resources/welcome/ntp_background/nux_ntp_background.js
@@ -62,13 +62,13 @@ Polymer({
ntpBackgroundProxy_: null,
/** @override */
- ready: function() {
+ ready() {
this.ntpBackgroundProxy_ = NtpBackgroundProxyImpl.getInstance();
this.metricsManager_ =
new ModuleMetricsManager(NtpBackgroundMetricsProxyImpl.getInstance());
},
- onRouteEnter: function() {
+ onRouteEnter() {
this.finalized_ = false;
const defaultBackground = {
id: -1,
@@ -90,7 +90,7 @@ Polymer({
this.metricsManager_.recordPageInitialized();
},
- onRouteExit: function() {
+ onRouteExit() {
if (this.imageIsLoading_) {
this.ntpBackgroundProxy_.recordBackgroundImageNeverLoaded();
}
@@ -101,7 +101,7 @@ Polymer({
this.metricsManager_.recordBrowserBackOrForward();
},
- onRouteUnload: function() {
+ onRouteUnload() {
if (this.imageIsLoading_) {
this.ntpBackgroundProxy_.recordBackgroundImageNeverLoaded();
}
@@ -116,7 +116,7 @@ Polymer({
* @return {boolean}
* @private
*/
- hasValidSelectedBackground_: function() {
+ hasValidSelectedBackground_() {
return this.selectedBackground_.id > -1;
},
@@ -124,12 +124,12 @@ Polymer({
* @param {!NtpBackgroundData} background
* @private
*/
- isSelectedBackground_: function(background) {
- return background == this.selectedBackground_;
+ isSelectedBackground_(background) {
+ return background === this.selectedBackground_;
},
/** @private */
- onSelectedBackgroundChange_: function() {
+ onSelectedBackgroundChange_() {
const id = this.selectedBackground_.id;
if (id > -1) {
@@ -157,7 +157,7 @@ Polymer({
},
/** @private */
- onBackgroundPreviewTransitionEnd_: function() {
+ onBackgroundPreviewTransitionEnd_() {
// Whenever the #backgroundPreview transitions to a non-active, hidden
// state, remove the background image. This way, when the element
// transitions back to active, the previous background is not displayed.
@@ -170,7 +170,7 @@ Polymer({
* @param {!{model: !{item: !NtpBackgroundData}}} e
* @private
*/
- onBackgroundClick_: function(e) {
+ onBackgroundClick_(e) {
this.selectedBackground_ = e.model.item;
this.metricsManager_.recordClickedOption();
this.fire('iron-announce', {
@@ -183,10 +183,10 @@ Polymer({
* @param {!Event} e
* @private
*/
- onBackgroundKeyUp_: function(e) {
- if (e.key == 'ArrowRight' || e.key == 'ArrowDown') {
+ onBackgroundKeyUp_(e) {
+ if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
this.changeFocus_(e.currentTarget, 1);
- } else if (e.key == 'ArrowLeft' || e.key == 'ArrowUp') {
+ } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
this.changeFocus_(e.currentTarget, -1);
} else {
this.changeFocus_(e.currentTarget, 0);
@@ -226,12 +226,12 @@ Polymer({
* @param {!Event} e
* @private
*/
- onBackgroundPointerDown_: function(e) {
+ onBackgroundPointerDown_(e) {
e.currentTarget.classList.remove(KEYBOARD_FOCUSED_CLASS);
},
/** @private */
- onNextClicked_: function() {
+ onNextClicked_() {
this.finalized_ = true;
if (this.selectedBackground_ && this.selectedBackground_.id > -1) {
@@ -244,7 +244,7 @@ Polymer({
},
/** @private */
- onSkipClicked_: function() {
+ onSkipClicked_() {
this.finalized_ = true;
this.metricsManager_.recordNoThanks();
navigateToNextStep();
diff --git a/chromium/chrome/browser/resources/welcome/set_as_default/BUILD.gn b/chromium/chrome/browser/resources/welcome/set_as_default/BUILD.gn
index 0c82491a12e..d553722f577 100644
--- a/chromium/chrome/browser/resources/welcome/set_as_default/BUILD.gn
+++ b/chromium/chrome/browser/resources/welcome/set_as_default/BUILD.gn
@@ -11,9 +11,7 @@ js_type_check("closure_compile") {
"js_module_root=../../chrome/browser/resources/welcome/",
"js_module_root=gen/chrome/browser/resources/welcome/",
]
- deps = [
- ":nux_set_as_default",
- ]
+ deps = [ ":nux_set_as_default" ]
}
js_library("nux_set_as_default") {
@@ -28,9 +26,7 @@ js_library("nux_set_as_default") {
}
js_library("nux_set_as_default_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
externs_list = [ "$externs_path/metrics_private.js" ]
}
diff --git a/chromium/chrome/browser/resources/welcome/set_as_default/nux_set_as_default.js b/chromium/chrome/browser/resources/welcome/set_as_default/nux_set_as_default.js
index c2be7a3c5ee..9612319a626 100644
--- a/chromium/chrome/browser/resources/welcome/set_as_default/nux_set_as_default.js
+++ b/chromium/chrome/browser/resources/welcome/set_as_default/nux_set_as_default.js
@@ -53,7 +53,7 @@ Polymer({
navigateToNextStep_: navigateToNextStep,
/** @override */
- ready: function() {
+ ready() {
this.browserProxy_ = NuxSetAsDefaultProxyImpl.getInstance();
this.addWebUIListener(
@@ -61,12 +61,12 @@ Polymer({
this.onDefaultBrowserChange_.bind(this));
},
- onRouteEnter: function() {
+ onRouteEnter() {
this.finalized_ = false;
this.browserProxy_.recordPageShown();
},
- onRouteExit: function() {
+ onRouteExit() {
if (this.finalized_) {
return;
}
@@ -74,7 +74,7 @@ Polymer({
this.browserProxy_.recordNavigatedAwayThroughBrowserHistory();
},
- onRouteUnload: function() {
+ onRouteUnload() {
if (this.finalized_) {
return;
}
@@ -83,7 +83,7 @@ Polymer({
},
/** @private */
- onDeclineClick_: function() {
+ onDeclineClick_() {
if (this.finalized_) {
return;
}
@@ -93,7 +93,7 @@ Polymer({
},
/** @private */
- onSetDefaultClick_: function() {
+ onSetDefaultClick_() {
if (this.finalized_) {
return;
}
@@ -107,7 +107,7 @@ Polymer({
* @param {!DefaultBrowserInfo} status
* @private
*/
- onDefaultBrowserChange_: function(status) {
+ onDefaultBrowserChange_(status) {
if (status.isDefault) {
this.browserProxy_.recordSuccessfullySetDefault();
// Triggers toast in the containing welcome-app.
@@ -127,7 +127,7 @@ Polymer({
},
/** @private */
- finished_: function() {
+ finished_() {
this.finalized_ = true;
this.navigateToNextStep_();
},
diff --git a/chromium/chrome/browser/resources/welcome/shared/BUILD.gn b/chromium/chrome/browser/resources/welcome/shared/BUILD.gn
index 9ebc573c885..f7254eb1469 100644
--- a/chromium/chrome/browser/resources/welcome/shared/BUILD.gn
+++ b/chromium/chrome/browser/resources/welcome/shared/BUILD.gn
@@ -20,9 +20,7 @@ js_type_check("closure_compile") {
}
js_library("bookmark_proxy") {
- deps = [
- "//ui/webui/resources/js:cr.m",
- ]
+ deps = [ "//ui/webui/resources/js:cr.m" ]
externs_list = [
"$externs_path/chrome_extensions.js",
"$externs_path/chrome_send.js",
@@ -86,7 +84,7 @@ polymer_modulizer("step_indicator") {
}
group("polymer3_elements") {
- deps = [
+ public_deps = [
":action_link_style_css_module",
":animations_css_module",
":chooser_shared_css_module",
diff --git a/chromium/chrome/browser/resources/welcome/shared/module_metrics_proxy.js b/chromium/chrome/browser/resources/welcome/shared/module_metrics_proxy.js
index 75819f2e515..6c3c3eb9a0d 100644
--- a/chromium/chrome/browser/resources/welcome/shared/module_metrics_proxy.js
+++ b/chromium/chrome/browser/resources/welcome/shared/module_metrics_proxy.js
@@ -199,14 +199,14 @@ export class ModuleMetricsManager {
recordClickedOption() {
// Only overwrite this.firstPart if it's not overwritten already
- if (this.firstPart == this.options_.didNothing) {
+ if (this.firstPart === this.options_.didNothing) {
this.firstPart = this.options_.choseAnOption;
}
}
recordClickedDisabledButton() {
// Only overwrite this.firstPart if it's not overwritten already
- if (this.firstPart == this.options_.didNothing) {
+ if (this.firstPart === this.options_.didNothing) {
this.firstPart = this.options_.clickedDisabledNextButton;
}
}
diff --git a/chromium/chrome/browser/resources/welcome/shared/step_indicator.js b/chromium/chrome/browser/resources/welcome/shared/step_indicator.js
index 8d4b45c0ff5..cf93d8f35d1 100644
--- a/chromium/chrome/browser/resources/welcome/shared/step_indicator.js
+++ b/chromium/chrome/browser/resources/welcome/shared/step_indicator.js
@@ -33,7 +33,7 @@ Polymer({
* @return {!Array<undefined>}
* @private
*/
- computeDots_: function() {
+ computeDots_() {
// If total is 1, show nothing.
return new Array(this.model.total > 1 ? this.model.total : 0);
},
@@ -43,7 +43,7 @@ Polymer({
* @return {string}
* @private
*/
- getActiveClass_: function(index) {
- return index == this.model.active ? 'active' : '';
+ getActiveClass_(index) {
+ return index === this.model.active ? 'active' : '';
},
});
diff --git a/chromium/chrome/browser/resources/welcome/signin_view.js b/chromium/chrome/browser/resources/welcome/signin_view.js
index b0c8befc300..389b69c33ef 100644
--- a/chromium/chrome/browser/resources/welcome/signin_view.js
+++ b/chromium/chrome/browser/resources/welcome/signin_view.js
@@ -33,17 +33,17 @@ Polymer({
signinViewProxy_: null,
/** @override */
- ready: function() {
+ ready() {
this.welcomeBrowserProxy_ = WelcomeBrowserProxyImpl.getInstance();
this.signinViewProxy_ = SigninViewProxyImpl.getInstance();
},
- onRouteEnter: function() {
+ onRouteEnter() {
this.finalized_ = false;
this.signinViewProxy_.recordPageShown();
},
- onRouteExit: function() {
+ onRouteExit() {
if (this.finalized_) {
return;
}
@@ -51,7 +51,7 @@ Polymer({
this.signinViewProxy_.recordNavigatedAwayThroughBrowserHistory();
},
- onRouteUnload: function() {
+ onRouteUnload() {
// URL is expected to change when signing in or skipping.
if (this.finalized_) {
return;
@@ -61,14 +61,14 @@ Polymer({
},
/** private */
- onSignInClick_: function() {
+ onSignInClick_() {
this.finalized_ = true;
this.signinViewProxy_.recordSignIn();
this.welcomeBrowserProxy_.handleActivateSignIn(null);
},
/** @private */
- onNoThanksClick_: function() {
+ onNoThanksClick_() {
this.finalized_ = true;
this.signinViewProxy_.recordSkip();
this.welcomeBrowserProxy_.handleUserDecline();
diff --git a/chromium/chrome/browser/resources/welcome/welcome_app.js b/chromium/chrome/browser/resources/welcome/welcome_app.js
index 029129172ef..b39af05ccb5 100644
--- a/chromium/chrome/browser/resources/welcome/welcome_app.js
+++ b/chromium/chrome/browser/resources/welcome/welcome_app.js
@@ -81,7 +81,7 @@ Polymer({
},
/** @private */
- onDefaultBrowserChange_: function() {
+ onDefaultBrowserChange_() {
this.$$('cr-toast').show();
},
@@ -90,7 +90,7 @@ Polymer({
* @param {number} step
* @private
*/
- onRouteChange: function(route, step) {
+ onRouteChange(route, step) {
const setStep = () => {
// If the specified step doesn't exist, that means there are no more
// steps. In that case, replace this page with NTP.
@@ -106,7 +106,7 @@ Polymer({
};
// If the route changed, initialize the steps of modules for that route.
- if (this.currentRoute_ != route) {
+ if (this.currentRoute_ !== route) {
this.initializeModules(route).then(setStep);
} else {
setStep();
@@ -116,14 +116,14 @@ Polymer({
},
/** @param {Routes} route */
- initializeModules: function(route) {
+ initializeModules(route) {
// Remove all views except landing.
this.$.viewManager
.querySelectorAll('[slot="view"]:not([id="step-landing"])')
.forEach(element => element.remove());
// If it is on landing route, end here.
- if (route == Routes.LANDING) {
+ if (route === Routes.LANDING) {
return Promise.resolve();
}
@@ -153,7 +153,7 @@ Polymer({
])
.then(([canSetDefault]) => {
modules = modules.filter(module => {
- if (module == 'nux-set-as-default') {
+ if (module === 'nux-set-as-default') {
return canSetDefault;
}
diff --git a/chromium/chrome/browser/safe_browsing/BUILD.gn b/chromium/chrome/browser/safe_browsing/BUILD.gn
index 0f60694e2d9..14bef91c537 100644
--- a/chromium/chrome/browser/safe_browsing/BUILD.gn
+++ b/chromium/chrome/browser/safe_browsing/BUILD.gn
@@ -20,22 +20,22 @@ jumbo_static_library("safe_browsing") {
"//chrome/app:generated_resources",
"//chrome/common",
"//chrome/common:constants",
- "//chrome/common/safe_browsing:file_type_policies",
"//components/browser_sync",
"//components/keyed_service/content",
"//components/language/core/browser",
+ "//components/page_info",
"//components/password_manager/core/browser",
"//components/password_manager/core/browser:hash_password_manager",
"//components/pref_registry",
"//components/resources:components_resources_grit",
"//components/safe_browsing:buildflags",
- "//components/safe_browsing:features",
- "//components/safe_browsing:ping_manager",
- "//components/safe_browsing/browser:referrer_chain_provider",
- "//components/safe_browsing/common:interfaces",
- "//components/safe_browsing/db:database_manager",
- "//components/safe_browsing/db:v4_local_database_manager",
- "//components/safe_browsing/web_ui",
+ "//components/safe_browsing/content/web_ui",
+ "//components/safe_browsing/core:features",
+ "//components/safe_browsing/core:ping_manager",
+ "//components/safe_browsing/core/browser:referrer_chain_provider",
+ "//components/safe_browsing/core/common:interfaces",
+ "//components/safe_browsing/core/db:database_manager",
+ "//components/safe_browsing/core/db:v4_local_database_manager",
"//components/search_engines",
"//components/sessions",
"//components/signin/public/identity_manager",
@@ -97,29 +97,30 @@ jumbo_static_library("safe_browsing") {
"trigger_creator.h",
"ui_manager.cc",
"ui_manager.h",
+ "user_interaction_observer.cc",
+ "user_interaction_observer.h",
]
deps += [
+ ":url_lookup_service_factory",
+ ":verdict_cache_manager_factory",
+ "//chrome/browser/engagement:mojo_bindings",
"//chrome/common/safe_browsing:proto",
- "//components/safe_browsing:csd_proto",
- "//components/safe_browsing:safe_browsing",
-
- # TODO(crbug/996380): This is needed because the DownloadProtectionService
- # is being built on Android. Since we don't actually use any
- # DownloadProtectionService features on Android, we should fix that
- # dependency and move this to the 'safe_browsing_mode == 1' section.
- "//components/safe_browsing:webprotect_proto",
- "//components/safe_browsing/browser",
- "//components/safe_browsing/common",
- "//components/safe_browsing/common:safe_browsing_prefs",
- "//components/safe_browsing/db:allowlist_checker_client",
- "//components/safe_browsing/db:metadata_proto",
- "//components/safe_browsing/password_protection",
- "//components/safe_browsing/triggers",
- "//components/safe_browsing/triggers:ad_popup_trigger",
- "//components/safe_browsing/triggers:ad_redirect_trigger",
- "//components/safe_browsing/triggers:ad_sampler_trigger",
- "//components/safe_browsing/triggers:suspicious_site_trigger",
- "//components/safe_browsing/triggers:trigger_throttler",
+ "//components/safe_browsing/content",
+ "//components/safe_browsing/content/browser",
+ "//components/safe_browsing/content/password_protection",
+ "//components/safe_browsing/content/triggers:ad_popup_trigger",
+ "//components/safe_browsing/content/triggers:ad_redirect_trigger",
+ "//components/safe_browsing/content/triggers:ad_sampler_trigger",
+ "//components/safe_browsing/content/triggers:suspicious_site_trigger",
+ "//components/safe_browsing/core:csd_proto",
+ "//components/safe_browsing/core:file_type_policies",
+ "//components/safe_browsing/core/browser",
+ "//components/safe_browsing/core/common",
+ "//components/safe_browsing/core/common:safe_browsing_prefs",
+ "//components/safe_browsing/core/db:allowlist_checker_client",
+ "//components/safe_browsing/core/db:metadata_proto",
+ "//components/safe_browsing/core/triggers",
+ "//components/safe_browsing/core/triggers:trigger_throttler",
]
if (safe_browsing_mode == 1) {
# "Safe Browsing Full" files in addition to the "basic" ones to use for
@@ -141,10 +142,16 @@ jumbo_static_library("safe_browsing") {
"cloud_content_scanning/binary_fcm_service.h",
"cloud_content_scanning/binary_upload_service.cc",
"cloud_content_scanning/binary_upload_service.h",
+ "cloud_content_scanning/binary_upload_service_factory.cc",
+ "cloud_content_scanning/binary_upload_service_factory.h",
"cloud_content_scanning/deep_scanning_dialog_delegate.cc",
"cloud_content_scanning/deep_scanning_dialog_delegate.h",
+ "cloud_content_scanning/deep_scanning_dialog_views.cc",
+ "cloud_content_scanning/deep_scanning_dialog_views.h",
"cloud_content_scanning/deep_scanning_utils.cc",
"cloud_content_scanning/deep_scanning_utils.h",
+ "cloud_content_scanning/file_source_request.cc",
+ "cloud_content_scanning/file_source_request.h",
"cloud_content_scanning/multipart_uploader.cc",
"cloud_content_scanning/multipart_uploader.h",
"dm_token_utils.cc",
@@ -155,6 +162,8 @@ jumbo_static_library("safe_browsing") {
"download_protection/check_client_download_request_base.h",
"download_protection/check_native_file_system_write_request.cc",
"download_protection/check_native_file_system_write_request.h",
+ "download_protection/deep_scanning_request.cc",
+ "download_protection/deep_scanning_request.h",
"download_protection/download_feedback.cc",
"download_protection/download_feedback.h",
"download_protection/download_feedback_service.cc",
@@ -239,8 +248,10 @@ jumbo_static_library("safe_browsing") {
"//components/content_settings/core/browser",
"//components/language/core/common",
"//components/prefs",
- "//components/safe_browsing/db",
+ "//components/safe_browsing/core:webprotect_proto",
+ "//components/safe_browsing/core/db",
"//components/security_interstitials/content:security_interstitial_page",
+ "//components/security_interstitials/core:unsafe_resource",
"//content/public/browser",
"//net",
]
@@ -264,6 +275,38 @@ jumbo_static_library("safe_browsing") {
}
}
+source_set("url_lookup_service_factory") {
+ sources = [
+ "url_lookup_service_factory.cc",
+ "url_lookup_service_factory.h",
+ ]
+
+ deps = [
+ ":verdict_cache_manager_factory",
+ "//chrome/common",
+ "//components/keyed_service/content",
+ "//components/safe_browsing/core/realtime:url_lookup_service",
+ "//components/signin/public/identity_manager",
+ "//content/public/browser",
+ ]
+}
+
+source_set("verdict_cache_manager_factory") {
+ sources = [
+ "verdict_cache_manager_factory.cc",
+ "verdict_cache_manager_factory.h",
+ ]
+
+ deps = [
+ "//components/content_settings/core/browser",
+ "//components/history/core/browser",
+ "//components/keyed_service/content",
+ "//components/prefs",
+ "//components/safe_browsing/core:verdict_cache_manager",
+ "//content/public/browser",
+ ]
+}
+
static_library("advanced_protection") {
sources = [
"advanced_protection_status_manager.cc",
@@ -275,8 +318,8 @@ static_library("advanced_protection") {
deps = [
"//components/keyed_service/content",
"//components/prefs",
- "//components/safe_browsing/common",
- "//components/safe_browsing/common:safe_browsing_prefs",
+ "//components/safe_browsing/core/common",
+ "//components/safe_browsing/core/common:safe_browsing_prefs",
"//components/signin/public/identity_manager",
"//content/public/browser",
]
@@ -293,9 +336,9 @@ source_set("test_support") {
":safe_browsing",
"//chrome/common/safe_browsing:proto",
"//components/safe_browsing:buildflags",
- "//components/safe_browsing/db:database_manager",
- "//components/safe_browsing/db:test_database_manager",
- "//components/safe_browsing/db:v4_protocol_manager_util",
+ "//components/safe_browsing/core/db:database_manager",
+ "//components/safe_browsing/core/db:test_database_manager",
+ "//components/safe_browsing/core/db:v4_protocol_manager_util",
"//content/public/browser",
]
}
diff --git a/chromium/chrome/browser/safe_browsing/chrome_cleaner/BUILD.gn b/chromium/chrome/browser/safe_browsing/chrome_cleaner/BUILD.gn
index 668bbdd1c24..5cb868b9950 100644
--- a/chromium/chrome/browser/safe_browsing/chrome_cleaner/BUILD.gn
+++ b/chromium/chrome/browser/safe_browsing/chrome_cleaner/BUILD.gn
@@ -67,7 +67,7 @@ jumbo_static_library("chrome_cleaner") {
"//components/crx_file",
"//components/pref_registry",
"//components/prefs",
- "//components/safe_browsing/common:safe_browsing_prefs",
+ "//components/safe_browsing/core/common:safe_browsing_prefs",
"//content/public/browser",
"//extensions/browser",
"//third_party/protobuf:protobuf_lite",
diff --git a/chromium/chrome/browser/safe_browsing/incident_reporting/BUILD.gn b/chromium/chrome/browser/safe_browsing/incident_reporting/BUILD.gn
index 4de023f0c17..2934b9ba5a5 100644
--- a/chromium/chrome/browser/safe_browsing/incident_reporting/BUILD.gn
+++ b/chromium/chrome/browser/safe_browsing/incident_reporting/BUILD.gn
@@ -5,7 +5,5 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("state_store_data_proto") {
- sources = [
- "state_store_data.proto",
- ]
+ sources = [ "state_store_data.proto" ]
}
diff --git a/chromium/chrome/browser/safe_browsing/incident_reporting/verifier_test/BUILD.gn b/chromium/chrome/browser/safe_browsing/incident_reporting/verifier_test/BUILD.gn
index be7f890c615..386bc793063 100644
--- a/chromium/chrome/browser/safe_browsing/incident_reporting/verifier_test/BUILD.gn
+++ b/chromium/chrome/browser/safe_browsing/incident_reporting/verifier_test/BUILD.gn
@@ -10,11 +10,6 @@ shared_library("verifier_test_dll_1") {
"verifier_test_dll.cc",
"verifier_test_dll_1.def",
]
-
- # Unconditionally disable incremental linking for these modules so that
- # their exports do not go through an ILT jmp stub.
- configs -= [ "//build/config/win:default_incremental_linking" ]
- configs += [ "//build/config/win:no_incremental_linking" ]
}
shared_library("verifier_test_dll_2") {
@@ -23,6 +18,4 @@ shared_library("verifier_test_dll_2") {
"verifier_test_dll.cc",
"verifier_test_dll_2.def",
]
- configs -= [ "//build/config/win:default_incremental_linking" ]
- configs += [ "//build/config/win:no_incremental_linking" ]
}
diff --git a/chromium/chrome/browser/search/BUILD.gn b/chromium/chrome/browser/search/BUILD.gn
index c610750bd07..affdfffc8ed 100644
--- a/chromium/chrome/browser/search/BUILD.gn
+++ b/chromium/chrome/browser/search/BUILD.gn
@@ -25,9 +25,7 @@ action("local_ntp_code_generate") {
voice_js,
]
- outputs = [
- header_path,
- ]
+ outputs = [ header_path ]
args = [
"--output_path=" + rebase_path(header_path, root_build_dir),
@@ -44,7 +42,5 @@ action("local_ntp_code_generate") {
source_set("generated") {
sources = get_target_outputs(":local_ntp_code_generate")
- public_deps = [
- ":local_ntp_code_generate",
- ]
+ public_deps = [ ":local_ntp_code_generate" ]
}
diff --git a/chromium/chrome/browser/settings/BUILD.gn b/chromium/chrome/browser/settings/BUILD.gn
new file mode 100644
index 00000000000..b49326cbfcf
--- /dev/null
+++ b/chromium/chrome/browser/settings/BUILD.gn
@@ -0,0 +1,38 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+ sources = [ "android/java/src/org/chromium/chrome/browser/settings/ChromeManagedPreferenceDelegate.java" ]
+ deps = [
+ "//chrome/browser/preferences:java",
+ "//components/browser_ui/settings/android:java",
+ ]
+}
+
+android_library("javatests") {
+ testonly = true
+
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/settings/ChromeBasePreferenceTest.java",
+ "android/java/src/org/chromium/chrome/browser/settings/ChromeImageViewPreferenceTest.java",
+ "android/java/src/org/chromium/chrome/browser/settings/DummySettingsForTest.java",
+ "android/java/src/org/chromium/chrome/browser/settings/ManagedPreferencesUtilsTest.java",
+ ]
+
+ deps = [
+ ":java",
+ "//chrome/android:chrome_java",
+ "//chrome/test/android:chrome_java_test_support",
+ "//content/public/test/android:content_java_test_support",
+ "//third_party/android_deps:android_support_v7_appcompat_java",
+ "//third_party/android_deps:androidx_preference_preference_java",
+ "//third_party/android_support_test_runner:rules_java",
+ "//third_party/android_support_test_runner:runner_java",
+ "//third_party/espresso:espresso_all_java",
+ "//third_party/hamcrest:hamcrest_java",
+ "//third_party/junit",
+ ]
+}
diff --git a/chromium/chrome/browser/share/BUILD.gn b/chromium/chrome/browser/share/BUILD.gn
index d35da0ba858..5cf94f28eb1 100644
--- a/chromium/chrome/browser/share/BUILD.gn
+++ b/chromium/chrome/browser/share/BUILD.gn
@@ -7,7 +7,5 @@ source_set("share") {
"features.cc",
"features.h",
]
- deps = [
- "//base",
- ]
+ deps = [ "//base" ]
}
diff --git a/chromium/chrome/browser/share/android/BUILD.gn b/chromium/chrome/browser/share/android/BUILD.gn
index ba6fd64b425..d630fe60b66 100644
--- a/chromium/chrome/browser/share/android/BUILD.gn
+++ b/chromium/chrome/browser/share/android/BUILD.gn
@@ -5,11 +5,21 @@
import("//build/config/android/rules.gni")
android_resources("java_resources") {
- # TODO(gayane): remove dependency on chrome/android:chrome_app_java_resources
- # once strings and common styles move out of chrome/android
- deps = [
- "//chrome/android:chrome_app_java_resources",
+ sources = [
+ "java/res/drawable-hdpi/camera.png",
+ "java/res/drawable-mdpi/camera.png",
+ "java/res/drawable-xhdpi/camera.png",
+ "java/res/drawable-xxhdpi/camera.png",
+ "java/res/drawable-xxxhdpi/camera.png",
+ "java/res/drawable/qrcode_background.xml",
+ "java/res/layout/qrcode_camera_error_layout.xml",
+ "java/res/layout/qrcode_dialog.xml",
+ "java/res/layout/qrcode_open_settings_layout.xml",
+ "java/res/layout/qrcode_permission_layout.xml",
+ "java/res/layout/qrcode_share_layout.xml",
+ "java/res/values-sw600dp/dimens.xml",
+ "java/res/values/colors.xml",
+ "java/res/values/dimens.xml",
]
- resource_dirs = [ "java/res" ]
custom_package = "org.chromium.chrome.browser.share.qrcode"
}
diff --git a/chromium/chrome/browser/share/android/java_sources.gni b/chromium/chrome/browser/share/android/java_sources.gni
index dd4a557216f..767fcd5bf86 100644
--- a/chromium/chrome/browser/share/android/java_sources.gni
+++ b/chromium/chrome/browser/share/android/java_sources.gni
@@ -2,19 +2,29 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-# TODO(gayane): This should be a separate build target when circular dependencies are removed.
+# TODO(crbug/1022172): This should be a separate build target when circular
+# dependencies are removed.
share_java_sources = [
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/SaveImageNotificationManager.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ShareImageFileUtils.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProvider.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeCoordinator.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialog.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialogTab.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodePageAdapter.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeShareActivity.java",
- "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareView.java",
- "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareCoordinator.java",
- "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanView.java",
- "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanCoordinator.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/TabLayoutPageListener.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/CameraPreview.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/CameraPreviewOverlay.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanCoordinator.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanMediator.java",
- "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanViewProperties.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanView.java",
"//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanViewBinder.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanViewProperties.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareCoordinator.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareMediator.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareView.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareViewBinder.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareViewProperties.java",
+ "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotCoordinator.java",
]
diff --git a/chromium/chrome/browser/share/android/test_java_sources.gni b/chromium/chrome/browser/share/android/test_java_sources.gni
new file mode 100644
index 00000000000..f891735ffcb
--- /dev/null
+++ b/chromium/chrome/browser/share/android/test_java_sources.gni
@@ -0,0 +1,6 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO(crbug.com/1022172): This should be a separate build target when circular dependencies are removed.
+share_test_java_sources = [ "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/ShareImageFileUtilsTest.java" ]
diff --git a/chromium/chrome/browser/sharing/BUILD.gn b/chromium/chrome/browser/sharing/BUILD.gn
new file mode 100644
index 00000000000..6123786becb
--- /dev/null
+++ b/chromium/chrome/browser/sharing/BUILD.gn
@@ -0,0 +1,11 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/buildflag_header.gni")
+import("//chrome/browser/sharing/buildflags.gni")
+
+buildflag_header("buildflags") {
+ header = "buildflags.h"
+ flags = [ "ENABLE_DISCOVERY=$enable_discovery" ]
+}
diff --git a/chromium/chrome/browser/sharing/buildflags.gni b/chromium/chrome/browser/sharing/buildflags.gni
new file mode 100644
index 00000000000..11393cd5f2d
--- /dev/null
+++ b/chromium/chrome/browser/sharing/buildflags.gni
@@ -0,0 +1,7 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+declare_args() {
+ enable_discovery = false
+}
diff --git a/chromium/chrome/browser/sharing/proto/BUILD.gn b/chromium/chrome/browser/sharing/proto/BUILD.gn
new file mode 100644
index 00000000000..67a6d2dc5d6
--- /dev/null
+++ b/chromium/chrome/browser/sharing/proto/BUILD.gn
@@ -0,0 +1,20 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import("//third_party/protobuf/proto_library.gni")
+group("proto_lite") {
+ public_deps = [
+ ":proto",
+ "//third_party/protobuf:protobuf_lite",
+ ]
+}
+proto_library("proto") {
+ sources = [
+ "click_to_call_message.proto",
+ "peer_connection_messages.proto",
+ "remote_copy_message.proto",
+ "shared_clipboard_message.proto",
+ "sharing_message.proto",
+ "sms_fetch_message.proto",
+ ]
+}
diff --git a/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc b/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
index d13c36c5278..bce592b0662 100644
--- a/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
+++ b/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.cc
@@ -7,11 +7,13 @@
#include "base/bind.h"
#include "base/no_destructor.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
#include "chrome/browser/spellchecker/spellcheck_custom_dictionary.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "components/spellcheck/browser/spellcheck_host_metrics.h"
#include "components/spellcheck/browser/spellcheck_platform.h"
+#include "components/spellcheck/spellcheck_buildflags.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
@@ -21,10 +23,6 @@
#include "chrome/browser/spellchecker/spelling_request.h"
#endif
-#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
-#include "components/spellcheck/common/spellcheck_common.h"
-#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
-
namespace {
SpellCheckHostChromeImpl::Binder& GetSpellCheckHostBinderOverride() {
@@ -175,53 +173,43 @@ void SpellCheckHostChromeImpl::RequestTextCheck(
int route_id,
RequestTextCheckCallback callback) {
DCHECK(!text.empty());
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ // Initialize the spellcheck service if needed. The service will send the
+ // language code for text breaking to the renderer. (Text breaking is required
+ // for the context menu to show spelling suggestions.) Initialization must
+ // happen on UI thread.
+ SpellcheckService* spellcheck = GetSpellcheckService();
+
+ if (!spellcheck) { // Teardown.
+ std::move(callback).Run({});
+ return;
+ }
// OK to store unretained |this| in a |SpellingRequest| owned by |this|.
- auto request = std::make_unique<SpellingRequest>(
- &client_, text, render_process_id_, route_id, std::move(callback),
+ requests_.insert(std::make_unique<SpellingRequest>(
+ spellcheck->platform_spell_checker(), &client_, text, render_process_id_,
+ route_id, std::move(callback),
base::BindOnce(&SpellCheckHostChromeImpl::OnRequestFinished,
- base::Unretained(this)));
- QueueRequest(std::move(request));
+ base::Unretained(this))));
}
#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
void SpellCheckHostChromeImpl::GetPerLanguageSuggestions(
const base::string16& word,
GetPerLanguageSuggestionsCallback callback) {
- spellcheck_platform::GetPerLanguageSuggestions(word, std::move(callback));
-}
+ SpellcheckService* spellcheck = GetSpellcheckService();
-void SpellCheckHostChromeImpl::RequestPartialTextCheck(
- const base::string16& text,
- int route_id,
- const std::vector<SpellCheckResult>& partial_results,
- bool fill_suggestions,
- RequestPartialTextCheckCallback callback) {
- DCHECK(!text.empty());
+ if (!spellcheck) { // Teardown.
+ std::move(callback).Run({});
+ return;
+ }
- // OK to store unretained |this| in a |SpellingRequest| owned by |this|.
- auto request = std::make_unique<SpellingRequest>(
- &client_, text, render_process_id_, route_id, partial_results,
- fill_suggestions, std::move(callback),
- base::BindOnce(&SpellCheckHostChromeImpl::OnRequestFinished,
- base::Unretained(this)));
- QueueRequest(std::move(request));
+ spellcheck_platform::GetPerLanguageSuggestions(
+ spellcheck->platform_spell_checker(), word, std::move(callback));
}
#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
-void SpellCheckHostChromeImpl::QueueRequest(
- std::unique_ptr<SpellingRequest> request) {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- // Initialize the spellcheck service if needed. The service will send the
- // language code for text breaking to the renderer. (Text breaking is required
- // for the context menu to show spelling suggestions.) Initialization must
- // happen on UI thread.
- GetSpellcheckService();
-
- requests_.insert(std::move(request));
-}
-
void SpellCheckHostChromeImpl::OnRequestFinished(SpellingRequest* request) {
auto iterator = requests_.find(request);
requests_.erase(iterator);
diff --git a/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.h b/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.h
index 074b32ad11e..984b852311b 100644
--- a/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.h
+++ b/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl.h
@@ -9,6 +9,7 @@
#include "base/containers/unique_ptr_adapters.h"
#include "build/build_config.h"
#include "components/spellcheck/browser/spell_check_host_impl.h"
+#include "components/spellcheck/spellcheck_buildflags.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#if BUILDFLAG(ENABLE_SPELLING_SERVICE)
@@ -82,16 +83,8 @@ class SpellCheckHostChromeImpl : public SpellCheckHostImpl {
void GetPerLanguageSuggestions(
const base::string16& word,
GetPerLanguageSuggestionsCallback callback) override;
- void RequestPartialTextCheck(
- const base::string16& text,
- int route_id,
- const std::vector<SpellCheckResult>& partial_results,
- bool fill_suggestions,
- RequestPartialTextCheckCallback callback) override;
#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
- void QueueRequest(std::unique_ptr<SpellingRequest> request);
-
// Clears a finished request from |requests_|. Exposed to SpellingRequest.
void OnRequestFinished(SpellingRequest* request);
diff --git a/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc b/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc
index a47d8d9de41..ec20bc039a1 100644
--- a/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc
+++ b/chromium/chrome/browser/spellchecker/spell_check_host_chrome_impl_win_browsertest.cc
@@ -9,19 +9,32 @@
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/win/windows_version.h"
+#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/spellchecker/spellcheck_factory.h"
+#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "components/spellcheck/browser/spellcheck_platform.h"
#include "components/spellcheck/common/spellcheck_features.h"
+#include "components/spellcheck/spellcheck_buildflags.h"
#include "content/public/browser/browser_context.h"
#include "content/public/test/mock_render_process_host.h"
#include "mojo/public/cpp/bindings/remote.h"
+class PlatformSpellChecker;
+
class SpellCheckHostChromeImplWinBrowserTest : public InProcessBrowserTest {
public:
SpellCheckHostChromeImplWinBrowserTest() {
+#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
+ feature_list_.InitWithFeatures(
+ /*enabled_features=*/{spellcheck::kWinUseBrowserSpellChecker,
+ spellcheck::kWinUseHybridSpellChecker},
+ /*disabled_features=*/{});
+#else
feature_list_.InitAndEnableFeature(spellcheck::kWinUseBrowserSpellChecker);
+#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
}
void SetUpOnMainThread() override {
@@ -30,17 +43,28 @@ class SpellCheckHostChromeImplWinBrowserTest : public InProcessBrowserTest {
SpellCheckHostChromeImpl::Create(
renderer_->GetID(), spell_check_host_.BindNewPipeAndPassReceiver());
+
+ platform_spell_checker_ = SpellcheckServiceFactory::GetForContext(context)
+ ->platform_spell_checker();
}
void TearDownOnMainThread() override { renderer_.reset(); }
- void LogResult(const std::vector<SpellCheckResult>& result) {
+ void OnSpellcheckResult(const std::vector<SpellCheckResult>& result) {
received_result_ = true;
result_ = result;
if (quit_)
std::move(quit_).Run();
}
+ void OnSuggestionResult(
+ const std::vector<std::vector<::base::string16>>& suggestions) {
+ received_result_ = true;
+ suggestion_result_ = suggestions;
+ if (quit_)
+ std::move(quit_).Run();
+ }
+
void SetLanguageCompletionCallback(bool result) {
received_result_ = true;
if (quit_)
@@ -59,32 +83,37 @@ class SpellCheckHostChromeImplWinBrowserTest : public InProcessBrowserTest {
}
protected:
+ PlatformSpellChecker* platform_spell_checker_;
base::test::ScopedFeatureList feature_list_;
std::unique_ptr<content::MockRenderProcessHost> renderer_;
mojo::Remote<spellcheck::mojom::SpellCheckHost> spell_check_host_;
bool received_result_ = false;
std::vector<SpellCheckResult> result_;
+ std::vector<std::vector<::base::string16>> suggestion_result_;
base::OnceClosure quit_;
};
// Uses browsertest to setup chrome threads.
IN_PROC_BROWSER_TEST_F(SpellCheckHostChromeImplWinBrowserTest,
SpellCheckReturnMessage) {
- if (base::win::GetVersion() < base::win::Version::WIN8)
+ if (!spellcheck::WindowsVersionSupportsSpellchecker()) {
return;
+ }
spellcheck_platform::SetLanguage(
- "en-US", base::BindOnce(&SpellCheckHostChromeImplWinBrowserTest::
- SetLanguageCompletionCallback,
- base::Unretained(this)));
-
+ platform_spell_checker_, "en-US",
+ base::BindOnce(&SpellCheckHostChromeImplWinBrowserTest::
+ SetLanguageCompletionCallback,
+ base::Unretained(this)));
RunUntilResultReceived();
spell_check_host_->RequestTextCheck(
- base::UTF8ToUTF16("zz."), 123,
- base::BindOnce(&SpellCheckHostChromeImplWinBrowserTest::LogResult,
- base::Unretained(this)));
+ base::UTF8ToUTF16("zz."),
+ /*route_id=*/123,
+ base::BindOnce(
+ &SpellCheckHostChromeImplWinBrowserTest::OnSpellcheckResult,
+ base::Unretained(this)));
RunUntilResultReceived();
ASSERT_EQ(1U, result_.size());
@@ -92,3 +121,30 @@ IN_PROC_BROWSER_TEST_F(SpellCheckHostChromeImplWinBrowserTest,
EXPECT_EQ(result_[0].length, 2);
EXPECT_EQ(result_[0].decoration, SpellCheckResult::SPELLING);
}
+
+#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
+IN_PROC_BROWSER_TEST_F(SpellCheckHostChromeImplWinBrowserTest,
+ GetPerLanguageSuggestions) {
+ if (!spellcheck::WindowsVersionSupportsSpellchecker()) {
+ return;
+ }
+
+ spellcheck_platform::SetLanguage(
+ platform_spell_checker_, "en-US",
+ base::BindOnce(&SpellCheckHostChromeImplWinBrowserTest::
+ SetLanguageCompletionCallback,
+ base::Unretained(this)));
+ RunUntilResultReceived();
+
+ spell_check_host_->GetPerLanguageSuggestions(
+ base::UTF8ToUTF16("tihs"),
+ base::BindOnce(
+ &SpellCheckHostChromeImplWinBrowserTest::OnSuggestionResult,
+ base::Unretained(this)));
+ RunUntilResultReceived();
+
+ // Should have 1 vector of results, which should contain at least 1 suggestion
+ ASSERT_EQ(1U, suggestion_result_.size());
+ EXPECT_GT(suggestion_result_[0].size(), 0U);
+}
+#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc b/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
index 0decf90b820..7b85b1eb915 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
@@ -20,6 +20,7 @@
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/task_runner_util.h"
#include "base/threading/scoped_blocking_call.h"
#include "chrome/common/chrome_constants.h"
@@ -222,8 +223,8 @@ int SpellcheckCustomDictionary::Change::Sanitize(
SpellcheckCustomDictionary::SpellcheckCustomDictionary(
const base::FilePath& dictionary_directory_name)
- : task_runner_(base::CreateSequencedTaskRunner(
- {base::ThreadPool(), base::MayBlock()})),
+ : task_runner_(
+ base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
custom_dictionary_path_(
dictionary_directory_name.Append(chrome::kCustomDictionaryFileName)),
is_loaded_(false) {}
@@ -349,7 +350,7 @@ void SpellcheckCustomDictionary::StopSyncing(syncer::ModelType type) {
sync_error_handler_.reset();
}
-syncer::SyncDataList SpellcheckCustomDictionary::GetAllSyncData(
+syncer::SyncDataList SpellcheckCustomDictionary::GetAllSyncDataForTesting(
syncer::ModelType type) const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_EQ(syncer::DICTIONARY, type);
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.h b/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.h
index 7ea9991617c..61e2e8a57fc 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.h
+++ b/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary.h
@@ -154,7 +154,7 @@ class SpellcheckCustomDictionary : public SpellcheckDictionary,
std::unique_ptr<syncer::SyncChangeProcessor> sync_processor,
std::unique_ptr<syncer::SyncErrorFactory> sync_error_handler) override;
void StopSyncing(syncer::ModelType type) override;
- syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const override;
+ syncer::SyncDataList GetAllSyncDataForTesting(syncer::ModelType type) const;
syncer::SyncError ProcessSyncChanges(
const base::Location& from_here,
const syncer::SyncChangeList& change_list) override;
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc b/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc
index 1b75004b2f1..385d13fe3e8 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_custom_dictionary_unittest.cc
@@ -300,13 +300,14 @@ TEST_F(SpellcheckCustomDictionaryTest,
SpellcheckServiceFactory::GetForContext(
&profile_)->GetCustomDictionary();
- syncer::SyncDataList data = dictionary->GetAllSyncData(syncer::DICTIONARY);
+ syncer::SyncDataList data =
+ dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY);
EXPECT_TRUE(data.empty());
EXPECT_TRUE(dictionary->AddWord("bar"));
EXPECT_TRUE(dictionary->AddWord("foo"));
- data = dictionary->GetAllSyncData(syncer::DICTIONARY);
+ data = dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY);
EXPECT_EQ(2UL, data.size());
std::vector<std::string> words;
words.push_back("bar");
@@ -321,7 +322,7 @@ TEST_F(SpellcheckCustomDictionaryTest,
EXPECT_TRUE(dictionary->RemoveWord("bar"));
EXPECT_TRUE(dictionary->RemoveWord("foo"));
- data = dictionary->GetAllSyncData(syncer::DICTIONARY);
+ data = dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY);
EXPECT_TRUE(data.empty());
}
@@ -338,25 +339,25 @@ TEST_F(SpellcheckCustomDictionaryTest, GetAllSyncDataHasLimit) {
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords - 1,
dictionary->GetWords().size());
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords - 1,
- dictionary->GetAllSyncData(syncer::DICTIONARY).size());
+ dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
dictionary->AddWord("baz");
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
dictionary->GetWords().size());
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- dictionary->GetAllSyncData(syncer::DICTIONARY).size());
+ dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
dictionary->AddWord("bar");
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords + 1,
dictionary->GetWords().size());
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- dictionary->GetAllSyncData(syncer::DICTIONARY).size());
+ dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
dictionary->AddWord("snafoo");
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords + 2,
dictionary->GetWords().size());
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- dictionary->GetAllSyncData(syncer::DICTIONARY).size());
+ dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, ProcessSyncChanges) {
@@ -455,17 +456,18 @@ TEST_F(SpellcheckCustomDictionaryTest, MergeDataAndStartSyncing) {
Apply(*custom_dictionary2, change2);
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
@@ -515,17 +517,18 @@ TEST_F(SpellcheckCustomDictionaryTest, SyncBeforeLoadDoesNotDuplicateWords) {
EXPECT_TRUE(custom_dictionary->GetWords().empty());
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
@@ -563,17 +566,18 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigBeforeSyncing) {
Apply(*custom_dictionary, change);
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(custom_dictionary->IsSyncing());
@@ -582,10 +586,12 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigBeforeSyncing) {
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
custom_dictionary2->GetWords().size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigAndServerFull) {
@@ -616,17 +622,18 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigAndServerFull) {
custom_dictionary2->GetWords().size());
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(custom_dictionary->IsSyncing());
@@ -635,10 +642,12 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigAndServerFull) {
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
custom_dictionary2->GetWords().size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, ServerTooBig) {
@@ -687,10 +696,12 @@ TEST_F(SpellcheckCustomDictionaryTest, ServerTooBig) {
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords + 1,
custom_dictionary2->GetWords().size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToStartSyncing) {
@@ -715,17 +726,18 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToStartSyncing) {
custom_dictionary2->AddWord("baz");
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(custom_dictionary->IsSyncing());
@@ -734,10 +746,12 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToStartSyncing) {
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
custom_dictionary2->GetWords().size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToContiueSyncing) {
@@ -759,17 +773,18 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToContiueSyncing) {
Apply(*custom_dictionary, change);
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
@@ -786,10 +801,12 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionaryTooBigToContiueSyncing) {
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
custom_dictionary2->GetWords().size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStart) {
@@ -807,17 +824,18 @@ TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStart) {
custom_dictionary->AddWord("foo");
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
@@ -830,8 +848,12 @@ TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStart) {
EXPECT_EQ(2UL, custom_dictionary->GetWords().size());
EXPECT_EQ(2UL, custom_dictionary2->GetWords().size());
- EXPECT_EQ(2UL, custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
- EXPECT_EQ(2UL, custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ 2UL,
+ custom_dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ 2UL,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStartTooBigToSync) {
@@ -849,17 +871,18 @@ TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStartTooBigToSync) {
custom_dictionary->AddWord("foo");
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
@@ -877,10 +900,12 @@ TEST_F(SpellcheckCustomDictionaryTest, LoadAfterSyncStartTooBigToSync) {
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
custom_dictionary2->GetWords().size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, LoadDuplicatesAfterSync) {
@@ -902,17 +927,18 @@ TEST_F(SpellcheckCustomDictionaryTest, LoadDuplicatesAfterSync) {
Apply(*custom_dictionary, change);
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
@@ -926,10 +952,12 @@ TEST_F(SpellcheckCustomDictionaryTest, LoadDuplicatesAfterSync) {
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords / 2,
custom_dictionary2->GetWords().size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords / 2,
- custom_dictionary->GetAllSyncData(syncer::DICTIONARY).size());
- EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords / 2,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords / 2,
+ custom_dictionary->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
+ EXPECT_EQ(
+ spellcheck::kMaxSyncableDictionaryWords / 2,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY).size());
}
TEST_F(SpellcheckCustomDictionaryTest, DictionaryLoadNotification) {
@@ -1024,17 +1052,18 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncNotification) {
custom_dictionary2->AddObserver(&observer2);
int error_counter = 0;
- EXPECT_FALSE(custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- custom_dictionary2->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- custom_dictionary2)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(
+ custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ custom_dictionary2->GetAllSyncDataForTesting(syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ custom_dictionary2)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
@@ -1074,18 +1103,18 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncLimit) {
Apply(*custom_dictionary, change);
int error_counter = 0;
- EXPECT_FALSE(
- custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- server_custom_dictionary)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ server_custom_dictionary->GetAllSyncDataForTesting(
+ syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ server_custom_dictionary)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_TRUE(custom_dictionary->IsSyncing());
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords,
@@ -1120,18 +1149,18 @@ TEST_F(SpellcheckCustomDictionaryTest, DictionarySyncLimit) {
// Associate the server and the client.
int error_counter = 0;
- EXPECT_FALSE(
- client_custom_dictionary
- ->MergeDataAndStartSyncing(
- syncer::DICTIONARY,
- server_custom_dictionary->GetAllSyncData(syncer::DICTIONARY),
- std::unique_ptr<syncer::SyncChangeProcessor>(
- new syncer::SyncChangeProcessorWrapperForTest(
- server_custom_dictionary)),
- std::unique_ptr<syncer::SyncErrorFactory>(
- new SyncErrorFactoryStub(&error_counter)))
- .error()
- .IsSet());
+ EXPECT_FALSE(client_custom_dictionary
+ ->MergeDataAndStartSyncing(
+ syncer::DICTIONARY,
+ server_custom_dictionary->GetAllSyncDataForTesting(
+ syncer::DICTIONARY),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::SyncChangeProcessorWrapperForTest(
+ server_custom_dictionary)),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new SyncErrorFactoryStub(&error_counter)))
+ .error()
+ .IsSet());
EXPECT_EQ(0, error_counter);
EXPECT_FALSE(client_custom_dictionary->IsSyncing());
EXPECT_EQ(spellcheck::kMaxSyncableDictionaryWords * 2,
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc b/chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
index 8f1c8d53401..47179fbe844 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.cc
@@ -16,6 +16,7 @@
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/task_runner_util.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -110,16 +111,13 @@ SpellcheckHunspellDictionary::SpellcheckHunspellDictionary(
const std::string& language,
content::BrowserContext* browser_context,
SpellcheckService* spellcheck_service)
- : task_runner_(base::CreateSequencedTaskRunner(
- {base::ThreadPool(), base::MayBlock()})),
+ : task_runner_(
+ base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})),
language_(language),
use_browser_spellchecker_(false),
browser_context_(browser_context),
-#if !defined(OS_ANDROID)
spellcheck_service_(spellcheck_service),
-#endif
- download_status_(DOWNLOAD_NONE) {
-}
+ download_status_(DOWNLOAD_NONE) {}
SpellcheckHunspellDictionary::~SpellcheckHunspellDictionary() {
if (dictionary_file_.file.IsValid()) {
@@ -131,8 +129,9 @@ SpellcheckHunspellDictionary::~SpellcheckHunspellDictionary() {
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
// Disable the language from platform spellchecker.
if (spellcheck::UseBrowserSpellChecker())
- spellcheck_platform::DisableLanguage(language_);
-#endif
+ spellcheck_platform::DisableLanguage(
+ spellcheck_service_->platform_spell_checker(), language_);
+#endif // BUILDFLAG(USE_BROWSER_SPELLCHECKER)
}
void SpellcheckHunspellDictionary::Load() {
@@ -142,10 +141,10 @@ void SpellcheckHunspellDictionary::Load() {
if (spellcheck::UseBrowserSpellChecker() &&
spellcheck_platform::SpellCheckerAvailable()) {
spellcheck_platform::PlatformSupportsLanguage(
- language_,
+ spellcheck_service_->platform_spell_checker(), language_,
base::BindOnce(
&SpellcheckHunspellDictionary::PlatformSupportsLanguageComplete,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
return;
}
#endif // USE_BROWSER_SPELLCHECKER
@@ -445,9 +444,10 @@ void SpellcheckHunspellDictionary::PlatformSupportsLanguageComplete(
#if BUILDFLAG(USE_BROWSER_SPELLCHECKER)
if (spellcheck::UseBrowserSpellChecker()) {
spellcheck_platform::SetLanguage(
- language_, base::BindOnce(&SpellcheckHunspellDictionary::
- SpellCheckPlatformSetLanguageComplete,
- base::Unretained(this)));
+ spellcheck_service_->platform_spell_checker(), language_,
+ base::BindOnce(&SpellcheckHunspellDictionary::
+ SpellCheckPlatformSetLanguageComplete,
+ weak_ptr_factory_.GetWeakPtr()));
return;
}
#endif // BUILDFLAG(USE_BROWSER_SPELLCHECKER)
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h b/chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
index 074e9516d72..4af3201238d 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
+++ b/chromium/chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h
@@ -169,9 +169,7 @@ class SpellcheckHunspellDictionary
// Used for downloading the dictionary file.
std::unique_ptr<network::SimpleURLLoader> simple_loader_;
-#if !defined(OS_ANDROID)
SpellcheckService* const spellcheck_service_;
-#endif
// Observers of Hunspell dictionary events.
base::ObserverList<Observer>::Unchecked observers_;
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc b/chromium/chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc
index 70135a8f31b..77fd7c2490d 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc
@@ -40,12 +40,12 @@ bool SpellcheckLanguageBlacklistPolicyHandler::CheckPolicySettings(
SortBlacklistedLanguages(policies, &blacklisted, &unknown, &duplicates);
#if !defined(OS_MACOSX)
- for (const std::string language : duplicates) {
+ for (const std::string& language : duplicates) {
errors->AddError(policy_name(), IDS_POLICY_SPELLCHECK_BLACKLIST_IGNORE,
language);
}
- for (const std::string language : unknown) {
+ for (const std::string& language : unknown) {
errors->AddError(policy_name(), IDS_POLICY_SPELLCHECK_UNKNOWN_LANGUAGE,
language);
}
@@ -75,14 +75,14 @@ void SpellcheckLanguageBlacklistPolicyHandler::ApplyPolicySettings(
std::vector<std::string> duplicates;
SortBlacklistedLanguages(policies, &blacklisted, &unknown, &duplicates);
- for (const std::string language : duplicates) {
+ for (const std::string& language : duplicates) {
SYSLOG(WARNING)
<< "SpellcheckLanguageBlacklist policy: an entry was also found in"
" the SpellcheckLanguage policy: \""
<< language << "\". Blacklist entry will be ignored.";
}
- for (const std::string language : unknown) {
+ for (const std::string& language : unknown) {
SYSLOG(WARNING) << "SpellcheckLanguageBlacklist policy: Unknown or "
"unsupported language \""
<< language << "\"";
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_mac_view_browsertest.mm b/chromium/chrome/browser/spellchecker/spellcheck_mac_view_interactive_uitest.mm
index 4ab4943a317..5bb646f0fca 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_mac_view_browsertest.mm
+++ b/chromium/chrome/browser/spellchecker/spellcheck_mac_view_interactive_uitest.mm
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#import <Cocoa/Cocoa.h>
+
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
@@ -17,13 +18,14 @@
namespace {
-class SpellCheckMacViewBrowserTest : public InProcessBrowserTest {
+class SpellCheckMacViewInteractiveUiTest : public InProcessBrowserTest {
public:
- SpellCheckMacViewBrowserTest() {}
+ SpellCheckMacViewInteractiveUiTest() {}
};
#if BUILDFLAG(ENABLE_SPELLCHECK)
-IN_PROC_BROWSER_TEST_F(SpellCheckMacViewBrowserTest, SpellCheckPanelVisible) {
+IN_PROC_BROWSER_TEST_F(SpellCheckMacViewInteractiveUiTest,
+ SpellCheckPanelVisible) {
spellcheck::SpellCheckPanelBrowserTestHelper test_helper;
ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_service.cc b/chromium/chrome/browser/spellchecker/spellcheck_service.cc
index 6a508168067..7d3ddb783ca 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_service.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_service.cc
@@ -39,6 +39,13 @@
#include "content/public/browser/storage_partition.h"
#include "mojo/public/cpp/bindings/remote.h"
+#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "components/spellcheck/browser/windows_spell_checker.h"
+#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+
using content::BrowserThread;
namespace {
@@ -61,6 +68,16 @@ SpellcheckService::EventType g_status_type =
SpellcheckService::SpellcheckService(content::BrowserContext* context)
: context_(context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+#if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+ // The Windows spell checker must be created before the dictionaries are
+ // initialized.
+ if (spellcheck::WindowsVersionSupportsSpellchecker()) {
+ platform_spell_checker_ = std::make_unique<WindowsSpellChecker>(
+ base::ThreadPool::CreateCOMSTATaskRunner({base::MayBlock()}));
+ }
+#endif // defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER)
+
PrefService* prefs = user_prefs::UserPrefs::Get(context);
pref_change_registrar_.Init(prefs);
StringListPrefMember dictionaries_pref;
@@ -189,8 +206,8 @@ void SpellcheckService::StartRecordingMetrics(bool spellcheck_enabled) {
OnUseSpellingServiceChanged();
#if defined(OS_WIN)
- RecordMissingLanguagePacksCount();
- RecordHunspellUnsupportedLanguageCount(GetNormalizedAcceptLanguages());
+ RecordChromeLocalesStats();
+ RecordSpellcheckLocalesStats();
#endif // defined(OS_WIN)
}
@@ -270,7 +287,7 @@ void SpellcheckService::LoadHunspellDictionaries() {
}
#if defined(OS_WIN)
- RecordMissingLanguagePacksCount();
+ RecordSpellcheckLocalesStats();
#endif // defined(OS_WIN)
}
@@ -415,44 +432,46 @@ void SpellcheckService::OnAcceptLanguagesChanged() {
dictionaries_pref.SetValue(filtered_dictionaries);
#if defined(OS_WIN)
- RecordHunspellUnsupportedLanguageCount(accept_languages);
+ RecordChromeLocalesStats();
#endif // defined(OS_WIN)
}
-std::vector<std::string> SpellcheckService::GetNormalizedAcceptLanguages()
- const {
+std::vector<std::string> SpellcheckService::GetNormalizedAcceptLanguages(
+ bool normalize_for_spellcheck) const {
PrefService* prefs = user_prefs::UserPrefs::Get(context_);
std::vector<std::string> accept_languages =
base::SplitString(prefs->GetString(language::prefs::kAcceptLanguages),
",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- std::transform(accept_languages.begin(), accept_languages.end(),
- accept_languages.begin(),
- &spellcheck::GetCorrespondingSpellCheckLanguage);
+
+ if (normalize_for_spellcheck) {
+ std::transform(accept_languages.begin(), accept_languages.end(),
+ accept_languages.begin(),
+ &spellcheck::GetCorrespondingSpellCheckLanguage);
+ }
+
return accept_languages;
}
#if defined(OS_WIN)
-void SpellcheckService::RecordMissingLanguagePacksCount() {
+void SpellcheckService::RecordSpellcheckLocalesStats() {
if (spellcheck::WindowsVersionSupportsSpellchecker() && metrics_ &&
- !hunspell_dictionaries_.empty()) {
+ platform_spell_checker() && !hunspell_dictionaries_.empty()) {
std::vector<std::string> hunspell_locales;
for (auto& dict : hunspell_dictionaries_) {
hunspell_locales.push_back(dict->GetLanguage());
}
- spellcheck_platform::RecordMissingLanguagePacksCount(
- std::move(hunspell_locales), metrics_.get());
+ spellcheck_platform::RecordSpellcheckLocalesStats(
+ platform_spell_checker(), std::move(hunspell_locales), metrics_.get());
}
}
-void SpellcheckService::RecordHunspellUnsupportedLanguageCount(
- const std::vector<std::string>& accept_languages) {
+void SpellcheckService::RecordChromeLocalesStats() {
+ const auto& accept_languages =
+ GetNormalizedAcceptLanguages(/* normalize_for_spellcheck */ false);
if (spellcheck::WindowsVersionSupportsSpellchecker() && metrics_ &&
- !accept_languages.empty()) {
- metrics_->RecordHunspellUnsupportedLanguageCount(std::count_if(
- accept_languages.begin(), accept_languages.end(),
- [](const std::string& s) {
- return spellcheck::GetCorrespondingSpellCheckLanguage(s).empty();
- }));
+ platform_spell_checker() && !accept_languages.empty()) {
+ spellcheck_platform::RecordChromeLocalesStats(
+ platform_spell_checker(), std::move(accept_languages), metrics_.get());
}
}
#endif // defined(OS_WIN)
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_service.h b/chromium/chrome/browser/spellchecker/spellcheck_service.h
index d5af9d5829c..803c7dad0d3 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_service.h
+++ b/chromium/chrome/browser/spellchecker/spellcheck_service.h
@@ -20,7 +20,9 @@
#include "chrome/browser/spellchecker/spellcheck_hunspell_dictionary.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/prefs/pref_change_registrar.h"
-#include "components/spellcheck/common/spellcheck.mojom.h"
+#include "components/spellcheck/browser/platform_spell_checker.h"
+#include "components/spellcheck/common/spellcheck.mojom-forward.h"
+#include "components/spellcheck/spellcheck_buildflags.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "mojo/public/cpp/bindings/remote.h"
@@ -143,6 +145,13 @@ class SpellcheckService : public KeyedService,
void OnHunspellDictionaryDownloadFailure(
const std::string& language) override;
+ // The returned pointer can be null if the current platform doesn't need a
+ // per-profile, platform-specific spell check object. Currently, only Windows
+ // requires one, and only on certain versions.
+ PlatformSpellChecker* platform_spell_checker() {
+ return platform_spell_checker_.get();
+ }
+
// Allows tests to override how SpellcheckService binds its interface
// receiver, instead of going through a RenderProcessHost by default.
using SpellCheckerBinder = base::RepeatingCallback<void(
@@ -176,19 +185,28 @@ class SpellcheckService : public KeyedService,
// prefs::kAcceptLanguages.
void OnAcceptLanguagesChanged();
- // Gets the user languages from the accept_languages pref and normalizes them
- // to official language codes.
- std::vector<std::string> GetNormalizedAcceptLanguages() const;
+ // Gets the user languages from the accept_languages pref and trims them of
+ // leading and trailing whitespaces. If |normalize_for_spellcheck| is |true|,
+ // also normalizes the format to xx or xx-YY based on the list of spell check
+ // languages supported by Hunspell. Note that if |normalize_for_spellcheck| is
+ // |true|, languages not supported by Hunspell will be returned as empty
+ // strings.
+ std::vector<std::string> GetNormalizedAcceptLanguages(
+ bool normalize_for_spellcheck = true) const;
- // Records how many user languages are not supported by Hunspell, and how many
- // user spellcheck languages are currently not supported by the Windows OS
- // spellchecker (due to missing language packs).
#if defined(OS_WIN)
- void RecordMissingLanguagePacksCount();
- void RecordHunspellUnsupportedLanguageCount(
- const std::vector<std::string>& accept_languages);
+ // Records statistics about spell check support for the user's Chrome locales.
+ void RecordChromeLocalesStats();
+
+ // Records statistics about which spell checker supports which of the user's
+ // enabled spell check locales.
+ void RecordSpellcheckLocalesStats();
#endif // defined(OS_WIN)
+ // WindowsSpellChecker must be created before the dictionary instantiation and
+ // destroyed after dictionary destruction.
+ std::unique_ptr<PlatformSpellChecker> platform_spell_checker_;
+
PrefChangeRegistrar pref_change_registrar_;
content::NotificationRegistrar registrar_;
diff --git a/chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
index 743faab36fe..109bf1ae019 100644
--- a/chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
+++ b/chromium/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
@@ -19,6 +20,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
+#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h"
#include "chrome/browser/spellchecker/spellcheck_factory.h"
@@ -32,6 +34,7 @@
#include "components/spellcheck/common/spellcheck.mojom.h"
#include "components/spellcheck/common/spellcheck_common.h"
#include "components/spellcheck/common/spellcheck_result.h"
+#include "components/spellcheck/spellcheck_buildflags.h"
#include "components/user_prefs/user_prefs.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/mock_render_process_host.h"
@@ -40,6 +43,10 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
+#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
+#include "components/spellcheck/common/spellcheck_features.h"
+#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
+
using content::BrowserContext;
using content::RenderProcessHost;
@@ -95,6 +102,14 @@ class SpellcheckServiceBrowserTest : public InProcessBrowserTest,
SpellcheckService* spellcheck =
SpellcheckServiceFactory::GetForContext(renderer_->GetBrowserContext());
+
+#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
+ if (spellcheck::UseWinHybridSpellChecker()) {
+ // If the Windows hybrid spell checker is in use, initialization is async.
+ RunTestRunLoop();
+ }
+#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
+
ASSERT_NE(nullptr, spellcheck);
}
@@ -445,6 +460,15 @@ IN_PROC_BROWSER_TEST_F(SpellcheckServiceHostBrowserTest, CallSpellingService) {
// Tests that we can delete a corrupted BDICT file used by hunspell. We do not
// run this test on Mac because Mac does not use hunspell by default.
IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, DeleteCorruptedBDICT) {
+#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
+ if (spellcheck::UseWinHybridSpellChecker()) {
+ // If doing hybrid spell checking on Windows, Hunspell dictionaries are not
+ // used for en-US, so the corrupt dictionary event will never be raised.
+ // Skip this test.
+ return;
+ }
+#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
+
// Corrupted BDICT data: please do not use this BDICT data for other tests.
const uint8_t kCorruptedBDICT[] = {
0x42, 0x44, 0x69, 0x63, 0x02, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00,
diff --git a/chromium/chrome/browser/spellchecker/spelling_request.cc b/chromium/chrome/browser/spellchecker/spelling_request.cc
index e3ba12ee074..37e993acff9 100644
--- a/chromium/chrome/browser/spellchecker/spelling_request.cc
+++ b/chromium/chrome/browser/spellchecker/spelling_request.cc
@@ -26,7 +26,8 @@ bool CompareLocation(const SpellCheckResult& r1, const SpellCheckResult& r2) {
} // namespace
-SpellingRequest::SpellingRequest(SpellingServiceClient* client,
+SpellingRequest::SpellingRequest(PlatformSpellChecker* platform_spell_checker,
+ SpellingServiceClient* client,
const base::string16& text,
int render_process_id,
int document_tag,
@@ -36,28 +37,15 @@ SpellingRequest::SpellingRequest(SpellingServiceClient* client,
text_(text),
callback_(std::move(callback)),
destruction_callback_(std::move(destruction_callback)) {
- StartRequest(client, render_process_id, document_tag);
-}
+ DCHECK(!text_.empty());
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
-SpellingRequest::SpellingRequest(
- SpellingServiceClient* client,
- const base::string16& text,
- int render_process_id,
- int document_tag,
- const std::vector<SpellCheckResult>& partial_results,
- bool fill_suggestions,
- RequestPartialTextCheckCallback callback,
- DestructionCallback destruction_callback)
- : remote_success_(false),
- text_(text),
- partial_results_(partial_results),
- fill_suggestions_(fill_suggestions),
- callback_(std::move(callback)),
- destruction_callback_(std::move(destruction_callback)) {
- StartRequest(client, render_process_id, document_tag);
+ completion_barrier_ =
+ BarrierClosure(2, base::BindOnce(&SpellingRequest::OnCheckCompleted,
+ weak_factory_.GetWeakPtr()));
+ RequestRemoteCheck(client, render_process_id);
+ RequestLocalCheck(platform_spell_checker, document_tag);
}
-#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
SpellingRequest::~SpellingRequest() = default;
@@ -77,6 +65,8 @@ void SpellingRequest::CombineResults(
local_iter++;
}
+ remote_iter->spelling_service_used = true;
+
// Unless local and remote result coincide, result is GRAMMAR.
remote_iter->decoration = SpellCheckResult::GRAMMAR;
if (local_iter != local_results.end() &&
@@ -87,19 +77,6 @@ void SpellingRequest::CombineResults(
}
}
-void SpellingRequest::StartRequest(SpellingServiceClient* client,
- int render_process_id,
- int document_tag) {
- DCHECK(!text_.empty());
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- completion_barrier_ =
- BarrierClosure(2, base::BindOnce(&SpellingRequest::OnCheckCompleted,
- weak_factory_.GetWeakPtr()));
- RequestRemoteCheck(client, render_process_id);
- RequestLocalCheck(document_tag);
-}
-
void SpellingRequest::RequestRemoteCheck(SpellingServiceClient* client,
int render_process_id) {
auto* host = content::RenderProcessHost::FromID(render_process_id);
@@ -113,20 +90,12 @@ void SpellingRequest::RequestRemoteCheck(SpellingServiceClient* client,
weak_factory_.GetWeakPtr()));
}
-void SpellingRequest::RequestLocalCheck(int document_tag) {
+void SpellingRequest::RequestLocalCheck(
+ PlatformSpellChecker* platform_spell_checker,
+ int document_tag) {
// |this| may be gone at callback invocation if the owner has been removed.
-#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
- if (spellcheck::UseWinHybridSpellChecker()) {
- spellcheck_platform::RequestTextCheck(
- document_tag, text_, std::move(partial_results_), fill_suggestions_,
- base::BindOnce(&SpellingRequest::OnLocalCheckCompletedOnAnyThread,
- weak_factory_.GetWeakPtr()));
- return;
- }
-#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
-
spellcheck_platform::RequestTextCheck(
- document_tag, text_,
+ platform_spell_checker, document_tag, text_,
base::BindOnce(&SpellingRequest::OnLocalCheckCompletedOnAnyThread,
weak_factory_.GetWeakPtr()));
}
diff --git a/chromium/chrome/browser/spellchecker/spelling_request.h b/chromium/chrome/browser/spellchecker/spelling_request.h
index 511c2f544c5..a0ead52dd83 100644
--- a/chromium/chrome/browser/spellchecker/spelling_request.h
+++ b/chromium/chrome/browser/spellchecker/spelling_request.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_SPELLCHECKER_SPELLING_REQUEST_H_
#include "base/containers/unique_ptr_adapters.h"
+#include "components/spellcheck/browser/platform_spell_checker.h"
#include "components/spellcheck/browser/spell_check_host_impl.h"
#include "components/spellcheck/browser/spelling_service_client.h"
@@ -20,29 +21,14 @@ class SpellingRequest {
spellcheck::mojom::SpellCheckHost::RequestTextCheckCallback;
using DestructionCallback = base::OnceCallback<void(SpellingRequest*)>;
-#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
- using RequestPartialTextCheckCallback =
- spellcheck::mojom::SpellCheckHost::RequestPartialTextCheckCallback;
-#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
-
- SpellingRequest(SpellingServiceClient* client,
+ SpellingRequest(PlatformSpellChecker* platform_spell_checker,
+ SpellingServiceClient* client,
const base::string16& text,
int render_process_id,
int document_tag,
RequestTextCheckCallback callback,
DestructionCallback destruction_callback);
-#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
- SpellingRequest(SpellingServiceClient* client,
- const base::string16& text,
- int render_process_id,
- int document_tag,
- const std::vector<SpellCheckResult>& partial_results,
- bool fill_suggestions,
- RequestPartialTextCheckCallback callback,
- DestructionCallback destruction_callback);
-#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
-
~SpellingRequest();
// Exposed to tests only.
@@ -51,16 +37,12 @@ class SpellingRequest {
const std::vector<SpellCheckResult>& local_results);
private:
- // Requests local and remote checks (starts the request).
- void StartRequest(SpellingServiceClient* client,
- int render_process_id,
- int document_tag);
-
// Request server-side checking for |text_|.
void RequestRemoteCheck(SpellingServiceClient* client, int render_process_id);
// Request a check for |text_| from local spell checker.
- void RequestLocalCheck(int document_tag);
+ void RequestLocalCheck(PlatformSpellChecker* platform_spell_checker,
+ int document_tag);
// Check if all pending requests are done, send reply to render process if so.
void OnCheckCompleted();
@@ -88,17 +70,6 @@ class SpellingRequest {
// The string to be spell-checked.
base::string16 text_;
-#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
- // Partial results from Hunspell for locales unsupported by the native
- // spellchecker.
- std::vector<SpellCheckResult> partial_results_;
-
- // Whether the local check should fill the suggestions at spellcheck time. If
- // this is false, no suggestions will be looked up (it will instead happen
- // when the user explicitly requests suggestions).
- bool fill_suggestions_;
-#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER)
-
// Callback to send the results to renderer. Note that both RequestTextCheck
// and RequestPartialTextCheck have the same callback signatures, so both
// callback types can be assigned to this member (the generated
diff --git a/chromium/chrome/browser/storage_access_api/BUILD.gn b/chromium/chrome/browser/storage_access_api/BUILD.gn
new file mode 100644
index 00000000000..001ffa434cb
--- /dev/null
+++ b/chromium/chrome/browser/storage_access_api/BUILD.gn
@@ -0,0 +1,21 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("permissions") {
+ sources = [
+ "storage_access_grant_permission_context.cc",
+ "storage_access_grant_permission_context.h",
+ ]
+
+ public_deps = [
+ "//components/permissions",
+ ]
+
+ deps = [
+ "//chrome/common",
+ "//components/content_settings/core/browser",
+ "//content/public/browser",
+ "//services/network/public/mojom",
+ ]
+}
diff --git a/chromium/chrome/browser/subresource_filter/BUILD.gn b/chromium/chrome/browser/subresource_filter/BUILD.gn
index f838a1cbdfa..d112ecdc244 100644
--- a/chromium/chrome/browser/subresource_filter/BUILD.gn
+++ b/chromium/chrome/browser/subresource_filter/BUILD.gn
@@ -8,22 +8,18 @@ if (is_android) {
import("//build/config/android/rules.gni")
generate_jni("jni_headers") {
- sources = [
- "../../android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java",
- ]
+ sources = [ "../../android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java" ]
}
android_library("subresource_filter_java_test_support") {
testonly = true
- java_files = [ "../../android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java" ]
- deps = [
- "//base:base_java",
- ]
+ sources = [ "../../android/javatests/src/org/chromium/chrome/browser/subresource_filter/TestRulesetPublisher.java" ]
+ deps = [ "//base:base_java" ]
}
android_library("subresource_filter_javatests") {
testonly = true
- java_files = [ "../../android/javatests/src/org/chromium/chrome/browser/subresource_filter/SubresourceFilterTest.java" ]
+ sources = [ "../../android/javatests/src/org/chromium/chrome/browser/subresource_filter/SubresourceFilterTest.java" ]
deps = [
":subresource_filter_java_test_support",
"//base:base_java_test_support",
diff --git a/chromium/chrome/browser/supervised_user/BUILD.gn b/chromium/chrome/browser/supervised_user/BUILD.gn
new file mode 100644
index 00000000000..93832b65bb7
--- /dev/null
+++ b/chromium/chrome/browser/supervised_user/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//tools/grit/grit_rule.gni")
+
+grit("supervised_user_unscaled_resources") {
+ source = "supervised_user_unscaled_resources.grd"
+ outputs = [
+ "grit/supervised_user_unscaled_resources.h",
+ "supervised_user_unscaled_resources.pak",
+ ]
+ output_dir = "$root_gen_dir/chrome/browser/supervised_user"
+
+ grit_flags = [
+ "-E",
+ "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+ ]
+}
diff --git a/chromium/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn b/chromium/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn
index 997f2b5eb09..0c22b4c8c09 100644
--- a/chromium/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn
+++ b/chromium/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn
@@ -24,17 +24,13 @@ static_library("supervised_user_error_page") {
if (is_android) {
java_cpp_enum("enums_srcjar") {
- sources = [
- "supervised_user_error_page.h",
- ]
+ sources = [ "supervised_user_error_page.h" ]
}
}
source_set("unit_tests") {
testonly = true
- sources = [
- "supervised_user_error_page_unittest.cc",
- ]
+ sources = [ "supervised_user_error_page_unittest.cc" ]
deps = [
":supervised_user_error_page",
"//base",
diff --git a/chromium/chrome/browser/supervised_user/supervised_user_unscaled_resources.grd b/chromium/chrome/browser/supervised_user/supervised_user_unscaled_resources.grd
new file mode 100644
index 00000000000..8d4792b7fb5
--- /dev/null
+++ b/chromium/chrome/browser/supervised_user/supervised_user_unscaled_resources.grd
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
+ <outputs>
+ <output filename="grit/supervised_user_unscaled_resources.h" type="rc_header" >
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="supervised_user_unscaled_resources.pak" type="data_package" />
+ </outputs>
+ <release seq="1">
+ <includes>
+ <include name="IDR_FAMILY_LINK_LOGO" file="supervised_user_error_page/resources/default_100_percent/family_link_logo.png" type="BINDATA" />
+ </includes>
+ </release>
+</grit>
diff --git a/chromium/chrome/browser/sync_file_system/drive_backend/BUILD.gn b/chromium/chrome/browser/sync_file_system/drive_backend/BUILD.gn
index 99f079b0fd6..18f1984a996 100644
--- a/chromium/chrome/browser/sync_file_system/drive_backend/BUILD.gn
+++ b/chromium/chrome/browser/sync_file_system/drive_backend/BUILD.gn
@@ -5,7 +5,5 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("sync_file_system_drive_proto") {
- sources = [
- "metadata_database.proto",
- ]
+ sources = [ "metadata_database.proto" ]
}
diff --git a/chromium/chrome/browser/tab_contents/OWNERS b/chromium/chrome/browser/tab_contents/OWNERS
new file mode 100644
index 00000000000..a3d4786e775
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/OWNERS
@@ -0,0 +1,2 @@
+avi@chromium.org
+# COMPONENT: UI>Browser
diff --git a/chromium/chrome/browser/tab_contents/form_interaction_tab_helper.cc b/chromium/chrome/browser/tab_contents/form_interaction_tab_helper.cc
new file mode 100644
index 00000000000..a051fd57620
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/form_interaction_tab_helper.cc
@@ -0,0 +1,116 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/tab_contents/form_interaction_tab_helper.h"
+
+#include "base/bind.h"
+#include "base/task/post_task.h"
+#include "components/performance_manager/public/graph/graph.h"
+#include "components/performance_manager/public/graph/page_node.h"
+#include "components/performance_manager/public/performance_manager.h"
+#include "components/performance_manager/public/web_contents_proxy.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace {
+
+#if DCHECK_IS_ON()
+bool g_observer_exists = false;
+#endif
+
+} // namespace
+
+// Graph observer used to receive the page form interaction events.
+class FormInteractionTabHelper::GraphObserver
+ : public performance_manager::PageNode::ObserverDefaultImpl,
+ public performance_manager::GraphOwned {
+ public:
+ GraphObserver() = default;
+ ~GraphObserver() override = default;
+ GraphObserver(const GraphObserver& other) = delete;
+ GraphObserver& operator=(const GraphObserver&) = delete;
+
+ private:
+ // Should be called on the UI thread to dispatch the OnHadFormInteraction
+ // signal received on the PM sequence.
+ static void DispatchOnHadFormInteraction(
+ const performance_manager::WebContentsProxy& contents_proxy,
+ bool had_form_interaction);
+
+ // performance_manager::PageNode::ObserverDefaultImpl:
+ void OnHadFormInteractionChanged(
+ const performance_manager::PageNode* page_node) override;
+
+ // performance_manager::GraphOwned:
+ void OnPassedToGraph(performance_manager::Graph* graph) override;
+ void OnTakenFromGraph(performance_manager::Graph* graph) override;
+};
+
+// static
+void FormInteractionTabHelper::GraphObserver::DispatchOnHadFormInteraction(
+ const performance_manager::WebContentsProxy& contents_proxy,
+ bool had_form_interaction) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ // If the web contents is still alive then dispatch to the actual
+ // implementation in TabLifecycleUnitSource.
+ if (auto* contents = contents_proxy.Get()) {
+ // Notifications can be emitted by extensions, ignore these.
+ if (auto* tab_helper =
+ FormInteractionTabHelper::FromWebContents(contents)) {
+ // Sanity check against spurious changes.
+ DCHECK_NE(tab_helper->had_form_interaction_, had_form_interaction);
+ tab_helper->had_form_interaction_ = had_form_interaction;
+ }
+ }
+}
+
+void FormInteractionTabHelper::GraphObserver::OnHadFormInteractionChanged(
+ const performance_manager::PageNode* page_node) {
+ // Forward the notification over to the UI thread.
+ base::PostTask(FROM_HERE, {content::BrowserThread::UI},
+ base::BindOnce(&GraphObserver::DispatchOnHadFormInteraction,
+ page_node->GetContentsProxy(),
+ page_node->HadFormInteraction()));
+}
+
+void FormInteractionTabHelper::GraphObserver::OnPassedToGraph(
+ performance_manager::Graph* graph) {
+#if DCHECK_IS_ON()
+ DCHECK(!g_observer_exists);
+ g_observer_exists = true;
+#endif
+ graph->AddPageNodeObserver(this);
+}
+
+void FormInteractionTabHelper::GraphObserver::OnTakenFromGraph(
+ performance_manager::Graph* graph) {
+#if DCHECK_IS_ON()
+ DCHECK(g_observer_exists);
+ g_observer_exists = false;
+#endif
+ graph->RemovePageNodeObserver(this);
+}
+
+// static
+std::unique_ptr<performance_manager::GraphOwned>
+FormInteractionTabHelper::CreateGraphObserver() {
+ return std::make_unique<FormInteractionTabHelper::GraphObserver>();
+}
+
+FormInteractionTabHelper::FormInteractionTabHelper(
+ content::WebContents* contents) {}
+
+FormInteractionTabHelper::~FormInteractionTabHelper() = default;
+
+bool FormInteractionTabHelper::had_form_interaction() const {
+#if DCHECK_IS_ON()
+ // The observer is allowed to not exist in tests that don't use
+ // PerformanceManager, in which case this function will always return false.
+ DCHECK(g_observer_exists ||
+ !performance_manager::PerformanceManager::IsAvailable());
+#endif
+ return had_form_interaction_;
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(FormInteractionTabHelper)
diff --git a/chromium/chrome/browser/tab_contents/form_interaction_tab_helper.h b/chromium/chrome/browser/tab_contents/form_interaction_tab_helper.h
new file mode 100644
index 00000000000..5217e39b130
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/form_interaction_tab_helper.h
@@ -0,0 +1,47 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TAB_CONTENTS_FORM_INTERACTION_TAB_HELPER_H_
+#define CHROME_BROWSER_TAB_CONTENTS_FORM_INTERACTION_TAB_HELPER_H_
+
+#include "base/macros.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace performance_manager {
+class GraphOwned;
+}
+
+// Tab helper that indicates if a tab contains forms that have been interacted
+// with.
+class FormInteractionTabHelper
+ : public content::WebContentsUserData<FormInteractionTabHelper> {
+ public:
+ // Must be called once to and passed to the PerformanceManager graph to start
+ // maintaining FormInteractionTabHelpers attached to WebContents.
+ static std::unique_ptr<performance_manager::GraphOwned> CreateGraphObserver();
+
+ ~FormInteractionTabHelper() override;
+ FormInteractionTabHelper(const FormInteractionTabHelper& other) = delete;
+ FormInteractionTabHelper& operator=(const FormInteractionTabHelper&) = delete;
+
+ // Note: This function will always return false in tests that don't
+ // instantiate PerformanceManager.
+ bool had_form_interaction() const;
+
+ void OnHadFormInteractionChangedForTesting(bool had_form_interaction) {
+ had_form_interaction_ = had_form_interaction;
+ }
+
+ private:
+ friend class content::WebContentsUserData<FormInteractionTabHelper>;
+ class GraphObserver;
+
+ explicit FormInteractionTabHelper(content::WebContents* contents);
+
+ bool had_form_interaction_ = false;
+
+ WEB_CONTENTS_USER_DATA_KEY_DECL();
+};
+
+#endif // CHROME_BROWSER_TAB_CONTENTS_FORM_INTERACTION_TAB_HELPER_H_
diff --git a/chromium/chrome/browser/tab_contents/form_interaction_tab_helper_unittest.cc b/chromium/chrome/browser/tab_contents/form_interaction_tab_helper_unittest.cc
new file mode 100644
index 00000000000..88bc9fe0d5a
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/form_interaction_tab_helper_unittest.cc
@@ -0,0 +1,161 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/tab_contents/form_interaction_tab_helper.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind_helpers.h"
+#include "base/run_loop.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/performance_manager/test_support/page_aggregator.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/performance_manager/embedder/performance_manager_registry.h"
+#include "components/performance_manager/performance_manager_impl.h"
+#include "components/performance_manager/public/performance_manager.h"
+#include "components/performance_manager/test_support/graph_impl.h"
+#include "components/performance_manager/test_support/mock_graphs.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class FormInteractionTabHelperTest : public ChromeRenderViewHostTestHarness {
+ public:
+ FormInteractionTabHelperTest() = default;
+ ~FormInteractionTabHelperTest() override = default;
+ FormInteractionTabHelperTest(const FormInteractionTabHelperTest& other) =
+ delete;
+ FormInteractionTabHelperTest& operator=(const FormInteractionTabHelperTest&) =
+ delete;
+
+ void SetUp() override {
+ ChromeRenderViewHostTestHarness::SetUp();
+ perf_man_ =
+ performance_manager::PerformanceManagerImpl::Create(base::DoNothing());
+ registry_ = performance_manager::PerformanceManagerRegistry::Create();
+ performance_manager::testing::CreatePageAggregatorAndPassItToGraph();
+ performance_manager::PerformanceManagerImpl::CallOnGraph(
+ FROM_HERE, base::BindOnce([](performance_manager::Graph* graph) {
+ graph->PassToGraph(FormInteractionTabHelper::CreateGraphObserver());
+ }));
+ }
+
+ std::unique_ptr<content::WebContents> CreateTestWebContents() {
+ std::unique_ptr<content::WebContents> contents =
+ ChromeRenderViewHostTestHarness::CreateTestWebContents();
+ registry_->CreatePageNodeForWebContents(contents.get());
+ FormInteractionTabHelper::CreateForWebContents(contents.get());
+ // Simulate a navigation event to force the initialization of the main
+ // frame.
+ content::WebContentsTester::For(contents.get())
+ ->NavigateAndCommit(GURL("https://foo.com"));
+ task_environment()->RunUntilIdle();
+ return contents;
+ }
+
+ void TearDown() override {
+ registry_->TearDown();
+ registry_.reset();
+ performance_manager::PerformanceManagerImpl::Destroy(std::move(perf_man_));
+ task_environment()->RunUntilIdle();
+ ChromeRenderViewHostTestHarness::TearDown();
+ }
+
+ private:
+ std::unique_ptr<performance_manager::PerformanceManagerImpl> perf_man_;
+ std::unique_ptr<performance_manager::PerformanceManagerRegistry> registry_;
+};
+
+TEST_F(FormInteractionTabHelperTest, HadFormInteractionSingleFrame) {
+ std::unique_ptr<content::WebContents> contents = CreateTestWebContents();
+ auto* helper = FormInteractionTabHelper::FromWebContents(contents.get());
+
+ EXPECT_FALSE(helper->had_form_interaction());
+
+ // Indicates that a form on the main frame has been interacted with.
+ {
+ base::RunLoop run_loop;
+ // Use a |QuitWhenIdleClosure| as the task posted to the UI thread by
+ // PerformanceManager will have a lower priority (USER_VISIBLE) than the one
+ // of a QuitClosure's task runner (USER_BLOCKING).
+ auto graph_callback = base::BindLambdaForTesting(
+ [quit_loop = run_loop.QuitWhenIdleClosure(),
+ page_node =
+ performance_manager::PerformanceManager::GetPageNodeForWebContents(
+ contents.get())]() {
+ auto* frame_node = performance_manager::FrameNodeImpl::FromNode(
+ page_node->GetMainFrameNode());
+ frame_node->SetIsCurrent(true);
+ frame_node->SetHadFormInteraction();
+ std::move(quit_loop).Run();
+ });
+ performance_manager::PerformanceManagerImpl::CallOnGraph(
+ FROM_HERE, std::move(graph_callback));
+ run_loop.Run();
+ }
+
+ EXPECT_TRUE(helper->had_form_interaction());
+
+ // A navigation event should reset the |had_form_interaction| for this page.
+ content::WebContentsTester::For(contents.get())
+ ->NavigateAndCommit(GURL("https://bar.com"));
+ // Some task are posted to the graph after a navigation event, wait for them
+ // to complete.
+ task_environment()->RunUntilIdle();
+
+ EXPECT_FALSE(helper->had_form_interaction());
+}
+
+TEST_F(FormInteractionTabHelperTest, HadFormInteractionWithChildFrames) {
+ std::unique_ptr<content::WebContents> contents = CreateTestWebContents();
+ auto* helper = FormInteractionTabHelper::FromWebContents(contents.get());
+
+ EXPECT_FALSE(helper->had_form_interaction());
+
+ auto* parent_tester =
+ content::RenderFrameHostTester::For(contents->GetMainFrame());
+ auto* child = content::NavigationSimulator::NavigateAndCommitFromDocument(
+ GURL("https://foochild.com"), parent_tester->AppendChild("child"));
+
+ // Indicates that a form on the child frame has been interacted with.
+ {
+ base::RunLoop run_loop;
+ // Use a |QuitWhenIdleClosure| as the task posted to the UI thread by
+ // PerformanceManager will have a lower priority (USER_VISIBLE) than the one
+ // of a QuitClosure's task runner (USER_BLOCKING).
+ auto graph_callback = base::BindLambdaForTesting(
+ [quit_loop = run_loop.QuitWhenIdleClosure(),
+ page_node =
+ performance_manager::PerformanceManager::GetPageNodeForWebContents(
+ contents.get())]() {
+ auto children = page_node->GetMainFrameNode()->GetChildFrameNodes();
+ EXPECT_EQ(1U, children.size());
+ auto* frame_node =
+ performance_manager::FrameNodeImpl::FromNode(*children.begin());
+ frame_node->SetIsCurrent(true);
+ frame_node->SetHadFormInteraction();
+ std::move(quit_loop).Run();
+ });
+ performance_manager::PerformanceManagerImpl::CallOnGraph(
+ FROM_HERE, std::move(graph_callback));
+ run_loop.Run();
+ }
+
+ EXPECT_TRUE(helper->had_form_interaction());
+
+ // A navigation event should reset the |had_form_interaction| for this page.
+ content::NavigationSimulator::NavigateAndCommitFromDocument(
+ GURL("https://barchild.com"), child);
+
+ // Some task are posted to the graph after a navigation event, wait for them
+ // to complete.
+ task_environment()->RunUntilIdle();
+
+ EXPECT_FALSE(helper->had_form_interaction());
+}
diff --git a/chromium/chrome/browser/tab_contents/navigation_metrics_recorder.cc b/chromium/chrome/browser/tab_contents/navigation_metrics_recorder.cc
new file mode 100644
index 00000000000..859d8eedb4b
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/navigation_metrics_recorder.cc
@@ -0,0 +1,87 @@
+// 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 "chrome/browser/tab_contents/navigation_metrics_recorder.h"
+
+#include "build/build_config.h"
+#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_metrics.h"
+#include "components/navigation_metrics/navigation_metrics.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/site_instance.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
+NavigationMetricsRecorder::NavigationMetricsRecorder(
+ content::WebContents* web_contents)
+ : content::WebContentsObserver(web_contents) {
+#if defined(OS_ANDROID)
+ // The site isolation synthetic field trial is only needed on Android, as on
+ // desktop it would be unnecessarily set for all users.
+ is_synthetic_isolation_trial_enabled_ = true;
+#else
+ is_synthetic_isolation_trial_enabled_ = false;
+#endif
+}
+
+NavigationMetricsRecorder::~NavigationMetricsRecorder() {
+}
+
+void NavigationMetricsRecorder::EnableSiteIsolationSyntheticTrialForTesting() {
+ is_synthetic_isolation_trial_enabled_ = true;
+}
+
+void NavigationMetricsRecorder::DidFinishNavigation(
+ content::NavigationHandle* navigation_handle) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (!navigation_handle->HasCommitted())
+ return;
+
+ // See if the navigation committed for a site that required a dedicated
+ // process and register a synthetic field trial if so. Note that this needs
+ // to go before the IsInMainFrame() check, as we want to register navigations
+ // to isolated sites from both main frames and subframes.
+ if (is_synthetic_isolation_trial_enabled_ &&
+ navigation_handle->GetRenderFrameHost()
+ ->GetSiteInstance()
+ ->RequiresDedicatedProcess()) {
+ ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
+ "SiteIsolationActive", "Enabled");
+ }
+
+ // Also register a synthetic field trial when we encounter a navigation to an
+ // OOPIF.
+ if (is_synthetic_isolation_trial_enabled_ &&
+ navigation_handle->GetRenderFrameHost()->IsCrossProcessSubframe()) {
+ ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
+ "OutOfProcessIframesActive", "Enabled");
+ }
+
+ if (!navigation_handle->IsInMainFrame())
+ return;
+
+ content::BrowserContext* context = web_contents()->GetBrowserContext();
+ content::NavigationEntry* last_committed_entry =
+ web_contents()->GetController().GetLastCommittedEntry();
+
+ Profile* profile = Profile::FromBrowserContext(context);
+ navigation_metrics::RecordMainFrameNavigation(
+ last_committed_entry->GetVirtualURL(),
+ navigation_handle->IsSameDocument(), profile->IsOffTheRecord(),
+ ProfileMetrics::GetBrowserProfileType(profile));
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(NavigationMetricsRecorder)
diff --git a/chromium/chrome/browser/tab_contents/navigation_metrics_recorder.h b/chromium/chrome/browser/tab_contents/navigation_metrics_recorder.h
new file mode 100644
index 00000000000..9eac02c3e7e
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/navigation_metrics_recorder.h
@@ -0,0 +1,38 @@
+// 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 CHROME_BROWSER_TAB_CONTENTS_NAVIGATION_METRICS_RECORDER_H_
+#define CHROME_BROWSER_TAB_CONTENTS_NAVIGATION_METRICS_RECORDER_H_
+
+#include "base/macros.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+class NavigationMetricsRecorder
+ : public content::WebContentsObserver,
+ public content::WebContentsUserData<NavigationMetricsRecorder> {
+ public:
+ ~NavigationMetricsRecorder() override;
+
+ // Turns on a synthetic field trial that is set on any navigation to a site
+ // that requires a dedicated process. Normally this is only used on Android,
+ // but tests on other platforms can also turn this behavior on.
+ void EnableSiteIsolationSyntheticTrialForTesting();
+
+ private:
+ explicit NavigationMetricsRecorder(content::WebContents* web_contents);
+ friend class content::WebContentsUserData<NavigationMetricsRecorder>;
+
+ // content::WebContentsObserver overrides:
+ void DidFinishNavigation(
+ content::NavigationHandle* navigation_handle) override;
+
+ bool is_synthetic_isolation_trial_enabled_;
+
+ WEB_CONTENTS_USER_DATA_KEY_DECL();
+
+ DISALLOW_COPY_AND_ASSIGN(NavigationMetricsRecorder);
+};
+
+#endif // CHROME_BROWSER_TAB_CONTENTS_NAVIGATION_METRICS_RECORDER_H_
diff --git a/chromium/chrome/browser/tab_contents/navigation_metrics_recorder_browsertest.cc b/chromium/chrome/browser/tab_contents/navigation_metrics_recorder_browsertest.cc
new file mode 100644
index 00000000000..397aad0fd05
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/navigation_metrics_recorder_browsertest.cc
@@ -0,0 +1,38 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/metrics/histogram_tester.h"
+#include "chrome/browser/tab_contents/navigation_metrics_recorder.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+
+namespace {
+
+typedef InProcessBrowserTest NavigationMetricsRecorderBrowserTest;
+
+IN_PROC_BROWSER_TEST_F(NavigationMetricsRecorderBrowserTest, TestMetrics) {
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+
+ NavigationMetricsRecorder* recorder =
+ content::WebContentsUserData<NavigationMetricsRecorder>::FromWebContents(
+ web_contents);
+ ASSERT_TRUE(recorder);
+
+ base::HistogramTester histograms;
+ ui_test_utils::NavigateToURL(browser(),
+ GURL("data:text/html, <html></html>"));
+ histograms.ExpectTotalCount("Navigation.MainFrameScheme", 1);
+ histograms.ExpectBucketCount("Navigation.MainFrameScheme", 5 /* data: */, 1);
+ histograms.ExpectTotalCount("Navigation.MainFrameSchemeDifferentPage", 1);
+ histograms.ExpectBucketCount("Navigation.MainFrameSchemeDifferentPage",
+ 5 /* data: */, 1);
+}
+
+} // namespace
diff --git a/chromium/chrome/browser/tab_contents/tab_util.cc b/chromium/chrome/browser/tab_contents/tab_util.cc
new file mode 100644
index 00000000000..fd5c97ec5ca
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/tab_util.cc
@@ -0,0 +1,79 @@
+// 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 "chrome/browser/tab_contents/tab_util.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/public/browser/browser_url_handler.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/buildflags/buildflags.h"
+#include "url/gurl.h"
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+#include "extensions/browser/extension_registry.h"
+#endif
+
+using content::RenderFrameHost;
+using content::RenderViewHost;
+using content::SiteInstance;
+using content::WebContents;
+
+namespace tab_util {
+
+content::WebContents* GetWebContentsByID(int render_process_id,
+ int render_view_id) {
+ RenderViewHost* render_view_host =
+ RenderViewHost::FromID(render_process_id, render_view_id);
+ if (!render_view_host)
+ return NULL;
+ return WebContents::FromRenderViewHost(render_view_host);
+}
+
+content::WebContents* GetWebContentsByFrameID(int render_process_id,
+ int render_frame_id) {
+ RenderFrameHost* render_frame_host =
+ RenderFrameHost::FromID(render_process_id, render_frame_id);
+ if (!render_frame_host)
+ return NULL;
+ return WebContents::FromRenderFrameHost(render_frame_host);
+}
+
+scoped_refptr<SiteInstance> GetSiteInstanceForNewTab(Profile* profile,
+ GURL url) {
+ // Rewrite the |url| if necessary, to ensure that the SiteInstance is
+ // associated with a |url| that will actually be loaded. For example,
+ // |url| set to chrome://newtab/ might actually result in a navigation to a
+ // different URL like chrome-search://local-ntp/local-ntp.html
+ content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(&url,
+ profile);
+
+ // If |url| is a WebUI or extension, we set the SiteInstance up front so that
+ // we don't end up with an extra process swap on the first navigation.
+ if (ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL(profile, url))
+ return SiteInstance::CreateForURL(profile, url);
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+ if (extensions::ExtensionRegistry::Get(profile)
+ ->enabled_extensions()
+ .GetHostedAppByURL(url))
+ return SiteInstance::CreateForURL(profile, url);
+#endif
+
+ // We used to share the SiteInstance for same-site links opened in new tabs,
+ // to leverage the in-memory cache and reduce process creation. It now
+ // appears that it is more useful to have such links open in a new process,
+ // so we create new tabs in a new BrowsingInstance.
+ // Create a new SiteInstance for the |url| unless it is not desirable.
+ if (!SiteInstance::ShouldAssignSiteForURL(url))
+ return nullptr;
+
+ return SiteInstance::CreateForURL(profile, url);
+}
+
+} // namespace tab_util
diff --git a/chromium/chrome/browser/tab_contents/tab_util.h b/chromium/chrome/browser/tab_contents/tab_util.h
new file mode 100644
index 00000000000..ca98c7fc5dd
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/tab_util.h
@@ -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.
+
+#ifndef CHROME_BROWSER_TAB_CONTENTS_TAB_UTIL_H_
+#define CHROME_BROWSER_TAB_CONTENTS_TAB_UTIL_H_
+
+#include "content/public/browser/site_instance.h"
+#include "url/gurl.h"
+
+class Profile;
+
+namespace content {
+class WebContents;
+}
+
+namespace tab_util {
+
+// Helper to find the WebContents that originated the given request. Can be
+// NULL if the tab has been closed or some other error occurs.
+// Should only be called from the UI thread, since it accesses WebContents.
+content::WebContents* GetWebContentsByID(int render_process_id,
+ int render_view_id);
+
+content::WebContents* GetWebContentsByFrameID(int render_process_id,
+ int render_frame_id);
+
+// Returns a new SiteInstance for WebUI and app URLs. Returns NULL otherwise.
+scoped_refptr<content::SiteInstance> GetSiteInstanceForNewTab(Profile* profile,
+ GURL url);
+
+} // namespace tab_util
+
+#endif // CHROME_BROWSER_TAB_CONTENTS_TAB_UTIL_H_
diff --git a/chromium/chrome/browser/tab_contents/view_source_browsertest.cc b/chromium/chrome/browser/tab_contents/view_source_browsertest.cc
new file mode 100644
index 00000000000..0231b9e9235
--- /dev/null
+++ b/chromium/chrome/browser/tab_contents/view_source_browsertest.cc
@@ -0,0 +1,685 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/back_forward_cache.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
+#include "content/public/test/url_loader_interceptor.h"
+#include "net/base/features.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+using testing::HasSubstr;
+using testing::ContainsRegex;
+
+namespace {
+const char kTestHtml[] = "/viewsource/test.html";
+const char kTestNavigationHtml[] = "/viewsource/navigation.html";
+const char kTestMedia[] = "/media/pink_noise_140ms.wav";
+}
+
+class ViewSourceTest : public InProcessBrowserTest {
+ public:
+ ViewSourceTest() {}
+
+ protected:
+ void SetUpOnMainThread() override {
+ InProcessBrowserTest::SetUpOnMainThread();
+ host_resolver()->AddRule("*", "127.0.0.1");
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ViewSourceTest);
+};
+
+class ViewSourceFeaturePolicyTest : public ViewSourceTest {
+ public:
+ ViewSourceFeaturePolicyTest() : ViewSourceTest() {}
+
+ protected:
+ void SetUpOnMainThread() override {
+ InProcessBrowserTest::SetUpOnMainThread();
+ host_resolver()->AddRule("*", "127.0.0.1");
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ViewSourceFeaturePolicyTest);
+};
+
+// This test renders a page in view-source and then checks to see if the title
+// set in the html was set successfully (it shouldn't because we rendered the
+// page in view source).
+// Flaky; see http://crbug.com/72201.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, DoesBrowserRenderInViewSource) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // First we navigate to our view-source test page.
+ GURL url(content::kViewSourceScheme + std::string(":") +
+ embedded_test_server()->GetURL(kTestHtml).spec());
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ // Check that the title didn't get set. It should not be there (because we
+ // are in view-source mode).
+ EXPECT_NE(base::ASCIIToUTF16("foo"),
+ browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
+}
+
+// This test renders a page normally and then renders the same page in
+// view-source mode. This is done since we had a problem at one point during
+// implementation of the view-source: prefix being consumed (removed from the
+// URL) if the URL was not changed (apart from adding the view-source prefix)
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, DoesBrowserConsumeViewSourcePrefix) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // First we navigate to google.html.
+ GURL url(embedded_test_server()->GetURL(kTestHtml));
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ // Then we navigate to the same url but with the "view-source:" prefix.
+ GURL url_viewsource(content::kViewSourceScheme + std::string(":") +
+ url.spec());
+ ui_test_utils::NavigateToURL(browser(), url_viewsource);
+
+ // The URL should still be prefixed with "view-source:".
+ EXPECT_EQ(url_viewsource.spec(),
+ browser()->tab_strip_model()->GetActiveWebContents()->
+ GetURL().spec());
+}
+
+// Make sure that when looking at the actual page, we can select "View Source"
+// from the menu.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, ViewSourceInMenuEnabledOnANormalPage) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url(embedded_test_server()->GetURL(kTestHtml));
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ EXPECT_TRUE(chrome::CanViewSource(browser()));
+}
+
+// For page that is media content, make sure that we cannot select "View Source"
+// See http://crbug.com/83714
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, ViewSourceInMenuDisabledOnAMediaPage) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url(embedded_test_server()->GetURL(kTestMedia));
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ const char* mime_type = browser()->tab_strip_model()->GetActiveWebContents()->
+ GetContentsMimeType().c_str();
+
+ EXPECT_STREQ("audio/wav", mime_type);
+ EXPECT_FALSE(chrome::CanViewSource(browser()));
+}
+
+// Make sure that when looking at the page source, we can't select "View Source"
+// from the menu.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest,
+ ViewSourceInMenuDisabledWhileViewingSource) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url_viewsource(content::kViewSourceScheme + std::string(":") +
+ embedded_test_server()->GetURL(kTestHtml).spec());
+ ui_test_utils::NavigateToURL(browser(), url_viewsource);
+
+ EXPECT_FALSE(chrome::CanViewSource(browser()));
+}
+
+// Tests that reload initiated by the script on the view-source page leaves
+// the page in view-source mode.
+// Times out on Mac, Windows, ChromeOS Linux: crbug.com/162080
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, DISABLED_TestViewSourceReload) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url_viewsource(content::kViewSourceScheme + std::string(":") +
+ embedded_test_server()->GetURL(kTestHtml).spec());
+
+ content::WindowedNotificationObserver observer(
+ content::NOTIFICATION_LOAD_STOP,
+ content::NotificationService::AllSources());
+ ui_test_utils::NavigateToURL(browser(), url_viewsource);
+ observer.Wait();
+
+ ASSERT_TRUE(
+ content::ExecuteScript(browser()->tab_strip_model()->GetWebContentsAt(0),
+ "window.location.reload();"));
+
+ content::WindowedNotificationObserver observer2(
+ content::NOTIFICATION_LOAD_STOP,
+ content::NotificationService::AllSources());
+ observer2.Wait();
+ ASSERT_TRUE(browser()->tab_strip_model()->GetWebContentsAt(0)->
+ GetController().GetActiveEntry()->IsViewSourceMode());
+}
+
+// This test ensures that view-source session history navigations work
+// correctly when switching processes. See https://crbug.com/544868.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest,
+ ViewSourceCrossProcessAndBack) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url_viewsource(content::kViewSourceScheme + std::string(":") +
+ embedded_test_server()->GetURL(kTestHtml).spec());
+ ui_test_utils::NavigateToURL(browser(), url_viewsource);
+ EXPECT_FALSE(chrome::CanViewSource(browser()));
+ EXPECT_EQ(1, browser()->tab_strip_model()->count());
+
+ // Open another tab to the same origin, so the process is kept alive while
+ // the original tab is navigated cross-process. This is required for the
+ // original bug to reproduce.
+ {
+ GURL url = embedded_test_server()->GetURL("/title1.html");
+ ui_test_utils::UrlLoadObserver load_complete(
+ url, content::NotificationService::AllSources());
+ EXPECT_TRUE(content::ExecuteScript(
+ browser()->tab_strip_model()->GetActiveWebContents(),
+ "window.open('" + url.spec() + "');"));
+ load_complete.Wait();
+ EXPECT_EQ(2, browser()->tab_strip_model()->count());
+ }
+
+ // Switch back to the first tab and navigate it cross-process.
+ browser()->tab_strip_model()->ActivateTabAt(
+ 0, {TabStripModel::GestureType::kOther});
+ ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIVersionURL));
+ EXPECT_TRUE(chrome::CanViewSource(browser()));
+
+ // Navigate back in session history to ensure view-source mode is still
+ // active.
+ {
+ ui_test_utils::UrlLoadObserver load_complete(
+ url_viewsource, content::NotificationService::AllSources());
+ chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
+ load_complete.Wait();
+ }
+
+ // Check whether the page is in view-source mode or not by checking if an
+ // expected element on the page exists or not. In view-source mode it
+ // should not be found.
+ bool result = false;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+ browser()->tab_strip_model()->GetActiveWebContents(),
+ "domAutomationController.send(document.getElementById('bar') === null);",
+ &result));
+ EXPECT_TRUE(result);
+ EXPECT_FALSE(chrome::CanViewSource(browser()));
+}
+
+// Tests that view-source mode of b.com subframe won't commit in an a.com (main
+// frame) process. This is a regresion test for https://crbug.com/770946.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, CrossSiteSubframe) {
+ // Navigate to a page with a cross-site frame.
+ content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL main_url(
+ embedded_test_server()->GetURL("a.com", "/iframe_cross_site.html"));
+ ui_test_utils::NavigateToURL(browser(), main_url);
+
+ // Grab the original frames.
+ content::WebContents* original_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ content::RenderFrameHost* original_main_frame =
+ original_contents->GetMainFrame();
+ ASSERT_LE(2u, original_contents->GetAllFrames().size());
+ content::RenderFrameHost* original_child_frame =
+ original_contents->GetAllFrames()[1];
+
+ // Do a sanity check that in this particular test page the main frame and the
+ // subframe are cross-site.
+ EXPECT_NE(original_main_frame->GetLastCommittedURL().GetOrigin(),
+ original_child_frame->GetLastCommittedURL().GetOrigin());
+ if (content::AreAllSitesIsolatedForTesting()) {
+ EXPECT_NE(original_main_frame->GetSiteInstance(),
+ original_child_frame->GetSiteInstance());
+ EXPECT_NE(original_main_frame->GetProcess()->GetID(),
+ original_child_frame->GetProcess()->GetID());
+ }
+
+ // Open view-source mode tab for the subframe. This tries to mimic the
+ // behavior of RenderViewContextMenu::ExecuteCommand when it handles
+ // IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE.
+ content::WebContentsAddedObserver view_source_contents_observer;
+ original_child_frame->ViewSource();
+
+ // Grab the view-source frame and wait for load stop.
+ content::WebContents* view_source_contents =
+ view_source_contents_observer.GetWebContents();
+ content::RenderFrameHost* view_source_frame =
+ view_source_contents->GetMainFrame();
+ EXPECT_TRUE(WaitForLoadStop(view_source_contents));
+
+ // Verify that the last committed URL is the same in the original and the
+ // view-source frames.
+ EXPECT_EQ(original_child_frame->GetLastCommittedURL(),
+ view_source_frame->GetLastCommittedURL());
+
+ // Verify that the original main frame and the view-source subframe are in a
+ // different process (e.g. if the main frame was malicious and the subframe
+ // was an isolated origin, then the malicious frame shouldn't be able to see
+ // the contents of the isolated document). See https://crbug.com/770946.
+ EXPECT_NE(original_main_frame->GetSiteInstance(),
+ view_source_frame->GetSiteInstance());
+
+ // Verify that the original subframe and the view-source subframe are in a
+ // different process - see https://crbug.com/699493.
+ EXPECT_NE(original_child_frame->GetSiteInstance(),
+ view_source_frame->GetSiteInstance());
+
+ // Verify the contents of the view-source tab (should match title1.html).
+ std::string source_text;
+ std::string view_source_extraction_script = R"(
+ output = "";
+ document.querySelectorAll(".line-content").forEach(function(elem) {
+ output += elem.innerText;
+ });
+ domAutomationController.send(output); )";
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ view_source_contents, view_source_extraction_script, &source_text));
+ EXPECT_EQ("<html><head></head><body>This page has no title.</body></html>",
+ source_text);
+
+ // Verify the title is derived from the subframe URL.
+ GURL original_url = original_child_frame->GetLastCommittedURL();
+ std::string title = base::UTF16ToUTF8(view_source_contents->GetTitle());
+ EXPECT_THAT(title, HasSubstr(content::kViewSourceScheme));
+ EXPECT_THAT(title, HasSubstr(original_url.host()));
+ EXPECT_THAT(title, HasSubstr(original_url.port()));
+ EXPECT_THAT(title, HasSubstr(original_url.path()));
+}
+
+// Tests that "View Source" works fine for pages shown via HTTP POST.
+// This is a regression test for https://crbug.com/523.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, HttpPostInMainframe) {
+ // Navigate to a page with a form.
+ content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL form_url(embedded_test_server()->GetURL(
+ "a.com", "/form_that_posts_to_echoall.html"));
+ ui_test_utils::NavigateToURL(browser(), form_url);
+ content::WebContents* original_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ content::RenderFrameHost* original_main_frame =
+ original_contents->GetMainFrame();
+
+ // Submit the form and verify that we arrived at the expected location.
+ content::TestNavigationObserver form_post_observer(original_contents, 1);
+ EXPECT_TRUE(ExecuteScript(original_main_frame,
+ "document.getElementById('form').submit();"));
+ form_post_observer.Wait();
+ GURL target_url(embedded_test_server()->GetURL("a.com", "/echoall"));
+ EXPECT_EQ(target_url, original_main_frame->GetLastCommittedURL());
+
+ // Extract the response nonce.
+ std::string response_nonce;
+ std::string response_nonce_extraction_script = R"(
+ domAutomationController.send(
+ document.getElementById('response-nonce').innerText); )";
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ original_main_frame, response_nonce_extraction_script, &response_nonce));
+
+ // Open view-source mode tab for the main frame. This tries to mimic the
+ // behavior of RenderViewContextMenu::ExecuteCommand when it handles
+ // IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE.
+ content::WebContentsAddedObserver view_source_contents_observer;
+ original_main_frame->ViewSource();
+ content::WebContents* view_source_contents =
+ view_source_contents_observer.GetWebContents();
+ EXPECT_TRUE(WaitForLoadStop(view_source_contents));
+
+ // Verify contents of the view-source tab. In particular:
+ // 1) the sources should contain the POST data
+ // 2) the sources should contain the original response-nonce
+ // (i.e. no new network request should be made - the data should be
+ // retrieved from the cache)
+ std::string source_text;
+ std::string view_source_extraction_script = R"(
+ output = "";
+ document.querySelectorAll(".line-content").forEach(function(elem) {
+ output += elem.innerText;
+ });
+ domAutomationController.send(output); )";
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ view_source_contents, view_source_extraction_script, &source_text));
+ EXPECT_THAT(source_text,
+ HasSubstr("<h1>Request Body:</h1><pre>text=value</pre>"));
+ EXPECT_THAT(source_text,
+ HasSubstr("<pre id='request-headers'>POST /echoall HTTP"));
+ EXPECT_THAT(source_text,
+ ContainsRegex("Request Headers:.*Referer: " + form_url.spec()));
+ EXPECT_THAT(
+ source_text,
+ ContainsRegex(
+ "Request Headers:.*Content-Type: application/x-www-form-urlencoded"));
+ EXPECT_THAT(source_text, HasSubstr("<h1>Response nonce:</h1>"
+ "<pre id='response-nonce'>" +
+ response_nonce + "</pre>"));
+ EXPECT_THAT(source_text,
+ HasSubstr("<title>EmbeddedTestServer - EchoAll</title>"));
+
+ // Verify that the original contents and the view-source contents are in a
+ // different process - see https://crbug.com/699493.
+ EXPECT_NE(original_main_frame->GetSiteInstance(),
+ view_source_contents->GetMainFrame()->GetSiteInstance());
+
+ // Verify the title of view-source is derived from the URL (not from the title
+ // of the original contents).
+ std::string title = base::UTF16ToUTF8(view_source_contents->GetTitle());
+ EXPECT_EQ("EmbeddedTestServer - EchoAll",
+ base::UTF16ToUTF8(original_contents->GetTitle()));
+ EXPECT_THAT(title, Not(HasSubstr("EmbeddedTestServer - EchoAll")));
+ GURL original_url = original_main_frame->GetLastCommittedURL();
+ EXPECT_THAT(title, HasSubstr(content::kViewSourceScheme));
+ EXPECT_THAT(title, HasSubstr(original_url.host()));
+ EXPECT_THAT(title, HasSubstr(original_url.port()));
+ EXPECT_THAT(title, HasSubstr(original_url.path()));
+}
+
+class ViewSourceWithSplitCacheTest
+ : public ViewSourceTest,
+ public ::testing::WithParamInterface<bool> {
+ public:
+ void SetUp() override {
+ bool split_cache_by_network_isolation_key = GetParam();
+ feature_list_.InitWithFeatureState(
+ net::features::kSplitCacheByNetworkIsolationKey,
+ split_cache_by_network_isolation_key);
+ ViewSourceTest::SetUp();
+ }
+
+ private:
+ base::test::ScopedFeatureList feature_list_;
+};
+
+// Tests that "View Source" works fine for *subframes* shown via HTTP POST.
+// This is a regression test for https://crbug.com/774691.
+IN_PROC_BROWSER_TEST_P(ViewSourceWithSplitCacheTest, HttpPostInSubframe) {
+ // Navigate to a page with multiple frames.
+ content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL main_url(
+ embedded_test_server()->GetURL("a.com", "/iframe_cross_site.html"));
+ ui_test_utils::NavigateToURL(browser(), main_url);
+ content::WebContents* original_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+
+ // Navigate a child frame to a document with a form.
+ GURL form_url(embedded_test_server()->GetURL(
+ "b.com", "/form_that_posts_to_echoall.html"));
+ EXPECT_TRUE(
+ content::NavigateIframeToURL(original_contents, "frame1", form_url));
+ EXPECT_LE(2u, original_contents->GetAllFrames().size());
+ content::RenderFrameHost* original_child_frame =
+ original_contents->GetAllFrames()[1];
+
+ // Submit the form and verify that we arrived at the expected location.
+ content::TestNavigationObserver form_post_observer(original_contents, 1);
+ EXPECT_TRUE(ExecuteScript(original_child_frame,
+ "document.getElementById('form').submit();"));
+ form_post_observer.Wait();
+ GURL target_url(embedded_test_server()->GetURL("b.com", "/echoall"));
+ EXPECT_EQ(target_url, original_child_frame->GetLastCommittedURL());
+
+ // Extract the response nonce.
+ std::string response_nonce;
+ std::string response_nonce_extraction_script = R"(
+ domAutomationController.send(
+ document.getElementById('response-nonce').innerText); )";
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ original_child_frame, response_nonce_extraction_script, &response_nonce));
+
+ // Open view-source mode tab for the subframe. This tries to mimic the
+ // behavior of RenderViewContextMenu::ExecuteCommand when it handles
+ // IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE.
+ content::WebContentsAddedObserver view_source_contents_observer;
+ original_child_frame->ViewSource();
+ content::WebContents* view_source_contents =
+ view_source_contents_observer.GetWebContents();
+ EXPECT_TRUE(WaitForLoadStop(view_source_contents));
+
+ // Verify contents of the view-source tab. In particular:
+ // 1) the sources should contain the POST data
+ // 2) the sources should contain the original response-nonce
+ // (i.e. no new network request should be made - the data should be
+ // retrieved from the cache)
+ std::string source_text;
+ std::string view_source_extraction_script = R"(
+ output = "";
+ document.querySelectorAll(".line-content").forEach(function(elem) {
+ output += elem.innerText;
+ });
+ domAutomationController.send(output); )";
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ view_source_contents, view_source_extraction_script, &source_text));
+ EXPECT_THAT(source_text,
+ HasSubstr("<h1>Request Body:</h1><pre>text=value</pre>"));
+ EXPECT_THAT(source_text,
+ HasSubstr("<pre id='request-headers'>POST /echoall HTTP"));
+ EXPECT_THAT(source_text,
+ ContainsRegex("Request Headers:.*Referer: " + form_url.spec()));
+ EXPECT_THAT(
+ source_text,
+ ContainsRegex(
+ "Request Headers:.*Content-Type: application/x-www-form-urlencoded"));
+ EXPECT_THAT(source_text, HasSubstr("<h1>Response nonce:</h1>"
+ "<pre id='response-nonce'>" +
+ response_nonce + "</pre>"));
+ EXPECT_THAT(source_text,
+ HasSubstr("<title>EmbeddedTestServer - EchoAll</title>"));
+
+ // Verify that view-source opens in a new process - https://crbug.com/699493.
+ EXPECT_NE(original_child_frame->GetSiteInstance(),
+ view_source_contents->GetMainFrame()->GetSiteInstance());
+ EXPECT_NE(original_contents->GetSiteInstance(),
+ view_source_contents->GetMainFrame()->GetSiteInstance());
+
+ // Verify the title is derived from the URL.
+ GURL original_url = original_child_frame->GetLastCommittedURL();
+ std::string title = base::UTF16ToUTF8(view_source_contents->GetTitle());
+ EXPECT_THAT(title, HasSubstr(content::kViewSourceScheme));
+ EXPECT_THAT(title, HasSubstr(original_url.host()));
+ EXPECT_THAT(title, HasSubstr(original_url.port()));
+ EXPECT_THAT(title, HasSubstr(original_url.path()));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ ViewSourceWithSplitCacheTest,
+ testing::Bool());
+
+using ViewSourceWithSplitCacheEnabledTest = ViewSourceWithSplitCacheTest;
+
+// Tests that the network isolation key for the view-source request is reused
+// in the back-navigation request to the view-source page.
+//
+// The test runs the following steps:
+// 1. Navigate to page a.com/title1.html
+// 2. Create a cross-site subframe b.com/title1.html
+// 3. View-source the subframe
+// 4. Navigate the view-source page to a c.com/title1.html
+// 5. Navigate back to the view-source page
+//
+// In the end, the test checks whether the back navigation request resource
+// exists in the cache. |exists_in_cache == true| implies the top_frame_origin
+// of the network isolation key is a.com (reused).
+IN_PROC_BROWSER_TEST_P(ViewSourceWithSplitCacheEnabledTest,
+ NetworkIsolationKeyReusedForBackNavigation) {
+ content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // 1. Navigate to page a.com/title1.html
+ GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ ui_test_utils::NavigateToURL(browser(), main_url);
+
+ content::WebContents* original_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+
+ std::string subframe_url =
+ GURL(embedded_test_server()->GetURL("b.com", "/title1.html")).spec();
+ {
+ // 2. Create a cross-site subframe b.com/title1.html
+ std::string create_frame_script = base::StringPrintf(
+ "let frame = document.createElement('iframe');"
+ "frame.src = '%s';"
+ "document.body.appendChild(frame);",
+ subframe_url.c_str());
+ content::TestNavigationObserver navigation_observer(original_contents);
+ original_contents->GetMainFrame()->ExecuteJavaScriptForTests(
+ base::ASCIIToUTF16(create_frame_script), base::NullCallback());
+ navigation_observer.Wait();
+ }
+
+ // 3. View-source the subframe
+ content::WebContentsAddedObserver view_source_contents_observer;
+ original_contents->GetAllFrames()[1]->ViewSource();
+ content::WebContents* view_source_contents =
+ view_source_contents_observer.GetWebContents();
+ EXPECT_TRUE(WaitForLoadStop(view_source_contents));
+ // This test expects us to re-load a page after a back navigation (and reuse
+ // the network isolation key while doing so), which won't happen when the
+ // page is restored from the back forward cache. We are disabling caching for
+ // |view_source_contents| to make sure it will not be put into the back
+ // forward cache.
+ view_source_contents->GetController().GetBackForwardCache().DisableForTesting(
+ content::BackForwardCache::TEST_ASSUMES_NO_CACHING);
+
+ // 4. Navigate the view-source page to a c.com/title1.html
+ ui_test_utils::NavigateToURL(
+ browser(), GURL(embedded_test_server()->GetURL("c.com", "/title1.html")));
+
+ base::RunLoop cache_status_waiter;
+ content::URLLoaderInterceptor interceptor(
+ base::BindLambdaForTesting(
+ [&](content::URLLoaderInterceptor::RequestParams* params) {
+ return false;
+ }),
+ base::BindLambdaForTesting(
+ [&](const GURL& request_url,
+ const network::URLLoaderCompletionStatus& status) {
+ if (request_url == subframe_url) {
+ EXPECT_TRUE(status.exists_in_cache);
+ cache_status_waiter.Quit();
+ }
+ }),
+ {});
+
+ {
+ // 5. Navigate back to the view-source page
+ content::WebContents* new_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ content::TestNavigationObserver navigation_observer(new_contents);
+ chrome::GoBack(browser(), WindowOpenDisposition::CURRENT_TAB);
+ navigation_observer.Wait();
+ }
+
+ cache_status_waiter.Run();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ ViewSourceWithSplitCacheEnabledTest,
+ ::testing::Values(true));
+
+// Verify that links clicked from view-source do not send a Referer header.
+// See https://crbug.com/834023.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, NavigationOmitsReferrer) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url(content::kViewSourceScheme + std::string(":") +
+ embedded_test_server()->GetURL(kTestNavigationHtml).spec());
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ // Click the first link in the view-source markup.
+ content::WebContentsAddedObserver nav_observer;
+ EXPECT_TRUE(content::ExecuteScript(
+ browser()->tab_strip_model()->GetActiveWebContents(),
+ "document.getElementsByTagName('A')[0].click();"));
+ content::WebContents* new_contents = nav_observer.GetWebContents();
+ EXPECT_TRUE(WaitForLoadStop(new_contents));
+
+ // Validate that no referrer was sent.
+ std::string response_text;
+ std::string response_text_extraction_script =
+ "domAutomationController.send(document.body.innerText);";
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ new_contents, response_text_extraction_script, &response_text));
+ EXPECT_EQ("None", response_text);
+}
+
+// Verify that JavaScript URIs are sanitized to about:blank.
+IN_PROC_BROWSER_TEST_F(ViewSourceTest, JavaScriptURISanitized) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL url(content::kViewSourceScheme + std::string(":") +
+ embedded_test_server()->GetURL(kTestNavigationHtml).spec());
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ // Get the href of the second link in the view-source markup.
+ std::string link_href;
+ std::string link_href_extraction_script = R"(
+ domAutomationController.send(
+ document.getElementsByTagName('A')[1].href);)";
+
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ browser()->tab_strip_model()->GetActiveWebContents(),
+ link_href_extraction_script, &link_href));
+ EXPECT_EQ("about:blank", link_href);
+}
+
+// This test verifies that 'view-source' documents are not affected by vertical
+// scroll (see https://crbug.com/898688).
+IN_PROC_BROWSER_TEST_F(ViewSourceFeaturePolicyTest,
+ ViewSourceNotAffectedByHeaderPolicy) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ const std::string k_verify_feature = R"(
+ var all_features = document.featurePolicy.allowedFeatures();
+ var vs = all_features.find((f) => f === 'vertical-scroll');
+ console.log(vs);
+ domAutomationController.send("" + vs);)";
+ // Sanity-check: 'vertical-scroll' is disabled in the actual page (set by the
+ // mock headers).
+ GURL url(embedded_test_server()->GetURL(kTestHtml));
+ ui_test_utils::NavigateToURL(browser(), url);
+ std::string response;
+ ASSERT_TRUE(ExecuteScriptAndExtractString(
+ browser()->tab_strip_model()->GetActiveWebContents(), k_verify_feature,
+ &response));
+ EXPECT_EQ("undefined", response);
+ // Ensure the policy is enabled in the view-source version.
+ ui_test_utils::NavigateToURL(browser(), GURL(content::kViewSourceScheme +
+ std::string(":") + url.spec()));
+ ASSERT_TRUE(ExecuteScriptAndExtractString(
+ browser()->tab_strip_model()->GetActiveWebContents(), k_verify_feature,
+ &response));
+ EXPECT_EQ("vertical-scroll", response);
+}
diff --git a/chromium/chrome/browser/thumbnail/BUILD.gn b/chromium/chrome/browser/thumbnail/BUILD.gn
new file mode 100644
index 00000000000..2388bac2d90
--- /dev/null
+++ b/chromium/chrome/browser/thumbnail/BUILD.gn
@@ -0,0 +1,48 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+ import("//build/config/android/config.gni")
+ import("//build/config/android/rules.gni")
+ import("//third_party/protobuf/proto_library.gni")
+}
+
+group("thumbnail") {
+ public_deps = [ "//chrome/browser/thumbnail/generator" ]
+
+ if (is_android) {
+ public_deps += [ "//chrome/browser/thumbnail/cc" ]
+ }
+}
+
+if (is_android) {
+ java_group("java") {
+ deps = [ "//chrome/browser/thumbnail/generator:java" ]
+ }
+
+ group("unit_tests") {
+ testonly = true
+
+ deps = [ "//chrome/browser/thumbnail/cc:unit_tests" ]
+ }
+
+ java_group("javatests") {
+ testonly = true
+
+ deps = [ "//chrome/browser/thumbnail/generator:javatests" ]
+ }
+
+ java_group("thumbnail_java_test_support") {
+ testonly = true
+
+ deps =
+ [ "//chrome/browser/thumbnail/generator:generator_java_test_support" ]
+ }
+
+ group("test_support") {
+ testonly = true
+
+ public_deps = [ "//chrome/browser/thumbnail/generator:test_support" ]
+ }
+}
diff --git a/chromium/chrome/browser/thumbnail/cc/BUILD.gn b/chromium/chrome/browser/thumbnail/cc/BUILD.gn
new file mode 100644
index 00000000000..9d20cff10c0
--- /dev/null
+++ b/chromium/chrome/browser/thumbnail/cc/BUILD.gn
@@ -0,0 +1,46 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+ import("//build/config/android/config.gni")
+ import("//build/config/android/rules.gni")
+ import("//third_party/protobuf/proto_library.gni")
+}
+
+source_set("cc") {
+ deps = [
+ "//base",
+ "//cc",
+ "//chrome/browser/image_decoder",
+ "//chrome/common",
+ "//chrome/services/media_gallery_util/public/cpp",
+ "//chrome/services/media_gallery_util/public/mojom",
+ "//content/public/browser",
+ "//media",
+ "//mojo/public/cpp/bindings",
+ "//skia",
+ "//ui/gfx",
+ ]
+
+ sources = [
+ "scoped_ptr_expiring_cache.h",
+ "thumbnail.cc",
+ "thumbnail.h",
+ "thumbnail_cache.cc",
+ "thumbnail_cache.h",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+
+ deps = [
+ ":cc",
+ "//base",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+
+ sources = [ "scoped_ptr_expiring_cache_unittest.cc" ]
+}
diff --git a/chromium/chrome/browser/thumbnail/generator/BUILD.gn b/chromium/chrome/browser/thumbnail/generator/BUILD.gn
new file mode 100644
index 00000000000..ccee81b7018
--- /dev/null
+++ b/chromium/chrome/browser/thumbnail/generator/BUILD.gn
@@ -0,0 +1,163 @@
+# Copyright 2019 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+ import("//build/config/android/config.gni")
+ import("//build/config/android/rules.gni")
+ import("//third_party/protobuf/proto_library.gni")
+}
+
+source_set("generator") {
+ deps = [
+ "//base",
+ "//cc",
+ "//chrome/browser/image_decoder",
+ "//chrome/common",
+ "//chrome/services/media_gallery_util/public/cpp",
+ "//chrome/services/media_gallery_util/public/mojom",
+ "//content/public/browser",
+ "//media",
+ "//mojo/public/cpp/bindings",
+ "//skia",
+ "//ui/gfx",
+ ]
+
+ sources = [
+ "image_thumbnail_request.cc",
+ "image_thumbnail_request.h",
+ "thumbnail_util.cc",
+ "thumbnail_util.h",
+ ]
+
+ if (is_android) {
+ sources += [
+ "android/local_media_data_source_factory.cc",
+ "android/local_media_data_source_factory.h",
+ "android/stats.cc",
+ "android/stats.h",
+ "android/thumbnail_generator.cc",
+ "android/thumbnail_generator.h",
+ "android/thumbnail_media_parser.cc",
+ "android/thumbnail_media_parser.h",
+ ]
+
+ deps += [
+ ":jni_headers",
+ "//third_party/android_opengl/etc1",
+ ]
+ }
+}
+
+if (is_android) {
+ android_library("java") {
+ deps = [
+ ":jni_headers",
+ ":proto_java",
+ "//base:base_java",
+ "//base:jni_java",
+ "//chrome/browser/util:java",
+ "//content/public/android:content_java",
+ "//third_party/android_deps:android_support_v4_java",
+ "//third_party/android_deps:androidx_annotation_annotation_java",
+ "//third_party/android_deps:androidx_collection_collection_java",
+ "//third_party/android_deps:com_google_protobuf_protobuf_javalite_java",
+ ]
+
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailDiskStorage.java",
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailGenerator.java",
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailGeneratorCallback.java",
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailProvider.java",
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailProviderImpl.java",
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailStorageDelegate.java",
+ ]
+
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+ }
+
+ generate_jni("jni_headers") {
+ visibility = [ ":*" ]
+
+ sources = [ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailGenerator.java" ]
+ }
+
+ proto_java_library("proto_java") {
+ proto_path =
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator"
+ sources = [ "$proto_path/thumbnail_cache_entry.proto" ]
+ }
+
+ android_library("javatests") {
+ testonly = true
+
+ deps = [
+ ":generator_java_test_support",
+ ":java",
+ "//base:base_java",
+ "//base:base_java_test_support",
+ "//chrome/browser/flags:java",
+ "//chrome/browser/util:java",
+ "//chrome/test/android:chrome_java_test_support",
+ "//content/public/android:content_java",
+ "//content/public/test/android:content_java_test_support",
+ "//third_party/android_deps:android_support_v4_java",
+ "//third_party/android_support_test_runner:runner_java",
+ "//third_party/junit",
+ "//ui/android:ui_java_test_support",
+ ]
+
+ data = [ "//chrome/browser/thumbnail/generator/test/data/android/" ]
+
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailDiskStorageTest.java",
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserTest.java",
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailProviderImplTest.java",
+ ]
+ }
+
+ generate_jni("test_support_jni_headers") {
+ testonly = true
+
+ visibility = [ ":*" ]
+
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaData.java",
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserBridge.java",
+ ]
+ }
+
+ android_library("generator_java_test_support") {
+ testonly = true
+
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaData.java",
+ "android/java/src/org/chromium/chrome/browser/thumbnail/generator/ThumbnailMediaParserBridge.java",
+ ]
+
+ deps = [
+ ":test_support_jni_headers",
+ "//base:base_java",
+ "//base:jni_java",
+ ]
+
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+ }
+
+ source_set("test_support") {
+ testonly = true
+
+ deps = [
+ ":generator",
+ ":test_support_jni_headers",
+ "//base",
+ "//skia",
+ "//ui/gfx",
+ ]
+
+ sources = [
+ "android/thumbnail_media_parser_bridge.cc",
+ "android/thumbnail_media_parser_bridge.h",
+ ]
+ }
+}
diff --git a/chromium/chrome/browser/touch_to_fill/BUILD.gn b/chromium/chrome/browser/touch_to_fill/BUILD.gn
index 3647ba71f18..b440b3080cd 100644
--- a/chromium/chrome/browser/touch_to_fill/BUILD.gn
+++ b/chromium/chrome/browser/touch_to_fill/BUILD.gn
@@ -20,18 +20,12 @@ source_set("factory") {
"touch_to_fill_view_factory.h",
]
- deps = [
- "//chrome/browser/touch_to_fill/android",
- ]
+ deps = [ "//chrome/browser/touch_to_fill/android" ]
}
- public_deps = [
- ":public",
- ]
+ public_deps = [ ":public" ]
}
source_set("public") {
- sources = [
- "touch_to_fill_view.h",
- ]
+ sources = [ "touch_to_fill_view.h" ]
}
diff --git a/chromium/chrome/browser/touch_to_fill/android/BUILD.gn b/chromium/chrome/browser/touch_to_fill/android/BUILD.gn
index 2667e4002ac..d8ad039a4a6 100644
--- a/chromium/chrome/browser/touch_to_fill/android/BUILD.gn
+++ b/chromium/chrome/browser/touch_to_fill/android/BUILD.gn
@@ -31,20 +31,19 @@ android_library("public_java") {
# TODO(crbug.com/1004415): Remove dependency on chrome_java and depend on
# bottomsheet directly. Add public_java to chrome_java target instead.
"//chrome/android:chrome_java",
- "//chrome/android:chrome_public_java",
"//ui/android:ui_java",
]
- java_files = [
- "java/src/org/chromium/chrome/browser/touch_to_fill/data/Credential.java",
+ sources = [
"java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillComponent.java",
+ "java/src/org/chromium/chrome/browser/touch_to_fill/data/Credential.java",
]
}
junit_binary("touch_to_fill_junit_tests") {
testonly = true
- java_files = [ "junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java" ]
+ sources = [ "junit/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillControllerTest.java" ]
deps = [
"//base:base_java_test_support",
@@ -60,7 +59,7 @@ junit_binary("touch_to_fill_junit_tests") {
android_library("test_java") {
testonly = true
- java_files = [
+ sources = [
"javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java",
]
@@ -75,7 +74,7 @@ android_library("test_java") {
"//chrome/browser/touch_to_fill/android/internal:java",
"//chrome/test/android:chrome_java_test_support",
"//content/public/test/android:content_java_test_support",
- "//third_party/android_deps:com_android_support_recyclerview_v7_java",
+ "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
"//third_party/espresso:espresso_all_java",
"//third_party/hamcrest:hamcrest_java",
"//third_party/junit",
diff --git a/chromium/chrome/browser/touch_to_fill/android/internal/BUILD.gn b/chromium/chrome/browser/touch_to_fill/android/internal/BUILD.gn
index 6e01b6b8e64..28683e96f91 100644
--- a/chromium/chrome/browser/touch_to_fill/android/internal/BUILD.gn
+++ b/chromium/chrome/browser/touch_to_fill/android/internal/BUILD.gn
@@ -12,15 +12,18 @@ android_library("java") {
"//base:base_java",
"//base:jni_java",
"//chrome/android:chrome_java",
- "//chrome/android/public/profiles:java",
+ "//chrome/browser/flags:java",
+ "//chrome/browser/profiles/android:java",
"//chrome/browser/touch_to_fill/android:public_java",
+ "//chrome/browser/ui/android/favicon:java",
"//chrome/browser/util:java",
+ "//components/embedder_support/android:util_java",
"//components/url_formatter/android:url_formatter_java",
- "//third_party/android_deps:com_android_support_recyclerview_v7_java",
+ "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
"//ui/android:ui_java",
]
- java_files = [
+ sources = [
"java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillBridge.java",
"java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillCoordinator.java",
"java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillMediator.java",
@@ -39,7 +42,17 @@ android_resources("java_resources") {
"//third_party/android_deps:android_support_v7_appcompat_java",
"//ui/android:ui_java_resources",
]
- resource_dirs = [ "java/res" ]
+ sources = [
+ "java/res/drawable-night/touch_to_fill_header_image.xml",
+ "java/res/drawable/touch_to_fill_credential_background.xml",
+ "java/res/drawable/touch_to_fill_header_image.xml",
+ "java/res/layout/touch_to_fill_credential_item.xml",
+ "java/res/layout/touch_to_fill_fill_button.xml",
+ "java/res/layout/touch_to_fill_footer.xml",
+ "java/res/layout/touch_to_fill_header_item.xml",
+ "java/res/layout/touch_to_fill_sheet.xml",
+ "java/res/values/dimens.xml",
+ ]
custom_package = "org.chromium.chrome.browser.touch_to_fill"
}
diff --git a/chromium/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd b/chromium/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd
index 3aa425dfbe5..7654801f0b4 100644
--- a/chromium/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd
+++ b/chromium/chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd
@@ -5,10 +5,15 @@
<grit current_release="1" latest_public_release="0" output_all_resource_defines="false">
<outputs>
+ <output filename="values-af/android_touch_to_fill_strings.xml" lang="af" type="android" />
<output filename="values-am/android_touch_to_fill_strings.xml" lang="am" type="android" />
<output filename="values-ar/android_touch_to_fill_strings.xml" lang="ar" type="android" />
+ <output filename="values-as/android_touch_to_fill_strings.xml" lang="as" type="android" />
+ <output filename="values-az/android_touch_to_fill_strings.xml" lang="az" type="android" />
+ <output filename="values-be/android_touch_to_fill_strings.xml" lang="be" type="android" />
<output filename="values-bg/android_touch_to_fill_strings.xml" lang="bg" type="android" />
<output filename="values-bn/android_touch_to_fill_strings.xml" lang="bn" type="android" />
+ <output filename="values-bs/android_touch_to_fill_strings.xml" lang="bs" type="android" />
<output filename="values-ca/android_touch_to_fill_strings.xml" lang="ca" type="android" />
<output filename="values-cs/android_touch_to_fill_strings.xml" lang="cs" type="android" />
<output filename="values-da/android_touch_to_fill_strings.xml" lang="da" type="android" />
@@ -19,34 +24,52 @@
<output filename="values-es/android_touch_to_fill_strings.xml" lang="es" type="android" />
<output filename="values-es-rUS/android_touch_to_fill_strings.xml" lang="es-419" type="android" />
<output filename="values-et/android_touch_to_fill_strings.xml" lang="et" type="android" />
+ <output filename="values-eu/android_touch_to_fill_strings.xml" lang="eu" type="android" />
<output filename="values-fa/android_touch_to_fill_strings.xml" lang="fa" type="android" />
<output filename="values-fi/android_touch_to_fill_strings.xml" lang="fi" type="android" />
<output filename="values-tl/android_touch_to_fill_strings.xml" lang="fil" type="android" />
<output filename="values-fr/android_touch_to_fill_strings.xml" lang="fr" type="android" />
+ <output filename="values-fr-rCA/android_touch_to_fill_strings.xml" lang="fr-CA" type="android" />
+ <output filename="values-gl/android_touch_to_fill_strings.xml" lang="gl" type="android" />
<output filename="values-gu/android_touch_to_fill_strings.xml" lang="gu" type="android" />
<output filename="values-hi/android_touch_to_fill_strings.xml" lang="hi" type="android" />
<output filename="values-hr/android_touch_to_fill_strings.xml" lang="hr" type="android" />
<output filename="values-hu/android_touch_to_fill_strings.xml" lang="hu" type="android" />
+ <output filename="values-hy/android_touch_to_fill_strings.xml" lang="hy" type="android" />
<output filename="values-in/android_touch_to_fill_strings.xml" lang="id" type="android" />
+ <output filename="values-is/android_touch_to_fill_strings.xml" lang="is" type="android" />
<output filename="values-it/android_touch_to_fill_strings.xml" lang="it" type="android" />
<output filename="values-iw/android_touch_to_fill_strings.xml" lang="iw" type="android" />
<output filename="values-ja/android_touch_to_fill_strings.xml" lang="ja" type="android" />
+ <output filename="values-ka/android_touch_to_fill_strings.xml" lang="ka" type="android" />
+ <output filename="values-kk/android_touch_to_fill_strings.xml" lang="kk" type="android" />
+ <output filename="values-km/android_touch_to_fill_strings.xml" lang="km" type="android" />
<output filename="values-kn/android_touch_to_fill_strings.xml" lang="kn" type="android" />
<output filename="values-ko/android_touch_to_fill_strings.xml" lang="ko" type="android" />
+ <output filename="values-ky/android_touch_to_fill_strings.xml" lang="ky" type="android" />
+ <output filename="values-lo/android_touch_to_fill_strings.xml" lang="lo" type="android" />
<output filename="values-lt/android_touch_to_fill_strings.xml" lang="lt" type="android" />
<output filename="values-lv/android_touch_to_fill_strings.xml" lang="lv" type="android" />
+ <output filename="values-mk/android_touch_to_fill_strings.xml" lang="mk" type="android" />
<output filename="values-ml/android_touch_to_fill_strings.xml" lang="ml" type="android" />
+ <output filename="values-mn/android_touch_to_fill_strings.xml" lang="mn" type="android" />
<output filename="values-mr/android_touch_to_fill_strings.xml" lang="mr" type="android" />
<output filename="values-ms/android_touch_to_fill_strings.xml" lang="ms" type="android" />
+ <output filename="values-my/android_touch_to_fill_strings.xml" lang="my" type="android" />
+ <output filename="values-ne/android_touch_to_fill_strings.xml" lang="ne" type="android" />
<output filename="values-nl/android_touch_to_fill_strings.xml" lang="nl" type="android" />
<output filename="values-nb/android_touch_to_fill_strings.xml" lang="no" type="android" />
+ <output filename="values-or/android_touch_to_fill_strings.xml" lang="or" type="android" />
+ <output filename="values-pa/android_touch_to_fill_strings.xml" lang="pa" type="android" />
<output filename="values-pl/android_touch_to_fill_strings.xml" lang="pl" type="android" />
<output filename="values-pt-rBR/android_touch_to_fill_strings.xml" lang="pt-BR" type="android" />
<output filename="values-pt-rPT/android_touch_to_fill_strings.xml" lang="pt-PT" type="android" />
<output filename="values-ro/android_touch_to_fill_strings.xml" lang="ro" type="android" />
<output filename="values-ru/android_touch_to_fill_strings.xml" lang="ru" type="android" />
+ <output filename="values-si/android_touch_to_fill_strings.xml" lang="si" type="android" />
<output filename="values-sk/android_touch_to_fill_strings.xml" lang="sk" type="android" />
<output filename="values-sl/android_touch_to_fill_strings.xml" lang="sl" type="android" />
+ <output filename="values-sq/android_touch_to_fill_strings.xml" lang="sq" type="android" />
<output filename="values-sr/android_touch_to_fill_strings.xml" lang="sr" type="android" />
<output filename="values-sv/android_touch_to_fill_strings.xml" lang="sv" type="android" />
<output filename="values-sw/android_touch_to_fill_strings.xml" lang="sw" type="android" />
@@ -55,9 +78,13 @@
<output filename="values-th/android_touch_to_fill_strings.xml" lang="th" type="android" />
<output filename="values-tr/android_touch_to_fill_strings.xml" lang="tr" type="android" />
<output filename="values-uk/android_touch_to_fill_strings.xml" lang="uk" type="android" />
+ <output filename="values-ur/android_touch_to_fill_strings.xml" lang="ur" type="android" />
+ <output filename="values-uz/android_touch_to_fill_strings.xml" lang="uz" type="android" />
<output filename="values-vi/android_touch_to_fill_strings.xml" lang="vi" type="android" />
<output filename="values-zh-rCN/android_touch_to_fill_strings.xml" lang="zh-CN" type="android" />
+ <output filename="values-zh-rHK/android_touch_to_fill_strings.xml" lang="zh-HK" type="android" />
<output filename="values-zh-rTW/android_touch_to_fill_strings.xml" lang="zh-TW" type="android" />
+ <output filename="values-zu/android_touch_to_fill_strings.xml" lang="zu" type="android" />
</outputs>
<translations>
<file lang="af" path="translations/android_touch_to_fill_strings_af.xtb" />
@@ -125,6 +152,7 @@
<file lang="sl" path="translations/android_touch_to_fill_strings_sl.xtb" />
<file lang="sq" path="translations/android_touch_to_fill_strings_sq.xtb" />
<file lang="sr" path="translations/android_touch_to_fill_strings_sr.xtb" />
+ <file lang="sr-Latn" path="translations/android_touch_to_fill_strings_sr-Latn.xtb" />
<file lang="sv" path="translations/android_touch_to_fill_strings_sv.xtb" />
<file lang="sw" path="translations/android_touch_to_fill_strings_sw.xtb" />
<file lang="ta" path="translations/android_touch_to_fill_strings_ta.xtb" />
diff --git a/chromium/chrome/browser/ui/BUILD.gn b/chromium/chrome/browser/ui/BUILD.gn
index 7932e2421de..dfffff81bcf 100644
--- a/chromium/chrome/browser/ui/BUILD.gn
+++ b/chromium/chrome/browser/ui/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/buildflags_paint_preview.gni")
import("//build/config/chromecast_build.gni")
import("//build/config/compiler/compiler.gni")
import("//build/config/crypto.gni")
@@ -9,6 +10,7 @@ import("//build/config/features.gni")
import("//build/config/jumbo.gni")
import("//build/config/linux/gtk/gtk.gni")
import("//build/config/ui.gni")
+import("//chrome/browser/buildflags.gni")
import("//chrome/common/features.gni")
import("//chromeos/assistant/assistant.gni")
import("//components/feature_engagement/features.gni")
@@ -40,8 +42,8 @@ jumbo_static_library("ui") {
"autofill/autofill_popup_controller_impl.h",
"autofill/autofill_popup_controller_impl_mac.h",
"autofill/autofill_popup_controller_impl_mac.mm",
- "autofill/autofill_popup_layout_model.cc",
- "autofill/autofill_popup_layout_model.h",
+ "autofill/autofill_popup_controller_utils.cc",
+ "autofill/autofill_popup_controller_utils.h",
"autofill/autofill_popup_view.h",
"autofill/autofill_popup_view_delegate.h",
"autofill/chrome_autofill_client.cc",
@@ -58,8 +60,6 @@ jumbo_static_library("ui") {
"autofill/popup_constants.h",
"autofill/popup_controller_common.cc",
"autofill/popup_controller_common.h",
- "autofill/popup_view_common.cc",
- "autofill/popup_view_common.h",
"autofill/test/test_autofill_bubble_handler.cc",
"autofill/test/test_autofill_bubble_handler.h",
"blocked_content/blocked_window_params.cc",
@@ -90,41 +90,42 @@ jumbo_static_library("ui") {
"chrome_select_file_policy.h",
"color_chooser.h",
"confirm_bubble.h",
+ "cookie_controls/cookie_controls_controller.cc",
+ "cookie_controls/cookie_controls_controller.h",
+ "cookie_controls/cookie_controls_service.cc",
+ "cookie_controls/cookie_controls_service.h",
+ "cookie_controls/cookie_controls_service_factory.cc",
+ "cookie_controls/cookie_controls_service_factory.h",
"crypto_module_password_dialog.h",
"cryptuiapi_shim.h",
"enterprise_startup_dialog.h",
"find_bar/find_bar.h",
+ "find_bar/find_bar_state.cc",
"find_bar/find_bar_state.h",
"find_bar/find_bar_state_factory.cc",
"find_bar/find_bar_state_factory.h",
- "find_bar/find_notification_details.h",
- "find_bar/find_result_observer.h",
- "find_bar/find_tab_helper.cc",
- "find_bar/find_tab_helper.h",
- "find_bar/find_types.h",
"interventions/framebust_block_message_delegate.cc",
"interventions/framebust_block_message_delegate.h",
"interventions/intervention_delegate.h",
"interventions/intervention_infobar_delegate.cc",
"interventions/intervention_infobar_delegate.h",
- "javascript_dialogs/chrome_javascript_native_app_modal_dialog_factory.h",
- "javascript_dialogs/javascript_dialog.h",
- "javascript_dialogs/javascript_dialog_tab_helper.cc",
- "javascript_dialogs/javascript_dialog_tab_helper.h",
+ "javascript_dialogs/chrome_javascript_app_modal_dialog_view_factory.h",
+ "javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_android.cc",
+ "javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_android.h",
"login/login_handler.cc",
"login/login_handler.h",
- "login/login_interstitial_delegate.cc",
- "login/login_interstitial_delegate.h",
"login/login_navigation_throttle.cc",
"login/login_navigation_throttle.h",
"login/login_tab_helper.cc",
"login/login_tab_helper.h",
+ "native_file_system_dialogs.cc",
+ "native_file_system_dialogs.h",
"navigation_correction_tab_observer.cc",
"navigation_correction_tab_observer.h",
- "page_info/page_info.cc",
- "page_info/page_info.h",
- "page_info/page_info_ui.cc",
- "page_info/page_info_ui.h",
+ "page_info/chrome_page_info_delegate.cc",
+ "page_info/chrome_page_info_delegate.h",
+ "page_info/chrome_page_info_ui_delegate.cc",
+ "page_info/chrome_page_info_ui_delegate.h",
"passwords/account_avatar_fetcher.cc",
"passwords/account_avatar_fetcher.h",
"passwords/manage_passwords_state.cc",
@@ -138,14 +139,11 @@ jumbo_static_library("ui") {
"passwords/password_generation_popup_observer.h",
"passwords/password_generation_popup_view.cc",
"passwords/password_generation_popup_view.h",
- "passwords/settings/password_access_authenticator.cc",
- "passwords/settings/password_access_authenticator.h",
"passwords/settings/password_manager_porter.cc",
"passwords/settings/password_manager_porter.h",
"passwords/settings/password_manager_presenter.cc",
"passwords/settings/password_manager_presenter.h",
"passwords/settings/password_ui_view.h",
- "permission_bubble/permission_prompt.h",
"prefs/pref_watcher.cc",
"prefs/pref_watcher.h",
"prefs/prefs_tab_helper.cc",
@@ -171,6 +169,7 @@ jumbo_static_library("ui") {
"startup/bad_flags_prompt.cc",
"startup/bad_flags_prompt.h",
"status_bubble.h",
+ "storage_pressure_bubble.h",
"sync/tab_contents_synced_tab_delegate.cc",
"sync/tab_contents_synced_tab_delegate.h",
"tab_contents/chrome_web_contents_view_delegate.h",
@@ -208,10 +207,14 @@ jumbo_static_library("ui") {
"webui/autofill_and_password_manager_internals/internals_ui_handler.h",
"webui/autofill_and_password_manager_internals/password_manager_internals_ui.cc",
"webui/autofill_and_password_manager_internals/password_manager_internals_ui.h",
+ "webui/chrome_url_disabled_ui.cc",
+ "webui/chrome_url_disabled_ui.h",
"webui/chrome_web_ui_controller_factory.cc",
"webui/chrome_web_ui_controller_factory.h",
- "webui/components_ui.cc",
- "webui/components_ui.h",
+ "webui/components/components_handler.cc",
+ "webui/components/components_handler.h",
+ "webui/components/components_ui.cc",
+ "webui/components/components_ui.h",
"webui/constrained_web_dialog_ui.cc",
"webui/constrained_web_dialog_ui.h",
"webui/cookies_tree_model_util.cc",
@@ -252,6 +255,10 @@ jumbo_static_library("ui") {
"webui/log_web_ui_url.h",
"webui/media/media_engagement_ui.cc",
"webui/media/media_engagement_ui.h",
+ "webui/media/media_feeds_ui.cc",
+ "webui/media/media_feeds_ui.h",
+ "webui/media/media_history_ui.cc",
+ "webui/media/media_history_ui.h",
"webui/media/webrtc_logs_ui.cc",
"webui/media/webrtc_logs_ui.h",
"webui/memory_internals_ui.cc",
@@ -385,10 +392,14 @@ jumbo_static_library("ui") {
"//chrome/app/theme:chrome_unscaled_resources",
"//chrome/app/theme:theme_resources",
"//chrome/app/vector_icons",
+ "//chrome/browser:buildflags",
+ "//chrome/browser:dev_ui_browser_resources",
"//chrome/browser:resource_prefetch_predictor_proto",
"//chrome/browser/devtools",
"//chrome/browser/engagement:mojo_bindings",
+ "//chrome/browser/image_decoder",
"//chrome/browser/media:mojo_bindings",
+ "//chrome/browser/media/feeds:mojo_bindings",
"//chrome/browser/notifications/scheduler/public",
"//chrome/browser/profiling_host",
"//chrome/browser/resources/invalidations:invalidations_resources",
@@ -398,7 +409,6 @@ jumbo_static_library("ui") {
"//chrome/browser/resources/quota_internals:quota_internals_resources",
"//chrome/browser/resources/usb_internals:resources",
"//chrome/browser/safe_browsing",
- "//chrome/browser/ssl:proto",
"//chrome/browser/ui/webui/bluetooth_internals",
"//chrome/browser/ui/webui/downloads:mojo_bindings",
"//chrome/browser/ui/webui/interventions_internals:mojo_bindings",
@@ -408,9 +418,10 @@ jumbo_static_library("ui") {
"//chrome/common",
"//chrome/common/net",
"//chrome/installer/util:with_no_strings",
+ "//chrome/services/qrcode_generator/public/cpp",
+ "//chrome/services/qrcode_generator/public/mojom",
"//components/about_ui",
"//components/account_id",
- "//components/app_modal",
"//components/autofill/content/browser:risk_proto",
"//components/autofill/core/browser",
"//components/bookmarks/browser",
@@ -418,9 +429,11 @@ jumbo_static_library("ui") {
"//components/browser_sync",
"//components/browsing_data/content",
"//components/browsing_data/core",
- "//components/bubble",
+ "//components/captive_portal/content",
+ "//components/captive_portal/core:buildflags",
"//components/consent_auditor/",
"//components/content_settings/core/browser",
+ "//components/country_codes",
"//components/crx_file",
"//components/data_reduction_proxy/core/browser",
"//components/device_event_log",
@@ -428,6 +441,7 @@ jumbo_static_library("ui") {
"//components/domain_reliability",
"//components/download/content/factory",
"//components/download/content/public",
+ "//components/embedder_support",
"//components/encrypted_messages:encrypted_message_proto",
"//components/favicon/content",
"//components/favicon/core",
@@ -437,6 +451,7 @@ jumbo_static_library("ui") {
"//components/feed/content:feed_content",
"//components/feed/core:feed_core",
"//components/feedback",
+ "//components/find_in_page",
"//components/flags_ui",
"//components/gcm_driver",
"//components/google/core/common",
@@ -447,10 +462,12 @@ jumbo_static_library("ui") {
"//components/image_fetcher/core",
"//components/infobars/core",
"//components/invalidation/impl",
+ "//components/javascript_dialogs",
"//components/keyed_service/content",
"//components/keyed_service/core",
"//components/language/core/browser",
"//components/language/core/common",
+ "//components/lookalikes",
"//components/metrics_services_manager",
"//components/navigation_metrics",
"//components/net_log",
@@ -460,6 +477,7 @@ jumbo_static_library("ui") {
"//components/omnibox/browser",
"//components/omnibox/browser:vector_icons",
"//components/onc",
+ "//components/paint_preview/buildflags",
"//components/password_manager/content/browser",
"//components/password_manager/core/browser",
"//components/password_manager/core/browser:affiliation",
@@ -469,6 +487,7 @@ jumbo_static_library("ui") {
"//components/payments/core:error_strings",
"//components/pdf/browser",
"//components/performance_manager",
+ "//components/permissions",
"//components/policy/core/browser",
"//components/pref_registry",
"//components/previews/content",
@@ -478,21 +497,22 @@ jumbo_static_library("ui") {
"//components/rappor",
"//components/renderer_context_menu",
"//components/resources",
- "//components/safe_browsing:csd_proto",
- "//components/safe_browsing:features",
- "//components/safe_browsing/common",
- "//components/safe_browsing/common:safe_browsing_prefs",
- "//components/safe_browsing/db:database_manager",
- "//components/safe_browsing/db:util",
- "//components/safe_browsing/password_protection",
- "//components/safe_browsing/password_protection:password_protection_metrics_util",
- "//components/safe_browsing/triggers:ad_popup_trigger",
- "//components/safe_browsing/triggers:ad_redirect_trigger",
- "//components/safe_browsing/web_ui",
+ "//components/safe_browsing/content/password_protection",
+ "//components/safe_browsing/content/password_protection:password_protection_metrics_util",
+ "//components/safe_browsing/content/triggers:ad_popup_trigger",
+ "//components/safe_browsing/content/triggers:ad_redirect_trigger",
+ "//components/safe_browsing/content/web_ui",
+ "//components/safe_browsing/core:csd_proto",
+ "//components/safe_browsing/core:features",
+ "//components/safe_browsing/core/common",
+ "//components/safe_browsing/core/common:safe_browsing_prefs",
+ "//components/safe_browsing/core/db:database_manager",
+ "//components/safe_browsing/core/db:util",
"//components/search",
"//components/search_engines",
"//components/security_interstitials/content:security_interstitial_page",
"//components/security_interstitials/core",
+ "//components/security_interstitials/core:unsafe_resource",
"//components/security_state/content",
"//components/security_state/core",
"//components/send_tab_to_self",
@@ -502,7 +522,7 @@ jumbo_static_library("ui") {
"//components/signin/public/identity_manager",
"//components/spellcheck/browser",
"//components/ssl_errors",
- "//components/startup_metric_utils/browser:lib",
+ "//components/startup_metric_utils/browser",
"//components/strings",
"//components/subresource_filter/content/browser",
"//components/subresource_filter/core/browser",
@@ -510,6 +530,7 @@ jumbo_static_library("ui") {
"//components/sync/driver:resources",
"//components/sync_preferences",
"//components/sync_sessions",
+ "//components/tab_groups",
"//components/tracing:startup_tracing",
"//components/translate/translate_internals",
"//components/ui_devtools",
@@ -599,16 +620,20 @@ jumbo_static_library("ui") {
deps += [
"//chrome/browser/ui/webui/explore_sites_internals:mojo_bindings",
"//chrome/browser/ui/webui/snippets_internals:mojo_bindings",
+ "//components/browser_ui/util/android",
]
if (enable_feed_in_chrome) {
deps += [ "//chrome/browser/ui/webui/feed_internals:mojo_bindings" ]
}
+ } else {
+ # !is_android
+ deps += [ "//components/autofill/content/browser/webauthn" ]
}
if (!is_fuchsia) {
# TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
deps += [
- "//components/crash/content/app",
+ "//components/crash/core/app",
"//components/crash/core/browser",
]
}
@@ -647,6 +672,7 @@ jumbo_static_library("ui") {
"android/autofill/credit_card_scanner_view_android.h",
"android/chrome_http_auth_handler.cc",
"android/chrome_http_auth_handler.h",
+ "android/chrome_javascript_app_modal_dialog_android.cc",
"android/color_chooser_dialog_android.cc",
"android/content_settings/ads_blocked_infobar_delegate.cc",
"android/content_settings/ads_blocked_infobar_delegate.h",
@@ -704,23 +730,17 @@ jumbo_static_library("ui") {
"android/infobars/simple_confirm_infobar_builder.cc",
"android/infobars/survey_infobar.cc",
"android/infobars/survey_infobar.h",
+ "android/infobars/sync_error_infobar.cc",
+ "android/infobars/sync_error_infobar.h",
"android/infobars/translate_compact_infobar.cc",
"android/infobars/translate_compact_infobar.h",
"android/infobars/update_password_infobar.cc",
"android/infobars/update_password_infobar.h",
- "android/javascript_app_modal_dialog_android.cc",
- "android/javascript_app_modal_dialog_android.h",
- "android/javascript_dialog_android.cc",
- "android/javascript_dialog_android.h",
"android/login_handler_android.cc",
- "android/omnibox/omnibox_url_emphasizer.cc",
- "android/omnibox/omnibox_url_emphasizer.h",
"android/omnibox/omnibox_view_util.cc",
"android/omnibox/omnibox_view_util.h",
"android/overlay/overlay_window_android.cc",
"android/overlay/overlay_window_android.h",
- "android/page_info/certificate_chain_helper.cc",
- "android/page_info/certificate_viewer_android.cc",
"android/page_info/connection_info_popup_android.cc",
"android/page_info/connection_info_popup_android.h",
"android/page_info/page_info_controller_android.cc",
@@ -735,13 +755,13 @@ jumbo_static_library("ui") {
"android/passwords/password_generation_dialog_view_android.h",
"android/passwords/password_generation_editing_popup_view_android.cc",
"android/passwords/password_generation_editing_popup_view_android.h",
+ "android/safe_browsing/password_reuse_dialog_view_android.cc",
+ "android/safe_browsing/password_reuse_dialog_view_android.h",
"android/simple_message_box_android.cc",
"android/sms/sms_infobar.cc",
"android/sms/sms_infobar.h",
"android/sms/sms_infobar_delegate.cc",
"android/sms/sms_infobar_delegate.h",
- "android/snackbars/auto_signin_prompt_controller.cc",
- "android/snackbars/auto_signin_prompt_controller.h",
"android/ssl_client_certificate_request.cc",
"android/status_tray_android.cc",
"android/tab_contents/chrome_web_contents_view_delegate_android.cc",
@@ -789,14 +809,28 @@ jumbo_static_library("ui") {
"webui/feed_internals/feed_internals_ui.cc",
"webui/feed_internals/feed_internals_ui.h",
]
+ deps += [ "//components/feed/core/common:feed_core_common" ]
+ }
+
+ if (enable_password_change_in_leaked_dialog) {
+ sources += [
+ "android/passwords/credential_leak_dialog_password_change_view_android.cc",
+ "android/passwords/credential_leak_dialog_password_change_view_android.h",
+ ]
}
deps += [
"//chrome/android:jni_headers",
"//chrome/android/features/dev_ui:buildflags",
"//chrome/browser/android/thin_webview:thin_webview",
+ "//chrome/browser/image_decoder",
"//chrome/browser/resources/webapks:webapks_ui_resources",
+ "//components/embedder_support/android:context_menu",
"//components/embedder_support/android:web_contents_delegate",
+ "//components/javascript_dialogs/android:jni_headers",
"//components/navigation_interception",
+ "//components/optimization_guide/proto:optimization_guide_proto",
+ "//components/page_info",
+ "//components/page_info/android:android",
"//components/subresource_filter/core/browser",
"//crypto:platform",
"//device/vr/buildflags",
@@ -885,8 +919,6 @@ jumbo_static_library("ui") {
"browser_window.h",
"browser_window_state.cc",
"browser_window_state.h",
- "chrome_bubble_manager.cc",
- "chrome_bubble_manager.h",
"chrome_pages.cc",
"chrome_pages.h",
"chrome_web_modal_dialog_manager_delegate.cc",
@@ -926,6 +958,8 @@ jumbo_static_library("ui") {
"find_bar/find_bar_platform_helper.cc",
"find_bar/find_bar_platform_helper.h",
"find_bar/find_bar_platform_helper_mac.mm",
+ "focus_tab_after_navigation_helper.cc",
+ "focus_tab_after_navigation_helper.h",
"global_error/global_error.cc",
"global_error/global_error.h",
"global_error/global_error_bubble_view_base.h",
@@ -963,6 +997,8 @@ jumbo_static_library("ui") {
"hats/hats_service.h",
"hats/hats_service_factory.cc",
"hats/hats_service_factory.h",
+ "hats/hats_survey_status_checker.cc",
+ "hats/hats_survey_status_checker.h",
"hid/hid_chooser.cc",
"hid/hid_chooser.h",
"hid/hid_chooser_controller.cc",
@@ -984,6 +1020,8 @@ jumbo_static_library("ui") {
"in_product_help/reopen_tab_in_product_help_trigger.h",
"intent_picker_tab_helper.cc",
"intent_picker_tab_helper.h",
+ "javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_desktop.cc",
+ "javascript_dialogs/javascript_tab_modal_dialog_manager_delegate_desktop.h",
"layout_constants.cc",
"layout_constants.h",
"location_bar/location_bar.h",
@@ -1026,6 +1064,8 @@ jumbo_static_library("ui") {
"omnibox/chrome_omnibox_navigation_observer.h",
"omnibox/clipboard_utils.cc",
"omnibox/clipboard_utils.h",
+ "omnibox/omnibox_tab_helper.cc",
+ "omnibox/omnibox_tab_helper.h",
"omnibox/omnibox_theme.cc",
"omnibox/omnibox_theme.h",
"page_action/page_action_icon_type.h",
@@ -1035,6 +1075,22 @@ jumbo_static_library("ui") {
"page_info/page_info_infobar_delegate.h",
"page_info/permission_menu_model.cc",
"page_info/permission_menu_model.h",
+ "passwords/bubble_controllers/auto_sign_in_bubble_controller.cc",
+ "passwords/bubble_controllers/auto_sign_in_bubble_controller.h",
+ "passwords/bubble_controllers/generation_confirmation_bubble_controller.cc",
+ "passwords/bubble_controllers/generation_confirmation_bubble_controller.h",
+ "passwords/bubble_controllers/items_bubble_controller.cc",
+ "passwords/bubble_controllers/items_bubble_controller.h",
+ "passwords/bubble_controllers/password_bubble_controller_base.cc",
+ "passwords/bubble_controllers/password_bubble_controller_base.h",
+ "passwords/bubble_controllers/save_unsynced_credentials_locally_bubble_controller.cc",
+ "passwords/bubble_controllers/save_unsynced_credentials_locally_bubble_controller.h",
+ "passwords/bubble_controllers/save_update_bubble_controller.cc",
+ "passwords/bubble_controllers/save_update_bubble_controller.h",
+ "passwords/bubble_controllers/save_update_with_account_store_bubble_controller.cc",
+ "passwords/bubble_controllers/save_update_with_account_store_bubble_controller.h",
+ "passwords/bubble_controllers/sign_in_promo_bubble_controller.cc",
+ "passwords/bubble_controllers/sign_in_promo_bubble_controller.h",
"passwords/credential_leak_dialog_controller.h",
"passwords/credential_leak_dialog_controller_impl.cc",
"passwords/credential_leak_dialog_controller_impl.h",
@@ -1043,8 +1099,6 @@ jumbo_static_library("ui") {
"passwords/credential_manager_dialog_controller_impl.h",
"passwords/google_password_manager_navigation_throttle.cc",
"passwords/google_password_manager_navigation_throttle.h",
- "passwords/manage_passwords_bubble_model.cc",
- "passwords/manage_passwords_bubble_model.h",
"passwords/manage_passwords_icon_view.h",
"passwords/manage_passwords_ui_controller.cc",
"passwords/manage_passwords_ui_controller.h",
@@ -1059,8 +1113,7 @@ jumbo_static_library("ui") {
"pdf/adobe_reader_info_win.h",
"pdf/chrome_pdf_web_contents_helper_client.cc",
"pdf/chrome_pdf_web_contents_helper_client.h",
- "permission_bubble/chooser_bubble_delegate.cc",
- "permission_bubble/chooser_bubble_delegate.h",
+ "permission_bubble/permission_prompt.h",
"sad_tab.cc",
"sad_tab.h",
"sad_tab_helper.cc",
@@ -1075,6 +1128,8 @@ jumbo_static_library("ui") {
"search/ntp_user_data_logger.cc",
"search/ntp_user_data_logger.h",
"search/ntp_user_data_types.h",
+ "search/omnibox_utils.cc",
+ "search/omnibox_utils.h",
"search/search_ipc_router.cc",
"search/search_ipc_router.h",
"search/search_ipc_router_policy_impl.cc",
@@ -1124,6 +1179,8 @@ jumbo_static_library("ui") {
"tab_sharing/tab_sharing_ui.h",
"tabs/existing_tab_group_sub_menu_model.cc",
"tabs/existing_tab_group_sub_menu_model.h",
+ "tabs/existing_window_sub_menu_model.cc",
+ "tabs/existing_window_sub_menu_model.h",
"tabs/hover_tab_selector.cc",
"tabs/hover_tab_selector.h",
"tabs/pinned_tab_codec.cc",
@@ -1136,14 +1193,14 @@ jumbo_static_library("ui") {
"tabs/tab_group.cc",
"tabs/tab_group.h",
"tabs/tab_group_controller.h",
- "tabs/tab_group_id.cc",
- "tabs/tab_group_id.h",
"tabs/tab_group_model.cc",
"tabs/tab_group_model.h",
- "tabs/tab_group_visual_data.cc",
- "tabs/tab_group_visual_data.h",
+ "tabs/tab_group_theme.cc",
+ "tabs/tab_group_theme.h",
"tabs/tab_menu_model.cc",
"tabs/tab_menu_model.h",
+ "tabs/tab_menu_model_factory.cc",
+ "tabs/tab_menu_model_factory.h",
"tabs/tab_network_state.cc",
"tabs/tab_network_state.h",
"tabs/tab_renderer_data.cc",
@@ -1171,9 +1228,6 @@ jumbo_static_library("ui") {
"task_manager/task_manager_table_model.h",
"thumbnails/thumbnail_image.cc",
"thumbnails/thumbnail_image.h",
- "thumbnails/thumbnail_page_event_adapter.cc",
- "thumbnails/thumbnail_page_event_adapter.h",
- "thumbnails/thumbnail_page_observer.h",
"thumbnails/thumbnail_tab_helper.cc",
"thumbnails/thumbnail_tab_helper.h",
"toolbar/app_menu_icon_controller.cc",
@@ -1204,10 +1258,6 @@ jumbo_static_library("ui") {
"uma_browsing_activity_observer.h",
"unload_controller.cc",
"unload_controller.h",
- "views/intent_picker_bubble_view.cc",
- "views/intent_picker_bubble_view.h",
- "views/location_bar/intent_picker_view.cc",
- "views/location_bar/intent_picker_view.h",
"webui/app_launcher_login_handler.cc",
"webui/app_launcher_login_handler.h",
"webui/app_management/app_management_page_handler.cc",
@@ -1270,6 +1320,8 @@ jumbo_static_library("ui") {
"webui/new_tab_page/new_tab_page_handler.h",
"webui/new_tab_page/new_tab_page_ui.cc",
"webui/new_tab_page/new_tab_page_ui.h",
+ "webui/new_tab_page/untrusted_source.cc",
+ "webui/new_tab_page/untrusted_source.h",
"webui/ntp/app_icon_webui_handler.cc",
"webui/ntp/app_icon_webui_handler.h",
"webui/ntp/app_launcher_handler.cc",
@@ -1286,6 +1338,8 @@ jumbo_static_library("ui") {
"webui/ntp/ntp_resource_cache.h",
"webui/ntp/ntp_resource_cache_factory.cc",
"webui/ntp/ntp_resource_cache_factory.h",
+ "webui/omnibox/omnibox_popup_handler.cc",
+ "webui/omnibox/omnibox_popup_handler.h",
"webui/page_not_available_for_guest/page_not_available_for_guest_ui.cc",
"webui/page_not_available_for_guest/page_not_available_for_guest_ui.h",
"webui/plural_string_handler.cc",
@@ -1294,6 +1348,8 @@ jumbo_static_library("ui") {
"webui/policy_indicator_localized_strings_provider.h",
"webui/profile_info_watcher.cc",
"webui/profile_info_watcher.h",
+ "webui/recent_site_settings_helper.cc",
+ "webui/recent_site_settings_helper.h",
"webui/settings/about_handler.cc",
"webui/settings/about_handler.h",
"webui/settings/accessibility_main_handler.cc",
@@ -1302,8 +1358,6 @@ jumbo_static_library("ui") {
"webui/settings/appearance_handler.h",
"webui/settings/browser_lifetime_handler.cc",
"webui/settings/browser_lifetime_handler.h",
- "webui/settings/change_password_handler.cc",
- "webui/settings/change_password_handler.h",
"webui/settings/custom_home_pages_table_model.cc",
"webui/settings/custom_home_pages_table_model.h",
"webui/settings/downloads_handler.cc",
@@ -1312,6 +1366,10 @@ jumbo_static_library("ui") {
"webui/settings/extension_control_handler.h",
"webui/settings/font_handler.cc",
"webui/settings/font_handler.h",
+ "webui/settings/hats_handler.cc",
+ "webui/settings/hats_handler.h",
+ "webui/settings/import_data_handler.cc",
+ "webui/settings/import_data_handler.h",
"webui/settings/languages_handler.cc",
"webui/settings/languages_handler.h",
"webui/settings/metrics_reporting_handler.cc",
@@ -1326,6 +1384,8 @@ jumbo_static_library("ui") {
"webui/settings/protocol_handlers_handler.h",
"webui/settings/reset_settings_handler.cc",
"webui/settings/reset_settings_handler.h",
+ "webui/settings/safe_browsing_handler.cc",
+ "webui/settings/safe_browsing_handler.h",
"webui/settings/safety_check_handler.cc",
"webui/settings/safety_check_handler.h",
"webui/settings/search_engines_handler.cc",
@@ -1334,20 +1394,22 @@ jumbo_static_library("ui") {
"webui/settings/settings_clear_browsing_data_handler.h",
"webui/settings/settings_cookies_view_handler.cc",
"webui/settings/settings_cookies_view_handler.h",
- "webui/settings/settings_import_data_handler.cc",
- "webui/settings/settings_import_data_handler.h",
"webui/settings/settings_localized_strings_provider.cc",
"webui/settings/settings_localized_strings_provider.h",
"webui/settings/settings_media_devices_selection_handler.cc",
"webui/settings/settings_media_devices_selection_handler.h",
"webui/settings/settings_page_ui_handler.cc",
"webui/settings/settings_page_ui_handler.h",
+ "webui/settings/settings_secure_dns_handler.cc",
+ "webui/settings/settings_secure_dns_handler.h",
"webui/settings/settings_security_key_handler.cc",
"webui/settings/settings_security_key_handler.h",
"webui/settings/settings_startup_pages_handler.cc",
"webui/settings/settings_startup_pages_handler.h",
"webui/settings/settings_ui.cc",
"webui/settings/settings_ui.h",
+ "webui/settings/shared_settings_localized_strings_provider.cc",
+ "webui/settings/shared_settings_localized_strings_provider.h",
"webui/settings/site_settings_handler.cc",
"webui/settings/site_settings_handler.h",
"webui/settings_utils.cc",
@@ -1394,9 +1456,14 @@ jumbo_static_library("ui") {
"//chrome/browser/resource_coordinator:tab_metrics_event_proto",
"//chrome/browser/resource_coordinator/tab_ranker",
"//chrome/browser/safe_browsing:advanced_protection",
+ "//chrome/browser/ui/color:color_headers",
+ "//chrome/browser/ui/color:mixers",
"//chrome/browser/ui/webui/app_management:mojo_bindings",
"//chrome/common:buildflags",
"//chrome/common:search_mojom",
+ "//chrome/common/media_router/mojom:media_router",
+ "//chrome/common/search:generate_chrome_colors_info",
+ "//chrome/common/themes:autogenerated_theme_util",
"//chrome/services/app_service/public/cpp:app_update",
"//chrome/services/app_service/public/mojom",
"//components/feedback/proto",
@@ -1404,6 +1471,7 @@ jumbo_static_library("ui") {
"//components/network_session_configurator/common",
"//components/page_load_metrics/browser",
"//components/profile_metrics",
+ "//components/search_provider_logos",
"//components/ui_metrics",
"//components/url_formatter",
"//components/vector_icons",
@@ -1437,19 +1505,21 @@ jumbo_static_library("ui") {
"//chrome/browser/web_applications",
# TODO(loyso): Erase these. crbug.com/877898.
+ "//chrome/browser/web_applications:common",
"//chrome/browser/web_applications:web_applications_on_extensions",
"//chrome/browser/web_applications/components",
"//chrome/browser/web_applications/extensions",
"//google_apis/drive",
]
}
+ }
- if (use_color_pipeline) {
- deps += [
- "//chrome/browser/ui/color:color",
- "//chrome/browser/ui/color:mixers",
- ]
- }
+ if (enable_kaleidoscope) {
+ deps += [ "//chrome/browser/media/kaleidoscope/internal" ]
+ }
+
+ if (enable_paint_preview) {
+ deps += [ "//components/paint_preview/browser" ]
}
if (enable_supervised_users) {
@@ -1484,6 +1554,8 @@ jumbo_static_library("ui") {
"app_list/search/launcher_search/launcher_search_result.h",
"ash/accessibility/accessibility_controller_client.cc",
"ash/accessibility/accessibility_controller_client.h",
+ "ash/ambient/photo_client.cc",
+ "ash/ambient/photo_client.h",
"ash/ambient/photo_controller_impl.cc",
"ash/ambient/photo_controller_impl.h",
"ash/arc_chrome_actions_client.cc",
@@ -1494,6 +1566,8 @@ jumbo_static_library("ui") {
"ash/ash_shell_init.h",
"ash/ash_util.cc",
"ash/ash_util.h",
+ "ash/back_gesture_contextual_nudge_delegate.cc",
+ "ash/back_gesture_contextual_nudge_delegate.h",
"ash/cast_config_controller_media_router.cc",
"ash/cast_config_controller_media_router.h",
"ash/chrome_accessibility_delegate.cc",
@@ -1545,6 +1619,8 @@ jumbo_static_library("ui") {
"ash/launcher/extension_app_window_launcher_item_controller.h",
"ash/launcher/extension_shelf_context_menu.cc",
"ash/launcher/extension_shelf_context_menu.h",
+ "ash/launcher/extension_uninstaller.cc",
+ "ash/launcher/extension_uninstaller.h",
"ash/launcher/launcher_app_updater.cc",
"ash/launcher/launcher_app_updater.h",
"ash/launcher/launcher_controller_helper.cc",
@@ -1618,6 +1694,8 @@ jumbo_static_library("ui") {
"views/apps/chrome_native_app_window_views_aura_ash.cc",
"views/apps/chrome_native_app_window_views_aura_ash.h",
"views/chrome_views_delegate_chromeos.cc",
+ "views/extensions/print_job_confirmation_dialog_view.cc",
+ "views/extensions/print_job_confirmation_dialog_view.h",
"views/extensions/request_file_system_dialog_view.cc",
"views/extensions/request_file_system_dialog_view.h",
"views/frame/browser_frame_ash.cc",
@@ -1710,6 +1788,8 @@ jumbo_static_library("ui") {
"webui/chromeos/cryptohome_web_ui_handler.h",
"webui/chromeos/drive_internals_ui.cc",
"webui/chromeos/drive_internals_ui.h",
+ "webui/chromeos/edu_account_login_handler_chromeos.cc",
+ "webui/chromeos/edu_account_login_handler_chromeos.h",
"webui/chromeos/first_run/first_run_actor.cc",
"webui/chromeos/first_run/first_run_actor.h",
"webui/chromeos/first_run/first_run_handler.cc",
@@ -1738,8 +1818,6 @@ jumbo_static_library("ui") {
"webui/chromeos/login/app_downloading_screen_handler.h",
"webui/chromeos/login/app_launch_splash_screen_handler.cc",
"webui/chromeos/login/app_launch_splash_screen_handler.h",
- "webui/chromeos/login/arc_kiosk_splash_screen_handler.cc",
- "webui/chromeos/login/arc_kiosk_splash_screen_handler.h",
"webui/chromeos/login/arc_terms_of_service_screen_handler.cc",
"webui/chromeos/login/arc_terms_of_service_screen_handler.h",
"webui/chromeos/login/assistant_optin_flow_screen_handler.cc",
@@ -1797,6 +1875,8 @@ jumbo_static_library("ui") {
"webui/chromeos/login/fingerprint_setup_screen_handler.h",
"webui/chromeos/login/gaia_screen_handler.cc",
"webui/chromeos/login/gaia_screen_handler.h",
+ "webui/chromeos/login/gesture_navigation_screen_handler.cc",
+ "webui/chromeos/login/gesture_navigation_screen_handler.h",
"webui/chromeos/login/hid_detection_screen_handler.cc",
"webui/chromeos/login/hid_detection_screen_handler.h",
"webui/chromeos/login/js_calls_container.cc",
@@ -1886,10 +1966,6 @@ jumbo_static_library("ui") {
"webui/chromeos/sys_internals/sys_internals_ui.h",
"webui/chromeos/system_web_dialog_delegate.cc",
"webui/chromeos/system_web_dialog_delegate.h",
- "webui/chromeos/terminal/terminal_source.cc",
- "webui/chromeos/terminal/terminal_source.h",
- "webui/chromeos/terminal/terminal_ui.cc",
- "webui/chromeos/terminal/terminal_ui.h",
"webui/chromeos/user_image_source.cc",
"webui/chromeos/user_image_source.h",
"webui/chromeos/video_source.cc",
@@ -1904,10 +1980,14 @@ jumbo_static_library("ui") {
"webui/settings/chromeos/accessibility_handler.h",
"webui/settings/chromeos/account_manager_handler.cc",
"webui/settings/chromeos/account_manager_handler.h",
+ "webui/settings/chromeos/ambient_mode_handler.cc",
+ "webui/settings/chromeos/ambient_mode_handler.h",
"webui/settings/chromeos/android_apps_handler.cc",
"webui/settings/chromeos/android_apps_handler.h",
"webui/settings/chromeos/app_management/app_management_page_handler_factory.cc",
"webui/settings/chromeos/app_management/app_management_page_handler_factory.h",
+ "webui/settings/chromeos/calculator/size_calculator.cc",
+ "webui/settings/chromeos/calculator/size_calculator.h",
"webui/settings/chromeos/change_picture_handler.cc",
"webui/settings/chromeos/change_picture_handler.h",
"webui/settings/chromeos/crostini_handler.cc",
@@ -1932,16 +2012,37 @@ jumbo_static_library("ui") {
"webui/settings/chromeos/google_assistant_handler.h",
"webui/settings/chromeos/internet_handler.cc",
"webui/settings/chromeos/internet_handler.h",
+ "webui/settings/chromeos/internet_strings_provider.cc",
+ "webui/settings/chromeos/internet_strings_provider.h",
"webui/settings/chromeos/kerberos_accounts_handler.cc",
"webui/settings/chromeos/kerberos_accounts_handler.h",
"webui/settings/chromeos/multidevice_handler.cc",
"webui/settings/chromeos/multidevice_handler.h",
+ "webui/settings/chromeos/os_settings_localized_strings_provider.cc",
+ "webui/settings/chromeos/os_settings_localized_strings_provider.h",
+ "webui/settings/chromeos/os_settings_localized_strings_provider_factory.cc",
+ "webui/settings/chromeos/os_settings_localized_strings_provider_factory.h",
+ "webui/settings/chromeos/os_settings_per_page_strings_provider.cc",
+ "webui/settings/chromeos/os_settings_per_page_strings_provider.h",
"webui/settings/chromeos/os_settings_ui.cc",
"webui/settings/chromeos/os_settings_ui.h",
"webui/settings/chromeos/parental_controls_handler.cc",
"webui/settings/chromeos/parental_controls_handler.h",
"webui/settings/chromeos/plugin_vm_handler.cc",
"webui/settings/chromeos/plugin_vm_handler.h",
+ "webui/settings/chromeos/pref_names.cc",
+ "webui/settings/chromeos/pref_names.h",
+ "webui/settings/chromeos/quick_unlock_handler.cc",
+ "webui/settings/chromeos/quick_unlock_handler.h",
+ "webui/settings/chromeos/search/search_concept.h",
+ "webui/settings/chromeos/search/search_handler.cc",
+ "webui/settings/chromeos/search/search_handler.h",
+ "webui/settings/chromeos/search/search_handler_factory.cc",
+ "webui/settings/chromeos/search/search_handler_factory.h",
+ "webui/settings/chromeos/search/settings_user_action_tracker.cc",
+ "webui/settings/chromeos/search/settings_user_action_tracker.h",
+ "webui/settings/chromeos/server_printer_url_util.cc",
+ "webui/settings/chromeos/server_printer_url_util.h",
"webui/settings/chromeos/wallpaper_handler.cc",
"webui/settings/chromeos/wallpaper_handler.h",
"webui/settings/tts_handler.cc",
@@ -1959,11 +2060,11 @@ jumbo_static_library("ui") {
deps += [
"//ash",
- "//ash/components/shortcut_viewer",
"//ash/keyboard/ui",
"//ash/public/cpp",
"//ash/public/cpp/resources:ash_public_unscaled_resources",
"//ash/public/cpp/vector_icons",
+ "//ash/shortcut_viewer",
"//chrome/browser/chromeos",
"//chrome/browser/chromeos:backdrop_wallpaper_proto",
"//chrome/browser/resources/chromeos:camera_resources",
@@ -1972,7 +2073,9 @@ jumbo_static_library("ui") {
"//chrome/browser/ui/webui/chromeos/crostini_installer:mojo_bindings",
"//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings",
"//chrome/browser/ui/webui/chromeos/machine_learning:mojo_bindings",
+ "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings",
"//chrome/services/file_util/public/cpp",
+ "//chrome/services/local_search_service",
"//chromeos",
"//chromeos/assistant:buildflags",
"//chromeos/audio",
@@ -1982,8 +2085,10 @@ jumbo_static_library("ui") {
"//chromeos/components/multidevice",
"//chromeos/components/multidevice/debug_webui",
"//chromeos/components/multidevice/logging",
+ "//chromeos/components/print_management",
"//chromeos/components/proximity_auth",
"//chromeos/components/tether",
+ "//chromeos/components/web_applications",
"//chromeos/constants",
"//chromeos/cryptohome",
"//chromeos/dbus",
@@ -2016,7 +2121,7 @@ jumbo_static_library("ui") {
"//chromeos/strings",
"//chromeos/system",
"//components/arc",
- "//components/captive_portal",
+ "//components/captive_portal/core",
"//components/consent_auditor:consent_auditor",
"//components/exo",
"//components/login",
@@ -2042,15 +2147,32 @@ jumbo_static_library("ui") {
"webui/chromeos/emulator/device_emulator_ui.cc",
"webui/chromeos/emulator/device_emulator_ui.h",
]
+ deps += [ "//chromeos/components/sample_system_web_app_ui" ]
}
if (use_cras) {
defines += [ "USE_CRAS" ]
}
+
+ if (enable_cros_libassistant) {
+ sources += [
+ "ash/ambient/backdrop/photo_client_impl.cc",
+ "ash/ambient/backdrop/photo_client_impl.h",
+ ]
+
+ deps += [
+ "//chromeos/assistant/internal/ambient",
+ "//chromeos/assistant/internal/proto/google3",
+ ]
+ }
}
if (is_win || is_mac || is_desktop_linux || is_chromeos) {
sources += [
+ "autofill/payments/virtual_card_selection_dialog_controller.h",
+ "autofill/payments/virtual_card_selection_dialog_controller_impl.cc",
+ "autofill/payments/virtual_card_selection_dialog_controller_impl.h",
+ "autofill/payments/virtual_card_selection_dialog_view.h",
"autofill/payments/webauthn_dialog_controller.h",
"autofill/payments/webauthn_dialog_controller_impl.cc",
"autofill/payments/webauthn_dialog_controller_impl.h",
@@ -2059,13 +2181,20 @@ jumbo_static_library("ui") {
"autofill/payments/webauthn_dialog_model_observer.h",
"autofill/payments/webauthn_dialog_state.h",
"autofill/payments/webauthn_dialog_view.h",
+ "avatar_button_error_controller.cc",
+ "avatar_button_error_controller.h",
+ "avatar_button_error_controller_delegate.h",
"frame/window_frame_util.cc",
"frame/window_frame_util.h",
+ "signin_reauth_popup_delegate.cc",
+ "signin_reauth_popup_delegate.h",
"signin_view_controller.cc",
"signin_view_controller.h",
"signin_view_controller_delegate.h",
"tab_contents/chrome_web_contents_view_handle_drop.cc",
"tab_contents/chrome_web_contents_view_handle_drop.h",
+ "views/autofill/payments/virtual_card_selection_dialog_view_impl.cc",
+ "views/autofill/payments/virtual_card_selection_dialog_view_impl.h",
"views/autofill/payments/webauthn_dialog_view_impl.cc",
"views/autofill/payments/webauthn_dialog_view_impl.h",
"views/close_bubble_on_tab_activation_helper.cc",
@@ -2076,6 +2205,8 @@ jumbo_static_library("ui") {
"views/hats/hats_web_dialog.h",
"views/profiles/incognito_menu_view.cc",
"views/profiles/incognito_menu_view.h",
+ "views/profiles/profile_menu_view.cc",
+ "views/profiles/profile_menu_view.h",
"views/profiles/profile_menu_view_base.cc",
"views/profiles/profile_menu_view_base.h",
"views/profiles/signin_view_controller_delegate_views.cc",
@@ -2084,6 +2215,8 @@ jumbo_static_library("ui") {
"webui/discards/discards_ui.h",
"webui/discards/graph_dump_impl.cc",
"webui/discards/graph_dump_impl.h",
+ "webui/discards/site_data_provider_impl.cc",
+ "webui/discards/site_data_provider_impl.h",
"webui/signin/inline_login_handler.cc",
"webui/signin/inline_login_handler.h",
"webui/signin/inline_login_ui.cc",
@@ -2100,9 +2233,6 @@ jumbo_static_library("ui") {
if (is_win || is_mac || is_desktop_linux) {
sources += [
- "avatar_button_error_controller.cc",
- "avatar_button_error_controller.h",
- "avatar_button_error_controller_delegate.h",
"bookmarks/bookmark_bubble_sign_in_delegate.cc",
"bookmarks/bookmark_bubble_sign_in_delegate.h",
"startup/default_browser_infobar_delegate.cc",
@@ -2118,8 +2248,6 @@ jumbo_static_library("ui") {
"views/external_protocol_dialog.h",
"views/profiles/badged_profile_photo.cc",
"views/profiles/badged_profile_photo.h",
- "views/profiles/profile_menu_view.cc",
- "views/profiles/profile_menu_view.h",
"views/profiles/user_manager_view.cc",
"views/profiles/user_manager_view.h",
"webui/app_launcher_page_ui.cc",
@@ -2275,14 +2403,8 @@ jumbo_static_library("ui") {
"cocoa/fullscreen/fullscreen_toolbar_animation_controller.mm",
"cocoa/fullscreen/fullscreen_toolbar_controller.h",
"cocoa/fullscreen/fullscreen_toolbar_controller.mm",
- "cocoa/fullscreen/fullscreen_toolbar_controller_views.h",
- "cocoa/fullscreen/fullscreen_toolbar_controller_views.mm",
"cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.h",
"cocoa/fullscreen/fullscreen_toolbar_mouse_tracker.mm",
- "cocoa/fullscreen/fullscreen_toolbar_visibility_lock_controller.h",
- "cocoa/fullscreen/fullscreen_toolbar_visibility_lock_controller.mm",
- "cocoa/fullscreen/immersive_fullscreen_controller.h",
- "cocoa/fullscreen/immersive_fullscreen_controller.mm",
"cocoa/handoff_active_url_observer.cc",
"cocoa/handoff_active_url_observer.h",
"cocoa/handoff_active_url_observer_bridge.h",
@@ -2508,6 +2630,8 @@ jumbo_static_library("ui") {
"views/frame/browser_desktop_window_tree_host.h",
"views/frame/desktop_browser_frame_aura_linux.cc",
"views/frame/desktop_browser_frame_aura_linux.h",
+ "views/status_icons/status_icon_button_linux.cc",
+ "views/status_icons/status_icon_button_linux.h",
"views/status_icons/status_icon_linux_wrapper.cc",
"views/status_icons/status_icon_linux_wrapper.h",
"webui/help/version_updater_basic.cc",
@@ -2515,6 +2639,7 @@ jumbo_static_library("ui") {
"webui/settings_utils_linux.cc",
]
deps += [
+ "//ui/base:wm_role_names",
"//ui/base/ime",
"//ui/events:dom_keycode_converter",
]
@@ -2544,8 +2669,6 @@ jumbo_static_library("ui") {
"views/javascript_app_modal_dialog_views_x11.h",
"views/javascript_app_modal_event_blocker_x11.cc",
"views/javascript_app_modal_event_blocker_x11.h",
- "views/status_icons/status_icon_linux_x11.cc",
- "views/status_icons/status_icon_linux_x11.h",
]
configs += [ "//build/config/linux:x11" ]
deps += [
@@ -2570,10 +2693,11 @@ jumbo_static_library("ui") {
"views/frame/browser_desktop_window_tree_host_linux.cc",
"views/frame/browser_desktop_window_tree_host_linux.h",
]
+ deps += [ "//ui/platform_window/extensions" ]
}
if (use_gtk) {
# This is the only component that can interact with gtk.
- deps += [ "//chrome/browser/ui/libgtkui" ]
+ deps += [ "//ui/gtk" ]
}
}
@@ -2603,6 +2727,13 @@ jumbo_static_library("ui") {
}
}
+ if (is_chromeos) {
+ sources += [
+ "views/parent_permission_dialog_view.cc",
+ "views/parent_permission_dialog_view.h",
+ ]
+ }
+
if (toolkit_views) {
sources += [
"autofill/payments/local_card_migration_bubble.h",
@@ -2621,9 +2752,13 @@ jumbo_static_library("ui") {
"autofill/payments/save_card_bubble_controller_impl.h",
"autofill/payments/save_card_bubble_view.h",
"autofill/payments/save_card_ui.h",
+ "autofill/payments/save_payment_icon_controller.cc",
+ "autofill/payments/save_payment_icon_controller.h",
+ "autofill/payments/save_upi_bubble.h",
+ "autofill/payments/save_upi_bubble_controller.h",
+ "autofill/payments/save_upi_bubble_controller_impl.cc",
+ "autofill/payments/save_upi_bubble_controller_impl.h",
"bubble_anchor_util.h",
- "cookie_controls/cookie_controls_controller.cc",
- "cookie_controls/cookie_controls_controller.h",
"cookie_controls/cookie_controls_view.h",
"manifest_web_app_browser_controller.cc",
"manifest_web_app_browser_controller.h",
@@ -2637,10 +2772,16 @@ jumbo_static_library("ui") {
# This test header is included because it contains forward declarations
# needed for "friend" statements for use in tests.
"translate/translate_bubble_test_utils.h",
+ "views/accessibility/caption_bubble.cc",
+ "views/accessibility/caption_bubble.h",
"views/accessibility/invert_bubble_view.cc",
"views/accessibility/invert_bubble_view.h",
"views/accessibility/non_accessible_image_view.cc",
"views/accessibility/non_accessible_image_view.h",
+ "views/apps/app_dialog/app_dialog_view.cc",
+ "views/apps/app_dialog/app_dialog_view.h",
+ "views/apps/app_dialog/app_uninstall_dialog_view.cc",
+ "views/apps/app_dialog/app_uninstall_dialog_view.h",
"views/apps/app_info_dialog/app_info_dialog_container.cc",
"views/apps/app_info_dialog/app_info_dialog_container.h",
"views/apps/app_info_dialog/app_info_dialog_views.cc",
@@ -2657,10 +2798,6 @@ jumbo_static_library("ui") {
"views/apps/app_info_dialog/app_info_permissions_panel.h",
"views/apps/app_info_dialog/app_info_summary_panel.cc",
"views/apps/app_info_dialog/app_info_summary_panel.h",
- "views/apps/app_pause_dialog_view.cc",
- "views/apps/app_pause_dialog_view.h",
- "views/apps/app_uninstall_dialog_view.cc",
- "views/apps/app_uninstall_dialog_view.h",
"views/apps/chrome_native_app_window_views.cc",
"views/apps/chrome_native_app_window_views.h",
"views/autofill/autofill_bubble_handler_impl.cc",
@@ -2669,6 +2806,8 @@ jumbo_static_library("ui") {
"views/autofill/autofill_popup_base_view.h",
"views/autofill/autofill_popup_view_native_views.cc",
"views/autofill/autofill_popup_view_native_views.h",
+ "views/autofill/autofill_popup_view_utils.cc",
+ "views/autofill/autofill_popup_view_utils.h",
"views/autofill/payments/card_unmask_prompt_views.cc",
"views/autofill/payments/card_unmask_prompt_views.h",
"views/autofill/payments/dialog_view_ids.h",
@@ -2688,16 +2827,16 @@ jumbo_static_library("ui") {
"views/autofill/payments/save_card_bubble_views.h",
"views/autofill/payments/save_card_failure_bubble_views.cc",
"views/autofill/payments/save_card_failure_bubble_views.h",
- "views/autofill/payments/save_card_icon_view.cc",
- "views/autofill/payments/save_card_icon_view.h",
"views/autofill/payments/save_card_manage_cards_bubble_views.cc",
"views/autofill/payments/save_card_manage_cards_bubble_views.h",
"views/autofill/payments/save_card_offer_bubble_views.cc",
"views/autofill/payments/save_card_offer_bubble_views.h",
"views/autofill/payments/save_card_sign_in_promo_bubble_views.cc",
"views/autofill/payments/save_card_sign_in_promo_bubble_views.h",
- "views/autofill/view_util.cc",
- "views/autofill/view_util.h",
+ "views/autofill/payments/save_payment_icon_view.cc",
+ "views/autofill/payments/save_payment_icon_view.h",
+ "views/autofill/payments/save_upi_offer_bubble_views.cc",
+ "views/autofill/payments/save_upi_offer_bubble_views.h",
"views/bookmarks/bookmark_bar_view.cc",
"views/bookmarks/bookmark_bar_view.h",
"views/bookmarks/bookmark_bar_view_observer.h",
@@ -2782,18 +2921,21 @@ jumbo_static_library("ui") {
"views/exclusive_access_bubble_views.cc",
"views/exclusive_access_bubble_views.h",
"views/exclusive_access_bubble_views_context.h",
- "views/extensions/bookmark_app_confirmation_view.cc",
- "views/extensions/bookmark_app_confirmation_view.h",
"views/extensions/chooser_dialog_view.cc",
"views/extensions/chooser_dialog_view.h",
+ "views/extensions/expandable_container_view.cc",
+ "views/extensions/expandable_container_view.h",
"views/extensions/extension_context_menu_controller.cc",
"views/extensions/extension_context_menu_controller.h",
+ "views/extensions/extension_install_blocked_dialog_view.cc",
+ "views/extensions/extension_install_blocked_dialog_view.h",
"views/extensions/extension_install_dialog_view.cc",
"views/extensions/extension_install_dialog_view.h",
"views/extensions/extension_installed_bubble_view.cc",
- "views/extensions/extension_installed_bubble_view.h",
"views/extensions/extension_keybinding_registry_views.cc",
"views/extensions/extension_keybinding_registry_views.h",
+ "views/extensions/extension_permissions_view.cc",
+ "views/extensions/extension_permissions_view.h",
"views/extensions/extension_uninstall_dialog_view.cc",
"views/extensions/extensions_menu_button.cc",
"views/extensions/extensions_menu_button.h",
@@ -2805,10 +2947,6 @@ jumbo_static_library("ui") {
"views/extensions/extensions_toolbar_button.h",
"views/extensions/extensions_toolbar_container.cc",
"views/extensions/extensions_toolbar_container.h",
- "views/extensions/pwa_confirmation_bubble_view.cc",
- "views/extensions/pwa_confirmation_bubble_view.h",
- "views/extensions/web_app_info_image_source.cc",
- "views/extensions/web_app_info_image_source.h",
"views/feature_promos/feature_promo_bubble_timeout.cc",
"views/feature_promos/feature_promo_bubble_timeout.h",
"views/feature_promos/feature_promo_bubble_view.cc",
@@ -2865,6 +3003,8 @@ jumbo_static_library("ui") {
"views/frame/toolbar_button_provider.h",
"views/frame/top_container_background.cc",
"views/frame/top_container_background.h",
+ "views/frame/top_container_loading_bar.cc",
+ "views/frame/top_container_loading_bar.h",
"views/frame/top_container_view.cc",
"views/frame/top_container_view.h",
"views/frame/top_controls_slide_controller.h",
@@ -2873,8 +3013,6 @@ jumbo_static_library("ui") {
"views/frame/web_contents_close_handler_delegate.h",
"views/frame/web_footer_experiment_view.cc",
"views/frame/web_footer_experiment_view.h",
- "views/front_eliding_title_label.cc",
- "views/front_eliding_title_label.h",
"views/fullscreen_control/fullscreen_control_host.cc",
"views/fullscreen_control/fullscreen_control_host.h",
"views/fullscreen_control/fullscreen_control_popup.cc",
@@ -2912,8 +3050,10 @@ jumbo_static_library("ui") {
"views/infobars/infobar_container_view.h",
"views/infobars/infobar_view.cc",
"views/infobars/infobar_view.h",
- "views/javascript_dialog_views.cc",
- "views/javascript_dialog_views.h",
+ "views/intent_picker_bubble_view.cc",
+ "views/intent_picker_bubble_view.h",
+ "views/javascript_tab_modal_dialog_view_views.cc",
+ "views/javascript_tab_modal_dialog_view_views.h",
"views/layout/interpolating_layout_manager.cc",
"views/layout/interpolating_layout_manager.h",
"views/load_complete_listener.cc",
@@ -2930,6 +3070,8 @@ jumbo_static_library("ui") {
"views/location_bar/find_bar_icon.h",
"views/location_bar/icon_label_bubble_view.cc",
"views/location_bar/icon_label_bubble_view.h",
+ "views/location_bar/intent_picker_view.cc",
+ "views/location_bar/intent_picker_view.h",
"views/location_bar/keyword_hint_view.cc",
"views/location_bar/keyword_hint_view.h",
"views/location_bar/location_bar_bubble_delegate_view.cc",
@@ -2978,6 +3120,8 @@ jumbo_static_library("ui") {
"views/media_router/presentation_receiver_window_view.h",
"views/media_router/web_contents_display_observer_view.cc",
"views/media_router/web_contents_display_observer_view.h",
+ "views/message_box_dialog.cc",
+ "views/message_box_dialog.h",
"views/native_file_system/native_file_system_access_icon_view.cc",
"views/native_file_system/native_file_system_access_icon_view.h",
"views/native_file_system/native_file_system_directory_access_confirmation_view.cc",
@@ -3006,6 +3150,8 @@ jumbo_static_library("ui") {
"views/omnibox/remove_suggestion_bubble.h",
"views/omnibox/rounded_omnibox_results_frame.cc",
"views/omnibox/rounded_omnibox_results_frame.h",
+ "views/omnibox/webui_omnibox_popup_view.cc",
+ "views/omnibox/webui_omnibox_popup_view.h",
"views/overlay/back_to_tab_image_button.cc",
"views/overlay/back_to_tab_image_button.h",
"views/overlay/close_image_button.cc",
@@ -3020,10 +3166,14 @@ jumbo_static_library("ui") {
"views/overlay/skip_ad_label_button.h",
"views/overlay/track_image_button.cc",
"views/overlay/track_image_button.h",
- "views/page_action/page_action_icon_container_view.cc",
- "views/page_action/page_action_icon_container_view.h",
+ "views/page_action/page_action_icon_container.cc",
+ "views/page_action/page_action_icon_container.h",
+ "views/page_action/page_action_icon_controller.cc",
+ "views/page_action/page_action_icon_controller.h",
"views/page_action/page_action_icon_loading_indicator_view.cc",
"views/page_action/page_action_icon_loading_indicator_view.h",
+ "views/page_action/page_action_icon_params.cc",
+ "views/page_action/page_action_icon_params.h",
"views/page_action/page_action_icon_view.cc",
"views/page_action/page_action_icon_view.h",
"views/page_action/pwa_install_view.cc",
@@ -3058,14 +3208,18 @@ jumbo_static_library("ui") {
"views/passwords/password_auto_sign_in_view.h",
"views/passwords/password_bubble_view_base.cc",
"views/passwords/password_bubble_view_base.h",
+ "views/passwords/password_generation_confirmation_view.cc",
+ "views/passwords/password_generation_confirmation_view.h",
"views/passwords/password_generation_popup_view_views.cc",
"views/passwords/password_generation_popup_view_views.h",
"views/passwords/password_items_view.cc",
"views/passwords/password_items_view.h",
- "views/passwords/password_pending_view.cc",
- "views/passwords/password_pending_view.h",
- "views/passwords/password_save_confirmation_view.cc",
- "views/passwords/password_save_confirmation_view.h",
+ "views/passwords/password_save_unsynced_credentials_locally_view.cc",
+ "views/passwords/password_save_unsynced_credentials_locally_view.h",
+ "views/passwords/password_save_update_view.cc",
+ "views/passwords/password_save_update_view.h",
+ "views/passwords/password_save_update_with_account_store_view.cc",
+ "views/passwords/password_save_update_with_account_store_view.h",
"views/payments/contact_info_editor_view_controller.cc",
"views/payments/contact_info_editor_view_controller.h",
"views/payments/credit_card_editor_view_controller.cc",
@@ -3112,14 +3266,14 @@ jumbo_static_library("ui") {
"views/payments/view_stack.cc",
"views/payments/view_stack.h",
"views/permission_bubble/chooser_bubble_ui.cc",
- "views/permission_bubble/chooser_bubble_ui.h",
- "views/permission_bubble/chooser_bubble_ui_views.cc",
"views/permission_bubble/permission_prompt_bubble_view.cc",
"views/permission_bubble/permission_prompt_bubble_view.h",
"views/permission_bubble/permission_prompt_impl.cc",
"views/permission_bubble/permission_prompt_impl.h",
"views/profiles/avatar_toolbar_button.cc",
"views/profiles/avatar_toolbar_button.h",
+ "views/profiles/avatar_toolbar_button_delegate.cc",
+ "views/profiles/avatar_toolbar_button_delegate.h",
"views/qrcode_generator/qrcode_generator_bubble.cc",
"views/qrcode_generator/qrcode_generator_bubble.h",
"views/qrcode_generator/qrcode_generator_icon_view.cc",
@@ -3138,10 +3292,14 @@ jumbo_static_library("ui") {
"views/relaunch_notification/wall_clock_timer.h",
"views/sad_tab_view.cc",
"views/sad_tab_view.h",
+ "views/safe_browsing/deep_scanning_failure_modal_dialog.cc",
+ "views/safe_browsing/deep_scanning_failure_modal_dialog.h",
"views/safe_browsing/deep_scanning_modal_dialog.cc",
"views/safe_browsing/deep_scanning_modal_dialog.h",
"views/safe_browsing/password_reuse_modal_warning_dialog.cc",
"views/safe_browsing/password_reuse_modal_warning_dialog.h",
+ "views/safe_browsing/prompt_for_scanning_modal_dialog.cc",
+ "views/safe_browsing/prompt_for_scanning_modal_dialog.h",
"views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc",
"views/send_tab_to_self/send_tab_to_self_bubble_device_button.h",
"views/send_tab_to_self/send_tab_to_self_bubble_view_impl.cc",
@@ -3154,10 +3312,10 @@ jumbo_static_library("ui") {
"views/sharing/sharing_dialog_view.h",
"views/sharing/sharing_icon_view.cc",
"views/sharing/sharing_icon_view.h",
- "views/simple_message_box_views.cc",
- "views/simple_message_box_views.h",
"views/status_bubble_views.cc",
"views/status_bubble_views.h",
+ "views/storage/storage_pressure_bubble_view.cc",
+ "views/storage/storage_pressure_bubble_view.h",
"views/subtle_notification_view.cc",
"views/subtle_notification_view.h",
"views/sync/profile_signin_confirmation_dialog_views.cc",
@@ -3231,6 +3389,8 @@ jumbo_static_library("ui") {
"views/textfield_layout.h",
"views/theme_copying_widget.cc",
"views/theme_copying_widget.h",
+ "views/title_origin_label.cc",
+ "views/title_origin_label.h",
"views/toolbar/app_menu.cc",
"views/toolbar/app_menu.h",
"views/toolbar/browser_actions_container.cc",
@@ -3268,20 +3428,26 @@ jumbo_static_library("ui") {
"views/translate/translate_icon_view.h",
"views/update_recommended_message_box.cc",
"views/update_recommended_message_box.h",
+ "views/web_apps/pwa_confirmation_bubble_view.cc",
+ "views/web_apps/pwa_confirmation_bubble_view.h",
+ "views/web_apps/web_app_confirmation_view.cc",
+ "views/web_apps/web_app_confirmation_view.h",
"views/web_apps/web_app_frame_toolbar_view.cc",
"views/web_apps/web_app_frame_toolbar_view.h",
+ "views/web_apps/web_app_info_image_source.cc",
+ "views/web_apps/web_app_info_image_source.h",
"views/web_apps/web_app_menu_button.cc",
"views/web_apps/web_app_menu_button.h",
"views/web_apps/web_app_origin_text.cc",
"views/web_apps/web_app_origin_text.h",
+ "views/web_apps/web_app_uninstall_dialog_view.cc",
+ "views/web_apps/web_app_uninstall_dialog_view.h",
"views/webauthn/authenticator_ble_pin_entry_sheet_view.cc",
"views/webauthn/authenticator_ble_pin_entry_sheet_view.h",
"views/webauthn/authenticator_client_pin_entry_sheet_view.cc",
"views/webauthn/authenticator_client_pin_entry_sheet_view.h",
"views/webauthn/authenticator_client_pin_entry_view.cc",
"views/webauthn/authenticator_client_pin_entry_view.h",
- "views/webauthn/authenticator_qr_code.cc",
- "views/webauthn/authenticator_qr_code.h",
"views/webauthn/authenticator_qr_sheet_view.cc",
"views/webauthn/authenticator_qr_sheet_view.h",
"views/webauthn/authenticator_request_dialog_view.cc",
@@ -3302,6 +3468,7 @@ jumbo_static_library("ui") {
"views/webauthn/sheet_view_factory.h",
"webauthn/account_hover_list_model.cc",
"webauthn/account_hover_list_model.h",
+ "webauthn/authenticator_request_sheet_model.cc",
"webauthn/authenticator_request_sheet_model.h",
"webauthn/ble_device_hover_list_model.cc",
"webauthn/ble_device_hover_list_model.h",
@@ -3315,10 +3482,13 @@ jumbo_static_library("ui") {
"webauthn/transport_utils.cc",
"webauthn/transport_utils.h",
]
+
deps += [
"//chrome/browser/ui/views",
+ "//chrome/common/qr_code_generator",
"//components/constrained_window",
"//components/media_message_center",
+ "//components/page_info",
"//components/payments/content",
"//components/payments/core",
"//components/tab_count_metrics",
@@ -3330,7 +3500,7 @@ jumbo_static_library("ui") {
allow_circular_includes_from += [ "//chrome/browser/ui/views" ]
- if (enable_native_window_nav_buttons) {
+ if (is_desktop_linux) {
sources += [
"views/frame/desktop_linux_browser_frame_view.cc",
"views/frame/desktop_linux_browser_frame_view.h",
@@ -3365,6 +3535,13 @@ jumbo_static_library("ui") {
"views/ssl_client_certificate_selector_mac.h",
"views/ssl_client_certificate_selector_mac.mm",
]
+
+ # The Views task manager is not used on Mac - a native Cocoa
+ # implementation is used instead.
+ sources -= [
+ "views/task_manager_view.cc",
+ "views/task_manager_view.h",
+ ]
} else {
sources += [
"views/create_application_shortcut_view.cc",
@@ -3391,21 +3568,20 @@ jumbo_static_library("ui") {
sources += [
"views/chrome_browser_main_extra_parts_views_linux.cc",
"views/chrome_browser_main_extra_parts_views_linux.h",
- "views/linux_ui/linux_ui_factory.h",
]
if (use_gtk) {
- sources += [ "views/linux_ui/linux_ui_factory_gtk.cc" ]
-
- # This is the only component that can interact with gtk.
- deps += [ "//chrome/browser/ui/libgtkui" ]
- } else {
- sources += [ "views/linux_ui/linux_ui_factory.cc" ]
- }
- if (use_x11) {
- sources += [
- "views/chrome_browser_main_extra_parts_views_linux_x11.cc",
- "views/chrome_browser_main_extra_parts_views_linux_x11.h",
+ deps += [
+ "//ui/gtk",
]
+ if (use_x11) {
+ deps += [
+ "//ui/gfx/x",
+ "//ui/gtk:x",
+ ]
+ }
+ if (use_ozone) {
+ deps += [ "//ui/ozone" ]
+ }
}
}
}
@@ -3487,8 +3663,6 @@ jumbo_static_library("ui") {
"views/apps/glass_app_window_frame_view_win.h",
"views/apps/shaped_app_window_targeter.cc",
"views/apps/shaped_app_window_targeter.h",
- "views/color_chooser_aura.cc",
- "views/color_chooser_aura.h",
"views/dropdown_bar_host_aura.cc",
"views/frame/browser_non_client_frame_view_factory_chromeos.cc",
"views/ime/ime_window_frame_view.cc",
@@ -3515,6 +3689,13 @@ jumbo_static_library("ui") {
"views/frame/desktop_browser_frame_aura.h",
]
}
+
+ if (!is_win) {
+ sources += [
+ "views/color_chooser_aura.cc",
+ "views/color_chooser_aura.h",
+ ]
+ }
}
if (is_chromeos) {
@@ -3542,6 +3723,8 @@ jumbo_static_library("ui") {
"app_list/app_service/app_service_app_item.h",
"app_list/app_service/app_service_app_model_builder.cc",
"app_list/app_service/app_service_app_model_builder.h",
+ "app_list/app_service/app_service_context_menu.cc",
+ "app_list/app_service/app_service_context_menu.h",
"app_list/arc/arc_app_context_menu.cc",
"app_list/arc/arc_app_context_menu.h",
"app_list/arc/arc_app_dialog.h",
@@ -3549,10 +3732,6 @@ jumbo_static_library("ui") {
"app_list/arc/arc_app_icon.h",
"app_list/arc/arc_app_icon_descriptor.cc",
"app_list/arc/arc_app_icon_descriptor.h",
- "app_list/arc/arc_app_icon_loader.cc",
- "app_list/arc/arc_app_icon_loader.h",
- "app_list/arc/arc_app_item.cc",
- "app_list/arc/arc_app_item.h",
"app_list/arc/arc_app_launcher.cc",
"app_list/arc/arc_app_launcher.h",
"app_list/arc/arc_app_list_prefs.cc",
@@ -3594,24 +3773,14 @@ jumbo_static_library("ui") {
"app_list/crostini/crostini_app_context_menu.h",
"app_list/crostini/crostini_app_icon.cc",
"app_list/crostini/crostini_app_icon.h",
- "app_list/crostini/crostini_app_icon_loader.cc",
- "app_list/crostini/crostini_app_icon_loader.h",
- "app_list/crostini/crostini_app_item.cc",
- "app_list/crostini/crostini_app_item.h",
"app_list/extension_app_context_menu.cc",
"app_list/extension_app_context_menu.h",
"app_list/extension_app_item.cc",
"app_list/extension_app_item.h",
"app_list/extension_app_utils.cc",
"app_list/extension_app_utils.h",
- "app_list/extension_uninstaller.cc",
- "app_list/extension_uninstaller.h",
"app_list/internal_app/internal_app_context_menu.cc",
"app_list/internal_app/internal_app_context_menu.h",
- "app_list/internal_app/internal_app_icon_loader.cc",
- "app_list/internal_app/internal_app_icon_loader.h",
- "app_list/internal_app/internal_app_item.cc",
- "app_list/internal_app/internal_app_item.h",
"app_list/internal_app/internal_app_metadata.cc",
"app_list/internal_app/internal_app_metadata.h",
"app_list/md_icon_normalizer.cc",
@@ -3654,10 +3823,16 @@ jumbo_static_library("ui") {
"app_list/search/common/url_icon_source.h",
"app_list/search/cros_action_history/cros_action_recorder.cc",
"app_list/search/cros_action_history/cros_action_recorder.h",
+ "app_list/search/cros_action_history/cros_action_recorder_tab_tracker.cc",
+ "app_list/search/cros_action_history/cros_action_recorder_tab_tracker.h",
+ "app_list/search/drive_quick_access_chip_result.cc",
+ "app_list/search/drive_quick_access_chip_result.h",
"app_list/search/drive_quick_access_provider.cc",
"app_list/search/drive_quick_access_provider.h",
"app_list/search/drive_quick_access_result.cc",
"app_list/search/drive_quick_access_result.h",
+ "app_list/search/file_chip_result.cc",
+ "app_list/search/file_chip_result.h",
"app_list/search/mixer.cc",
"app_list/search/mixer.h",
"app_list/search/omnibox_provider.cc",
@@ -3688,6 +3863,8 @@ jumbo_static_library("ui") {
"app_list/search/search_result_ranker/app_list_launch_recorder_util.h",
"app_list/search/search_result_ranker/app_search_result_ranker.cc",
"app_list/search/search_result_ranker/app_search_result_ranker.h",
+ "app_list/search/search_result_ranker/chip_ranker.cc",
+ "app_list/search/search_result_ranker/chip_ranker.h",
"app_list/search/search_result_ranker/frecency_store.cc",
"app_list/search/search_result_ranker/frecency_store.h",
"app_list/search/search_result_ranker/histogram_util.cc",
@@ -3716,8 +3893,10 @@ jumbo_static_library("ui") {
"app_list/search/zero_state_file_provider.h",
"app_list/search/zero_state_file_result.cc",
"app_list/search/zero_state_file_result.h",
- "ash/assistant/assistant_client.cc",
- "ash/assistant/assistant_client.h",
+ "app_list/web_app_context_menu.cc",
+ "app_list/web_app_context_menu.h",
+ "ash/assistant/assistant_client_impl.cc",
+ "ash/assistant/assistant_client_impl.h",
"ash/assistant/assistant_context_util.cc",
"ash/assistant/assistant_context_util.h",
"ash/assistant/assistant_image_downloader.cc",
@@ -3728,24 +3907,46 @@ jumbo_static_library("ui") {
"ash/assistant/assistant_setup.h",
"ash/assistant/assistant_state_client.cc",
"ash/assistant/assistant_state_client.h",
+ "ash/assistant/assistant_web_view_factory_impl.cc",
+ "ash/assistant/assistant_web_view_factory_impl.h",
+ "ash/assistant/assistant_web_view_impl.cc",
+ "ash/assistant/assistant_web_view_impl.h",
+ "ash/assistant/conversation_starters_client_impl.cc",
+ "ash/assistant/conversation_starters_client_impl.h",
+ "ash/assistant/conversation_starters_parser.cc",
+ "ash/assistant/conversation_starters_parser.h",
"ash/assistant/device_actions.cc",
"ash/assistant/device_actions.h",
+ "ash/assistant/device_actions_delegate.h",
+ "ash/assistant/device_actions_delegate_impl.cc",
+ "ash/assistant/device_actions_delegate_impl.h",
"ash/assistant/proactive_suggestions_client_impl.cc",
"ash/assistant/proactive_suggestions_client_impl.h",
"ash/assistant/proactive_suggestions_loader.cc",
"ash/assistant/proactive_suggestions_loader.h",
- "ash/launcher/app_service_app_window_crostini_tracker.cc",
- "ash/launcher/app_service_app_window_crostini_tracker.h",
- "ash/launcher/app_service_app_window_launcher_controller.cc",
- "ash/launcher/app_service_app_window_launcher_controller.h",
- "ash/launcher/app_service_instance_registry_helper.cc",
- "ash/launcher/app_service_instance_registry_helper.h",
+ "ash/launcher/app_service/app_service_app_window_arc_tracker.cc",
+ "ash/launcher/app_service/app_service_app_window_arc_tracker.h",
+ "ash/launcher/app_service/app_service_app_window_crostini_tracker.cc",
+ "ash/launcher/app_service/app_service_app_window_crostini_tracker.h",
+ "ash/launcher/app_service/app_service_app_window_launcher_controller.cc",
+ "ash/launcher/app_service/app_service_app_window_launcher_controller.h",
+ "ash/launcher/app_service/app_service_app_window_launcher_item_controller.cc",
+ "ash/launcher/app_service/app_service_app_window_launcher_item_controller.h",
+ "ash/launcher/app_service/app_service_instance_registry_helper.cc",
+ "ash/launcher/app_service/app_service_instance_registry_helper.h",
+ "ash/launcher/app_service/app_service_shelf_context_menu.cc",
+ "ash/launcher/app_service/app_service_shelf_context_menu.h",
+ "ash/launcher/app_service/launcher_app_service_app_updater.cc",
+ "ash/launcher/app_service/launcher_app_service_app_updater.h",
"ash/launcher/app_window_base.cc",
"ash/launcher/app_window_base.h",
"ash/launcher/arc_app_shelf_id.cc",
"ash/launcher/arc_app_shelf_id.h",
"ash/launcher/arc_app_window.cc",
"ash/launcher/arc_app_window.h",
+ "ash/launcher/arc_app_window_delegate.h",
+ "ash/launcher/arc_app_window_info.cc",
+ "ash/launcher/arc_app_window_info.h",
"ash/launcher/arc_app_window_launcher_controller.cc",
"ash/launcher/arc_app_window_launcher_controller.h",
"ash/launcher/arc_app_window_launcher_item_controller.cc",
@@ -3764,36 +3965,37 @@ jumbo_static_library("ui") {
"ash/launcher/internal_app_shelf_context_menu.h",
"ash/launcher/internal_app_window_shelf_controller.cc",
"ash/launcher/internal_app_window_shelf_controller.h",
- "ash/launcher/launcher_app_service_app_updater.cc",
- "ash/launcher/launcher_app_service_app_updater.h",
- "ash/launcher/launcher_arc_app_updater.cc",
- "ash/launcher/launcher_arc_app_updater.h",
- "ash/launcher/launcher_crostini_app_updater.cc",
- "ash/launcher/launcher_crostini_app_updater.h",
"ash/launcher/shelf_spinner_controller.cc",
"ash/launcher/shelf_spinner_controller.h",
"ash/launcher/shelf_spinner_item_controller.cc",
"ash/launcher/shelf_spinner_item_controller.h",
+ "supervised_user/parent_permission_dialog.h",
+ "views/apps/app_dialog/app_block_dialog_view.cc",
+ "views/apps/app_dialog/app_block_dialog_view.h",
+ "views/apps/app_dialog/app_pause_dialog_view.cc",
+ "views/apps/app_dialog/app_pause_dialog_view.h",
"views/arc_app_dialog_view.cc",
"views/arc_data_removal_dialog_view.cc",
"views/crostini/crostini_ansible_software_config_view.cc",
"views/crostini/crostini_ansible_software_config_view.h",
"views/crostini/crostini_app_restart_view.cc",
"views/crostini/crostini_app_restart_view.h",
- "views/crostini/crostini_app_uninstaller_view.cc",
- "views/crostini/crostini_app_uninstaller_view.h",
"views/crostini/crostini_force_close_view.cc",
"views/crostini/crostini_force_close_view.h",
- "views/crostini/crostini_installer_view.cc",
- "views/crostini/crostini_installer_view.h",
+ "views/crostini/crostini_package_install_failure_view.cc",
+ "views/crostini/crostini_package_install_failure_view.h",
+ "views/crostini/crostini_recovery_view.cc",
+ "views/crostini/crostini_recovery_view.h",
"views/crostini/crostini_uninstaller_view.cc",
"views/crostini/crostini_uninstaller_view.h",
"views/crostini/crostini_update_component_view.cc",
"views/crostini/crostini_update_component_view.h",
"views/crostini/crostini_update_filesystem_view.cc",
"views/crostini/crostini_update_filesystem_view.h",
- "views/plugin_vm/plugin_vm_launcher_view.cc",
- "views/plugin_vm/plugin_vm_launcher_view.h",
+ "views/frame/custom_tab_browser_frame.cc",
+ "views/frame/custom_tab_browser_frame.h",
+ "views/plugin_vm/plugin_vm_installer_view.cc",
+ "views/plugin_vm/plugin_vm_installer_view.h",
]
deps += [
# TODO(wutao): Put new icons resources to ash/public/cpp/vector_icons/
@@ -3817,10 +4019,10 @@ jumbo_static_library("ui") {
"//chromeos/services/network_config/public/mojom",
"//components/assist_ranker",
"//components/assist_ranker/proto",
+ "//components/metrics/structured:structured_events",
"//components/services/app_service/public/cpp:app_file_handling",
"//services/audio/public/mojom",
"//services/device/public/mojom",
- "//services/identity/public/mojom",
"//services/media_session/public/mojom",
"//services/preferences/public/mojom",
"//ui/file_manager:file_manager",
@@ -3830,7 +4032,6 @@ jumbo_static_library("ui") {
if (enable_extensions) {
deps += [
"//apps",
- "//chrome/browser/apps",
"//chrome/browser/apps/platform_apps", # TODO(loyso): Remove this dep.
"//chrome/browser/apps/platform_apps/api",
"//chrome/browser/extensions",
@@ -3848,7 +4049,6 @@ jumbo_static_library("ui") {
"//chrome/browser/extensions",
]
sources += [
- "extensions/accelerator_priority.cc",
"extensions/accelerator_priority.h",
"extensions/app_launch_params.cc",
"extensions/app_launch_params.h",
@@ -3866,12 +4066,16 @@ jumbo_static_library("ui") {
"extensions/extension_install_ui_default.h",
"extensions/extension_install_ui_factory.cc",
"extensions/extension_install_ui_factory.h",
- "extensions/extension_installed_bubble.cc",
- "extensions/extension_installed_bubble.h",
+ "extensions/extension_installed_bubble_model.cc",
+ "extensions/extension_installed_bubble_model.h",
+ "extensions/extension_installed_waiter.cc",
+ "extensions/extension_installed_waiter.h",
"extensions/extension_message_bubble_bridge.cc",
"extensions/extension_message_bubble_bridge.h",
"extensions/extension_message_bubble_factory.cc",
"extensions/extension_message_bubble_factory.h",
+ "extensions/extension_removal_watcher.cc",
+ "extensions/extension_removal_watcher.h",
"extensions/extensions_container.h",
"extensions/hosted_app_browser_controller.cc",
"extensions/hosted_app_browser_controller.h",
@@ -3921,6 +4125,7 @@ jumbo_static_library("ui") {
"web_applications/web_app_metrics_factory.h",
"web_applications/web_app_ui_manager_impl.cc",
"web_applications/web_app_ui_manager_impl.h",
+ "web_applications/web_app_uninstall_dialog.h",
"webui/extensions/extension_basic_info.cc",
"webui/extensions/extension_basic_info.h",
"webui/extensions/extension_icon_source.cc",
@@ -3931,7 +4136,7 @@ jumbo_static_library("ui") {
deps += [ "//apps/ui/views" ]
}
if (use_aura) {
- sources += [ "views/chrome_javascript_native_dialog_factory_views.cc" ]
+ sources += [ "views/chrome_javascript_app_modal_view_factory_views.cc" ]
deps += [ "//ui/wm/public" ]
}
}
@@ -3987,6 +4192,7 @@ jumbo_static_library("ui") {
"webui/print_preview/printer_handler.h",
]
deps += [
+ "//components/printing/common:mojo_interfaces",
"//services/device/public/cpp/usb",
"//services/device/public/mojom:usb",
]
@@ -3996,8 +4202,6 @@ jumbo_static_library("ui") {
"webui/print_preview/local_printer_handler_chromeos.cc",
"webui/print_preview/local_printer_handler_chromeos.h",
]
-
- deps += [ "//services/identity/public/cpp:cpp_types" ]
} else {
sources += [
"webui/print_preview/local_printer_handler_default.cc",
@@ -4029,8 +4233,8 @@ jumbo_static_library("ui") {
deps += [
"//chrome/browser/ui/webui/reset_password:mojo_bindings",
"//chrome/common/safe_browsing:proto",
- "//components/safe_browsing:csd_proto",
- "//components/safe_browsing/password_protection:password_protection_metrics_util",
+ "//components/safe_browsing/content/password_protection:password_protection_metrics_util",
+ "//components/safe_browsing/core:csd_proto",
]
}
@@ -4078,12 +4282,21 @@ jumbo_static_library("ui") {
"views/frame/webui_tab_strip_container_view.h",
"views/toolbar/webui_tab_counter_button.cc",
"views/toolbar/webui_tab_counter_button.h",
+ "webui/tab_strip/chrome_content_browser_client_tab_strip_part.cc",
+ "webui/tab_strip/chrome_content_browser_client_tab_strip_part.h",
+ "webui/tab_strip/tab_before_unload_tracker.cc",
+ "webui/tab_strip/tab_before_unload_tracker.h",
"webui/tab_strip/tab_strip_ui.cc",
"webui/tab_strip/tab_strip_ui.h",
+ "webui/tab_strip/tab_strip_ui_embedder.h",
+ "webui/tab_strip/tab_strip_ui_handler.cc",
+ "webui/tab_strip/tab_strip_ui_handler.h",
"webui/tab_strip/tab_strip_ui_layout.cc",
"webui/tab_strip/tab_strip_ui_layout.h",
"webui/tab_strip/tab_strip_ui_metrics.cc",
"webui/tab_strip/tab_strip_ui_metrics.h",
+ "webui/tab_strip/tab_strip_ui_util.cc",
+ "webui/tab_strip/tab_strip_ui_util.h",
"webui/tab_strip/thumbnail_tracker.cc",
"webui/tab_strip/thumbnail_tracker.h",
]
@@ -4106,22 +4319,17 @@ static_library("test_support") {
"login/login_handler_test_utils.h",
"passwords/settings/password_ui_view_mock.cc",
"passwords/settings/password_ui_view_mock.h",
- "permission_bubble/mock_permission_prompt.cc",
- "permission_bubble/mock_permission_prompt.h",
- "permission_bubble/mock_permission_prompt_factory.cc",
- "permission_bubble/mock_permission_prompt_factory.h",
"toolbar/test_toolbar_action_view_controller.cc",
"toolbar/test_toolbar_action_view_controller.h",
]
- public_deps = [
- ":ui",
- ]
+ public_deps = [ ":ui" ]
deps = [
"//chrome/app/theme:theme_resources",
"//chrome/browser",
"//chrome/browser/devtools",
"//components/omnibox/browser",
"//components/password_manager/core/browser",
+ "//components/permissions",
"//components/sessions",
"//components/translate/content/browser",
"//content/public/browser",
@@ -4142,19 +4350,20 @@ static_library("test_support") {
"//ui/views:test_support",
]
sources += [
- "extensions/browser_action_test_util.h",
+ "extensions/extension_action_test_helper.h",
"views/extensions/extensions_menu_test_util.cc",
"views/extensions/extensions_menu_test_util.h",
"views/find_bar_host_unittest_util_views.cc",
"views/payments/test_chrome_payment_request_delegate.cc",
"views/payments/test_chrome_payment_request_delegate.h",
- "views/toolbar/browser_action_test_util_views.cc",
- "views/toolbar/browser_action_test_util_views_mac.mm",
+ "views/toolbar/extension_action_test_helper_mac.mm",
+ "views/toolbar/extension_action_test_helper_views.cc",
+ "views/toolbar/extension_action_test_helper_views.h",
"views/webauthn/authenticator_request_dialog_view_test_api.cc",
"views/webauthn/authenticator_request_dialog_view_test_api.h",
]
if (use_aura) {
- sources += [ "views/toolbar/browser_action_test_util_views_aura.cc" ]
+ sources += [ "views/toolbar/extension_action_test_helper_aura.cc" ]
deps += [
"//ui/aura",
"//ui/wm",
@@ -4171,6 +4380,8 @@ static_library("test_support") {
"exclusive_access/fullscreen_controller_test.h",
"global_error/global_error_waiter.cc",
"global_error/global_error_waiter.h",
+ "hats/mock_hats_service.cc",
+ "hats/mock_hats_service.h",
"passwords/credential_manager_dialog_controller_mock.cc",
"passwords/credential_manager_dialog_controller_mock.h",
"passwords/manage_passwords_ui_controller_mock.cc",
@@ -4227,16 +4438,16 @@ if (is_chromeos) {
"ash/keyboard/chrome_keyboard_controller_client_test_helper.cc",
"ash/keyboard/chrome_keyboard_controller_client_test_helper.h",
]
- deps = [
- "//ash",
- ]
+ deps = [ "//ash" ]
}
}
if (is_android) {
+ java_cpp_enum("cookie_controls_enforcement_javagen") {
+ sources = [ "cookie_controls/cookie_controls_service.h" ]
+ }
+
java_cpp_enum("tab_model_enums_java") {
- sources = [
- "android/tab_model/tab_model.h",
- ]
+ sources = [ "android/tab_model/tab_model.h" ]
}
}
diff --git a/chromium/chrome/browser/ui/android/appmenu/BUILD.gn b/chromium/chrome/browser/ui/android/appmenu/BUILD.gn
index 9b74c9dce4f..665fe8c6026 100644
--- a/chromium/chrome/browser/ui/android/appmenu/BUILD.gn
+++ b/chromium/chrome/browser/ui/android/appmenu/BUILD.gn
@@ -5,7 +5,7 @@ import("//build/config/android/rules.gni")
import("//chrome/android/features/android_library_factory_tmpl.gni")
android_library("java") {
- java_files = [
+ sources = [
"java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuBlocker.java",
"java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuButtonHelper.java",
"java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuCoordinator.java",
@@ -16,24 +16,18 @@ android_library("java") {
"java/src/org/chromium/chrome/browser/ui/appmenu/CustomViewBinder.java",
"java/src/org/chromium/chrome/browser/ui/appmenu/MenuButtonDelegate.java",
]
- deps = [
- "//chrome/lib/lifecycle/public/android:java",
- ]
+ deps = [ "//chrome/browser/android/lifecycle:java" ]
}
android_library_factory("factory_java") {
- deps = [
- ":java",
- ]
- sources = [
- "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuCoordinatorFactory.java",
- ]
+ deps = [ ":java" ]
+ sources = [ "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuCoordinatorFactory.java" ]
}
android_library("test_support_java") {
testonly = true
- java_files = [
+ sources = [
"test/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuTestSupport.java",
"test/java/src/org/chromium/chrome/browser/ui/appmenu/TestAppMenuObserver.java",
]
@@ -46,10 +40,10 @@ android_library("test_support_java") {
android_resources("java_resources") {
custom_package = "org.chromium.chrome.browser.ui.appmenu"
- resource_dirs = [ "java/res" ]
+ sources = [ "java/res/values/styles.xml" ]
deps = [
- "//chrome/browser/ui/android/styles:java_resources",
- "//third_party/android_deps:com_android_support_design_java",
+ "//components/browser_ui/styles/android:java_resources",
+ "//third_party/android_deps:com_google_android_material_material_java",
"//ui/android:ui_java_resources",
]
}
diff --git a/chromium/chrome/browser/ui/android/appmenu/internal/BUILD.gn b/chromium/chrome/browser/ui/android/appmenu/internal/BUILD.gn
index 04b1999e652..0bdd9235cc8 100644
--- a/chromium/chrome/browser/ui/android/appmenu/internal/BUILD.gn
+++ b/chromium/chrome/browser/ui/android/appmenu/internal/BUILD.gn
@@ -5,7 +5,7 @@
import("//build/config/android/rules.gni")
android_library("java") {
- java_files = [
+ sources = [
"java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java",
"java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapter.java",
"java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuButtonHelperImpl.java",
@@ -19,10 +19,10 @@ android_library("java") {
deps = [
":java_resources",
"//base:base_java",
+ "//chrome/browser/android/lifecycle:java",
"//chrome/browser/ui/android/appmenu:java",
"//chrome/browser/ui/android/appmenu:java_resources",
- "//chrome/browser/ui/android/widget:java",
- "//chrome/lib/lifecycle/public/android:java",
+ "//components/browser_ui/widget/android:java",
"//third_party/android_deps:android_support_v7_appcompat_java",
"//third_party/android_deps:androidx_annotation_annotation_java",
"//ui/android:ui_java",
@@ -31,22 +31,28 @@ android_library("java") {
android_resources("java_resources") {
custom_package = "org.chromium.chrome.browser.ui.appmenu.internal"
- resource_dirs = [ "java/res" ]
+ sources = [
+ "java/res/layout/icon_row_menu_item.xml",
+ "java/res/layout/menu_item.xml",
+ "java/res/layout/title_button_menu_item.xml",
+ "java/res/values/dimens.xml",
+ "java/res/values/ids.xml",
+ ]
# Include resource dependencies needed by :java so that resources may
# all be accessed through the same custom_package.
deps = [
"//chrome/browser/ui/android/appmenu:java_resources",
- "//chrome/browser/ui/android/widget:ui_widget_java_resources",
+ "//components/browser_ui/widget/android:java_resources",
]
}
android_library("javatests") {
testonly = true
- java_files = [
- "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterTest.java",
+ sources = [
"java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterRenderTest.java",
+ "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterTest.java",
"java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuTest.java",
"java/src/org/chromium/chrome/browser/ui/appmenu/TestAppMenuDelegate.java",
"java/src/org/chromium/chrome/browser/ui/appmenu/TestAppMenuPropertiesDelegate.java",
@@ -56,17 +62,18 @@ android_library("javatests") {
":test_java_resources",
"//base:base_java",
"//base:base_java_test_support",
+ "//chrome/browser/android/lifecycle:java",
"//chrome/browser/ui/android/appmenu:java",
"//chrome/browser/ui/android/appmenu:test_support_java",
- "//chrome/browser/ui/android/widget:test_support_java",
- "//chrome/lib/lifecycle/public/android:java",
"//chrome/test/android:chrome_java_test_support",
+ "//components/browser_ui/widget/android:test_support_java",
"//content/public/test/android:content_java_test_support",
"//third_party/android_deps:android_support_v7_appcompat_java",
"//third_party/android_support_test_runner:rules_java",
"//third_party/android_support_test_runner:runner_java",
"//third_party/junit",
"//third_party/mockito:mockito_java",
+ "//ui/android:ui_java_test_support",
]
}
@@ -74,17 +81,27 @@ android_resources("test_java_resources") {
testonly = true
custom_package = "org.chromium.chrome.browser.ui.appmenu.test"
- resource_dirs = [ "test/java/res" ]
- deps = [
- ":java_resources",
+ sources = [
+ "test/java/res/drawable/test_ic_arrow_downward_black_24dp.xml",
+ "test/java/res/drawable/test_ic_arrow_forward_black_24dp.xml",
+ "test/java/res/drawable/test_ic_info_outline_black_24dp.xml",
+ "test/java/res/drawable/test_ic_more_vert_black_24dp.xml",
+ "test/java/res/drawable/test_ic_refresh_black_24dp.xml",
+ "test/java/res/drawable/test_ic_star_border_black_24dp.xml",
+ "test/java/res/drawable/test_ic_vintage_filter.xml",
+ "test/java/res/layout/test_app_menu_activity_layout.xml",
+ "test/java/res/layout/test_menu_footer.xml",
+ "test/java/res/layout/test_menu_header.xml",
+ "test/java/res/menu/test_menu.xml",
]
+ deps = [ ":java_resources" ]
}
java_library("junit") {
# Skip platform checks since Robolectric depends on requires_android targets.
bypass_platform_checks = true
testonly = true
- java_files = [ "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuPopupPositionTest.java" ]
+ sources = [ "java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuPopupPositionTest.java" ]
deps = [
":java",
"//base:base_junit_test_support",
diff --git a/chromium/chrome/browser/ui/android/favicon/BUILD.gn b/chromium/chrome/browser/ui/android/favicon/BUILD.gn
new file mode 100644
index 00000000000..de37e227079
--- /dev/null
+++ b/chromium/chrome/browser/ui/android/favicon/BUILD.gn
@@ -0,0 +1,70 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+ sources = [
+ "java/src/org/chromium/chrome/browser/ui/favicon/FaviconHelper.java",
+ "java/src/org/chromium/chrome/browser/ui/favicon/FaviconUtils.java",
+ "java/src/org/chromium/chrome/browser/ui/favicon/LargeIconBridge.java",
+ "java/src/org/chromium/chrome/browser/ui/favicon/RoundedIconGenerator.java",
+ ]
+
+ deps = [
+ ":java_resources",
+ "//base:base_java",
+ "//base:jni_java",
+ "//chrome/browser/profiles/android:java",
+ "//chrome/browser/util:java",
+ "//components/embedder_support/android:util_java",
+ "//components/url_formatter/android:url_formatter_java",
+ "//content/public/android:content_java",
+ "//ui/android:ui_java",
+ "//url:gurl_java",
+ ]
+
+ srcjar_deps = [ "//components/favicon_base:favicon_base_enums_java" ]
+
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+}
+
+generate_jni("jni_headers") {
+ sources = [
+ "java/src/org/chromium/chrome/browser/ui/favicon/FaviconHelper.java",
+ "java/src/org/chromium/chrome/browser/ui/favicon/LargeIconBridge.java",
+ ]
+}
+
+android_resources("java_resources") {
+ custom_package = "org.chromium.chrome.browser.ui.favicon"
+ sources = [
+ "java/res/drawable-hdpi/chromelogo16.png",
+ "java/res/drawable-hdpi/default_favicon.png",
+ "java/res/drawable-mdpi/chromelogo16.png",
+ "java/res/drawable-mdpi/default_favicon.png",
+ "java/res/drawable-xhdpi/chromelogo16.png",
+ "java/res/drawable-xhdpi/default_favicon.png",
+ "java/res/drawable-xxhdpi/chromelogo16.png",
+ "java/res/drawable-xxhdpi/default_favicon.png",
+ "java/res/drawable-xxxhdpi/chromelogo16.png",
+ "java/res/drawable-xxxhdpi/default_favicon.png",
+ "java/res/values/colors.xml",
+ "java/res/values/dimens.xml",
+ ]
+
+ deps = [ "//ui/android:ui_java_resources" ]
+}
+
+android_library("javatests") {
+ testonly = true
+
+ sources = [ "java/src/org/chromium/chrome/browser/ui/favicon/RoundedIconGeneratorTest.java" ]
+ deps = [
+ ":java",
+ "//chrome/test/android:chrome_java_test_support",
+ "//third_party/android_support_test_runner:rules_java",
+ "//third_party/android_support_test_runner:runner_java",
+ "//third_party/junit",
+ ]
+}
diff --git a/chromium/chrome/browser/ui/android/native_page/BUILD.gn b/chromium/chrome/browser/ui/android/native_page/BUILD.gn
new file mode 100644
index 00000000000..8157eb75511
--- /dev/null
+++ b/chromium/chrome/browser/ui/android/native_page/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import("//build/config/android/rules.gni")
+import("//chrome/android/features/android_library_factory_tmpl.gni")
+
+android_library("java") {
+ sources = [
+ "java/src/org/chromium/chrome/browser/ui/native_page/BasicNativePage.java",
+ "java/src/org/chromium/chrome/browser/ui/native_page/FrozenNativePage.java",
+ "java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java",
+ "java/src/org/chromium/chrome/browser/ui/native_page/NativePageHost.java",
+ ]
+ deps = [
+ "//base:base_java",
+ "//components/browser_ui/styles/android:java",
+ "//content/public/android:content_java",
+ ]
+}
diff --git a/chromium/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chromium/chrome/browser/ui/android/strings/android_chrome_strings.grd
index fa06cd7dab7..be1676f7c93 100644
--- a/chromium/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chromium/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -32,10 +32,15 @@ CHAR-LIMIT guidelines:
<grit current_release="1" latest_public_release="0" output_all_resource_defines="false">
<outputs>
+ <output filename="values-af/android_chrome_strings.xml" lang="af" type="android" />
<output filename="values-am/android_chrome_strings.xml" lang="am" type="android" />
<output filename="values-ar/android_chrome_strings.xml" lang="ar" type="android" />
+ <output filename="values-as/android_chrome_strings.xml" lang="as" type="android" />
+ <output filename="values-az/android_chrome_strings.xml" lang="az" type="android" />
+ <output filename="values-be/android_chrome_strings.xml" lang="be" type="android" />
<output filename="values-bg/android_chrome_strings.xml" lang="bg" type="android" />
<output filename="values-bn/android_chrome_strings.xml" lang="bn" type="android" />
+ <output filename="values-bs/android_chrome_strings.xml" lang="bs" type="android" />
<output filename="values-ca/android_chrome_strings.xml" lang="ca" type="android" />
<output filename="values-cs/android_chrome_strings.xml" lang="cs" type="android" />
<output filename="values-da/android_chrome_strings.xml" lang="da" type="android" />
@@ -46,34 +51,52 @@ CHAR-LIMIT guidelines:
<output filename="values-es/android_chrome_strings.xml" lang="es" type="android" />
<output filename="values-es-rUS/android_chrome_strings.xml" lang="es-419" type="android" />
<output filename="values-et/android_chrome_strings.xml" lang="et" type="android" />
+ <output filename="values-eu/android_chrome_strings.xml" lang="eu" type="android" />
<output filename="values-fa/android_chrome_strings.xml" lang="fa" type="android" />
<output filename="values-fi/android_chrome_strings.xml" lang="fi" type="android" />
<output filename="values-tl/android_chrome_strings.xml" lang="fil" type="android" />
<output filename="values-fr/android_chrome_strings.xml" lang="fr" type="android" />
+ <output filename="values-fr-rCA/android_chrome_strings.xml" lang="fr-CA" type="android" />
+ <output filename="values-gl/android_chrome_strings.xml" lang="gl" type="android" />
<output filename="values-gu/android_chrome_strings.xml" lang="gu" type="android" />
<output filename="values-hi/android_chrome_strings.xml" lang="hi" type="android" />
<output filename="values-hr/android_chrome_strings.xml" lang="hr" type="android" />
<output filename="values-hu/android_chrome_strings.xml" lang="hu" type="android" />
+ <output filename="values-hy/android_chrome_strings.xml" lang="hy" type="android" />
<output filename="values-in/android_chrome_strings.xml" lang="id" type="android" />
+ <output filename="values-is/android_chrome_strings.xml" lang="is" type="android" />
<output filename="values-it/android_chrome_strings.xml" lang="it" type="android" />
<output filename="values-iw/android_chrome_strings.xml" lang="iw" type="android" />
<output filename="values-ja/android_chrome_strings.xml" lang="ja" type="android" />
+ <output filename="values-ka/android_chrome_strings.xml" lang="ka" type="android" />
+ <output filename="values-kk/android_chrome_strings.xml" lang="kk" type="android" />
+ <output filename="values-km/android_chrome_strings.xml" lang="km" type="android" />
<output filename="values-kn/android_chrome_strings.xml" lang="kn" type="android" />
<output filename="values-ko/android_chrome_strings.xml" lang="ko" type="android" />
+ <output filename="values-ky/android_chrome_strings.xml" lang="ky" type="android" />
+ <output filename="values-lo/android_chrome_strings.xml" lang="lo" type="android" />
<output filename="values-lt/android_chrome_strings.xml" lang="lt" type="android" />
<output filename="values-lv/android_chrome_strings.xml" lang="lv" type="android" />
+ <output filename="values-mk/android_chrome_strings.xml" lang="mk" type="android" />
<output filename="values-ml/android_chrome_strings.xml" lang="ml" type="android" />
+ <output filename="values-mn/android_chrome_strings.xml" lang="mn" type="android" />
<output filename="values-mr/android_chrome_strings.xml" lang="mr" type="android" />
<output filename="values-ms/android_chrome_strings.xml" lang="ms" type="android" />
+ <output filename="values-my/android_chrome_strings.xml" lang="my" type="android" />
+ <output filename="values-ne/android_chrome_strings.xml" lang="ne" type="android" />
<output filename="values-nl/android_chrome_strings.xml" lang="nl" type="android" />
<output filename="values-nb/android_chrome_strings.xml" lang="no" type="android" />
+ <output filename="values-or/android_chrome_strings.xml" lang="or" type="android" />
+ <output filename="values-pa/android_chrome_strings.xml" lang="pa" type="android" />
<output filename="values-pl/android_chrome_strings.xml" lang="pl" type="android" />
<output filename="values-pt-rBR/android_chrome_strings.xml" lang="pt-BR" type="android" />
<output filename="values-pt-rPT/android_chrome_strings.xml" lang="pt-PT" type="android" />
<output filename="values-ro/android_chrome_strings.xml" lang="ro" type="android" />
<output filename="values-ru/android_chrome_strings.xml" lang="ru" type="android" />
+ <output filename="values-si/android_chrome_strings.xml" lang="si" type="android" />
<output filename="values-sk/android_chrome_strings.xml" lang="sk" type="android" />
<output filename="values-sl/android_chrome_strings.xml" lang="sl" type="android" />
+ <output filename="values-sq/android_chrome_strings.xml" lang="sq" type="android" />
<output filename="values-sr/android_chrome_strings.xml" lang="sr" type="android" />
<output filename="values-sv/android_chrome_strings.xml" lang="sv" type="android" />
<output filename="values-sw/android_chrome_strings.xml" lang="sw" type="android" />
@@ -82,9 +105,13 @@ CHAR-LIMIT guidelines:
<output filename="values-th/android_chrome_strings.xml" lang="th" type="android" />
<output filename="values-tr/android_chrome_strings.xml" lang="tr" type="android" />
<output filename="values-uk/android_chrome_strings.xml" lang="uk" type="android" />
+ <output filename="values-ur/android_chrome_strings.xml" lang="ur" type="android" />
+ <output filename="values-uz/android_chrome_strings.xml" lang="uz" type="android" />
<output filename="values-vi/android_chrome_strings.xml" lang="vi" type="android" />
<output filename="values-zh-rCN/android_chrome_strings.xml" lang="zh-CN" type="android" />
+ <output filename="values-zh-rHK/android_chrome_strings.xml" lang="zh-HK" type="android" />
<output filename="values-zh-rTW/android_chrome_strings.xml" lang="zh-TW" type="android" />
+ <output filename="values-zu/android_chrome_strings.xml" lang="zu" type="android" />
</outputs>
<translations>
<file lang="af" path="translations/android_chrome_strings_af.xtb" />
@@ -152,6 +179,7 @@ CHAR-LIMIT guidelines:
<file lang="sl" path="translations/android_chrome_strings_sl.xtb" />
<file lang="sq" path="translations/android_chrome_strings_sq.xtb" />
<file lang="sr" path="translations/android_chrome_strings_sr.xtb" />
+ <file lang="sr-Latn" path="translations/android_chrome_strings_sr-Latn.xtb" />
<file lang="sv" path="translations/android_chrome_strings_sv.xtb" />
<file lang="sw" path="translations/android_chrome_strings_sw.xtb" />
<file lang="ta" path="translations/android_chrome_strings_ta.xtb" />
@@ -169,150 +197,15 @@ CHAR-LIMIT guidelines:
</translations>
<release allow_pseudo="false" seq="1">
<messages fallback_to_english="true">
- <!-- Generic strings -->
- <message name="IDS_DELETED" desc='Text that announces to the user that something was deleted.'>
- Deleted
- </message>
- <message name="IDS_OK" desc="Label for a confirm button. Used in multiple contexts. [CHAR-LIMIT=20]">
- OK
- </message>
- <message name="IDS_OK_GOT_IT" desc="Label of a button by which the user confirms that they read and understood the information or instructions. Used in multiple contexts. [CHAR-LIMIT=20]">
- OK, got it
- </message>
- <message name="IDS_CANCEL" desc="Label for a cancel button. Used in multiple contexts. [CHAR-LIMIT=20]">
- Cancel
- </message>
- <message name="IDS_NOT_NOW" desc="Label for a not now button. Used in multiple contexts. [CHAR-LIMIT=20]">
- Not now
- </message>
- <message name="IDS_SAVE" desc="Label for a button to save a change. Used in multiple contexts. [CHAR-LIMIT=20]">
- Save
- </message>
- <message name="IDS_DETAILS_LINK" desc="In 1) Settings > Clean up computer (desktop), a link to open details of incompatible applications. In 2) Settings > Lite mode (mobile), static title for data usage breakdown." meaning="Short for 'view details'. Link; static title.">
- Details
- </message>
- <message name="IDS_DONE" desc="Label for a button to save a change or finish editing data. Used in multiple contexts. [CHAR-LIMIT=20]">
- Done
- </message>
- <message name="IDS_DELETE" desc="Label for a delete button. Used in multiple contexts. [CHAR-LIMIT=20]">
- Delete
- </message>
- <message name="IDS_REMOVE" desc="Label for a button to remove an item (e.g. a bookmark) from a list. [CHAR-LIMIT=20]">
- Remove
- </message>
- <message name="IDS_RESET" desc="Label for a button to reset information you are editing to a default.">
- Reset
- </message>
- <message name="IDS_TITLE" desc="Text indicating the title of a button or a textfield. Ued in multiple contexts. [CHAR-LIMIT=32]">
- Title
- </message>
- <message name="IDS_TEXT_ON" desc="Text indicating that an option is turned on. [CHAR-LIMIT=20]">
- On
- </message>
- <message name="IDS_TEXT_OFF" desc="Text indicating that an option is turned off. [CHAR-LIMIT=20]">
- Off
- </message>
- <message name="IDS_LEARN_MORE" desc="Generic label for menu item to learn more about a feature. [CHAR-LIMIT=32]">
- Learn more
- </message>
- <message name="IDS_MORE" desc="Generic label for a button to show more items or options. [CHAR-LIMIT=20]">
- More
- </message>
- <message name="IDS_CLOSE" desc="Content description for a button to close a dialog or popup" >
- Close
- </message>
- <message name="IDS_NO_THANKS" desc="Generic label to say no thanks for a feature. [CHAR-LIMIT=32]">
- No thanks
- </message>
- <message name="IDS_NEXT" desc="Generic label for a button to advance to the next item. [CHAR-LIMIT=20]">
- Next
- </message>
- <message name="IDS_CONTINUE_BUTTON" desc="Generic label for a button to continue to the next screen. Used in multiple contexts. [CHAR-LIMIT=20]">
- Continue
- </message>
- <message name="IDS_SUBMIT" desc="Generic label for a button to submit data. Used in multiple contexts. [CHAR-LIMIT=20]">
- Submit
- </message>
- <message name="IDS_UNDO" desc="Generic label for a button to undo the previous action.">
- Undo
- </message>
- <message name="IDS_HELP" desc="Generic label for a button that displays help for the current screen.">
- Help
- </message>
- <message name="IDS_TODAY" desc="Generic Label saying the date is today.">
- Today
- </message>
- <message name="IDS_YESTERDAY" desc="Generic Label saying the date is yesterday.">
- Yesterday
- </message>
- <message name="IDS_SELECT" desc="Prompt for user to select something. [CHAR-LIMIT=20]">
- Select
- </message>
- <message name="IDS_ADD" desc="Prompt for the user to add something, like a new address. [CHAR-LIMIT=20]">
- Add
- </message>
- <message name="IDS_SHARE" desc="Content description for a button to share item(s). [CHAR-LIMIT=20]">
- Share
- </message>
- <message name="IDS_SEARCH" desc="The label for a search button.">
- Search
- </message>
- <message name="IDS_SHOW_INFO" desc="The label for a info button to show info.">
- Show Info
- </message>
- <message name="IDS_HIDE_INFO" desc="The label for a info button to hide info.">
- Hide Info
- </message>
- <message name="IDS_COPY_LINK" desc="The label for a menu item to copy a link. [CHAR-LIMIT=30]">
- Copy link
- </message>
- <message name="IDS_COPIED" desc="Notification telling the user that something has been copied to the clipboard.">
- Copied
- </message>
- <message name="IDS_TRY_AGAIN" desc="The label for a button allowing the user to try an action again. [CHAR-LIMIT=20]">
- Try again
- </message>
- <message name="IDS_BACK" desc="Label for a back button to return to a previous UI state or screen. Used in multiple contexts. [CHAR-LIMIT=20]">
- Back
- </message>
- <message name="IDS_CONFIRM" desc="Label for a confirm button. Used in multiple contexts. [CHAR-LIMIT=20]">
- Confirm
- </message>
- <message name="IDS_SHOW" desc="Label for a show button. Used in multiple contexts. [CHAR-LIMIT=20]">
- Show
- </message>
- <message name="IDS_USER" desc="Generic label for UI elements with information about user.">
- User
- </message>
- <message name="IDS_MENU_ITEM_MOVE_UP" desc="Option in item menu. User can click the 'Move up' option to move the item up by one position in its list. [CHAR-LIMIT=24]">
- Move up
- </message>
- <message name="IDS_MENU_ITEM_MOVE_DOWN" desc="Option in item menu. User can click the 'Move down' option to move the item down by one position in its list. [CHAR-LIMIT=24]">
- Move down
- </message>
- <message name="IDS_MENU_ITEM_MOVE_TO_TOP" desc="Option in item menu. User can click the 'Move to top' option to move the item up to the top of its list. [CHAR-LIMIT=24]">
- Move to top
- </message>
+ <!-- NOTE: Generic strings used across multiple features belong in //components/browser_ui/strings/android. -->
<!-- Main Preferences -->
- <message name="IDS_PREFERENCES" desc="Title for Chrome's Settings.">
+ <message name="IDS_SETTINGS" desc="Title for Chrome's Settings.">
Settings
</message>
<message name="IDS_MENU_HELP" desc="Menu item for opening the help page. [CHAR-LIMIT=27]">
Help &amp; feedback
</message>
- <message name="IDS_MANAGED_BY_YOUR_ORGANIZATION" desc="Popup message when the user clicks a UI element that has been disabled by enterprise policy.">
- Managed by your organization
- </message>
- <message name="IDS_MANAGED_BY_YOUR_PARENTS" desc="Popup message when the user clicks a UI element that has been disabled by their parents.">
- Managed by your parents
- </message>
- <message name="IDS_MANAGED_BY_YOUR_PARENT" desc="Popup message when the user clicks a UI element that has been disabled by their parent.">
- Managed by your parent
- </message>
- <message name="IDS_MANAGED_SETTINGS_CANNOT_BE_RESET" desc="Popup message when the user clicks a UI element that resets a list of settings that include managed settings.">
- Managed settings cannot be reset
- </message>
<message name="IDS_PREFS_SECTION_BASICS" desc='Title of "Basics" section of preferences. [CHAR-LIMIT=32]'>
Basics
</message>
@@ -461,8 +354,8 @@ CHAR-LIMIT guidelines:
Cancel sync
</message>
- <!-- Search engine preferences -->
- <message name="IDS_PREFS_SEARCH_ENGINE" desc="Title for Search Engine preferences. [CHAR-LIMIT=32]">
+ <!-- Search engine settings -->
+ <message name="IDS_SEARCH_ENGINE_SETTINGS" desc="Title for Search Engine settings. [CHAR-LIMIT=32]">
Search engine
</message>
<message name="IDS_SEARCH_ENGINE_LOCATION_AND_NOTIFICATIONS_ALLOWED" desc="The text of a link displayed when location and notifications permissions for a particular search engine are allowed.">
@@ -568,11 +461,11 @@ CHAR-LIMIT guidelines:
other {<ph name="CONTACT_PREVIEW">%1$s<ex>Jerry, 438-123-1922</ex></ph>\u2026 and <ph name="NUMBER_OF_ADDITIONAL_CONTACTS">%2$s<ex>2</ex></ph> more}}
</message>
- <!-- Save passwords preferences -->
- <message name="IDS_PREFS_SAVED_PASSWORDS_TITLE" desc="Title for the preferences screen with saved passwords and the header for the list of saved passwords in that screen. [CHAR-LIMIT=32]">
+ <!-- Password Settings -->
+ <message name="IDS_PASSWORD_SETTINGS_TITLE" desc="Title for the settings screen with saved passwords and the header for the list of saved passwords in that screen. [CHAR-LIMIT=32]">
Passwords
</message>
- <message name="IDS_PREFS_SAVED_PASSWORDS" desc="Title for the checkbox toggling whether passwords are saved or not. [CHAR-LIMIT=32]">
+ <message name="IDS_PASSWORD_SETTINGS_SAVE_PASSWORDS" desc="Title for the checkbox toggling whether passwords are saved or not. [CHAR-LIMIT=32]">
Save passwords
</message>
<message name="IDS_PASSWORDS_AUTO_SIGNIN_TITLE" desc="Title for checkbox to enable automatically signing the user in to websites">
@@ -593,9 +486,15 @@ CHAR-LIMIT guidelines:
<message name="IDS_MANAGE_PASSWORDS_TEXT" desc="Text for link to manage passwords on Account Central.">
View and manage saved passwords in your <ph name="BEGIN_LINK">&lt;link&gt;</ph>Google Account<ph name="END_LINK">&lt;/link&gt;</ph>
</message>
+ <message name="IDS_PHONE_AS_SECURITY_KEY_TEXT" desc="Text for link to use phone as a security key. A 'security key' is physical device used for authentication, usually as part of two-factor security. This option allows a phone to be used in place of a dedicated security key.">
+ Use phone as a security key
+ </message>
<message name="IDS_SAVED_PASSWORDS_NONE_TEXT" desc="Text when there are no saved passwords/exceptions.">
Saved passwords will appear here.
</message>
+ <message name="IDS_PASSWORD_NO_RESULT" desc="Text when a password search returned no results.">
+ Can’t find that password. Check your spelling and try again.
+ </message>
<message name="IDS_PASSWORD_ENTRY_VIEWER_TITLE" desc='Title of the overview screen for a saved password.'>
Saved password
</message>
@@ -653,10 +552,10 @@ CHAR-LIMIT guidelines:
<message name="IDS_PASSWORD_GENERATION_POPUP_CONTENT_DESCRIPTION" desc="The text announced by the screen reader when the password generation popup is shown.">
Showing password generation popup
</message>
- <message name="IDS_SAVE_PASSWORD_PREFERENCES_EXPORT_ACTION_TITLE" desc="The title of a menu item to trigger exporting passwords from the password settings.">
+ <message name="IDS_PASSWORD_SETTINGS_EXPORT_ACTION_TITLE" desc="The title of a menu item to trigger exporting passwords from the password settings.">
Export passwords…
</message>
- <message name="IDS_SAVE_PASSWORD_PREFERENCES_EXPORT_ACTION_DESCRIPTION" desc="The description of a menu item to trigger exporting passwords from the password settings.">
+ <message name="IDS_PASSWORD_SETTINGS_EXPORT_ACTION_DESCRIPTION" desc="The description of a menu item to trigger exporting passwords from the password settings.">
Export passwords stored with Chrome
</message>
<message name="IDS_SETTINGS_PASSWORDS_EXPORT_DESCRIPTION" desc="Text shown to the user who initiated exporting passwords, as a warning before any passwords have been exported.">
@@ -665,19 +564,19 @@ CHAR-LIMIT guidelines:
<message name="IDS_SETTINGS_PASSWORDS_PREPARING_EXPORT" desc="Text shown to the user above a progress bar, informing the user that passwords are being prepared for export.">
Preparing passwords…
</message>
- <message name="IDS_SAVE_PASSWORD_PREFERENCES_EXPORT_ERROR_TITLE" desc="The title of a dialog showing an error encountered during exporting passwords from the passwords settings.">
+ <message name="IDS_PASSWORD_SETTINGS_EXPORT_ERROR_TITLE" desc="The title of a dialog showing an error encountered during exporting passwords from the passwords settings.">
Can’t export passwords
</message>
- <message name="IDS_SAVE_PASSWORD_PREFERENCES_EXPORT_LEARN_GOOGLE_DRIVE" desc="The label of a button in an error dialog after exporting passwords from the settings failed. The button takes the user to a help article about using Google Drive.">
+ <message name="IDS_PASSWORD_SETTINGS_EXPORT_LEARN_GOOGLE_DRIVE" desc="The label of a button in an error dialog after exporting passwords from the settings failed. The button takes the user to a help article about using Google Drive.">
Learn how to use Google Drive
</message>
- <message name="IDS_SAVE_PASSWORD_PREFERENCES_EXPORT_NO_APP" desc="The explanation of the error when exporting passwords fails because the user has no Android app installed which could consume the exported data. The description is shown in the body of an alert dialog.">
+ <message name="IDS_PASSWORD_SETTINGS_EXPORT_NO_APP" desc="The explanation of the error when exporting passwords fails because the user has no Android app installed which could consume the exported data. The description is shown in the body of an alert dialog.">
Your device doesn’t have an app to store the passwords file.
</message>
- <message name="IDS_SAVE_PASSWORD_PREFERENCES_EXPORT_TIPS" desc="Tips on how to fix an error with exporting passwords. They are shown in the body of an alert dialog.">
+ <message name="IDS_PASSWORD_SETTINGS_EXPORT_TIPS" desc="Tips on how to fix an error with exporting passwords. They are shown in the body of an alert dialog.">
Try the following tips: make sure there is enough space on your device, try to export again.
</message>
- <message name="IDS_SAVE_PASSWORD_PREFERENCES_EXPORT_ERROR_DETAILS" desc="A short prefix to introduce a technical error message passed to the user from Android after exporting passwords through a temporary file fails. Both the prefix and the error message are shown in the body of an alert dialog.">
+ <message name="IDS_PASSWORD_SETTINGS_EXPORT_ERROR_DETAILS" desc="A short prefix to introduce a technical error message passed to the user from Android after exporting passwords through a temporary file fails. Both the prefix and the error message are shown in the body of an alert dialog.">
Details: <ph name="ERROR_DESCRIPTION">%1$s<ex>IOException: No space left on device</ex></ph>
</message>
@@ -691,17 +590,23 @@ CHAR-LIMIT guidelines:
<message name="IDS_LOCKSCREEN_DESCRIPTION_EXPORT" desc="When a user attempts to export saved passwords in Chrome's settings, Chrome launches a lock screen to verify the user's identity and displays the following explanation.">
Unlock to export your passwords
</message>
- <message name="IDS_SAVE_PASSWORD_PREFERENCES_EXPORT_SUBJECT" desc="Chrome sets this string to be the subject of the sharing intent for sharing exported passwords. How the subject is interpreted is up to the consumer app, e.g., Google Drive will make it the filename, GMail will make it the e-mail subject. In general, it describes what is being shared.">
+ <message name="IDS_PASSWORD_SETTINGS_EXPORT_SUBJECT" desc="Chrome sets this string to be the subject of the sharing intent for sharing exported passwords. How the subject is interpreted is up to the consumer app, e.g., Google Drive will make it the filename, GMail will make it the e-mail subject. In general, it describes what is being shared.">
Chrome Passwords
</message>
<!-- Homepage preferences -->
- <message name="IDS_OPTIONS_HOMEPAGE_EDIT_TITLE" desc="The title of the screen that allows users to change the URL that opens when they tap on the home page button in the omnibox.">
- Edit home page
+ <message name="IDS_OPTIONS_HOMEPAGE_EDIT_HINT" desc="Hint for the text edit on Homepage Preference setting, guiding user to enter their customized homepage setting">
+ Enter custom web address
+ </message>
+ <message name="IDS_OPTIONS_HOMEPAGE_EDIT_TITLE" desc="The title of the screen that allows users to change the URL that opens when they tap on the homepage button in the omnibox. This string is also used as a long-press menu item that navigates the user to the homepage settings.">
+ Edit homepage
</message>
- <message name="IDS_OPTIONS_HOMEPAGE_EDIT_LABEL" desc="The label for the edit text field that allows the user to change the URL that is opened when they tap on the home page button in the omnibox.">
+ <message name="IDS_OPTIONS_HOMEPAGE_EDIT_LABEL" desc="The label for the edit text field that allows the user to change the URL that is opened when they tap on the homepage button in the omnibox.">
Open this page
</message>
+ <message name="IDS_OPTIONS_HOMEPAGE_CHROME_HOMEPAGE" desc="The option that allows user to set Chrome's new tab page as the homepage." >
+ Chrome’s homepage
+ </message>
<!-- Notifications preferences -->
<message name="IDS_PREFS_NOTIFICATIONS" desc="Title for Notification preferences.">
@@ -720,8 +625,8 @@ CHAR-LIMIT guidelines:
Search and site suggestions disabled
</message>
- <!-- Themes preferences -->
- <message name="IDS_PREFS_THEMES" desc="Title for the Themes preferences. [CHAR-LIMIT=32]">
+ <!-- Themes settings -->
+ <message name="IDS_THEME_SETTINGS" desc="Title for the Theme settings. [CHAR-LIMIT=32]">
Themes
</message>
<message name="IDS_THEMES_SYSTEM_DEFAULT_TITLE" desc="Title for the System Default option. [CHAR-LIMIT=32]">
@@ -754,15 +659,20 @@ CHAR-LIMIT guidelines:
Sends URLs of some pages you visit to Google, when your security is at risk
</message>
<message name="IDS_CONTEXTUAL_SEARCH_TITLE" desc="Name for the Contextual Search feature, which allows users to search for a term in a web page by tapping on it.">
- Tap to Search
+ Touch to Search
+ </message>
+ <message name="IDS_CONTEXTUAL_SEARCH_TAP_DESCRIPTION" desc="Description for Contextual Search preference">
+ Learn about topics on websites without leaving the page. Touch to Search sends a word and its surrounding context to Google Search, returning definitions, pictures, search results, and other details.
+
+Tap any word to search. To refine your search, touch &amp; hold to select more or fewer words. To edit your search, open the panel, tap the icon to open in a new tab, and make your changes in the search box.
</message>
<message name="IDS_CONTEXTUAL_SEARCH_DESCRIPTION" desc="Description for Contextual Search preference">
- Learn about topics on websites without leaving the page. Tap to Search sends a word and its surrounding context to Google Search, returning definitions, pictures, search results, and other details.
+ Learn about topics on websites without leaving the page. Touch to Search sends a word and its surrounding context to Google Search, returning definitions, pictures, search results, and other details.
-To adjust your search term, long press to select. To refine your search, slide the panel all the way up and tap the search box.
+Touch &amp; hold any word to search. To refine your search, select more or fewer words. To edit your search, open the panel, tap the icon to open in a new tab, and make your changes in the search box.
</message>
- <message name="IDS_CONTEXTUAL_SEARCH_SHORT_DESCRIPTION" desc="A promo message shown to users who have Tap to Search enabled to explain the new behavior and provide an option to opt out">
- Tap to Search sends the selected word and the current page as context to Google Search. You can turn it off in <ph name="BEGIN_LINK">&lt;link&gt;</ph>Settings<ph name="END_LINK">&lt;/link&gt;</ph>.
+ <message name="IDS_CONTEXTUAL_SEARCH_SHORT_DESCRIPTION" desc="A promo message shown to users with Touch to Search to explain the new behavior and provide an option to opt in or out">
+ Touch to Search sends the selected word and the current page as context to Google Search. You can turn it off in <ph name="BEGIN_LINK">&lt;link&gt;</ph>Settings<ph name="END_LINK">&lt;/link&gt;</ph>.
</message>
<message name="IDS_CONTEXTUAL_SEARCH_ALLOW_BUTTON" desc="A button to confirm and dismiss opt out promo">
Allow
@@ -922,6 +832,9 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_ADS_PERMISSION_TITLE" desc="Title for the ads permission [CHAR-LIMIT=32]">
Ads
</message>
+ <message name="IDS_AR_PERMISSION_TITLE" desc="Title of the permission to use Augmented Reality [CHAR-LIMIT=32]">
+ Augmented reality
+ </message>
<message name="IDS_COOKIES_TITLE" desc="Title for the Cookies settings screen [CHAR-LIMIT=32]">
Cookies
</message>
@@ -955,6 +868,9 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_CLIPBOARD_PERMISSION_TITLE" desc="Title of the permission to read from clipboard [CHAR-LIMIT=32]">
Clipboard
</message>
+ <message name="IDS_VR_PERMISSION_TITLE" desc="Title of the permission to use Virtual Reality [CHAR-LIMIT=32]">
+ Virtual reality
+ </message>
<message name="IDS_ENABLE_NOTIFICATIONS_VIBRATE_TITLE" desc="Title for the preference to enable vibration for notifications">
Vibrate
</message>
@@ -1000,12 +916,18 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_COOKIES_BLOCK" desc="The description for the block Cookies for website dialog.">
Block cookies for a specific site.
</message>
+ <message name="IDS_WEBSITE_SETTINGS_THIRD_PARTY_COOKIES_EXCEPTION_LABEL" desc="The label for site exceptions that affect third party cookies.">
+ All cookies, on this site only
+ </message>
<message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_SOUND_ALLOW" desc="The description for the allow sound for website dialog.">
Allow sound for a specific site.
</message>
<message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_SOUND_BLOCK" desc="The description for the mute sound for website dialog.">
Mute sound for a specific site.
</message>
+ <message name="IDS_WEBSITE_SETTINGS_COOKIE_INFO" desc="Text describing cookie and third-party cookie settings.">
+ Cookies are files created by websites you visit. Sites use them to remember your preferences. Third-party cookies are created by other sites. These sites own some of the content, like ads or images, that you see on the webpage you visit.
+ </message>
<message name="IDS_WEBSITE_SETTINGS_ADD_SITE_SITE_URL" desc="The label for the input field where the user can type a website URL.">
Site URL
</message>
@@ -1048,18 +970,37 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_WEBSITE_SETTINGS_EXCEPTIONS_GROUP_HEADING" desc="The heading for a list of websites that have been granted an exception to access a particular permission, e.g. to access the user's location.">
Exceptions
</message>
- <message name="IDS_ACCESSIBILITY_EXPANDED_GROUP" desc="The accessibility text to read when the selected widget is expanded.">
- Expanded - click to collapse.
- </message>
- <message name="IDS_ACCESSIBILITY_COLLAPSED_GROUP" desc="The accessibility text to read when the selected widget is collapsed.">
- Collapsed - click to expand.
- </message>
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_ALLOWED_RECOMMENDED" desc="Summary text explaining that a permission is allowed, which is the recommended setting.">
Allowed (recommended)
</message>
+
+ <!-- Cookie settings strings. -->
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_ALLOWED" desc="Summary text explaining that sites are allowed to use cookies and that it is the recommended setting.">
Allow sites to save and read cookie data (recommended)
</message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_ALLOW_TITLE" desc="Text used to explain the allow cookies option in settings">
+ Allow cookies
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_BLOCK_THIRD_PARTY_INCOGNITO_TITLE" desc="Text used to explain the block third-party cookies in incognito option in settings">
+ Block third-party cookies in Incognito
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_BLOCK_THIRD_PARTY_TITLE" desc="Text used to explain the block third-party cookies option in settings">
+ Block third-party cookies
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_BLOCK_TITLE" desc="Text used to explain the block cookies option in settings">
+ Block all cookies (not recommended)
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_ALLOW_ADDITION" desc="Additional text used to explain the allow cookies option in settings">
+ Sites will work normally
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_BLOCK_THIRD_PARTY_ADDITION" desc="Additional text used to explain the block third-party cookies option in settings">
+ Features on some sites may break
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_COOKIE_BLOCK_ADDITION" desc="Additional text used to explain the block cookies option in settings">
+ Features on many sites may break
+ </message>
+
+
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_JAVASCRIPT_ALLOWED" desc="Summary text explaining that sites are allowed to run Javascript and that it is the recommended setting.">
Allow sites to run JavaScript (recommended)
</message>
@@ -1087,12 +1028,24 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_PROTECTED_CONTENT_BLOCKED" desc="Summary text explaining that sites are blocked from playing protected content.">
Block sites from playing protected content
</message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_AR_ASK" desc="Summary text explaining that sites need to ask for permission before using AR and that it is the recommended setting.">
+ Ask before allowing sites to create a 3D map of your surroundings or track camera position (recommended)
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_AR_BLOCKED" desc="Summary text explaining that sites are blocked from using AR.">
+ Block sites from creating a 3D map of your surroundings or tracking camera position
+ </message>
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_NFC_ASK" desc="Summary text explaining that sites need to ask for permission before using NFC and that it is the recommended setting.">
Ask before allowing sites to send and receive info when you tap NFC devices (recommended)
</message>
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_NFC_BLOCKED" desc="Summary text explaining that sites are blocked from using NFC.">
Block sites from sending and receiving info when you tap NFC devices
</message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_VR_ASK" desc="Summary text explaining that sites need to ask for permission before using VR and that it is the recommended setting.">
+ Ask before allowing sites to use your virtual reality device and data (recommended)
+ </message>
+ <message name="IDS_WEBSITE_SETTINGS_CATEGORY_VR_BLOCKED" desc="Summary text explaining that sites are blocked from using VR.">
+ Block sites from using your virtual reality device and data
+ </message>
<message name="IDS_WEBSITE_SETTINGS_CATEGORY_SENSORS_ALLOWED" desc="Summary text explaining that sites are allowed to use device's sensors and that it is the recommended setting.">
Allow sites to access sensors (recommended)
</message>
@@ -1192,8 +1145,8 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_WEBSITE_NOTIFICATION_SETTINGS" desc="Accessibility string for the notification settings">
Open notification settings
</message>
- <message name="IDS_WEBSITE_SETTINGS_EMBEDDED_IN" desc="String used to indicate the embedder origin of a site">
- Embedded in <ph name="WEBSITE_URL">%1$s<ex>google.com</ex></ph>
+ <message name="IDS_WEBSITE_SETTINGS_EMBEDDED_ON" desc="String used to indicate the embedder origin of a site">
+ Embedded on <ph name="WEBSITE_URL">%1$s<ex>google.com</ex></ph>
</message>
<!-- Single site settings -->
@@ -1201,14 +1154,14 @@ Your Google account may have other forms of browsing history like searches and a
Files saved by websites appear here
</message>
- <!-- Languages preferences -->
- <message name="IDS_PREFS_LANGUAGES" desc="Title for the Languages settings screen that allows users to manage their languages preferences. [CHAR-LIMIT=32]">
+ <!-- Language Settings -->
+ <message name="IDS_LANGUAGE_SETTINGS" desc="Title for the Languages settings screen that allows users to manage their languages preferences. [CHAR-LIMIT=32]">
Languages
</message>
- <message name="IDS_PREFS_ADD_LANGUAGE" desc="Title for the screen that allows users to add languages to their preferred language list. [CHAR-LIMIT=32]">
+ <message name="IDS_ADD_LANGUAGE" desc="Title for the screen that allows users to add languages to their preferred language list. [CHAR-LIMIT=32]">
Add language
</message>
- <message name="IDS_LANGUAGES_LIST_PREFS_DESCRIPTION" desc="Description on the Languages settings screen. Appears above a list of one or more languages that the user selects, to tell Chrome which languages they prefer to use to read website content.">
+ <message name="IDS_LANGUAGES_LIST_DESCRIPTION" desc="Description on the Languages settings screen. Appears above a list of one or more languages that the user selects, to tell Chrome which languages they prefer to use to read website content.">
Websites will show text in your preferred language, when possible.
</message>
<message name="IDS_LANGUAGES_OFFER_TRANSLATE_SWITCH" desc="Appears next to the 'offer to translate' switch that controls whether or not Chrome will display the Google Translate UI on web pages that are not in the user's preferred language(s).">
@@ -1585,8 +1538,17 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_OPEN_SOURCE_LICENSE_URL" desc="URL for open source license" translateable="false">
chrome://credits
</message>
- <message name="IDS_TERMS_OF_SERVICE_TITLE" desc="Title for terms of service">
- Chrome Terms of Service
+ <message name="IDS_GOOGLE_TERMS_OF_SERVICE_TITLE" desc="Title for Google terms of service">
+ Google Terms of Service
+ </message>
+ <message name="IDS_GOOGLE_TERMS_OF_SERVICE_URL" desc="URL for Google terms of service" translateable="false">
+ https://policies.google.com/terms
+ </message>
+ <message name="IDS_CHROME_ADDITIONAL_TERMS_OF_SERVICE_TITLE" desc="Title for Chrome and Chrome OS addtional terms of service">
+ Chrome &amp; Chrome OS Additional Terms of Service
+ </message>
+ <message name="IDS_CHROME_ADDITIONAL_TERMS_OF_SERVICE_URL" desc="URL for Chrome and Chrome OS additional terms of service" translateable="false">
+ https://www.google.com/chrome/terms/
</message>
<message name="IDS_PRIVACY_NOTICE_TITLE" desc="Title for the Chrome privacy notice">
Chrome Privacy Notice
@@ -1594,24 +1556,10 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_CHROME_PRIVACY_NOTICE_URL" desc="URL for the Chrome privacy notice" translateable="false">
https://www.google.com/intl/$LOCALE/chrome/browser/privacy/
</message>
- <message name="IDS_CHROME_TERMS_OF_SERVICE_URL" desc="URL for Google Chrome Terms of Service" translateable="false">
- https://www.google.com/intl/$LOCALE/chrome/browser/privacy/eula_text.html
- </message>
<message name="IDS_FAMILY_LINK_PRIVACY_POLICY_URL" desc="URL for the Family Link privacy policy" translateable="false">
https://families.google.com/intl/$LOCALE/familylink/privacy/child-policy/
</message>
- <!-- JavaScript dialogs -->
- <message name="IDS_LEAVE" desc="Dialog button to leave the current page and navigate to a new page. [CHAR-LIMIT=20]">
- Leave
- </message>
- <message name="IDS_RELOAD" desc="Dialog button to reload the current page. [CHAR-LIMIT=20]">
- Reload
- </message>
- <message name="IDS_SUPPRESS_JS_MODAL_DIALOGS" desc="Checkbox allowing users to forgo additional prompts from a web page.">
- Prevent this page from creating additional dialogs
- </message>
-
<!-- Certificate viewer -->
<message name="IDS_CERTTITLE" desc="Dialog box title for viewing security certificates. [CHAR-LIMIT=32]">
Certificate viewer
@@ -1675,6 +1623,12 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_SIGN_IN_SYNC" desc="Sync preference title in signed-in prefs and prefix for notification related to sync [CHAR-LIMIT=32]">
Sync
</message>
+ <message name="IDS_SEARCH_AND_BROWSE_CATEGORY" desc="Category to show the search and browse improvement toggle. [CHAR-LIMT=32]">
+ Search and browse
+ </message>
+ <message name="IDS_SYNCING_CATEGORY" desc="Category to separate search and browse section with sync related data types. [CHAR-LIMT=32]">
+ Syncing
+ </message>
<message name="IDS_SYNC_EVERYTHING_PREF" desc="Title for preference which enables sync'ing of all data types. [CHAR-LIMT=32]">
Sync everything
</message>
@@ -2085,18 +2039,6 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
</message>
<!-- Runtime permission strings -->
- <message name="IDS_INFOBAR_MISSING_CAMERA_PERMISSION_TEXT" desc="Text shown in an infobar when a website has requested access to the camera capabilities, but Chrome is missing the Android camera permission.">
- Chrome needs permission to access your camera for this site.
- </message>
- <message name="IDS_INFOBAR_MISSING_MICROPHONE_PERMISSION_TEXT" desc="Text shown in an infobar when a website has requested access to the microphone capabilities, but Chrome is missing the Android microphone permission.">
- Chrome needs permission to access your microphone for this site.
- </message>
- <message name="IDS_INFOBAR_MISSING_MICROPHONE_CAMERA_PERMISSIONS_TEXT" desc="Text shown in an infobar when a website has requested access to the microphone and camera capabilities, but Chrome is missing the Android microphone and camera permissions.">
- Chrome needs permission to access your camera and microphone for this site.
- </message>
- <message name="IDS_INFOBAR_MISSING_LOCATION_PERMISSION_TEXT" desc="Text shown in an infobar when a website has requested access to the location capabilities, but Chrome is missing the Android location permission.">
- Chrome needs access to your location to share your location with this site.
- </message>
<message name="IDS_MISSING_STORAGE_PERMISSION_DOWNLOAD_EDUCATION_TEXT" desc="Text shown educating the user that Chrome is missing the Android storage permission, which is required to download files.">
Chrome needs storage access to download files.
</message>
@@ -2150,6 +2092,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_CONTEXTMENU_LOAD_ORIGINAL_IMAGE" desc="Context sensitive menu item for Lite mode low fidelity placeholder images that loads the original version in place. [CHAR-LIMIT=30]">
Load image
</message>
+ <message name="IDS_CONTEXTMENU_COPY_IMAGE" desc="Context sensitive menu item for copying the selected image to the system clipboard. [CHAR-LIMIT=30]">
+ Copy image
+ </message>
<message name="IDS_CONTEXTMENU_SEARCH_WITH_GOOGLE_LENS" desc="Context sensitive menu item for deep linking into google lens. [CHAR-LIMIT=30]">
Search with Google Lens <ph name="BEGIN_NEW">&lt;new&gt;</ph>New<ph name="END_NEW">&lt;/new&gt;</ph>
</message>
@@ -2174,6 +2119,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_CONTEXTMENU_OPEN_IN_EPHEMERAL_TAB" desc="Context-sensitive menu item to open a quick preview of the selected linked page. Note that 'preview' is a verb, not a noun. We're also labeling it *New* to draw attention to it when first released. The selected link will open in an overlay panel on top of the current tab which will go away easily too. [CHAR-LIMIT=30]">
Preview page <ph name="BEGIN_NEW">&lt;new&gt;</ph>New<ph name="END_NEW">&lt;/new&gt;</ph>
</message>
+ <message name="IDS_CONTEXTMENU_PERFORMANCE_INFO_FAST" desc="This string is shown in the context sensitive menu for links and is shown underneath the link URL. It indicates to the user that the link's target website should load quickly. [CHAR-LIMIT=30]">
+ Fast site
+ </message>
<!-- Swipe refresh -->
<message name="IDS_ACCESSIBILITY_SWIPE_REFRESH" desc="Content description for the swipe refresh action.">
@@ -2208,14 +2156,6 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
A
</message>
- <!-- Android NFC Beam strings -->
- <message name="IDS_NFC_BEAM_ERROR_OVERLAY_ACTIVE" desc="Android Beam error - a tab is not in the foreground [CHAR-LIMIT=40]">
- Select a tab to beam
- </message>
- <message name="IDS_NFC_BEAM_ERROR_BAD_URL" desc="Android Beam error - the current tab has an invalid url [CHAR-LIMIT=40]">
- Can’t beam current tab
- </message>
-
<!-- Add to Home screen strings -->
<message name="IDS_MENU_ADD_TO_HOMESCREEN" desc="Menu item for adding a shortcut to the Home screen (default title). [CHAR-LIMIT=27]">
Add to Home screen
@@ -2252,6 +2192,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_PAGE_INFO_SITE_SETTINGS_BUTTON" desc="Text in the button that opens a website's Site Settings from the Page Info dialog.">
Site settings
</message>
+ <message name="IDS_PAGE_INFO_PERMISSIONS_TITLE" desc="Label used in the Page Info dialog above the permissions list.">
+ Permissions
+ </message>
<message name="IDS_PAGE_INFO_INSTANT_APP_BUTTON" desc="Text in the button that opens an Android Instant app that is associated with the website's URL.">
Open Instant App
</message>
@@ -2268,11 +2211,14 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Blocked
</message>
<message name="IDS_PAGE_INFO_ANDROID_PERMISSION_BLOCKED" desc="The label used in the Page Info dialog to indicate a permission has been blocked within Android settings">
- Turned off in Android Settings
+ Turned off in Android settings
</message>
<message name="IDS_PAGE_INFO_ANDROID_LOCATION_BLOCKED" desc="The label used in the Page Info dialog to indicate that location has been been disabled for the device in Android settings">
Turned off for this device
</message>
+ <message name="IDS_PAGE_INFO_ANDROID_NFC_UNSUPPORTED" desc="The label used in the Page Info dialog to indicate NFC is not supported by this device">
+ This device can't read NFC
+ </message>
<message name="IDS_PAGE_INFO_CONNECTION_OFFLINE" desc="Message to display in the page info bubble when viewing and offline page.">
You are viewing an offline copy of this page from <ph name="CREATION_TIME">%1$s<ex>Feb 9, 2016</ex></ph>
</message>
@@ -2612,17 +2558,17 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_FRE_ACTIVITY_LABEL" desc="Label for first run dialog in Android Recents.">
Chrome First Run Experience
</message>
- <message name="IDS_FRE_TOS_AND_PRIVACY" desc="Message explaining that use of Chrome is governed by Chrome's terms of service and privacy notice.">
- By using this application, you agree to Chrome’s <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph> and <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Privacy Notice<ph name="END_LINK2">&lt;/LINK2&gt;</ph>.
+ <message name="IDS_FRE_TOS" desc="Message explaining that use of Chrome is governed by terms of service.">
+ By using Chrome, you agree to the <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Google Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph>, and the <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Google Chrome and Chrome OS Additional Terms of Service<ph name="END_LINK2">&lt;/LINK2&gt;</ph>.
</message>
- <message name="IDS_FRE_TOS_AND_PRIVACY_CHILD_ACCOUNT" desc="Message explaining that use of Chrome is governed by Chrome's terms of service and privacy notice, and Family Link's privacy notice for children.">
- By using this application, you agree to Chrome’s <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph> and <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Privacy Notice<ph name="END_LINK2">&lt;/LINK2&gt;</ph>, and the <ph name="BEGIN_LINK3">&lt;LINK3&gt;</ph>Privacy Notice for Google Accounts Managed with Family Link<ph name="END_LINK3">&lt;/LINK3&gt;</ph>.
+ <message name="IDS_FRE_TOS_AND_PRIVACY_CHILD_ACCOUNT" desc="Message explaining that use of Chrome is governed by Chrome's terms of service, and Family Link's privacy notice for children.">
+ By using Chrome, you agree to the <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Google Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph>, and the <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Google Chrome and Chrome OS Additional Terms of Service<ph name="END_LINK2">&lt;/LINK2&gt;</ph>. The <ph name="BEGIN_LINK3">&lt;LINK3&gt;</ph>Privacy Notice for Google Accounts Managed with Family Link<ph name="END_LINK3">&lt;/LINK3&gt;</ph> also applies.
</message>
- <message name="IDS_LIGHTWEIGHT_FRE_ASSOCIATED_APP_TOS_AND_PRIVACY" desc="Message explaining that use of Chrome is governed by Chrome's terms of service and privacy notice.">
- <ph name="APP_NAME">%1$s<ex>Google Maps</ex></ph> will open in Chrome. By continuing, you agree to Chrome’s <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph> and <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Privacy Notice<ph name="END_LINK2">&lt;/LINK2&gt;</ph>.
+ <message name="IDS_LIGHTWEIGHT_FRE_ASSOCIATED_APP_TOS" desc="Message explaining that use of Chrome is governed by Chrome's terms of service.">
+ <ph name="APP_NAME">%1$s<ex>Google Maps</ex></ph> will open in Chrome. By continuing, you agree to the <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Google Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph>, and the <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Google Chrome and Chrome OS Additional Terms of Service<ph name="END_LINK2">&lt;/LINK2&gt;</ph>.
</message>
- <message name="IDS_LIGHTWEIGHT_FRE_ASSOCIATED_APP_TOS_AND_PRIVACY_CHILD_ACCOUNT" desc="Message explaining that use of Chrome is governed by Chrome's terms of service and privacy notice, and Family Link's privacy notice for children.">
- <ph name="APP_NAME">%1$s<ex>Google Maps</ex></ph> will open in Chrome. By continuing, you agree to Chrome's <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph> and <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Privacy Notice<ph name="END_LINK2">&lt;/LINK2&gt;</ph>, and the <ph name="BEGIN_LINK3">&lt;LINK3&gt;</ph>Privacy Notice for Google Accounts Managed with Family Link<ph name="END_LINK3">&lt;/LINK3&gt;</ph>.
+ <message name="IDS_LIGHTWEIGHT_FRE_ASSOCIATED_APP_TOS_AND_PRIVACY_CHILD_ACCOUNT" desc="Message explaining that use of Chrome is governed by Chrome's terms of service, and Family Link's privacy notice for children.">
+ <ph name="APP_NAME">%1$s<ex>Google Maps</ex></ph> will open in Chrome. By continuing, you agree to the <ph name="BEGIN_LINK1">&lt;LINK1&gt;</ph>Google Terms of Service<ph name="END_LINK1">&lt;/LINK1&gt;</ph>, and the <ph name="BEGIN_LINK2">&lt;LINK2&gt;</ph>Google Chrome and Chrome OS Additional Terms of Service<ph name="END_LINK2">&lt;/LINK2&gt;</ph>. The <ph name="BEGIN_LINK3">&lt;LINK3&gt;</ph>Privacy Notice for Google Accounts Managed with Family Link<ph name="END_LINK3">&lt;/LINK3&gt;</ph> also applies.
</message>
<message name="IDS_FRE_SEND_REPORT_CHECK" desc="Text for asking the user to allow sending stats and crash reports">
Help make Chrome better by sending usage statistics and crash reports to Google.
@@ -2808,15 +2754,6 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_NTP_EXPLORE_SITES_MORE" desc="Text on a button leading to a complete view of all categories for all popular websites">
More categories
</message>
- <message name="IDS_EXPLORE_SITES_DEFAULT_CATEGORY_NEWS" desc="The caption for a button that when clicked opens a UI in this tab that shows a list of websites with content related to news. [CHAR-LIMIT=12]">
- News
- </message>
- <message name="IDS_EXPLORE_SITES_DEFAULT_CATEGORY_SPORTS" desc="The caption for a button that when clicked opens a UI in this tab that shows a list of websites with content related to sports. For example, soccer, cricket, football, running [CHAR-LIMIT=12]">
- Sports
- </message>
- <message name="IDS_EXPLORE_SITES_DEFAULT_CATEGORY_SHOPPING" desc="The caption for a button that when clicked opens a UI in this tab that shows a list of websites with content related to shopping. [CHAR-LIMIT=12]">
- Shopping
- </message>
<message name="IDS_EXPLORE_SITES_LOADING_FROM_NET" desc="Caption for an indeterminate loading spinner indicating that we are loading the data from the internet">
Finding the best from the web…
</message>
@@ -2832,9 +2769,6 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_EXPLORE_SITES_LOADING_ERROR_NEXT_STEPS_CHECK_CONNECTION" desc="Text on an error screen indicating that checking network connection can fix this error.">
Checking your internet connection
</message>
- <message name="IDS_EXPLORE_SITES_TOP_SITES_TILE" desc="A label for a button that when clicked takes the user to a tab that contains categorized links to websites that are popular in their country. [CHAR_LIMIT=12]">
- Top sites
- </message>
<message name="IDS_EXPLORE_SITES_IPH" desc="An in-product-help message for the explore sites feature on Android. The message encourages users to open a tab that contains categorized links to websites that are popular in their country.">
See popular websites
</message>
@@ -2924,6 +2858,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_MENU_FIND_IN_PAGE" desc="Menu item allowing users to find text within the current page. [CHAR-LIMIT=27]">
Find in page
</message>
+ <message name="IDS_MENU_PAINT_PREVIEW_SHOW" desc="Menu item allowing users to capture and show a paint preview of a page. [CHAR-LIMIT=27]" translateable="false">
+ Show Paint Preview
+ </message>
<message name="IDS_MENU_REQUEST_DESKTOP_SITE" desc="Menu item in Chrome's overflow/options menu. By default, when a user navigates to a web page, Chrome shows the mobile site, that is, the version of the site designed for mobile phones. If this menu item is selected, however, Chrome will try to load the 'desktop' site instead, i.e. the site designed for desktop computers or laptop computers, which have larger screens. [CHAR-LIMIT=24]">
Desktop site
</message>
@@ -2936,7 +2873,7 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_MENU_READER_MODE_PREFS" desc="Menu item to show reader mode preferences pane, which allows users to change the appearance (font size, theme, etc.) of the page. [CHAR-LIMIT=27]">
Appearance
</message>
- <message name="IDS_MENU_PREFERENCES" desc="Menu item for opening browser preferences. [CHAR-LIMIT=27]">
+ <message name="IDS_MENU_SETTINGS" desc="Menu item for opening browser settings. [CHAR-LIMIT=27]">
Settings
</message>
<message name="IDS_MENU_CLOSE_ALL_TABS" desc="Menu item for closing all open tabs. [CHAR-LIMIT=27]">
@@ -3016,7 +2953,7 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Search your bookmarks
</message>
<message name="IDS_BOOKMARK_NO_RESULT" desc="Text explaining that no bookmarks are found to match a search query">
- No bookmarks found
+ Can’t find that bookmark. Check your spelling or add a new bookmark.
</message>
<message name="IDS_EDIT_BOOKMARK" desc='The string prompting the user to edit the content of a bookmark. [CHAR-LIMIT=30]'>
Edit bookmark
@@ -3075,6 +3012,14 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
See downloads
</message>
+ <!-- Offline indicator v2 -->
+ <message name="IDS_OFFLINE_INDICATOR_V2_OFFLINE_TEXT" desc="Text to be displayed in the status indicator above the toolbar that lets the users know they are offline.">
+ No internet connection
+ </message>
+ <message name="IDS_OFFLINE_INDICATOR_V2_BACK_ONLINE_TEXT" desc="Text to be displayed in the status indicator above the toolbar when the device goes back online.">
+ Back online
+ </message>
+
<!-- Find in page -->
<message name="IDS_HINT_FIND_IN_PAGE" desc="Hint text to show for the find in page search field when the search field is empty.">
Find in page
@@ -3128,15 +3073,7 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
</message>
<!-- Accessibility -->
- <message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_FORWARD" desc="Content description for the forward navigation button.">
- Go forward
- </message>
- <message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_BACK" desc="Content description for the backard navigation button.">
- Go back
- </message>
- <message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_MENU" desc="Content description for the settings menu button.">
- More options
- </message>
+
<message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_MENU_UPDATE" desc="Content description for the menu button when it is covered by the update icon that is displayed when a newer version of Chrome is available.">
Update available. More options
</message>
@@ -3149,21 +3086,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_SITE_INFO" desc="Content description for the page icon that gives more site information when clicked. The icon can be a magnifier for search result pages, or other icons representing the page state.">
Site information
</message>
- <message name="IDS_ACCESSIBILITY_SECURITY_BTN_WARN" desc="Content description for the security icon for pages with insecure passive content. The content description also includes the call to action for opening the page info bubble (Site information).">
- Your connection to this site is not secure. Site information
- </message>
- <message name="IDS_ACCESSIBILITY_SECURITY_BTN_SECURE" desc="Content description for the security icon for pages with a valid certificate. The content description also includes the call to action for opening the page info bubble (Site information).">
- Connection is secure. Site information
- </message>
- <message name="IDS_ACCESSIBILITY_SECURITY_BTN_DANGEROUS" desc="Content description for the security icon for dangerous pages. The content description also includes the call to action for opening the page info bubble (Site information).">
- This page is dangerous. Site information
- </message>
<message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_MIC" desc="Content description for the voice search button.">
Start voice search
</message>
- <message name="IDS_ACCESSIBILITY_TOOLBAR_BTN_DELETE_URL" desc="Content description for the clear text input button.">
- Clear input
- </message>
<message name="IDS_ACCESSIBILITY_NEW_TAB_PAGE" desc="Accessibility text to read aloud when the user focuses the new tab view.">
New tab
</message>
@@ -3236,18 +3161,8 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_ACCESSIBILITY_OMNIBOX_BTN_REFINE" desc="Content description for the omnibox refine button.">
Refine
</message>
- <message name="IDS_ACCESSIBILITY_CANCEL_SELECTION" desc="Content description for the cancel selection button that deselects the selected items in a selectable list view.">
- Cancel selection
- </message>
- <message name="IDS_ACCESSIBILITY_LIST_MENU_BUTTON" desc="Content description for the button that shows option menu for a list item.">
- <ph name="NAME_OF_LIST_ITEM">%1$s<ex>Movie Title</ex></ph> Options
- </message>
- <message name="IDS_ACCESSIBILITY_TOOLBAR_SCREEN_POSITION" desc="Accessibility announcement to inform users about a toolbar's location.">
- <ph name="ITEM_COUNT">%1$s<ex>3</ex></ph> selected. Options available near top of the screen
- </message>
- <message name="IDS_ACCESSIBILITY_TOOLBAR_MULTI_SELECT" desc="Accessibility announcement to inform users about more items selected.">
- <ph name="ITEM_COUNT">%1$s<ex>3</ex></ph> selected
- </message>
+
+
<message name="IDS_ACCESSIBILITY_SHARE_SELECTED_ITEMS" desc="Content description for the button to share selected items. [ICU Syntax]">
{NUM_SELECTED, plural,
=1 {Share 1 selected item}
@@ -3273,14 +3188,6 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Tabs
</message>
- <message name="IDS_SELECTED_ITEMS" desc="Content description for a number indicating how many items are selected. [ICU Syntax]">
- {NUM_SELECTED, plural,
- =1 {1 selected}
- other {# selected}}
- </message>
- <message name="IDS_SELECT_ITEMS" desc="Label shown on toolbar asking user to select items from the list.">
- Select items
- </message>
<message name="IDS_MEDIA_NOTIFICATION_LINK_TEXT" desc="Url of the current tab. The notification will display this text for the user to identify the tab to return to.">
Touch to return to <ph name="URL_OF_THE_CURRENT_TAB">%1$s<ex>https://apprtc.appspot.com</ex></ph>
</message>
@@ -3553,6 +3460,21 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_ACCESSIBILITY_PLAY_VIDEO" desc="The accessibility string for the play video button.">
Play video
</message>
+ <message name="IDS_ACCESSIBILITY_PAUSE_VIDEO" desc="The accessibility string for the pause video button.">
+ Pause video
+ </message>
+ <message name="IDS_ACCESSIBILITY_MUTE_VIDEO" desc="The accessibility string for the mute video button.">
+ Mute video
+ </message>
+ <message name="IDS_ACCESSIBILITY_UNMUTE_VIDEO" desc="The accessibility string for the unmute video button.">
+ Unmute video
+ </message>
+ <message name="IDS_ACCESSIBILITY_VIDEO_PLAYER" desc="The accessibility string for the video player.">
+ Video player
+ </message>
+ <message name="IDS_ACCESSIBILITY_PLAYBACK_TIME" desc="The accessibility string for how much time has elapsed while viewing the video and how long the video is in total.">
+ Elapsed time <ph name="ELAPSED_TIME">%1$s<ex>0:01</ex></ph> of <ph name="TOTAL_TIME">%2$s<ex>0:45</ex></ph>.
+ </message>
<!-- Special locale UI strings -->
<message name="IDS_SEARCH_WITH_SOGOU" desc="Text telling the user that the search engine will be switched to Sogou.">
@@ -3712,14 +3634,14 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
Augmented Reality
</message>
<message name="IDS_AR_IMMERSIVE_MODE_CONSENT_TITLE" desc="Title for dialog shown when a site requests consent for starting an augmented reality session.">
- Start Augmented Reality session?
+ Enter AR from <ph name="DOMAIN">%s<ex>example.com</ex></ph>?
</message>
<message name="IDS_AR_IMMERSIVE_MODE_CONSENT_MESSAGE" desc="Message for dialog shown when a site requests consent for starting an augmented reality session.">
- For the duration of this session, the site will be able to:
+ While you're in AR, this site may be able to:
• create a 3D map of your environment
• track camera motion
-The site does NOT gain access to the camera. The camera images are only visible to you.
+Only you can see what your camera is looking at. The site can't see your camera's images.
</message>
<message name="IDS_AR_IMMERSIVE_MODE_CONSENT_BUTTON" desc="Confirm button for dialog shown when a site requests consent for starting an augmented reality session.">
Enter AR
@@ -3873,6 +3795,14 @@ The site does NOT gain access to the camera. The camera images are only visible
Go to Chrome settings
</message>
+ <!-- Sharing Hub -->
+ <message name="IDS_SHARING_HUB_NO_DEVICES_AVAILABLE_TEXT" desc="Text to show when no device targets are available for sharing.">
+ To share this page to another device, turn on sync in Chrome settings on the other device
+ </message>
+ <message name="IDS_SHARING_HUB_SYNC_DISABLED_TEXT" desc="Text to show when sync is disabled on the current device.">
+ To share this page to another device, turn on sync in Chrome settings
+ </message>
+
<!-- ClickToCall -->
<message name="IDS_CLICK_TO_CALL_NOTIFICATION_TEXT" desc="Text displayed in a click to call notification to call on a number.">
Tap to make call
@@ -3965,6 +3895,9 @@ The site does NOT gain access to the camera. The camera images are only visible
<message name="IDS_PHOTO_PICKER_BROWSE" desc="The label for the Browse action in the Photo Picker (browsing for photos).">
Browse
</message>
+ <message name="IDS_PHOTO_PICKER_VIDEO_DURATION" desc="The label showing the duration time and current position of the video, as in: 0:01 / 0:10.">
+ <ph name="POSITION">%1$s<ex>0:01</ex></ph> / <ph name="DURATION">%2$s<ex>0:10</ex></ph>
+ </message>
<!-- Interventions -->
<message name="IDS_REDIRECT_BLOCKED_MESSAGE" desc="The message stating that a redirect (noun) was blocked on this page. This will be followed on a separate line with the address the user was being redirected to.">
@@ -3996,6 +3929,9 @@ The site does NOT gain access to the camera. The camera images are only visible
<message name="IDS_PREFS_AUTOFILL_ASSISTANT_SWITCH" desc="Title for the switch toggling whether Autofill Assistant is enabled. [CHAR-LIMIT=32]">
Assistant Triggered Checkout
</message>
+ <message name="IDS_PREFS_AUTOFILL_ASSISTANT_SUMMARY" desc="Description for the Autofill Assistant toggle.">
+ To help you complete tasks, Google will receive the URLs and contents of sites on which you use Assistant, as well as information you submit through Assistant
+ </message>
<!-- Usage Stats strings -->
<message name="IDS_USAGE_STATS_CONSENT_TITLE" desc="Title for activity authorizing Digital Wellbeing to access Chrome usage data">
Show your Chrome activity in Digital Wellbeing?
@@ -4079,6 +4015,67 @@ The site does NOT gain access to the camera. The camera images are only visible
Download
</message>
+ <!-- Sharing Hub -->
+ <message name="IDS_SHARING_MORE_ICON_LABEL" desc="Icon label for the More button in the sharing hub.">
+ More
+ </message>
+
+ <message name="IDS_SHARING_COPY_URL" desc="Label for the Copy URL button in the sharing hub.">
+ Copy link
+ </message>
+
+ <message name="IDS_SHARING_SCREENSHOT" desc="Label for Screenshot button in the sharing hub.">
+ Screenshot
+ </message>
+
+ <message name="IDS_LINK_COPIED" desc="Text shown in the toast notification when Copy Link is selected in the sharing hub.">
+ Link Copied
+ </message>
+
+ <message name="IDS_QR_CODE_CAMERA_FRAMING_RECT_DESCRIPTION" desc="Text under the framing rectangle in QR code camera preview.">
+ Position QR/barcode in this frame.
+ </message>
+
+ <message name="IDS_QR_CODE_PERMISSION_DESCRIPTION" desc="Text on QR code sharing tab indicating that permissions need to be given.">
+ Please enable your camera to scan a QR code
+ </message>
+
+ <message name="IDS_QR_CODE_OPEN_SETTINGS_DESCRIPTION" desc="Text on QR code sharing tab indicating that user needs to open settings to give camera permission.">
+ To scan a QR code, change your settings so that Chrome can use your camera
+ </message>
+
+ <message name="IDS_QR_CODE_PERMISSION_CONTINUE_LABEL" desc="Text on button on QR code sharing tab triggering camera permission dialog.">
+ Continue
+ </message>
+
+ <message name="IDS_QR_CODE_NO_CAMERA_ERROR" desc="Error text shown when no camera is found.">
+ To scan a QR code, use a device with a camera.
+ </message>
+
+ <message name="IDS_QR_CODE_DISABLED_CAMERA_ERROR" desc="Error text shown when the camera is disabled by the device policy manager.">
+ The organization that manages your device has turned off your camera.
+ </message>
+
+ <message name="IDS_QR_CODE_IN_USE_CAMERA_ERROR" desc="Error text shown when the camera is in use by other apps.">
+ Can't open your camera. Restart your device and try again.
+ </message>
+
+ <message name="IDS_QR_CODE_HARDWARE_CAMERA_ERROR" desc="Error text shown when the camera cannot start due to a hardware error.">
+ Can't open your camera. Something went wrong.
+ </message>
+
+ <message name="IDS_QR_CODE_OPEN_SETTINGS_LABEL" desc="Text on button on QR code sharing tab triggering Android settings.">
+ Open Settings
+ </message>
+
+ <message name="IDS_QR_CODE_NOT_A_URL_LABEL" desc="Text on toast on QR code scanning tab indicating that the QR Code does not correspond to a URL and can not be opened.">
+ This QR Code is not a URL: <ph name="QrCodeValue">%1$s<ex>QR Code Text</ex></ph>
+ </message>
+
+ <message name="IDS_QR_CODE_FILENAME_PREFIX" desc="File name prefix for downloaded qrcode that is followed by timestamp.">
+ chrome_qrcode_<ph name="CURRENT_TIMESTAMP_MS">%1$s<ex>1582667748515</ex></ph>
+ </message>
+
<!-- Chime DFM module strings -->
<message name="IDS_CHIME_MODULE_TITLE" desc="Text shown when the chime module is referenced in install start, success, failure UI (e.g. in IDS_MODULE_INSTALL_START_TEXT, which will expand to 'Installing Google Notifications Platform for Chrome…').">
Google Notifications Platform
@@ -4088,6 +4085,31 @@ The site does NOT gain access to the camera. The camera images are only visible
<message name="IDS_IMAGE_EDITOR_MODULE_TITLE" desc="Text shown when the image editor module is referenced in install start, success, failure UI (e.g. in IDS_MODULE_INSTALL_START_TEXT, which will expand to 'Installing Image Editor for Chrome…').">
Image Editor
</message>
+
+ <!-- NFC prompt -->
+ <message name="IDS_ANDROID_NFC_OFF_GLOBALLY" desc="The message to show when NFC has been turned off globally in Android. Contains a link to the settings menu to enable NFC.">
+ NFC is off for this device. Turn it on in <ph name="BEGIN_LINK">&lt;link&gt;</ph>Android Settings<ph name="END_LINK">&lt;/link&gt;</ph>.
+ </message>
+ <message name="IDS_ANDROID_NFC_UNSUPPORTED" desc="The message to show when NFC is not supported globally in Android">
+ This device can't read NFC
+ </message>
+
+ <!-- Paint Preview Demo -->
+ <message name="IDS_PAINT_PREVIEW_DEMO_CAPTURE_SUCCESS" desc="Toast message displayed when paint preview capture finishes successfully. Used in paint preview demo mode." translateable="false">
+ Paint Preview captured successfully.
+ </message>
+ <message name="IDS_PAINT_PREVIEW_DEMO_CAPTURE_FAILURE" desc="Toast message displayed when paint preview capture fails. Used in paint preview demo mode." translateable="false">
+ Failed to capture Paint Preview.
+ </message>
+ <message name="IDS_PAINT_PREVIEW_DEMO_PLAYBACK_START" desc="Toast message displayed when paint preview starts displaying. Used in paint preview demo mode." translateable="false">
+ Displaying Paint Preview. Press back to exit the Paint Preview demo.
+ </message>
+ <message name="IDS_PAINT_PREVIEW_DEMO_PLAYBACK_END" desc="Toast message displayed when the user exits paint preview demo. Used in paint preview demo mode." translateable="false">
+ Exited Paint Preview demo.
+ </message>
+ <message name="IDS_PAINT_PREVIEW_DEMO_PLAYBACK_FAILURE" desc="Toast message displayed when there is a failure in playing back a paint preview for the demo. Used in paint preview demo mode." translateable="false">
+ Paint Preview playback failed.
+ </message>
</messages>
</release>
</grit>
diff --git a/chromium/chrome/browser/ui/android/strings/xr_consent_ui_strings_java.grdp b/chromium/chrome/browser/ui/android/strings/xr_consent_ui_strings_java.grdp
index 700ce2694fd..5ff87217358 100644
--- a/chromium/chrome/browser/ui/android/strings/xr_consent_ui_strings_java.grdp
+++ b/chromium/chrome/browser/ui/android/strings/xr_consent_ui_strings_java.grdp
@@ -14,13 +14,14 @@ found in the LICENSE file.
<message name="IDS_XR_CONSENT_DIALOG_DESCRIPTION_DEFAULT" desc="This is the header for a bulleted list of potential concerns that we want to ensure the user is aware of before entering VR. This header and the appended items of the bulleted list make up the body of the user consent dialog displayed before a website may start a VR presentation.">
While you're in VR, this site may be able to learn about:
</message>
- <message name="IDS_XR_CONSENT_DIALOG_DESCRIPTION_PHYSICAL_FEATURES" desc="Item for the bulleted list of potential concerns in the consent dialog indicating that physical features may be exposed. Preceded with a newline and then two spaces to allow for being appended to the bulleted list at runtime.">
-'''
- - your physical features, such as height
+ <message name="IDS_XR_CONSENT_BULLET" desc="Unicode bullet for list items. Similar to IDS_LIST_BULLET from desktop generated_resources">
+ • <ph name="LIST_ITEM_TEXT">%s<ex>the layout of your room</ex></ph>
</message>
- <message name="IDS_XR_CONSENT_DIALOG_DESCRIPTION_FLOOR_PLAN" desc="Item for the bulleted list of potential concerns in the consent dialog indicating that phyiscal features may be exposed. Preceded with a newline and then two spaces to allow for being appended to the bulleted list at runtime.">
-'''
- - the layout of your room
+ <message name="IDS_XR_CONSENT_DIALOG_DESCRIPTION_PHYSICAL_FEATURES" desc="Item for the bulleted list of potential concerns in the consent dialog indicating that physical features may be exposed.">
+ your physical features, such as height
+ </message>
+ <message name="IDS_XR_CONSENT_DIALOG_DESCRIPTION_FLOOR_PLAN" desc="Item for the bulleted list of potential concerns in the consent dialog indicating that phyiscal features may be exposed.">
+ the layout of your room
</message>
<message name="IDS_XR_CONSENT_DIALOG_BUTTON_ALLOW_AND_ENTER_VR" desc="Text on the button of a user consent dialog which allows a website to start a VR presentation">
Enter VR
diff --git a/chromium/chrome/browser/ui/android/styles/BUILD.gn b/chromium/chrome/browser/ui/android/styles/BUILD.gn
deleted file mode 100644
index ab3ef484a7c..00000000000
--- a/chromium/chrome/browser/ui/android/styles/BUILD.gn
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/android/rules.gni")
-import("//ui/android/features.gni")
-
-android_library("java") {
- java_files =
- [ "java/src/org/chromium/chrome/browser/ui/styles/ChromeColors.java" ]
- deps = [
- ":java_resources",
- "//base:base_java",
- "//third_party/android_deps:android_support_v7_appcompat_java",
- "//third_party/android_deps:com_android_support_design_java",
-
- # TODO(crbug.com/1017190): Remove this workaround.
- "//ui/android:ui_java",
- ]
-}
-
-android_resources("java_resources") {
- custom_package = "org.chromium.chrome.browser.ui.styles"
- resource_dirs = [ "java/res" ]
- deps = [
- "//third_party/android_deps:com_android_support_design_java",
- "//ui/android:ui_java_resources",
- ]
-
- if (enable_android_night_mode) {
- resource_dirs += [ "java/res_night" ]
- }
-}
diff --git a/chromium/chrome/browser/ui/android/widget/BUILD.gn b/chromium/chrome/browser/ui/android/widget/BUILD.gn
deleted file mode 100644
index 311dac7cba3..00000000000
--- a/chromium/chrome/browser/ui/android/widget/BUILD.gn
+++ /dev/null
@@ -1,147 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/android/rules.gni")
-import("//ui/android/features.gni")
-
-android_library("java") {
- java_files = [
- "java/src/org/chromium/chrome/browser/ui/widget/AlwaysDismissedDialog.java",
- "java/src/org/chromium/chrome/browser/ui/widget/BoundedLinearLayout.java",
- "java/src/org/chromium/chrome/browser/ui/widget/ClipDrawableProgressBar.java",
- "java/src/org/chromium/chrome/browser/ui/widget/CompositeTouchDelegate.java",
- "java/src/org/chromium/chrome/browser/ui/widget/ContextMenuDialog.java",
- "java/src/org/chromium/chrome/browser/ui/widget/DualControlLayout.java",
- "java/src/org/chromium/chrome/browser/ui/widget/FadingShadow.java",
- "java/src/org/chromium/chrome/browser/ui/widget/FadingShadowView.java",
- "java/src/org/chromium/chrome/browser/ui/widget/FadingEdgeScrollView.java",
- "java/src/org/chromium/chrome/browser/ui/widget/LoadingView.java",
- "java/src/org/chromium/chrome/browser/ui/widget/PaddedFrameLayout.java",
- "java/src/org/chromium/chrome/browser/ui/widget/PromoDialog.java",
- "java/src/org/chromium/chrome/browser/ui/widget/PromoDialogLayout.java",
- "java/src/org/chromium/chrome/browser/ui/widget/MaterialProgressBar.java",
- "java/src/org/chromium/chrome/browser/ui/widget/MoreProgressButton.java",
- "java/src/org/chromium/chrome/browser/ui/widget/RadioButtonLayout.java",
- "java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescription.java",
- "java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayout.java",
- "java/src/org/chromium/chrome/browser/ui/widget/RoundedCornerImageView.java",
- "java/src/org/chromium/chrome/browser/ui/widget/RoundedIconGenerator.java",
- "java/src/org/chromium/chrome/browser/ui/widget/TintedDrawable.java",
- "java/src/org/chromium/chrome/browser/ui/widget/ViewResourceFrameLayout.java",
- "java/src/org/chromium/chrome/browser/ui/widget/WrappingLayout.java",
- "java/src/org/chromium/chrome/browser/ui/widget/animation/AnimatorProperties.java",
- "java/src/org/chromium/chrome/browser/ui/widget/animation/CancelAwareAnimatorListener.java",
- "java/src/org/chromium/chrome/browser/ui/widget/animation/FocusAnimator.java",
- "java/src/org/chromium/chrome/browser/ui/widget/animation/Interpolators.java",
- "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserver.java",
- "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserverAdapter.java",
- "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/HorizontalDisplayStyle.java",
- "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/UiConfig.java",
- "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/VerticalDisplayStyle.java",
- "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/ViewResizer.java",
- "java/src/org/chromium/chrome/browser/ui/widget/dragreorder/DragReorderableListAdapter.java",
- "java/src/org/chromium/chrome/browser/ui/widget/dragreorder/DragStateDelegate.java",
- "java/src/org/chromium/chrome/browser/ui/widget/highlight/PulseDrawable.java",
- "java/src/org/chromium/chrome/browser/ui/widget/highlight/PulseInterpolator.java",
- "java/src/org/chromium/chrome/browser/ui/widget/highlight/ViewHighlighter.java",
- "java/src/org/chromium/chrome/browser/ui/widget/listmenu/ListMenu.java",
- "java/src/org/chromium/chrome/browser/ui/widget/listmenu/BasicListMenu.java",
- "java/src/org/chromium/chrome/browser/ui/widget/listmenu/ListMenuButton.java",
- "java/src/org/chromium/chrome/browser/ui/widget/listmenu/ListMenuButtonDelegate.java",
- "java/src/org/chromium/chrome/browser/ui/widget/listmenu/ListMenuItemAdapter.java",
- "java/src/org/chromium/chrome/browser/ui/widget/listmenu/ListMenuItemViewBinder.java",
- "java/src/org/chromium/chrome/browser/ui/widget/listmenu/ListMenuItemProperties.java",
- "java/src/org/chromium/chrome/browser/ui/widget/text/AccessibleTextView.java",
- "java/src/org/chromium/chrome/browser/ui/widget/text/AlertDialogEditText.java",
- "java/src/org/chromium/chrome/browser/ui/widget/text/TextViewWithCompoundDrawables.java",
- "java/src/org/chromium/chrome/browser/ui/widget/text/VerticallyFixedEditText.java",
- "java/src/org/chromium/chrome/browser/ui/widget/textbubble/ArrowBubbleDrawable.java",
- "java/src/org/chromium/chrome/browser/ui/widget/textbubble/ImageTextBubble.java",
- "java/src/org/chromium/chrome/browser/ui/widget/textbubble/TextBubble.java",
- ]
-
- deps = [
- ":ui_widget_java_resources",
- "//base:base_java",
- "//chrome/browser/util:java",
- "//third_party/android_deps:android_support_v4_java",
- "//third_party/android_deps:android_support_v7_appcompat_java",
- "//third_party/android_deps:com_android_support_design_java",
- "//third_party/android_deps:com_android_support_interpolator_java",
- "//third_party/android_deps:com_android_support_recyclerview_v7_java",
- "//ui/android:ui_java",
- ]
-}
-
-android_resources("ui_widget_java_resources") {
- custom_package = "org.chromium.chrome.browser.ui.widget"
- resource_dirs = [ "java/res" ]
- deps = [
- "//chrome/browser/ui/android/strings:ui_strings_grd",
- "//chrome/browser/ui/android/styles:java_resources",
- "//third_party/android_deps:com_android_support_design_java",
- "//ui/android:ui_java_resources",
- ]
-}
-
-android_library("test_support_java") {
- testonly = true
-
- java_files = [ "test/java/src/org/chromium/chrome/browser/ui/widget/highlight/ViewHighlighterTestUtils.java" ]
- deps = [
- ":java",
- "//content/public/test/android:content_java_test_support",
- ]
-}
-
-android_library("ui_widget_java_tests") {
- testonly = true
-
- java_files = [
- "java/src/org/chromium/chrome/browser/ui/widget/DualControlLayoutTest.java",
- "java/src/org/chromium/chrome/browser/ui/widget/PromoDialogTest.java",
- "java/src/org/chromium/chrome/browser/ui/widget/RadioButtonLayoutTest.java",
- "java/src/org/chromium/chrome/browser/ui/widget/RadioButtonWithDescriptionLayoutTest.java",
- "java/src/org/chromium/chrome/browser/ui/widget/RoundedIconGeneratorTest.java",
- "java/src/org/chromium/chrome/browser/ui/widget/highlight/ViewHighlighterTest.java",
- "java/src/org/chromium/chrome/browser/ui/widget/MoreProgressButtonTest.java",
- ]
- deps = [
- ":java",
- ":test_support_java",
- ":ui_widget_java_resources",
- ":ui_widget_java_test_resources",
- "//base:base_java_test_support",
- "//chrome/test/android:chrome_java_test_support",
- "//content/public/test/android:content_java_test_support",
- "//third_party/android_deps:com_android_support_support_compat_java",
- "//third_party/android_support_test_runner:rules_java",
- "//third_party/android_support_test_runner:runner_java",
- "//third_party/junit",
- ]
-}
-
-android_resources("ui_widget_java_test_resources") {
- custom_package = "org.chromium.chrome.browser.ui.widget.test"
- resource_dirs = [ "test/java/res" ]
- deps = [
- ":ui_widget_java_resources",
- "//chrome/browser/ui/android/strings:ui_strings_grd",
- "//ui/android:ui_java_resources",
- ]
-}
-
-java_library("ui_widget_junit_tests") {
- # Skip platform checks since Robolectric depends on requires_android targets.
- bypass_platform_checks = true
- testonly = true
- java_files = [ "java/src/org/chromium/chrome/browser/ui/widget/CompositeTouchDelegateUnitTest.java" ]
- deps = [
- ":java",
- "//base:base_java",
- "//base:base_java_test_support",
- "//base:base_junit_test_support",
- "//base/test:test_support_java",
- ]
-}
diff --git a/chromium/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn b/chromium/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn
index 19d6c05846e..5f0ddf0afe5 100644
--- a/chromium/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn
+++ b/chromium/chrome/browser/ui/app_list/search/cros_action_history/BUILD.gn
@@ -5,7 +5,5 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("cros_action_proto") {
- sources = [
- "cros_action.proto",
- ]
+ sources = [ "cros_action.proto" ]
}
diff --git a/chromium/chrome/browser/ui/app_list/search/search_result_ranker/BUILD.gn b/chromium/chrome/browser/ui/app_list/search/search_result_ranker/BUILD.gn
index f3737af729b..cdbb313f9b1 100644
--- a/chromium/chrome/browser/ui/app_list/search/search_result_ranker/BUILD.gn
+++ b/chromium/chrome/browser/ui/app_list/search/search_result_ranker/BUILD.gn
@@ -5,21 +5,15 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("app_launch_event_logger_proto") {
- sources = [
- "app_launch_event_logger.proto",
- ]
+ sources = [ "app_launch_event_logger.proto" ]
}
proto_library("app_launch_predictor_proto") {
- sources = [
- "app_launch_predictor.proto",
- ]
+ sources = [ "app_launch_predictor.proto" ]
}
proto_library("app_list_launch_recorder_proto") {
- sources = [
- "app_list_launch_recorder_state.proto",
- ]
+ sources = [ "app_list_launch_recorder_state.proto" ]
}
proto_library("recurrence_ranker_proto") {
@@ -32,7 +26,5 @@ proto_library("recurrence_ranker_proto") {
}
proto_library("search_ranking_event_proto") {
- sources = [
- "search_ranking_event.proto",
- ]
+ sources = [ "search_ranking_event.proto" ]
}
diff --git a/chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn b/chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn
index 0f07a2501d7..dac35c0c3b1 100644
--- a/chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn
+++ b/chromium/chrome/browser/ui/cocoa/notifications/BUILD.gn
@@ -36,12 +36,12 @@ mac_app_bundle("alert_notification_xpc_service") {
ldflags = []
if (is_component_build) {
ldflags += [
- # The XPC service is in Chromium.app/Contents/Versions/X/Chromium \
+ # The XPC service is in Chromium.app/Contents/Frameworks/Chromium \
# Framework.framework/Versions/A/XPCServices/ \
# AlertNotificationService.xpc/Contents/MacOS/
# so set rpath up to the base.
"-rpath",
- "@loader_path/../../../../../../../../../../../",
+ "@loader_path/../../../../../../../../../../",
]
}
}
@@ -59,7 +59,5 @@ static_library("common") {
"xpc_mach_port.mm",
]
- deps = [
- "//base",
- ]
+ deps = [ "//base" ]
}
diff --git a/chromium/chrome/browser/ui/color/BUILD.gn b/chromium/chrome/browser/ui/color/BUILD.gn
index af9c61b8128..15f7ad86a83 100644
--- a/chromium/chrome/browser/ui/color/BUILD.gn
+++ b/chromium/chrome/browser/ui/color/BUILD.gn
@@ -4,27 +4,19 @@
import("//ui/base/ui_features.gni")
-assert(use_color_pipeline)
+source_set("color_headers") {
+ sources = [ "chrome_color_id.h" ]
-source_set("color") {
- sources = [
- "chrome_color_id.h",
- ]
-
- public_deps = [
- "//ui/color:color",
- ]
+ public_deps = [ "//ui/color:color_headers" ]
}
executable("dump_colors") {
testonly = true
- sources = [
- "tools/dump_colors.cc",
- ]
+ sources = [ "tools/dump_colors.cc" ]
deps = [
- ":color",
+ ":color_headers",
":mixers",
"//ui/color:mixers",
]
@@ -39,7 +31,8 @@ source_set("mixers") {
]
deps = [
- ":color",
+ ":color_headers",
+ "//ui/color:color",
"//ui/color:mixers",
]
}
diff --git a/chromium/chrome/browser/ui/libgtkui/BUILD.gn b/chromium/chrome/browser/ui/libgtkui/BUILD.gn
deleted file mode 100644
index b1b8e33e8b3..00000000000
--- a/chromium/chrome/browser/ui/libgtkui/BUILD.gn
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-assert(is_linux, "This file should only be referenced on Linux")
-
-import("//build/config/features.gni")
-import("//build/config/jumbo.gni")
-import("//build/config/linux/gtk/gtk.gni")
-import("//printing/buildflags/buildflags.gni")
-import("//ui/ozone/ozone.gni")
-
-jumbo_component("libgtkui") {
- sources = [
- "gtk_key_bindings_handler.cc",
- "gtk_key_bindings_handler.h",
- "gtk_ui.cc",
- "gtk_ui.h",
- "gtk_util.cc",
- "gtk_util.h",
- "input_method_context_impl_gtk.cc",
- "input_method_context_impl_gtk.h",
- "native_theme_gtk.cc",
- "native_theme_gtk.h",
- "nav_button_provider_gtk.cc",
- "nav_button_provider_gtk.h",
- "print_dialog_gtk.cc",
- "print_dialog_gtk.h",
- "printing_gtk_util.cc",
- "printing_gtk_util.h",
- "select_file_dialog_impl.cc",
- "select_file_dialog_impl.h",
- "select_file_dialog_impl_gtk.cc",
- "select_file_dialog_impl_gtk.h",
- "select_file_dialog_impl_kde.cc",
- "settings_provider.h",
- "settings_provider_gtk.cc",
- "settings_provider_gtk.h",
- ]
-
- configs += [ "//build/config/linux/pangocairo" ]
-
- if (use_gio) {
- sources += [
- "settings_provider_gsettings.cc",
- "settings_provider_gsettings.h",
- ]
- configs += [ "//build/linux:gio_config" ]
- }
-
- if (use_cups) {
- configs += [ "//printing:cups" ]
- }
-
- defines = [ "IS_LIBGTKUI_IMPL" ]
-
- deps = [
- "//base",
- "//build/config/linux/gtk",
- "//build/config/linux/gtk:gtkprint",
- "//chrome/browser/ui/views",
- "//chrome/common:constants",
- "//components/prefs",
- "//content/public/browser",
- "//printing",
- "//skia",
-
- # GTK pulls pangoft2, which requires HarfBuzz symbols. When linking
- # our own HarfBuzz avoid mixing symbols from system HarfBuzz and
- # our own through the indirect dependency to harfbuzz-ng here.
- "//third_party:freetype_harfbuzz",
- "//ui/aura",
- "//ui/base",
- "//ui/base/ime",
- "//ui/base/ime/linux",
- "//ui/display",
- "//ui/events",
- "//ui/events:dom_keyboard_layout",
- "//ui/events:dom_keycode_converter",
- "//ui/gfx",
- "//ui/gfx/geometry",
- "//ui/native_theme",
- "//ui/shell_dialogs",
- "//ui/strings",
- "//ui/views",
- ]
- public_deps = [
- "//chrome/browser:theme_properties",
- ]
-
- if (use_x11 || ozone_platform_x11) {
- sources += [
- "gtk_event_loop_x11.cc",
- "gtk_event_loop_x11.h",
- ]
-
- configs += [ "//build/config/linux:x11" ]
-
- defines += [ "USE_GTK_EVENT_LOOP_X11" ]
-
- deps += [
- "//ui/events/platform/x11",
- "//ui/gfx/x",
- ]
- }
-
- if (use_ozone) {
- deps += [ "//ui/ozone" ]
- }
-}
diff --git a/chromium/chrome/browser/ui/messages/android/BUILD.gn b/chromium/chrome/browser/ui/messages/android/BUILD.gn
new file mode 100644
index 00000000000..05e17f71c7f
--- /dev/null
+++ b/chromium/chrome/browser/ui/messages/android/BUILD.gn
@@ -0,0 +1,96 @@
+# Copyright 2019 The Chromium 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_resources("java_resources") {
+ custom_package = "org.chromium.chrome.ui.messages"
+ sources = [
+ "java/res/drawable-hdpi/infobar_shadow_left.9.png",
+ "java/res/drawable-hdpi/infobar_shadow_top.png",
+ "java/res/drawable-mdpi/infobar_shadow_left.9.png",
+ "java/res/drawable-mdpi/infobar_shadow_top.png",
+ "java/res/drawable-xhdpi/infobar_shadow_left.9.png",
+ "java/res/drawable-xhdpi/infobar_shadow_top.png",
+ "java/res/drawable-xxhdpi/infobar_shadow_left.9.png",
+ "java/res/drawable-xxhdpi/infobar_shadow_top.png",
+ "java/res/drawable-xxxhdpi/infobar_shadow_left.9.png",
+ "java/res/drawable-xxxhdpi/infobar_shadow_top.png",
+ "java/res/drawable/snackbar_background_tablet.xml",
+ "java/res/layout/infobar_control_icon_with_description.xml",
+ "java/res/layout/infobar_control_message.xml",
+ "java/res/layout/infobar_control_spinner.xml",
+ "java/res/layout/infobar_control_spinner_drop_down.xml",
+ "java/res/layout/infobar_control_spinner_view.xml",
+ "java/res/layout/infobar_control_toggle.xml",
+ "java/res/layout/snackbar.xml",
+ "java/res/values/dimens.xml",
+ "java/res/values/ids.xml",
+ ]
+ deps = [
+ "//chrome/browser/ui/android/strings:ui_strings_grd",
+ "//components/browser_ui/strings/android:browser_ui_strings_grd",
+ "//components/browser_ui/widget/android:java_resources",
+ "//ui/android:ui_java_resources",
+ ]
+}
+
+android_library("java") {
+ sources = [
+ "java/src/org/chromium/chrome/browser/ui/messages/infobar/InfoBarCompactLayout.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/infobar/InfoBarControlLayout.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/infobar/InfoBarInteractionHandler.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/infobar/InfoBarLayout.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/infobar/InfoBarMessageView.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/infobar/InfoBarUiItem.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollection.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarManager.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java",
+ ]
+ deps = [
+ ":java_resources",
+ "//base:base_java",
+ "//chrome/browser/util:java",
+ "//components/browser_ui/styles/android:java_resources",
+ "//components/browser_ui/widget/android:java",
+ "//components/infobars/core:infobar_enums_java",
+ "//third_party/android_deps:androidx_annotation_annotation_java",
+ "//third_party/android_deps:com_android_support_appcompat_v7_java",
+ "//ui/android:ui_full_java",
+ "//ui/android:ui_utils_java",
+ ]
+}
+
+java_library("junit") {
+ # Skip platform checks since Robolectric depends on requires_android targets.
+ bypass_platform_checks = true
+ testonly = true
+ sources = [ "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollectionUnitTest.java" ]
+ deps = [
+ ":java",
+ "//base:base_java_test_support",
+ "//third_party/junit",
+ "//third_party/mockito:mockito_java",
+ ]
+}
+
+android_library("javatests") {
+ testonly = true
+ sources = [
+ "java/src/org/chromium/chrome/browser/ui/messages/infobar/InfoBarControlLayoutTest.java",
+ "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarTest.java",
+ ]
+ deps = [
+ ":java",
+ "//base:base_java",
+ "//base:base_java_test_support",
+ "//chrome/test/android:chrome_java_test_support",
+ "//content/public/android:content_java",
+ "//content/public/test/android:content_java_test_support",
+ "//third_party/android_support_test_runner:rules_java",
+ "//third_party/android_support_test_runner:runner_java",
+ "//third_party/junit",
+ "//ui/android:ui_java_test_support",
+ ]
+}
diff --git a/chromium/chrome/browser/ui/views/BUILD.gn b/chromium/chrome/browser/ui/views/BUILD.gn
index 0241896ec54..7c9e5d3b547 100644
--- a/chromium/chrome/browser/ui/views/BUILD.gn
+++ b/chromium/chrome/browser/ui/views/BUILD.gn
@@ -43,12 +43,4 @@ component("views") {
if (is_chromeos) {
deps += [ "//ash" ]
}
-
- if (enable_native_window_nav_buttons) {
- sources += [ "nav_button_provider.h" ]
- deps += [
- "//ui/views",
- "//ui/views:buildflags",
- ]
- }
}
diff --git a/chromium/chrome/browser/ui/webui/about_ui.cc b/chromium/chrome/browser/ui/webui/about_ui.cc
index 948e17345ab..8973b1954c0 100644
--- a/chromium/chrome/browser/ui/webui/about_ui.cc
+++ b/chromium/chrome/browser/ui/webui/about_ui.cc
@@ -17,6 +17,7 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/command_line.h"
+#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/format_macros.h"
#include "base/i18n/number_formatting.h"
@@ -33,6 +34,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread.h"
#include "base/values.h"
@@ -85,8 +87,10 @@
#include "chrome/browser/chromeos/customization/customization_document.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/browser/component_updater/cros_component_manager.h"
#include "chromeos/system/statistics_provider.h"
#include "components/language/core/common/locale_util.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
#endif
using content::BrowserThread;
@@ -101,6 +105,8 @@ constexpr char kStringsJsPath[] = "strings.js";
constexpr char kKeyboardUtilsPath[] = "keyboard_utils.js";
+constexpr char kTerminaCreditsPath[] = "about_os_credits.html";
+
// APAC region name.
constexpr char kApac[] = "apac";
// EMEA region name.
@@ -203,37 +209,26 @@ class ChromeOSTermsHandler
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (path_ == chrome::kOemEulaURLPath) {
// Load local OEM EULA from the disk.
- base::PostTaskAndReply(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&ChromeOSTermsHandler::LoadOemEulaFileAsync, this),
base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
} else if (path_ == chrome::kArcTermsURLPath) {
// Load ARC++ terms from the file.
- base::PostTaskAndReply(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&ChromeOSTermsHandler::LoadArcTermsFileAsync, this),
base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
} else if (path_ == chrome::kArcPrivacyPolicyURLPath) {
// Load ARC++ privacy policy from the file.
- base::PostTaskAndReply(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&ChromeOSTermsHandler::LoadArcPrivacyPolicyFileAsync,
this),
base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
} else {
- // Load local ChromeOS terms from the file.
- base::PostTaskAndReply(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
- base::BindOnce(&ChromeOSTermsHandler::LoadEulaFileAsync, this),
- base::BindOnce(&ChromeOSTermsHandler::ResponseOnUIThread, this));
+ NOTREACHED();
+ ResponseOnUIThread();
}
}
@@ -255,23 +250,6 @@ class ChromeOSTermsHandler
}
}
- void LoadEulaFileAsync() {
- base::ScopedBlockingCall scoped_blocking_call(
- FROM_HERE, base::BlockingType::MAY_BLOCK);
-
- std::string file_path =
- base::StringPrintf(chrome::kEULAPathFormat, locale_.c_str());
- if (!base::ReadFileToString(base::FilePath(file_path), &contents_)) {
- // No EULA for given language - try en-US as default.
- file_path = base::StringPrintf(chrome::kEULAPathFormat, "en-US");
- if (!base::ReadFileToString(base::FilePath(file_path), &contents_)) {
- // File with EULA not found, ResponseOnUIThread will load EULA from
- // resources if contents_ is empty.
- contents_.clear();
- }
- }
- }
-
void LoadArcPrivacyPolicyFileAsync() {
base::ScopedBlockingCall scoped_blocking_call(
FROM_HERE, base::BlockingType::MAY_BLOCK);
@@ -390,9 +368,8 @@ class ChromeOSCreditsHandler
return;
}
// Load local Chrome OS credits from the disk.
- base::PostTaskAndReply(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::Bind(&ChromeOSCreditsHandler::LoadCreditsFileAsync, this),
base::Bind(&ChromeOSCreditsHandler::ResponseOnUIThread, this));
}
@@ -429,24 +406,24 @@ class ChromeOSCreditsHandler
DISALLOW_COPY_AND_ASSIGN(ChromeOSCreditsHandler);
};
-class LinuxCreditsHandler
- : public base::RefCountedThreadSafe<LinuxCreditsHandler> {
+class CrostiniCreditsHandler
+ : public base::RefCountedThreadSafe<CrostiniCreditsHandler> {
public:
static void Start(const std::string& path,
content::URLDataSource::GotDataCallback callback) {
- scoped_refptr<LinuxCreditsHandler> handler(
- new LinuxCreditsHandler(path, std::move(callback)));
+ scoped_refptr<CrostiniCreditsHandler> handler(
+ new CrostiniCreditsHandler(path, std::move(callback)));
handler->StartOnUIThread();
}
private:
- friend class base::RefCountedThreadSafe<LinuxCreditsHandler>;
+ friend class base::RefCountedThreadSafe<CrostiniCreditsHandler>;
- LinuxCreditsHandler(const std::string& path,
- content::URLDataSource::GotDataCallback callback)
+ CrostiniCreditsHandler(const std::string& path,
+ content::URLDataSource::GotDataCallback callback)
: path_(path), callback_(std::move(callback)) {}
- virtual ~LinuxCreditsHandler() {}
+ virtual ~CrostiniCreditsHandler() {}
void StartOnUIThread() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -457,16 +434,29 @@ class LinuxCreditsHandler
ResponseOnUIThread();
return;
}
- // Load local Linux credits from the disk.
- base::PostTaskAndReply(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
- base::Bind(&LinuxCreditsHandler::LoadLinuxCreditsFileAsync, this),
- base::Bind(&LinuxCreditsHandler::ResponseOnUIThread, this));
+ auto* component_manager =
+ g_browser_process->platform_part()->cros_component_manager();
+ if (!component_manager) {
+ LoadCredits(base::FilePath(chrome::kLinuxCreditsPath));
+ return;
+ }
+ component_manager->Load(
+ imageloader::kTerminaComponentName,
+ component_updater::CrOSComponentManager::MountPolicy::kMount,
+ component_updater::CrOSComponentManager::UpdatePolicy::kSkip,
+ base::BindOnce(&CrostiniCreditsHandler::OnTerminaLoaded, this));
+ }
+
+ void LoadCredits(base::FilePath path) {
+ // Load crostini credits from the disk.
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&CrostiniCreditsHandler::LoadCrostiniCreditsFileAsync,
+ this, std::move(path)),
+ base::BindOnce(&CrostiniCreditsHandler::ResponseOnUIThread, this));
}
- void LoadLinuxCreditsFileAsync() {
- base::FilePath credits_file_path(chrome::kLinuxCreditsPath);
+ void LoadCrostiniCreditsFileAsync(base::FilePath credits_file_path) {
if (!base::ReadFileToString(credits_file_path, &contents_)) {
// File with credits not found, ResponseOnUIThread will load credits
// from resources if contents_ is empty.
@@ -474,6 +464,15 @@ class LinuxCreditsHandler
}
}
+ void OnTerminaLoaded(component_updater::CrOSComponentManager::Error error,
+ const base::FilePath& path) {
+ if (error == component_updater::CrOSComponentManager::Error::NONE) {
+ LoadCredits(path.Append(kTerminaCreditsPath));
+ return;
+ }
+ LoadCredits(base::FilePath(chrome::kLinuxCreditsPath));
+ }
+
void ResponseOnUIThread() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// If we fail to load Linux credits from disk, load the placeholder from
@@ -496,7 +495,7 @@ class LinuxCreditsHandler
// Linux credits contents that was loaded from file.
std::string contents_;
- DISALLOW_COPY_AND_ASSIGN(LinuxCreditsHandler);
+ DISALLOW_COPY_AND_ASSIGN(CrostiniCreditsHandler);
};
#endif
@@ -625,18 +624,19 @@ void AboutUIHTMLSource::StartDataRequest(
} else if (source_name_ == chrome::kChromeUIOSCreditsHost) {
ChromeOSCreditsHandler::Start(path, std::move(callback));
return;
- } else if (source_name_ == chrome::kChromeUILinuxCreditsHost) {
- LinuxCreditsHandler::Start(path, std::move(callback));
+ } else if (source_name_ == chrome::kChromeUICrostiniCreditsHost) {
+ CrostiniCreditsHandler::Start(path, std::move(callback));
return;
#endif
#if !defined(OS_ANDROID)
} else if (source_name_ == chrome::kChromeUITermsHost) {
#if defined(OS_CHROMEOS)
- ChromeOSTermsHandler::Start(path, std::move(callback));
- return;
-#else
- response = l10n_util::GetStringUTF8(IDS_TERMS_HTML);
+ if (!path.empty()) {
+ ChromeOSTermsHandler::Start(path, std::move(callback));
+ return;
+ }
#endif
+ response = l10n_util::GetStringUTF8(IDS_TERMS_HTML);
#endif
}
@@ -665,7 +665,7 @@ std::string AboutUIHTMLSource::GetMimeType(const std::string& path) {
bool AboutUIHTMLSource::ShouldAddContentSecurityPolicy() {
#if defined(OS_CHROMEOS)
if (source_name_ == chrome::kChromeUIOSCreditsHost ||
- source_name_ == chrome::kChromeUILinuxCreditsHost) {
+ source_name_ == chrome::kChromeUICrostiniCreditsHost) {
return false;
}
#endif
diff --git a/chromium/chrome/browser/ui/webui/app_management/BUILD.gn b/chromium/chrome/browser/ui/webui/app_management/BUILD.gn
index 4395a4ca5f2..6db2265d29e 100644
--- a/chromium/chrome/browser/ui/webui/app_management/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/app_management/BUILD.gn
@@ -5,11 +5,7 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "app_management.mojom",
- ]
+ sources = [ "app_management.mojom" ]
- public_deps = [
- "//chrome/services/app_service/public/mojom",
- ]
+ public_deps = [ "//chrome/services/app_service/public/mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.cc b/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
index 1eba8c94094..5c0641f3604 100644
--- a/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
+++ b/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
@@ -152,7 +152,8 @@ void AppManagementPageHandler::GetApps(GetAppsCallback callback) {
std::vector<app_management::mojom::AppPtr> apps;
proxy->AppRegistryCache().ForEachApp(
[this, &apps](const apps::AppUpdate& update) {
- if (update.ShowInManagement() == apps::mojom::OptionalBool::kTrue) {
+ if (update.ShowInManagement() == apps::mojom::OptionalBool::kTrue &&
+ update.Readiness() != apps::mojom::Readiness::kUninstalledByUser) {
apps.push_back(CreateUIAppPtr(update));
}
});
diff --git a/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.h b/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.h
index 6bc45d49536..039c18af90e 100644
--- a/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.h
+++ b/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "base/scoped_observer.h"
-#include "chrome/browser/ui/webui/app_management/app_management.mojom.h"
+#include "chrome/browser/ui/webui/app_management/app_management.mojom-forward.h"
#include "chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h"
#include "chrome/services/app_service/public/cpp/app_registry_cache.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
diff --git a/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/autofill_internals_ui.h b/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/autofill_internals_ui.h
index c38a6d9b7da..4869bd69573 100644
--- a/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/autofill_internals_ui.h
+++ b/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/autofill_internals_ui.h
@@ -6,9 +6,12 @@
#define CHROME_BROWSER_UI_WEBUI_AUTOFILL_AND_PASSWORD_MANAGER_INTERNALS_AUTOFILL_INTERNALS_UI_H_
#include "base/macros.h"
-#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
+namespace content {
+class WebUI;
+}
+
class AutofillInternalsUI : public content::WebUIController {
public:
explicit AutofillInternalsUI(content::WebUI* web_ui);
diff --git a/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.cc b/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.cc
index 1c242488832..148cc97d24d 100644
--- a/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.cc
+++ b/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.cc
@@ -4,13 +4,15 @@
#include "chrome/browser/ui/webui/autofill_and_password_manager_internals/internals_ui_handler.h"
+#include <utility>
+
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/channel_info.h"
#include "components/autofill/core/browser/logging/log_router.h"
-#include "components/grit/components_resources.h"
+#include "components/grit/dev_ui_components_resources.h"
#include "components/version_info/version_info.h"
#include "components/version_ui/version_handler_helper.h"
#include "components/version_ui/version_ui_constants.h"
diff --git a/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui.h b/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui.h
index 19d8ed9f3f2..3e557ddb78a 100644
--- a/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui.h
+++ b/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui.h
@@ -6,9 +6,12 @@
#define CHROME_BROWSER_UI_WEBUI_AUTOFILL_AND_PASSWORD_MANAGER_INTERNALS_PASSWORD_MANAGER_INTERNALS_UI_H_
#include "base/macros.h"
-#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
+namespace content {
+class WebUI;
+}
+
class PasswordManagerInternalsUI : public content::WebUIController {
public:
explicit PasswordManagerInternalsUI(content::WebUI* web_ui);
diff --git a/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui_browsertest.cc
index 0a50d409f8c..79b870a64ba 100644
--- a/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui_browsertest.cc
@@ -64,7 +64,7 @@ void PasswordManagerInternalsWebUIBrowserTest::OpenInternalsPageWithBrowser(
url_string += chrome::kChromeUIPasswordManagerInternalsHost;
ui_test_utils::NavigateToURLWithDisposition(
browser, GURL(url_string), disposition,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
controller_ = static_cast<PasswordManagerInternalsUI*>(
GetWebContents()->GetWebUI()->GetController());
}
diff --git a/chromium/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn b/chromium/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn
index 210d8f365ed..d2a181073ad 100644
--- a/chromium/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/bluetooth_internals/BUILD.gn
@@ -12,9 +12,7 @@ source_set("bluetooth_internals") {
"bluetooth_internals_ui.h",
]
- public_deps = [
- "//device/bluetooth:deprecated_experimental_mojo",
- ]
+ public_deps = [ "//device/bluetooth:deprecated_experimental_mojo" ]
deps = [
":mojo_bindings",
@@ -31,11 +29,8 @@ source_set("bluetooth_internals") {
}
mojom("mojo_bindings") {
- sources = [
- "bluetooth_internals.mojom",
- ]
+ sources = [ "bluetooth_internals.mojom" ]
- deps = [
- "//device/bluetooth/public/mojom:deprecated_experimental_interfaces",
- ]
+ deps =
+ [ "//device/bluetooth/public/mojom:deprecated_experimental_interfaces" ]
}
diff --git a/chromium/chrome/browser/ui/webui/bluetooth_internals/OWNERS b/chromium/chrome/browser/ui/webui/bluetooth_internals/OWNERS
index 08850f42120..6c8da821308 100644
--- a/chromium/chrome/browser/ui/webui/bluetooth_internals/OWNERS
+++ b/chromium/chrome/browser/ui/webui/bluetooth_internals/OWNERS
@@ -1,2 +1,4 @@
+file://device/bluetooth/OWNERS
+
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.cc b/chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.cc
index 6f8ab24a1e9..912e21c429f 100644
--- a/chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.cc
@@ -39,14 +39,13 @@ BluetoothInternalsUI::BluetoothInternalsUI(content::WebUI* web_ui)
Profile* profile = Profile::FromWebUI(web_ui);
content::WebUIDataSource::Add(profile, html_source);
- AddHandlerToRegistry(
- base::BindRepeating(&BluetoothInternalsUI::BindBluetoothInternalsHandler,
- base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(BluetoothInternalsUI)
+
BluetoothInternalsUI::~BluetoothInternalsUI() {}
-void BluetoothInternalsUI::BindBluetoothInternalsHandler(
+void BluetoothInternalsUI::BindInterface(
mojo::PendingReceiver<mojom::BluetoothInternalsHandler> receiver) {
page_handler_ =
std::make_unique<BluetoothInternalsHandler>(std::move(receiver));
diff --git a/chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.h b/chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.h
index 2a69c29cc58..8f22cb5e613 100644
--- a/chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.h
+++ b/chromium/chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.h
@@ -6,7 +6,7 @@
#define CHROME_BROWSER_UI_WEBUI_BLUETOOTH_INTERNALS_BLUETOOTH_INTERNALS_UI_H_
#include "base/macros.h"
-#include "chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals.mojom.h"
+#include "chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -18,12 +18,16 @@ class BluetoothInternalsUI : public ui::MojoWebUIController {
explicit BluetoothInternalsUI(content::WebUI* web_ui);
~BluetoothInternalsUI() override;
- private:
- void BindBluetoothInternalsHandler(
+ // Instantiates the implementor of the mojom::BluetoothInternalsHandler mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<mojom::BluetoothInternalsHandler> receiver);
+ private:
std::unique_ptr<BluetoothInternalsHandler> page_handler_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(BluetoothInternalsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc b/chromium/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc
index dd3afef2ef4..60ec5a0f600 100644
--- a/chromium/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc
+++ b/chromium/chrome/browser/ui/webui/bookmarks/bookmarks_ui.cc
@@ -32,6 +32,7 @@
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/web_ui_util.h"
namespace {
diff --git a/chromium/chrome/browser/ui/webui/browser_switch/browser_switch_ui.cc b/chromium/chrome/browser/ui/webui/browser_switch/browser_switch_ui.cc
index f7db04bc6d5..47c701f06ae 100644
--- a/chromium/chrome/browser/ui/webui/browser_switch/browser_switch_ui.cc
+++ b/chromium/chrome/browser/ui/webui/browser_switch/browser_switch_ui.cc
@@ -180,6 +180,10 @@ class BrowserSwitchHandler : public content::WebUIMessageHandler {
// JavaScript promise is not resolved, because we close the tab anyways.
void HandleLaunchAlternativeBrowserAndCloseTab(const base::ListValue* args);
+ void OnLaunchFinished(base::TimeTicks start,
+ std::string callback_id,
+ bool success);
+
// Navigates to the New Tab Page.
void HandleGotoNewTabPage(const base::ListValue* args);
@@ -237,6 +241,8 @@ class BrowserSwitchHandler : public content::WebUIMessageHandler {
browser_switcher::BrowserSwitcherService::CallbackSubscription>
service_subscription_;
+ base::WeakPtrFactory<BrowserSwitchHandler> weak_ptr_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(BrowserSwitchHandler);
};
@@ -324,24 +330,31 @@ void BrowserSwitchHandler::HandleLaunchAlternativeBrowserAndCloseTab(
return;
}
- bool success;
- {
- SCOPED_UMA_HISTOGRAM_TIMER("BrowserSwitcher.LaunchTime");
- success = service->driver()->TryLaunch(url);
- UMA_HISTOGRAM_BOOLEAN("BrowserSwitcher.LaunchSuccess", success);
- }
+ service->driver()->TryLaunch(
+ url, base::BindOnce(&BrowserSwitchHandler::OnLaunchFinished,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::TimeTicks::Now(), std::move(callback_id)));
+}
+
+void BrowserSwitchHandler::OnLaunchFinished(base::TimeTicks start,
+ std::string callback_id,
+ bool success) {
+ const base::TimeDelta runtime = base::TimeTicks::Now() - start;
+ UMA_HISTOGRAM_TIMES("BrowserSwitcher.LaunchTime", runtime);
+ UMA_HISTOGRAM_BOOLEAN("BrowserSwitcher.LaunchSuccess", success);
if (!success) {
- RejectJavascriptCallback(args->GetList()[0], base::Value());
+ RejectJavascriptCallback(base::Value(callback_id), base::Value());
return;
}
+ auto* service = GetBrowserSwitcherService(web_ui());
auto* profile = Profile::FromWebUI(web_ui());
-
+ // We don't need to resolve the promise, because the tab will close (or
+ // navigate to about:newtab) anyways.
if (service->prefs().KeepLastTab() && IsLastTab(profile)) {
GotoNewTabPage(web_ui()->GetWebContents());
} else {
- // We don't need to resolve the promise, because the tab will close anyways.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(&content::WebContents::ClosePage,
diff --git a/chromium/chrome/browser/ui/webui/certificate_manager_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/certificate_manager_localized_strings_provider.cc
index c65864ab32c..1fb5f60dbe8 100644
--- a/chromium/chrome/browser/ui/webui/certificate_manager_localized_strings_provider.cc
+++ b/chromium/chrome/browser/ui/webui/certificate_manager_localized_strings_provider.cc
@@ -9,6 +9,7 @@
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/webui/web_ui_util.h"
namespace certificate_manager {
diff --git a/chromium/chrome/browser/ui/webui/certificate_viewer_ui.cc b/chromium/chrome/browser/ui/webui/certificate_viewer_ui.cc
index 7bc104262dd..1f56b479040 100644
--- a/chromium/chrome/browser/ui/webui/certificate_viewer_ui.cc
+++ b/chromium/chrome/browser/ui/webui/certificate_viewer_ui.cc
@@ -15,6 +15,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/webui/web_ui_util.h"
#include "ui/web_dialogs/web_dialog_delegate.h"
namespace {
diff --git a/chromium/chrome/browser/ui/webui/certificate_viewer_webui.cc b/chromium/chrome/browser/ui/webui/certificate_viewer_webui.cc
index e686be81023..2bd1c78de41 100644
--- a/chromium/chrome/browser/ui/webui/certificate_viewer_webui.cc
+++ b/chromium/chrome/browser/ui/webui/certificate_viewer_webui.cc
@@ -26,6 +26,7 @@
#include "chrome/common/net/x509_certificate_model_nss.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
#include "content/public/browser/host_zoom_map.h"
#include "content/public/browser/web_contents.h"
#include "net/cert/x509_util_nss.h"
diff --git a/chromium/chrome/browser/ui/webui/certificates_handler.cc b/chromium/chrome/browser/ui/webui/certificates_handler.cc
index 8342599150d..c545456883d 100644
--- a/chromium/chrome/browser/ui/webui/certificates_handler.cc
+++ b/chromium/chrome/browser/ui/webui/certificates_handler.cc
@@ -22,6 +22,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
@@ -224,8 +225,8 @@ base::CancelableTaskTracker::TaskId FileAccessProvider::StartRead(
std::string* data = new std::string();
// Post task to a background sequence to read file.
- auto task_runner = base::CreateTaskRunner(
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT});
+ auto task_runner = base::ThreadPool::CreateTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
return tracker->PostTaskAndReply(
task_runner.get(), FROM_HERE,
base::BindOnce(&FileAccessProvider::DoRead, this, path, saved_errno,
@@ -243,8 +244,8 @@ base::CancelableTaskTracker::TaskId FileAccessProvider::StartWrite(
int* bytes_written = new int(0);
// This task blocks shutdown because it saves critical user data.
- auto task_runner = base::CreateTaskRunner(
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ auto task_runner = base::ThreadPool::CreateTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
return tracker->PostTaskAndReply(
task_runner.get(), FROM_HERE,
@@ -277,7 +278,11 @@ CertificatesHandler::CertificatesHandler()
use_hardware_backed_(false),
file_access_provider_(base::MakeRefCounted<FileAccessProvider>()) {}
-CertificatesHandler::~CertificatesHandler() {}
+CertificatesHandler::~CertificatesHandler() {
+ if (select_file_dialog_.get())
+ select_file_dialog_->ListenerDestroyed();
+ select_file_dialog_ = nullptr;
+}
void CertificatesHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
diff --git a/chromium/chrome/browser/ui/webui/chrome_url_disabled_ui.cc b/chromium/chrome/browser/ui/webui/chrome_url_disabled_ui.cc
new file mode 100644
index 00000000000..4f9e4c1a239
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/chrome_url_disabled_ui.cc
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chrome_url_disabled_ui.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/grit/browser_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+ChromeURLDisabledUI::ChromeURLDisabledUI(content::WebUI* web_ui,
+ const std::string& host_name)
+ : content::WebUIController(web_ui), weak_factory_(this) {
+ content::WebUIDataSource* html_source =
+ content::WebUIDataSource::Create(host_name);
+
+ html_source->UseStringsJs();
+
+ html_source->AddLocalizedString("disabledPageHeader",
+ IDS_CHROME_URLS_DISABLED_PAGE_HEADER);
+ html_source->AddLocalizedString("disabledPageTitle",
+ IDS_CHROME_URLS_DISABLED_PAGE_TITLE);
+ html_source->AddLocalizedString("disabledPageMessage",
+ IDS_CHROME_URLS_DISABLED_PAGE_MESSAGE);
+ html_source->SetDefaultResource(IDR_CHROME_URLS_DISABLED_PAGE_HTML);
+
+ html_source->SetDefaultResource(IDR_CHROME_URLS_DISABLED_PAGE_HTML);
+
+ Profile* profile = Profile::FromWebUI(web_ui);
+ content::WebUIDataSource::Add(profile, html_source);
+}
+
+ChromeURLDisabledUI::~ChromeURLDisabledUI() = default;
diff --git a/chromium/chrome/browser/ui/webui/chrome_url_disabled_ui.h b/chromium/chrome/browser/ui/webui/chrome_url_disabled_ui.h
new file mode 100644
index 00000000000..96354ee890d
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/chrome_url_disabled_ui.h
@@ -0,0 +1,22 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROME_URL_DISABLED_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROME_URL_DISABLED_UI_H_
+
+#include "base/memory/weak_ptr.h"
+#include "content/public/browser/web_ui_controller.h"
+
+// For chrome:://.* error page when disabled by admin policy.
+class ChromeURLDisabledUI : public content::WebUIController {
+ public:
+ explicit ChromeURLDisabledUI(content::WebUI* web_ui,
+ const std::string& host_name);
+ ~ChromeURLDisabledUI() override;
+
+ private:
+ base::WeakPtrFactory<ChromeURLDisabledUI> weak_factory_;
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_CHROME_URL_DISABLED_UI_H_
diff --git a/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index f7b987878c4..7f7d97c607f 100644
--- a/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -15,8 +15,11 @@
#include "build/build_config.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/accessibility/accessibility_ui.h"
+#include "chrome/browser/buildflags.h"
#include "chrome/browser/devtools/devtools_ui_bindings.h"
#include "chrome/browser/engagement/site_engagement_service.h"
+#include "chrome/browser/media/feeds/media_feeds_service.h"
+#include "chrome/browser/media/history/media_history_keyed_service.h"
#include "chrome/browser/media/media_engagement_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -30,7 +33,7 @@
#include "chrome/browser/ui/webui/chromeos/account_migration_welcome_ui.h"
#include "chrome/browser/ui/webui/chromeos/camera/camera_ui.h"
#include "chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.h"
-#include "chrome/browser/ui/webui/components_ui.h"
+#include "chrome/browser/ui/webui/components/components_ui.h"
#include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
#include "chrome/browser/ui/webui/crashes_ui.h"
#include "chrome/browser/ui/webui/device_log_ui.h"
@@ -46,6 +49,8 @@
#include "chrome/browser/ui/webui/local_state/local_state_ui.h"
#include "chrome/browser/ui/webui/log_web_ui_url.h"
#include "chrome/browser/ui/webui/media/media_engagement_ui.h"
+#include "chrome/browser/ui/webui/media/media_feeds_ui.h"
+#include "chrome/browser/ui/webui/media/media_history_ui.h"
#include "chrome/browser/ui/webui/media/webrtc_logs_ui.h"
#include "chrome/browser/ui/webui/memory_internals_ui.h"
#include "chrome/browser/ui/webui/net_export_ui.h"
@@ -78,8 +83,8 @@
#include "components/nacl/common/buildflags.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/buildflags.h"
-#include "components/safe_browsing/web_ui/constants.h"
-#include "components/safe_browsing/web_ui/safe_browsing_ui.h"
+#include "components/safe_browsing/content/web_ui/safe_browsing_ui.h"
+#include "components/safe_browsing/core/web_ui/constants.h"
#include "components/security_interstitials/content/connection_help_ui.h"
#include "components/security_interstitials/content/known_interception_disclosure_ui.h"
#include "components/security_interstitials/content/urls.h"
@@ -96,6 +101,12 @@
#include "ui/web_dialogs/web_dialog_ui.h"
#include "url/gurl.h"
+#if BUILDFLAG(ENABLE_KALEIDOSCOPE)
+#include "chrome/browser/media/kaleidoscope/internal/kaleidoscope_content_ui.h"
+#include "chrome/browser/media/kaleidoscope/internal/kaleidoscope_ui.h"
+#include "media/base/media_switches.h"
+#endif // BUILDFLAG(ENABLE_KALEIDOSCOPE)
+
#if BUILDFLAG(ENABLE_NACL)
#include "chrome/browser/ui/webui/nacl_ui.h"
#endif
@@ -150,6 +161,8 @@
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_factory.h"
#include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_service_factory.h"
#include "chrome/browser/chromeos/secure_channel/secure_channel_client_provider.h"
+#include "chrome/browser/chromeos/web_applications/chrome_help_app_ui_delegate.h"
+#include "chrome/browser/chromeos/web_applications/chrome_media_app_ui_delegate.h"
#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h"
#include "chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.h"
#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h"
@@ -175,7 +188,6 @@
#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h"
#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.h"
#include "chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_ui.h"
-#include "chrome/browser/ui/webui/chromeos/terminal/terminal_ui.h"
#include "chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h"
#include "chrome/browser/ui/webui/signin/inline_login_ui.h"
#include "chromeos/components/help_app_ui/help_app_ui.h"
@@ -185,6 +197,10 @@
#include "chromeos/components/media_app_ui/url_constants.h"
#include "chromeos/components/multidevice/debug_webui/proximity_auth_ui.h"
#include "chromeos/components/multidevice/debug_webui/url_constants.h"
+#include "chromeos/components/print_management/print_management_ui.h"
+#include "chromeos/components/print_management/scanning_ui.h"
+#include "chromeos/components/print_management/url_constants.h"
+#include "chromeos/components/sample_system_web_app_ui/url_constants.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/services/multidevice_setup/multidevice_setup_service.h"
@@ -194,6 +210,7 @@
#if defined(OS_CHROMEOS) && !defined(OFFICIAL_BUILD)
#include "chrome/browser/ui/webui/chromeos/emulator/device_emulator_ui.h"
+#include "chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.h"
#endif
#if !defined(OS_CHROMEOS)
@@ -288,6 +305,19 @@ WebUIController* NewWebUI<chromeos::OobeUI>(WebUI* web_ui, const GURL& url) {
return new chromeos::OobeUI(web_ui, url);
}
+template <>
+WebUIController* NewWebUI<chromeos::HelpAppUI>(WebUI* web_ui, const GURL& url) {
+ auto delegate = std::make_unique<ChromeHelpAppUIDelegate>(web_ui);
+ return new chromeos::HelpAppUI(web_ui, std::move(delegate));
+}
+
+template <>
+WebUIController* NewWebUI<chromeos::MediaAppUI>(WebUI* web_ui,
+ const GURL& url) {
+ auto delegate = std::make_unique<ChromeMediaAppUIDelegate>(web_ui);
+ return new chromeos::MediaAppUI(web_ui, std::move(delegate));
+}
+
void BindMultiDeviceSetup(
Profile* profile,
mojo::PendingReceiver<chromeos::multidevice_setup::mojom::MultiDeviceSetup>
@@ -333,7 +363,7 @@ bool IsAboutUI(const GURL& url) {
#endif
#if defined(OS_CHROMEOS)
|| url.host_piece() == chrome::kChromeUIOSCreditsHost ||
- url.host_piece() == chrome::kChromeUILinuxCreditsHost
+ url.host_piece() == chrome::kChromeUICrostiniCreditsHost
#endif
); // NOLINT
}
@@ -448,7 +478,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
(url.host_piece() == chrome::kChromeUIAppLauncherPageHost ||
url.host_piece() == chrome::kChromeUIBookmarksHost ||
url.host_piece() == chrome::kChromeUIHistoryHost ||
- url.host_piece() == chrome::kChromeUIExtensionsHost)) {
+ url.host_piece() == chrome::kChromeUIExtensionsHost ||
+ url.host_piece() == chrome::kChromeUINewTabPageHost)) {
return &NewWebUI<PageNotAvailableForGuestUI>;
}
// Bookmarks are part of NTP on Android.
@@ -524,8 +555,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
return &NewWebUI<chromeos::cellular_setup::CellularSetupDialogUI>;
if (url.host_piece() == chrome::kChromeUICertificateManagerHost)
return &NewWebUI<chromeos::CertificateManagerDialogUI>;
- if (chromeos::CrostiniInstallerUI::IsEnabled() &&
- url.host_piece() == chrome::kChromeUICrostiniInstallerHost)
+ if (url.host_piece() == chrome::kChromeUICrostiniInstallerHost)
return &NewWebUI<chromeos::CrostiniInstallerUI>;
if (chromeos::CrostiniUpgraderUI::IsEnabled() &&
url.host_piece() == chrome::kChromeUICrostiniUpgraderHost)
@@ -554,11 +584,17 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
return &NewWebUI<chromeos::settings::OSSettingsUI>;
if (url.host_piece() == chrome::kChromeUIPowerHost)
return &NewWebUI<chromeos::PowerUI>;
+ if (base::FeatureList::IsEnabled(
+ chromeos::features::kPrintJobManagementApp) &&
+ url.host_piece() == chromeos::kChromeUIPrintManagementHost)
+ return &NewWebUI<chromeos::PrintManagementUI>;
+ if (base::FeatureList::IsEnabled(chromeos::features::kScanningUI) &&
+ url.host_piece() == chromeos::kChromeUIScanningHost) {
+ return &NewWebUI<chromeos::ScanningUI>;
+ }
if (base::FeatureList::IsEnabled(chromeos::features::kMediaApp)) {
if (url.host_piece() == chromeos::kChromeUIMediaAppHost)
return &NewWebUI<chromeos::MediaAppUI>;
- if (url.host_piece() == chromeos::kChromeUIMediaAppGuestHost)
- return &NewWebUI<chromeos::MediaAppGuestUI>;
}
if (url.host_piece() == chromeos::multidevice::kChromeUIProximityAuthHost &&
profile->IsRegularProfile()) {
@@ -580,8 +616,6 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
return &NewWebUI<chromeos::smb_dialog::SmbShareDialogUI>;
if (url.host_piece() == chrome::kChromeUISysInternalsHost)
return &NewWebUI<SysInternalsUI>;
- if (url.host_piece() == chrome::kChromeUITerminalHost)
- return &NewWebUI<TerminalUI>;
if (url.host_piece() == chrome::kChromeUIAssistantOptInHost)
return &NewWebUI<chromeos::AssistantOptInUI>;
if (url.host_piece() == chrome::kChromeUICameraHost &&
@@ -601,6 +635,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
if (url.host_piece() == chrome::kChromeUIDeviceEmulatorHost)
return &NewWebUI<DeviceEmulatorUI>;
}
+ if (url.host_piece() == chromeos::kChromeUISampleSystemWebAppHost)
+ return &NewWebUI<chromeos::SampleSystemWebAppUI>;
#endif // !defined(OFFICIAL_BUILD)
#endif // defined(OS_CHROMEOS)
#if defined(OS_ANDROID)
@@ -654,6 +690,14 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
return &NewWebUI<WelcomeUI>;
#endif
+#if BUILDFLAG(ENABLE_KALEIDOSCOPE)
+ if (base::FeatureList::IsEnabled(media::kKaleidoscope)) {
+ if (url.host_piece() == chrome::kChromeUIKaleidoscopeHost)
+ return &NewWebUI<KaleidoscopeUI>;
+ if (url.host_piece() == chrome::kChromeUIKaleidoscopeContentHost)
+ return &NewWebUI<KaleidoscopeContentUI>;
+ }
+#endif // BUILDFLAG(ENABLE_KALEIDOSCOPE)
#if BUILDFLAG(ENABLE_NACL)
if (url.host_piece() == chrome::kChromeUINaClHost)
return &NewWebUI<NaClUI>;
@@ -723,8 +767,7 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
if (IsAboutUI(url))
return &NewWebUI<AboutUI>;
- if (base::FeatureList::IsEnabled(features::kBundledConnectionHelpFeature) &&
- url.host_piece() == security_interstitials::kChromeUIConnectionHelpHost) {
+ if (url.host_piece() == security_interstitials::kChromeUIConnectionHelpHost) {
return &NewWebUI<security_interstitials::ConnectionHelpUI>;
}
@@ -738,6 +781,16 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui,
return &NewWebUI<MediaEngagementUI>;
}
+ if (media_feeds::MediaFeedsService::IsEnabled() &&
+ url.host_piece() == chrome::kChromeUIMediaFeedsHost) {
+ return &NewWebUI<MediaFeedsUI>;
+ }
+
+ if (media_history::MediaHistoryKeyedService::IsEnabled() &&
+ url.host_piece() == chrome::kChromeUIMediaHistoryHost) {
+ return &NewWebUI<MediaHistoryUI>;
+ }
+
#if BUILDFLAG(FULL_SAFE_BROWSING)
if (url.host_piece() == chrome::kChromeUIResetPasswordHost) {
return &NewWebUI<ResetPasswordUI>;
@@ -868,6 +921,11 @@ bool ChromeWebUIControllerFactory::IsWebUIAllowedToMakeNetworkRequests(
// https://crbug.com/829414
origin.host() == chrome::kChromeUIPrintHost ||
#endif
+#if BUILDFLAG(ENABLE_KALEIDOSCOPE)
+ // TODO(https://crbug.com/1039904): This is only for prototyping purposes.
+ // Must be removed before launch.
+ origin.host() == chrome::kChromeUIKaleidoscopeContentHost ||
+#endif
// https://crbug.com/831812
origin.host() == chrome::kChromeUISyncConfirmationHost ||
// https://crbug.com/831813
diff --git a/chromium/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc b/chromium/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc
new file mode 100644
index 00000000000..d78bd9681b0
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc
@@ -0,0 +1,111 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/web_ui_browsertest_util.h"
+#include "ipc/ipc_security_test_util.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/url_constants.h"
+
+// Tests embedder specific behavior of WebUIs.
+class ChromeWebUINavigationBrowserTest : public InProcessBrowserTest {
+ public:
+ ChromeWebUINavigationBrowserTest() {
+ content::WebUIControllerFactory::RegisterFactory(&factory_);
+ }
+
+ ~ChromeWebUINavigationBrowserTest() override {
+ content::WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
+ }
+
+ protected:
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ }
+
+ private:
+ content::TestWebUIControllerFactory factory_;
+};
+
+// Verify that a browser check stops websites from embeding chrome:// iframes.
+// This is a copy of the DisallowEmbeddingChromeSchemeFromWebFrameBrowserCheck
+// test in content/browser/webui/web_ui_navigation_browsertest.cc. We need a
+// copy here because the browser side check is done by embedders.
+IN_PROC_BROWSER_TEST_F(ChromeWebUINavigationBrowserTest,
+ DisallowEmbeddingChromeSchemeFromWebFrameBrowserCheck) {
+ GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+ auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+ auto* main_frame = web_contents->GetMainFrame();
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+ // Add iframe but don't navigate it to a chrome:// URL yet.
+ EXPECT_TRUE(content::ExecJs(main_frame,
+ "var frame = document.createElement('iframe');\n"
+ "document.body.appendChild(frame);\n",
+ content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+ 1 /* world_id */));
+
+ content::RenderFrameHost* child = content::ChildFrameAt(main_frame, 0);
+ EXPECT_EQ("about:blank", child->GetLastCommittedURL());
+
+ content::TestNavigationObserver observer(web_contents);
+ GURL webui_url(content::GetWebUIURL("web-ui/title1.html?noxfo=true"));
+ content::PwnMessageHelper::OpenURL(child->GetProcess(), child->GetRoutingID(),
+ webui_url);
+ observer.Wait();
+
+ // Retrieve the RenderFrameHost again since it might have been swapped.
+ child = content::ChildFrameAt(main_frame, 0);
+ EXPECT_EQ(content::kBlockedURL, child->GetLastCommittedURL());
+}
+
+// Verify that a browser check stops websites from embeding chrome-untrusted://
+// iframes. This is a copy of the
+// DisallowEmbeddingChromeUntrustedSchemeFromWebFrameBrowserCheck test in
+// content/browser/webui/web_ui_navigation_browsertest.cc. We need a copy here
+// because the browser side check is done by embedders.
+IN_PROC_BROWSER_TEST_F(
+ ChromeWebUINavigationBrowserTest,
+ DisallowEmbeddingChromeUntrustedSchemeFromWebFrameBrowserCheck) {
+ GURL main_frame_url(embedded_test_server()->GetURL("/title1.html"));
+ auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
+ auto* main_frame = web_contents->GetMainFrame();
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), main_frame_url));
+
+ // Add iframe but don't navigate it to a chrome-untrusted:// URL yet.
+ EXPECT_TRUE(content::ExecJs(main_frame,
+ "var frame = document.createElement('iframe');\n"
+ "document.body.appendChild(frame);\n",
+ content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+ 1 /* world_id */));
+
+ content::RenderFrameHost* child = content::ChildFrameAt(main_frame, 0);
+ EXPECT_EQ("about:blank", child->GetLastCommittedURL());
+
+ content::TestNavigationObserver observer(web_contents);
+ content::TestUntrustedDataSourceCSP csp;
+ csp.no_xfo = true;
+ content::AddUntrustedDataSource(browser()->profile(), "test-iframe-host",
+ csp);
+
+ GURL untrusted_url(
+ content::GetChromeUntrustedUIURL("test-iframe-host/title1.html"));
+ content::PwnMessageHelper::OpenURL(child->GetProcess(), child->GetRoutingID(),
+ untrusted_url);
+ observer.Wait();
+
+ // Retrieve the RenderFrameHost again since it might have been swapped.
+ child = content::ChildFrameAt(main_frame, 0);
+ EXPECT_EQ(content::kBlockedURL, child->GetLastCommittedURL());
+}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/OWNERS b/chromium/chrome/browser/ui/webui/chromeos/OWNERS
index d5176c55865..8ae3630ceb9 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/OWNERS
+++ b/chromium/chrome/browser/ui/webui/chromeos/OWNERS
@@ -1,8 +1,9 @@
achuith@chromium.org
+khorimoto@chromium.org
michaelpg@chromium.org
satorux@chromium.org
stevenjb@chromium.org
xiyuan@chromium.org
-per-file network*=file://chromeos/network/OWNERS
+per-file *net*=file://chromeos/network/OWNERS
per-file drive_internals_ui.*=file://ui/file_manager/OWNERS
diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.cc
index ed686a24eec..83c0f366342 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.cc
@@ -28,14 +28,27 @@ AccountManagerErrorUI::AccountManagerErrorUI(content::WebUI* web_ui)
html_source->UseStringsJs();
html_source->AddLocalizedString(
- "errorTitle", IDS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_TITLE);
+ "secondaryAccountsDisabledErrorTitle",
+ IDS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_TITLE);
html_source->AddLocalizedString(
- "errorMessage", IDS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_TEXT);
+ "secondaryAccountsDisabledErrorMessage",
+ IDS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_TEXT);
+
+ html_source->AddLocalizedString(
+ "childUserArcDisabledErrorTitle",
+ IDS_ACCOUNT_MANAGER_CHILD_USER_ARC_DISABLED_TITLE);
+ html_source->AddLocalizedString(
+ "childUserArcDisabledErrorMessage",
+ IDS_ACCOUNT_MANAGER_CHILD_USER_ARC_DISABLED_TEXT);
+
html_source->AddLocalizedString("okButton", IDS_APP_OK);
+
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
html_source->AddResourcePath("googleg.svg",
IDR_ACCOUNT_MANAGER_WELCOME_GOOGLE_LOGO_SVG);
#endif
+ html_source->AddResourcePath("family_link_logo.svg",
+ IDR_FAMILY_LINK_LOGO_SVG);
// Add required resources.
html_source->AddResourcePath("account_manager_shared.css",
diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.h b/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.h
index 60396df2316..95e8a498e36 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.h
@@ -15,11 +15,12 @@ namespace chromeos {
class AccountManagerErrorUI : public ui::WebDialogUI {
public:
explicit AccountManagerErrorUI(content::WebUI* web_ui);
+ AccountManagerErrorUI(const AccountManagerErrorUI&) = delete;
+ AccountManagerErrorUI& operator=(const AccountManagerErrorUI&) = delete;
~AccountManagerErrorUI() override;
private:
base::WeakPtrFactory<AccountManagerErrorUI> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(AccountManagerErrorUI);
};
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc
index 11c680f159a..254f9e96092 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc
@@ -14,6 +14,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/webui_url_constants.h"
#include "components/prefs/pref_service.h"
+#include "components/user_manager/user_manager.h"
#include "ui/aura/window.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/shadow_types.h"
@@ -49,6 +50,10 @@ bool AccountManagerWelcomeDialog::ShowIfRequired() {
}
// Check if the dialog should be shown.
+ if (user_manager::UserManager::Get()
+ ->IsCurrentUserCryptohomeDataEphemeral()) {
+ return false;
+ }
PrefService* pref_service =
ProfileManager::GetActiveUserProfile()->GetPrefs();
const int num_times_shown = pref_service->GetInteger(
diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_test.js b/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_test.js
index 14a78b0d887..b9918313a13 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_test.js
+++ b/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_test.js
@@ -43,7 +43,7 @@ AccountMigrationWelcomeUITest.prototype = {
*/
testDialogUrl: function() {
// Remove slash at the end of URL if present.
- let url = window.location.href.replace(/\/$/, '');
+ const url = window.location.href.replace(/\/$/, '');
assertEquals(chrome.getVariableValue('expectedUrl'), url);
},
diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/BUILD.gn b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/BUILD.gn
index 54b63f6b00a..4e580f60306 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/BUILD.gn
@@ -5,7 +5,5 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "add_supervision.mojom",
- ]
+ sources = [ "add_supervision.mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom
index c46353f4823..b898ae72334 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom
+++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom
@@ -28,4 +28,7 @@ interface AddSupervisionHandler {
// Indicates to the system that Supervision has been enabled for the primary
// user.
NotifySupervisionEnabled();
+
+ // Configures whether we should close the dialog when pressing Escape.
+ SetCloseOnEscape(bool enabled);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc
index 626b2d4cc9a..cc951296439 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc
@@ -23,7 +23,9 @@
#include "chrome/services/app_service/public/cpp/app_registry_cache.h"
#include "components/signin/public/identity_manager/access_token_fetcher.h"
#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/scope_set.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/web_ui.h"
#include "google_apis/gaia/gaia_constants.h"
@@ -89,7 +91,7 @@ void AddSupervisionHandler::GetInstalledArcApps(
}
void AddSupervisionHandler::GetOAuthToken(GetOAuthTokenCallback callback) {
- identity::ScopeSet scopes;
+ signin::ScopeSet scopes;
scopes.insert(GaiaConstants::kKidsSupervisionSetupChildOAuth2Scope);
scopes.insert(GaiaConstants::kPeopleApiReadOnlyOAuth2Scope);
scopes.insert(GaiaConstants::kAccountsReauthOAuth2Scope);
@@ -98,7 +100,9 @@ void AddSupervisionHandler::GetOAuthToken(GetOAuthTokenCallback callback) {
oauth2_access_token_fetcher_ =
identity_manager_->CreateAccessTokenFetcherForAccount(
- identity_manager_->GetPrimaryAccountId(), "add_supervision", scopes,
+ identity_manager_->GetPrimaryAccountId(
+ signin::ConsentLevel::kNotRequired),
+ "add_supervision", scopes,
base::BindOnce(&AddSupervisionHandler::OnAccessTokenFetchComplete,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
signin::AccessTokenFetcher::Mode::kImmediate);
@@ -142,4 +146,8 @@ void AddSupervisionHandler::OnAccessTokenFetchComplete(
}
}
+void AddSupervisionHandler::SetCloseOnEscape(bool enabled) {
+ delegate_->SetCloseOnEscape(enabled);
+}
+
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h
index 8310d5bda98..1ea2c89485a 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h
@@ -36,6 +36,12 @@ class AddSupervisionHandler
// the request to close the Add Supervision dialog and return
// a boolean to indicate whether the dialog is closing.
virtual bool CloseDialog() = 0;
+
+ // Allows controlling the behavior of the Add Supervision dialog when
+ // the user presses Escape (if enabled, Escape closes the dialog).
+ // Disabling the Escape key allows using it for actions inside the
+ // webview itself (e.g., as an accessibility shortcut).
+ virtual void SetCloseOnEscape(bool) = 0;
};
// |delegate| is owned by the caller and its lifetime must outlive |this|.
@@ -53,6 +59,7 @@ class AddSupervisionHandler
void GetOAuthToken(GetOAuthTokenCallback callback) override;
void LogOut() override;
void NotifySupervisionEnabled() override;
+ void SetCloseOnEscape(bool enabled) override;
private:
void OnAccessTokenFetchComplete(GetOAuthTokenCallback callback,
diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc
index 6579db46102..621e632159c 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc
@@ -82,9 +82,10 @@ void AddSupervisionDialog::Show(gfx::NativeView parent) {
}
// static
-SystemWebDialogDelegate* AddSupervisionDialog::GetInstance() {
- return SystemWebDialogDelegate::FindInstance(
- chrome::kChromeUIAddSupervisionURL);
+AddSupervisionDialog* AddSupervisionDialog::GetInstance() {
+ return static_cast<AddSupervisionDialog*>(
+ SystemWebDialogDelegate::FindInstance(
+ chrome::kChromeUIAddSupervisionURL));
}
// static
@@ -95,6 +96,14 @@ void AddSupervisionDialog::Close() {
}
}
+// static
+void AddSupervisionDialog::SetCloseOnEscape(bool enabled) {
+ AddSupervisionDialog* current_instance = GetInstance();
+ if (current_instance) {
+ current_instance->should_close_on_escape_ = enabled;
+ }
+}
+
void AddSupervisionDialog::CloseNowForTesting() {
SystemWebDialogDelegate* current_instance = GetInstance();
if (current_instance) {
@@ -123,6 +132,10 @@ bool AddSupervisionDialog::OnDialogCloseRequested() {
return true;
}
+bool AddSupervisionDialog::ShouldCloseDialogOnEscape() const {
+ return should_close_on_escape_;
+}
+
AddSupervisionDialog::AddSupervisionDialog()
: SystemWebDialogDelegate(GURL(chrome::kChromeUIAddSupervisionURL),
base::string16()) {}
@@ -136,16 +149,15 @@ signin::IdentityManager* AddSupervisionUI::test_identity_manager_ = nullptr;
AddSupervisionUI::AddSupervisionUI(content::WebUI* web_ui)
: ui::MojoWebUIController(web_ui) {
- // Register the Mojo API handler.
- AddHandlerToRegistry(base::BindRepeating(
- &AddSupervisionUI::BindAddSupervisionHandler, base::Unretained(this)));
-
// Set up the basic page framework.
SetUpResources();
}
+WEB_UI_CONTROLLER_TYPE_IMPL(AddSupervisionUI)
+
AddSupervisionUI::~AddSupervisionUI() = default;
+// AddSupervisionHandler::Delegate:
bool AddSupervisionUI::CloseDialog() {
bool showing_confirm_dialog = MaybeShowConfirmSignoutDialog();
if (!showing_confirm_dialog) {
@@ -155,12 +167,17 @@ bool AddSupervisionUI::CloseDialog() {
return !showing_confirm_dialog;
}
+// AddSupervisionHandler::Delegate:
+void AddSupervisionUI::SetCloseOnEscape(bool enabled) {
+ AddSupervisionDialog::SetCloseOnEscape(enabled);
+}
+
// static
void AddSupervisionUI::SetUpForTest(signin::IdentityManager* identity_manager) {
test_identity_manager_ = identity_manager;
}
-void AddSupervisionUI::BindAddSupervisionHandler(
+void AddSupervisionUI::BindInterface(
mojo::PendingReceiver<add_supervision::mojom::AddSupervisionHandler>
receiver) {
signin::IdentityManager* identity_manager =
diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h
index a05b13f8b31..4fb2d6ad691 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/macros.h"
-#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h"
+#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom-forward.h"
#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h"
#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -28,7 +28,7 @@ class AddSupervisionDialog : public SystemWebDialogDelegate {
// no-op.
static void Show(gfx::NativeView parent);
- static SystemWebDialogDelegate* GetInstance();
+ static AddSupervisionDialog* GetInstance();
// Closes the dialog; if the dialog doesn't exist, this function is a
// no-op.
@@ -36,6 +36,10 @@ class AddSupervisionDialog : public SystemWebDialogDelegate {
// right.
static void Close();
+ // Updates the ShouldCloseDialogOnEscape() state (i.e., whether pressing
+ // Escape closes the main dialog).
+ static void SetCloseOnEscape(bool enabled);
+
// Deletes this dialog window.
// Currently only used by AddSupervisionMetricsRecorderTest browser test to
// simulate closing the dialog cleanly.
@@ -46,12 +50,15 @@ class AddSupervisionDialog : public SystemWebDialogDelegate {
void GetDialogSize(gfx::Size* size) const override;
bool CanCloseDialog() const override;
bool OnDialogCloseRequested() override;
+ bool ShouldCloseDialogOnEscape() const override;
protected:
AddSupervisionDialog();
~AddSupervisionDialog() override;
private:
+ bool should_close_on_escape_ = true;
+
DISALLOW_COPY_AND_ASSIGN(AddSupervisionDialog);
};
@@ -64,13 +71,17 @@ class AddSupervisionUI : public ui::MojoWebUIController,
// AddSupervisionHandler::Delegate:
bool CloseDialog() override;
+ void SetCloseOnEscape(bool) override;
static void SetUpForTest(signin::IdentityManager* identity_manager);
- private:
- void BindAddSupervisionHandler(
+ // Instantiates the implementor of the mojom::AddSupervisionHandler mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<add_supervision::mojom::AddSupervisionHandler>
receiver);
+
+ private:
void SetUpResources();
GURL GetAddSupervisionURL();
@@ -82,6 +93,8 @@ class AddSupervisionUI : public ui::MojoWebUIController,
static signin::IdentityManager* test_identity_manager_;
bool allow_non_google_url_for_tests_ = false;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(AddSupervisionUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc
index a61830e3ee6..6d23c70d104 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc
@@ -47,7 +47,8 @@ class AddSupervisionBrowserTest : public InProcessBrowserTest {
// TODO(danan): See if this is possible to do this instead using
// FakeGaia.IssueOAuthToken().
identity_test_env_ = std::make_unique<signin::IdentityTestEnvironment>();
- identity_test_env_->MakePrimaryAccountAvailable("example@gmail.com");
+ identity_test_env_->MakeUnconsentedPrimaryAccountAvailable(
+ "example@gmail.com");
// This makes the identity manager return the string "access_token" for the
// access token.
identity_test_env_->SetAutomaticIssueOfAccessTokens(true);
diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.cc
index f9594134ec5..ff42bc9e1ee 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.cc
@@ -29,11 +29,11 @@ const int kDialogBodyTextWidth = 250;
} // namespace
ConfirmSignoutDialog::ConfirmSignoutDialog() {
- DialogDelegate::set_button_label(
+ DialogDelegate::SetButtonLabel(
ui::DIALOG_BUTTON_OK,
l10n_util::GetStringUTF16(
IDS_ADD_SUPERVISION_EXIT_DIALOG_SIGNOUT_BUTTON_LABEL));
- DialogDelegate::set_button_label(
+ DialogDelegate::SetButtonLabel(
ui::DIALOG_BUTTON_CANCEL,
l10n_util::GetStringUTF16(
IDS_ADD_SUPERVISION_EXIT_DIALOG_CANCEL_BUTTON_LABEL));
@@ -69,11 +69,6 @@ bool ConfirmSignoutDialog::Accept() {
return true;
}
-int ConfirmSignoutDialog::GetDialogButtons() const {
- return ui::DialogButton::DIALOG_BUTTON_OK |
- ui::DialogButton::DIALOG_BUTTON_CANCEL;
-}
-
// static
views::Widget* ConfirmSignoutDialog::current_instance_ = nullptr;
diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.h
index c8d7a820a6b..6e37acc2286 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.h
@@ -28,7 +28,6 @@ class ConfirmSignoutDialog : public views::DialogDelegateView {
// views::DialogDelegate:
bool Accept() override;
- int GetDialogButtons() const override;
static void Show();
static bool IsShowing();
diff --git a/chromium/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
index 78ff6eb1c28..1c281a9e6e2 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_handler.cc
@@ -20,6 +20,7 @@
#include "base/strings/string_tokenizer.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "chrome/browser/chromeos/arc/tracing/arc_graphics_jank_detector.h"
#include "chrome/browser/chromeos/arc/tracing/arc_system_model.h"
@@ -550,9 +551,8 @@ void ArcGraphicsTracingHandler::OnTracingStopped(
? GetLastTracingModelPath(profile)
: GetModelPathFromTitle(profile, active_task_title_);
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&BuildGraphicsModel, std::move(string_data), mode_,
active_task_title_, active_task_icon_png_, timestamp_,
std::move(system_stat_colletor_), tracing_time_min_,
@@ -576,9 +576,8 @@ void ArcGraphicsTracingHandler::HandleReady(const base::ListValue* args) {
if (mode_ != ArcGraphicsTracingMode::kFull)
return;
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&MaybeLoadLastGraphicsModel,
GetLastTracingModelPath(Profile::FromWebUI(web_ui()))),
base::BindOnce(&ArcGraphicsTracingHandler::OnGraphicsModelReady,
@@ -616,9 +615,8 @@ void ArcGraphicsTracingHandler::HandleLoadFromText(
return;
}
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&LoadGraphicsModel,
std::move(args->GetList()[0].GetString())),
base::BindOnce(&ArcGraphicsTracingHandler::OnGraphicsModelReady,
diff --git a/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
index 1ce28bd4be0..a94dae7c438 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
@@ -139,9 +139,7 @@ void AssistantOptInDialog::Show(
ash::AssistantSetup::StartAssistantOptInFlowCallback callback) {
#if !BUILDFLAG(ENABLE_CROS_LIBASSISTANT)
std::move(callback).Run(false);
- return;
-#endif
-
+#else
// Check Assistant allowed state.
if (::assistant::IsAssistantAllowedForProfile(
ProfileManager::GetActiveUserProfile()) !=
@@ -165,6 +163,7 @@ void AssistantOptInDialog::Show(
g_dialog = new AssistantOptInDialog(type, std::move(callback));
g_dialog->ShowSystemDialog();
+#endif
}
// static
diff --git a/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.cc b/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.cc
index 5fb5c3d2674..ca213a49b56 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.cc
@@ -18,6 +18,7 @@
#include "components/arc/arc_prefs.h"
#include "components/consent_auditor/consent_auditor.h"
#include "components/prefs/pref_service.h"
+#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/user_manager/user_manager.h"
#include "ui/base/l10n/l10n_util.h"
@@ -220,14 +221,17 @@ base::Value GetSettingsUiStrings(const assistant::SettingsUi& settings_ui,
return dictionary;
}
-using sync_pb::UserConsentTypes;
void RecordActivityControlConsent(Profile* profile,
std::string ui_audit_key,
bool opted_in) {
auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
- DCHECK(identity_manager->HasPrimaryAccount());
- const CoreAccountId account_id = identity_manager->GetPrimaryAccountId();
+ // This function doesn't care about browser sync consent.
+ DCHECK(
+ identity_manager->HasPrimaryAccount(signin::ConsentLevel::kNotRequired));
+ const CoreAccountId account_id =
+ identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kNotRequired);
+ using sync_pb::UserConsentTypes;
UserConsentTypes::AssistantActivityControlConsent consent;
consent.set_ui_audit_key(ui_audit_key);
consent.set_status(opted_in ? UserConsentTypes::GIVEN
diff --git a/chromium/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.cc
index b5015697f6f..c1e8120e9b8 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/webui/web_ui_util.h"
namespace chromeos {
namespace bluetooth_dialog {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/OWNERS b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/OWNERS
index e26edaf5262..f49c978c6a9 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/OWNERS
+++ b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/OWNERS
@@ -1,2 +1,3 @@
+azeemarshad@chromium.org
khorimoto@chromium.org
tbarzic@chromium.org
diff --git a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.cc
index 0468a85373a..c9c2b3e42a3 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.cc
@@ -123,20 +123,18 @@ CellularSetupDialogUI::CellularSetupDialogUI(content::WebUI* web_ui)
}
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
-
- // Add Mojo bindings to this WebUI so that Mojo calls can occur in JavaScript.
- AddHandlerToRegistry(base::BindRepeating(
- &CellularSetupDialogUI::BindCellularSetup, base::Unretained(this)));
}
CellularSetupDialogUI::~CellularSetupDialogUI() = default;
-void CellularSetupDialogUI::BindCellularSetup(
+void CellularSetupDialogUI::BindInterface(
mojo::PendingReceiver<mojom::CellularSetup> receiver) {
GetOrCreateServiceHolder(web_ui()->GetWebContents()->GetBrowserContext())
->BindReceiver(std::move(receiver));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(CellularSetupDialogUI)
+
} // namespace cellular_setup
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h
index 53b9ebffd69..6b7f05ee2da 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
-#include "chromeos/services/cellular_setup/public/mojom/cellular_setup.mojom.h"
+#include "chromeos/services/cellular_setup/public/mojom/cellular_setup.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/web_dialogs/web_dialog_ui.h"
@@ -40,9 +40,12 @@ class CellularSetupDialogUI : public ui::MojoWebDialogUI {
explicit CellularSetupDialogUI(content::WebUI* web_ui);
~CellularSetupDialogUI() override;
- private:
- void BindCellularSetup(mojo::PendingReceiver<mojom::CellularSetup> receiver);
+ // Instantiates implementor of the mojom::CellularSetup mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(mojo::PendingReceiver<mojom::CellularSetup> receiver);
+ private:
+ WEB_UI_CONTROLLER_TYPE_DECL();
DISALLOW_COPY_AND_ASSIGN(CellularSetupDialogUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
index 7a902928f0b..ed762b3237d 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
@@ -9,6 +9,7 @@
#include "components/login/localized_values_builder.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/webui/web_ui_util.h"
namespace chromeos {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.cc
index 542665cbd5a..2264f8ecfdb 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_dialog.cc
@@ -10,9 +10,9 @@
#include "chrome/browser/ui/simple_message_box.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
+#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
-#include "components/device_event_log/device_event_log.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/size.h"
@@ -54,7 +54,7 @@ void MobileSetupDialog::ShowByNetworkId(const std::string& network_id) {
NET_LOG(ERROR) << "MobileSetupDialog: Network ID not found: " << network_id;
return;
}
- NET_LOG(EVENT) << "Opening MobileSetupDialog, ID: " << network_id;
+ NET_LOG(EVENT) << "Opening MobileSetupDialog, ID: " << NetworkId(network);
dialog_instance = new MobileSetupDialog(*network);
dialog_instance->ShowSystemDialog();
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.cc
index 98688041836..4e225777c4f 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/cellular_setup/mobile_setup_ui.cc
@@ -27,10 +27,10 @@
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/network/device_state.h"
+#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/network_state_handler_observer.h"
-#include "components/device_event_log/device_event_log.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
@@ -114,7 +114,8 @@ base::string16 GetActivationErrorMessage(MobileActivator::ActivationError error,
void DataRequestFailed(const std::string& service_path,
content::URLDataSource::GotDataCallback callback) {
- NET_LOG(ERROR) << "Data Request Failed for Mobile Setup: " << service_path;
+ NET_LOG(ERROR) << "Data Request Failed for Mobile Setup: "
+ << NetworkPathId(service_path);
scoped_refptr<base::RefCountedBytes> html_bytes(new base::RefCountedBytes);
std::move(callback).Run(html_bytes.get());
}
@@ -283,14 +284,16 @@ void MobileSetupUIHTMLSource::StartDataRequest(
}
if (!network->Matches(NetworkTypePattern::Cellular())) {
- NET_LOG(ERROR) << "Mobile setup attempt for non cellular network: " << path;
+ NET_LOG(ERROR) << "Mobile setup attempt for non cellular network: "
+ << NetworkId(network);
DataRequestFailed(path, std::move(callback));
return;
}
if (network->payment_url().empty() &&
network->activation_state() != shill::kActivationStateActivated) {
- NET_LOG(ERROR) << "Mobile setup network in unexpected state: " << path
+ NET_LOG(ERROR) << "Mobile setup network in unexpected state: "
+ << NetworkId(network)
<< " payment_url: " << network->payment_url()
<< " activation_state: " << network->activation_state();
DataRequestFailed(path, std::move(callback));
@@ -307,7 +310,7 @@ void MobileSetupUIHTMLSource::StartDataRequest(
return;
}
- NET_LOG(EVENT) << "Starting mobile setup: " << path;
+ NET_LOG(EVENT) << "Starting mobile setup: " << NetworkId(network);
base::DictionaryValue strings;
strings.SetString(
@@ -441,7 +444,7 @@ void MobileSetupHandler::HandleStartActivation(const base::ListValue* args) {
if (path.empty())
return;
- NET_LOG(EVENT) << "Starting activation for service: " << path;
+ NET_LOG(EVENT) << "Starting activation for service: " << NetworkPathId(path);
active_ = true;
AllowJavascript();
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/BUILD.gn b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/BUILD.gn
index 78b16833763..10e8045874e 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/BUILD.gn
@@ -5,11 +5,8 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "crostini_installer.mojom",
- ]
+ sources = [ "crostini_installer.mojom" ]
- public_deps = [
- "//chrome/browser/chromeos/crostini:crostini_installer_types_mojom",
- ]
+ public_deps =
+ [ "//chrome/browser/chromeos/crostini:crostini_installer_types_mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/OWNERS b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/OWNERS
index 08850f42120..3a2b81f71a5 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/OWNERS
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/OWNERS
@@ -1,2 +1,6 @@
+file://chrome/browser/chromeos/guest_os/OWNERS
+
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+# COMPONENT: UI>Shell>Containers
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom
index d67ac5ac6dd..b2e95d941ac 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom
@@ -4,7 +4,7 @@
module chromeos.crostini_installer.mojom;
-import "chrome/browser/chromeos/crostini/crostini_installer_types.mojom";
+import "chrome/browser/chromeos/crostini/crostini_types.mojom";
// Lives in the browser process. A renderer uses this to create a page handler
// for controlling Crostini installation.
@@ -17,8 +17,9 @@ interface PageHandlerFactory {
// Lives in the browser process. A renderer use this to control Crostini
// installation.
interface PageHandler {
- // Start installation
- Install();
+ // Start installation, |disk_size| is in bytes, username is the user's
+ // desired username for inside the container.
+ Install(int64 disk_size, string username);
// Cancel an on-going installation
Cancel();
// If a user cancels the installation without starting it at all, this should
@@ -28,6 +29,9 @@ interface PageHandler {
// chrome.send('dialogClose') should not be used, which could kill the page
// handler before previous mojom calls have been run.
Close();
+ // Fetches the amount of free disk space, the result is sent via
+ // OnAmountOfFreeDiskSpace.
+ RequestAmountOfFreeDiskSpace();
};
// Lives in the renderer process. The browser uses this to sends installation
@@ -43,4 +47,7 @@ interface Page {
// After user cancels the installation, this is called when the cancellation
// finishes.
OnCanceled();
+ // Used to tell the UI how much disk space is available.
+ OnAmountOfFreeDiskSpace(array<crostini.mojom.DiskSliderTick> ticks,
+ int8 default_index);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc
index a22310fd5e0..b3f75d222e5 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc
@@ -4,6 +4,8 @@
#include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.h"
+#include "base/bind_helpers.h"
+#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/crostini/crostini_features.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
#include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h"
@@ -23,7 +25,8 @@ GURL GetUrl() {
namespace chromeos {
-void CrostiniInstallerDialog::Show(Profile* profile) {
+void CrostiniInstallerDialog::Show(Profile* profile,
+ OnLoadedCallback on_loaded_callback) {
DCHECK(crostini::CrostiniFeatures::Get()->IsUIAllowed(profile));
auto* instance = SystemWebDialogDelegate::FindInstance(GetUrl().spec());
if (instance) {
@@ -33,20 +36,25 @@ void CrostiniInstallerDialog::Show(Profile* profile) {
// TODO(lxj): Move installer status tracking into the CrostiniInstaller.
DCHECK(!crostini::CrostiniManager::GetForProfile(profile)
- ->GetInstallerViewStatus());
- crostini::CrostiniManager::GetForProfile(profile)->SetInstallerViewStatus(
- true);
+ ->GetCrostiniDialogStatus(crostini::DialogType::INSTALLER));
+ crostini::CrostiniManager::GetForProfile(profile)->SetCrostiniDialogStatus(
+ crostini::DialogType::INSTALLER, true);
- instance = new CrostiniInstallerDialog(profile);
+ instance =
+ new CrostiniInstallerDialog(profile, std::move(on_loaded_callback));
instance->ShowSystemDialog();
}
-CrostiniInstallerDialog::CrostiniInstallerDialog(Profile* profile)
- : SystemWebDialogDelegate{GetUrl(), /*title=*/{}}, profile_{profile} {}
+CrostiniInstallerDialog::CrostiniInstallerDialog(
+ Profile* profile,
+ OnLoadedCallback on_loaded_callback)
+ : SystemWebDialogDelegate(GetUrl(), /*title=*/base::string16()),
+ profile_(profile),
+ on_loaded_callback_(std::move(on_loaded_callback)) {}
CrostiniInstallerDialog::~CrostiniInstallerDialog() {
- crostini::CrostiniManager::GetForProfile(profile_)->SetInstallerViewStatus(
- false);
+ crostini::CrostiniManager::GetForProfile(profile_)->SetCrostiniDialogStatus(
+ crostini::DialogType::INSTALLER, false);
}
void CrostiniInstallerDialog::GetDialogSize(gfx::Size* size) const {
@@ -57,6 +65,13 @@ bool CrostiniInstallerDialog::ShouldShowCloseButton() const {
return false;
}
+// TODO(crbug.com/1053376): We should add a browser test for the dialog to check
+// that <esc> or X button in overview mode cannot close the dialog immediately
+// without the web page noticing it.
+bool CrostiniInstallerDialog::ShouldCloseDialogOnEscape() const {
+ return false;
+}
+
void CrostiniInstallerDialog::AdjustWidgetInitParams(
views::Widget::InitParams* params) {
params->z_order = ui::ZOrderLevel::kNormal;
@@ -81,4 +96,11 @@ void CrostiniInstallerDialog::OnCloseContents(content::WebContents* source,
return SystemWebDialogDelegate::OnCloseContents(source, out_close_dialog);
}
+void CrostiniInstallerDialog::OnWebContentsFinishedLoad() {
+ if (!on_loaded_callback_.is_null()) {
+ DCHECK(installer_ui_);
+ std::move(on_loaded_callback_).Run(installer_ui_);
+ }
+}
+
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.h
index 2c96d9f2f9a..5bd803e0e17 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_CROSTINI_INSTALLER_CROSTINI_INSTALLER_DIALOG_H_
#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CROSTINI_INSTALLER_CROSTINI_INSTALLER_DIALOG_H_
+#include "base/callback.h"
#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
class Profile;
@@ -15,23 +16,31 @@ class CrostiniInstallerUI;
class CrostiniInstallerDialog : public SystemWebDialogDelegate {
public:
- static void Show(Profile* profile);
+ using OnLoadedCallback = base::OnceCallback<void(CrostiniInstallerUI*)>;
+
+ // |on_loaded_callback| is ignored if the dialog is already showing.
+ static void Show(Profile* profile,
+ OnLoadedCallback on_loaded_callback = OnLoadedCallback());
private:
- explicit CrostiniInstallerDialog(Profile* profile);
+ CrostiniInstallerDialog(Profile* profile,
+ OnLoadedCallback on_loaded_callback);
~CrostiniInstallerDialog() override;
// SystemWebDialogDelegate:
void GetDialogSize(gfx::Size* size) const override;
bool ShouldShowCloseButton() const override;
+ bool ShouldCloseDialogOnEscape() const override;
void AdjustWidgetInitParams(views::Widget::InitParams* params) override;
bool CanCloseDialog() const override;
void OnDialogShown(content::WebUI* webui) override;
void OnCloseContents(content::WebContents* source,
bool* out_close_dialog) override;
+ void OnWebContentsFinishedLoad() override;
Profile* profile_;
CrostiniInstallerUI* installer_ui_ = nullptr;
+ OnLoadedCallback on_loaded_callback_;
};
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.cc
index 6e78fc63ba0..a92cd9390f9 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.cc
@@ -4,11 +4,28 @@
#include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h"
+#include <algorithm>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/optional.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/system/sys_info.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/chromeos/crostini/crostini_installer_ui_delegate.h"
+#include "chrome/browser/chromeos/crostini/crostini_types.mojom.h"
+#include "chrome/browser/chromeos/crostini/crostini_util.h"
+#include "chromeos/constants/chromeos_features.h"
+#include "ui/base/text/bytes_formatting.h"
+
+namespace {
+std::string FormatBytes(const int64_t value) {
+ return base::UTF16ToUTF8(ui::FormatBytes(value));
+}
+} // namespace
namespace chromeos {
@@ -25,11 +42,17 @@ CrostiniInstallerPageHandler::CrostiniInstallerPageHandler(
CrostiniInstallerPageHandler::~CrostiniInstallerPageHandler() = default;
-void CrostiniInstallerPageHandler::Install() {
- // TODO(crbug.com/1016195): Web page should allow input container username,
- // and here we will pass that to Install().
+void CrostiniInstallerPageHandler::Install(int64_t disk_size_bytes,
+ const std::string& username) {
+ crostini::CrostiniManager::RestartOptions options{};
+ if (base::FeatureList::IsEnabled(chromeos::features::kCrostiniDiskResizing)) {
+ options.disk_size_bytes = disk_size_bytes;
+ }
+ if (base::FeatureList::IsEnabled(chromeos::features::kCrostiniUsername)) {
+ options.container_username = username;
+ }
installer_ui_delegate_->Install(
- crostini::CrostiniManager::RestartOptions{},
+ std::move(options),
base::BindRepeating(&CrostiniInstallerPageHandler::OnProgressUpdate,
weak_ptr_factory_.GetWeakPtr()),
base::BindOnce(&CrostiniInstallerPageHandler::OnInstallFinished,
@@ -65,4 +88,27 @@ void CrostiniInstallerPageHandler::OnCanceled() {
page_->OnCanceled();
}
+void CrostiniInstallerPageHandler::RequestAmountOfFreeDiskSpace() {
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()},
+ base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace,
+ base::FilePath(crostini::kHomeDirectory)),
+ base::BindOnce(&CrostiniInstallerPageHandler::OnAmountOfFreeDiskSpace,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CrostiniInstallerPageHandler::OnAmountOfFreeDiskSpace(int64_t free_bytes) {
+ std::vector<int64_t> values = crostini::GetTicksForDiskSize(
+ crostini::CrostiniInstallerUIDelegate::kMinimumFreeDiskSpace, free_bytes);
+
+ std::vector<crostini::mojom::DiskSliderTickPtr> ticks;
+ for (const auto& val : values) {
+ std::string formatted_val = FormatBytes(val);
+ ticks.emplace_back(crostini::mojom::DiskSliderTick::New(val, formatted_val,
+ formatted_val));
+ }
+ // TODO(crbug/1043837): Pick a better default than always the minimum.
+ page_->OnAmountOfFreeDiskSpace(std::move(ticks), 0);
+}
+
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h
index 9060a95057b..94128cd43f6 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h
@@ -8,7 +8,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "chrome/browser/chromeos/crostini/crostini_installer_types.mojom-forward.h"
+#include "chrome/browser/chromeos/crostini/crostini_types.mojom-forward.h"
#include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -34,16 +34,18 @@ class CrostiniInstallerPageHandler
~CrostiniInstallerPageHandler() override;
// chromeos::crostini_installer::mojom::PageHandler:
- void Install() override;
+ void Install(int64_t disk_size_bytes, const std::string& username) override;
void Cancel() override;
void CancelBeforeStart() override;
void Close() override;
+ void RequestAmountOfFreeDiskSpace() override;
private:
void OnProgressUpdate(crostini::mojom::InstallerState installer_state,
double progress_fraction);
void OnInstallFinished(crostini::mojom::InstallerError error);
void OnCanceled();
+ void OnAmountOfFreeDiskSpace(int64_t free_bytes);
crostini::CrostiniInstallerUIDelegate* installer_ui_delegate_;
mojo::Receiver<chromeos::crostini_installer::mojom::PageHandler> receiver_;
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc
index b81f73de748..c1d13524b07 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/strings/string16.h"
#include "base/system/sys_info.h"
#include "chrome/browser/chromeos/crostini/crostini_installer.h"
@@ -23,6 +24,7 @@
#include "content/public/browser/web_ui_data_source.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/text/bytes_formatting.h"
+#include "ui/base/webui/web_ui_util.h"
#include "ui/chromeos/devicetype_utils.h"
#include "ui/resources/grit/webui_resources.h"
#include "ui/strings/grit/ui_strings.h"
@@ -32,6 +34,8 @@
namespace {
void AddStringResources(content::WebUIDataSource* source) {
static constexpr webui::LocalizedString kStrings[] = {
+ {"next", IDS_CROSTINI_INSTALLER_NEXT_BUTTON},
+ {"back", IDS_CROSTINI_INSTALLER_BACK_BUTTON},
{"install", IDS_CROSTINI_INSTALLER_INSTALL_BUTTON},
{"retry", IDS_CROSTINI_INSTALLER_RETRY_BUTTON},
{"close", IDS_APP_CLOSE},
@@ -52,6 +56,7 @@ void AddStringResources(content::WebUIDataSource* source) {
{"fetchSshKeysError", IDS_CROSTINI_INSTALLER_FETCH_SSH_KEYS_ERROR},
{"mountContainerError", IDS_CROSTINI_INSTALLER_MOUNT_CONTAINER_ERROR},
{"setupContainerError", IDS_CROSTINI_INSTALLER_SETUP_CONTAINER_ERROR},
+ {"unknownError", IDS_CROSTINI_INSTALLER_UNKNOWN_ERROR},
{"loadTerminaMessage", IDS_CROSTINI_INSTALLER_LOAD_TERMINA_MESSAGE},
{"startConciergeMessage", IDS_CROSTINI_INSTALLER_START_CONCIERGE_MESSAGE},
@@ -66,6 +71,16 @@ void AddStringResources(content::WebUIDataSource* source) {
{"fetchSshKeysMessage", IDS_CROSTINI_INSTALLER_FETCH_SSH_KEYS_MESSAGE},
{"mountContainerMessage", IDS_CROSTINI_INSTALLER_MOUNT_CONTAINER_MESSAGE},
{"cancelingMessage", IDS_CROSTINI_INSTALLER_CANCELING},
+
+ {"configureMessage", IDS_CROSTINI_INSTALLER_CONFIGURE_MESSAGE},
+ {"diskSizeMessage", IDS_CROSTINI_INSTALLER_DISK_SIZE_MESSAGE},
+ {"usernameMessage", IDS_CROSTINI_INSTALLER_USERNAME_MESSAGE},
+ {"usernameInvalidFirstCharacterError",
+ IDS_CROSTINI_INSTALLER_USERNAME_INVALID_FIRST_CHARACTER_ERROR},
+ {"usernameInvalidCharactersError",
+ IDS_CROSTINI_INSTALLER_USERNAME_INVALID_CHARACTERS_ERROR},
+ {"usernameNotAvailableError",
+ IDS_CROSTINI_INSTALLER_USERNAME_NOT_AVAILABLE_ERROR},
};
AddLocalizedStringsBulk(source, kStrings);
@@ -101,25 +116,29 @@ void AddStringResources(content::WebUIDataSource* source) {
namespace chromeos {
-bool CrostiniInstallerUI::IsEnabled() {
- return base::FeatureList::IsEnabled(
- chromeos::features::kCrostiniWebUIInstaller);
-}
-
CrostiniInstallerUI::CrostiniInstallerUI(content::WebUI* web_ui)
: ui::MojoWebDialogUI{web_ui} {
content::WebUIDataSource* source =
content::WebUIDataSource::Create(chrome::kChromeUICrostiniInstallerHost);
+ auto* profile = Profile::FromWebUI(web_ui);
source->OverrideContentSecurityPolicyScriptSrc(
"script-src chrome://resources chrome://test 'self';");
AddStringResources(source);
+ source->AddBoolean(
+ "diskResizingEnabled",
+ base::FeatureList::IsEnabled(chromeos::features::kCrostiniDiskResizing));
+ source->AddBoolean(
+ "crostiniCustomUsername",
+ base::FeatureList::IsEnabled(chromeos::features::kCrostiniUsername));
+ source->AddString("defaultContainerUsername",
+ crostini::DefaultContainerUserNameForProfile(profile));
source->AddResourcePath("app.js", IDR_CROSTINI_INSTALLER_APP_JS);
source->AddResourcePath("browser_proxy.js",
IDR_CROSTINI_INSTALLER_BROWSER_PROXY_JS);
source->AddResourcePath("crostini_installer.mojom-lite.js",
IDR_CROSTINI_INSTALLER_MOJO_LITE_JS);
- source->AddResourcePath("crostini_installer_types.mojom-lite.js",
+ source->AddResourcePath("crostini_types.mojom-lite.js",
IDR_CROSTINI_INSTALLER_TYPES_MOJO_LITE_JS);
source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER);
source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER);
@@ -129,10 +148,7 @@ CrostiniInstallerUI::CrostiniInstallerUI(content::WebUI* web_ui)
source->UseStringsJs();
source->EnableReplaceI18nInJS();
- content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
-
- AddHandlerToRegistry(base::BindRepeating(
- &CrostiniInstallerUI::BindPageHandlerFactory, base::Unretained(this)));
+ content::WebUIDataSource::Add(profile, source);
}
CrostiniInstallerUI::~CrostiniInstallerUI() = default;
@@ -141,7 +157,19 @@ bool CrostiniInstallerUI::can_close() {
return can_close_;
}
-void CrostiniInstallerUI::BindPageHandlerFactory(
+void CrostiniInstallerUI::ClickInstallForTesting() {
+ web_ui()->GetWebContents()->GetMainFrame()->ExecuteJavaScriptForTests(
+ base::ASCIIToUTF16(
+ "const app = document.querySelector('crostini-installer-app');"
+ // If flag CrostiniUsername or CrostiniDiskResizing is turned on,
+ // there will be a "next" button and we should click it to go to the
+ // config page before clicking "install" button.
+ "app.$$('#next:not([hidden])')?.click();"
+ "app.$.install.click();"),
+ base::NullCallback());
+}
+
+void CrostiniInstallerUI::BindInterface(
mojo::PendingReceiver<
chromeos::crostini_installer::mojom::PageHandlerFactory>
pending_receiver) {
@@ -174,4 +202,6 @@ void CrostiniInstallerUI::OnWebUICloseDialog() {
ui::MojoWebDialogUI::CloseDialog(nullptr);
}
+WEB_UI_CONTROLLER_TYPE_IMPL(CrostiniInstallerUI)
+
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h
index f59bc1886b5..8f4fee5f139 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h
@@ -21,19 +21,19 @@ class CrostiniInstallerUI
: public ui::MojoWebDialogUI,
public chromeos::crostini_installer::mojom::PageHandlerFactory {
public:
- static bool IsEnabled();
-
explicit CrostiniInstallerUI(content::WebUI* web_ui);
~CrostiniInstallerUI() override;
bool can_close();
+ void ClickInstallForTesting();
- private:
- void BindPageHandlerFactory(
- mojo::PendingReceiver<
- chromeos::crostini_installer::mojom::PageHandlerFactory>
- pending_receiver);
+ // Instantiates implementor of the mojom::PageHandlerFactory
+ // mojo interface passing the pending receiver that will be internally bound.
+ void BindInterface(mojo::PendingReceiver<
+ chromeos::crostini_installer::mojom::PageHandlerFactory>
+ pending_receiver);
+ private:
// chromeos::crostini_installer::mojom::PageHandlerFactory:
void CreatePageHandler(
mojo::PendingRemote<chromeos::crostini_installer::mojom::Page>
@@ -48,6 +48,8 @@ class CrostiniInstallerUI
page_factory_receiver_{this};
bool can_close_ = false;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(CrostiniInstallerUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/BUILD.gn b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/BUILD.gn
index 9ec07204dbd..bccf718e7c8 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/BUILD.gn
@@ -5,7 +5,5 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "crostini_upgrader.mojom",
- ]
+ sources = [ "crostini_upgrader.mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/OWNERS b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/OWNERS
index 08850f42120..3a2b81f71a5 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/OWNERS
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/OWNERS
@@ -1,2 +1,6 @@
+file://chrome/browser/chromeos/guest_os/OWNERS
+
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+# COMPONENT: UI>Shell>Containers
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom
index 3876fea7ec8..7f01682dc54 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom
@@ -4,6 +4,18 @@
module chromeos.crostini_upgrader.mojom;
+enum UpgradePrecheckStatus {
+ // Good to continue
+ OK,
+ // No network connectivity
+ NETWORK_FAILURE,
+ // Battery is low and not charging
+ LOW_POWER,
+ // Not enough space to do the upgrade
+ INSUFFICIENT_SPACE
+};
+
+
// Lives in the browser process. A renderer uses this to create a page handler
// for controlling Crostini upgrade.
interface PageHandlerFactory {
@@ -15,8 +27,12 @@ interface PageHandlerFactory {
// Lives in the browser process. A renderer uses this to control Crostini
// upgrade.
interface PageHandler {
- // Backup the existing container.
- Backup();
+ // Backup the existing container. If |show_file_chooser| is true, the
+ // user will be shown a dialog to decide where to store the backup.
+ Backup(bool show_file_chooser);
+ // Start running upgrade prechecks. Result is asynchronously
+ // returned via Page::PrecheckStatus.
+ StartPrechecks();
// Start upgrade
Upgrade();
// Cancel an on-going upgrade
@@ -24,6 +40,8 @@ interface PageHandler {
// If a user cancels the upgrade without starting it at all, this should
// be called so that metrics can be recorded.
CancelBeforeStart();
+ // If an upgrade fails, the user may choose to restore a container backup.
+ Restore();
// The page normally is displayed in a dialog. Call this to close the dialog.
// chrome.send('dialogClose') should not be used, which could kill the page
// handler before previous mojom calls have been run.
@@ -39,16 +57,27 @@ interface Page {
// Callback to receive the container backup progress once the export has
// started.
OnBackupProgress(int32 percent);
- // This is called when the backup succeeded.
- OnBackupSucceeded();
+ // This is called when the backup succeeded. If the user cancels the backup,
+ // we treat this as a success and proceed with upgrading (though the backup
+ // will not be used if the upgrade fails).
+ OnBackupSucceeded(bool was_cancelled);
// This is called when the backup failed.
OnBackupFailed();
+ // Handle the result of the prechecks.
+ PrecheckStatus(UpgradePrecheckStatus status);
// Callback to receive the upgrade progress once the upgrade has started.
OnUpgradeProgress(array<string> progress_messages);
// This is called when the upgrade succeeded.
OnUpgradeSucceeded();
// This is called when the upgrade failed.
OnUpgradeFailed();
+ // Callback to receive the container restore progress once the import has
+ // started.
+ OnRestoreProgress(int32 percent);
+ // This is called when the restore succeeded.
+ OnRestoreSucceeded();
+ // This is called when the restore failed.
+ OnRestoreFailed();
// After user cancels the upgrade, this is called when the cancellation
// finishes.
OnCanceled();
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
index 62f5e4f0ed3..e5848706a81 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
@@ -4,7 +4,10 @@
#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h"
+#include "base/metrics/histogram_functions.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h"
+#include "chrome/browser/chromeos/crostini/crostini_simple_types.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h"
#include "chrome/common/webui_url_constants.h"
@@ -21,20 +24,26 @@ GURL GetUrl() {
namespace chromeos {
-void CrostiniUpgraderDialog::Show(Profile* profile,
- base::OnceClosure launch_closure) {
+void CrostiniUpgraderDialog::Show(base::OnceClosure launch_closure,
+ bool only_run_launch_closure_on_restart) {
auto* instance = SystemWebDialogDelegate::FindInstance(GetUrl().spec());
if (instance) {
instance->Focus();
return;
}
- instance = new CrostiniUpgraderDialog(std::move(launch_closure));
+ instance = new CrostiniUpgraderDialog(std::move(launch_closure),
+ only_run_launch_closure_on_restart);
instance->ShowSystemDialog();
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kDialogShown);
}
-CrostiniUpgraderDialog::CrostiniUpgraderDialog(base::OnceClosure launch_closure)
+CrostiniUpgraderDialog::CrostiniUpgraderDialog(
+ base::OnceClosure launch_closure,
+ bool only_run_launch_closure_on_restart)
: SystemWebDialogDelegate{GetUrl(), /*title=*/{}},
+ only_run_launch_closure_on_restart_(only_run_launch_closure_on_restart),
launch_closure_{std::move(launch_closure)} {}
CrostiniUpgraderDialog::~CrostiniUpgraderDialog() = default;
@@ -47,6 +56,10 @@ bool CrostiniUpgraderDialog::ShouldShowCloseButton() const {
return false;
}
+bool CrostiniUpgraderDialog::ShouldCloseDialogOnEscape() const {
+ return false;
+}
+
void CrostiniUpgraderDialog::AdjustWidgetInitParams(
views::Widget::InitParams* params) {
params->z_order = ui::ZOrderLevel::kNormal;
@@ -60,15 +73,60 @@ bool CrostiniUpgraderDialog::CanCloseDialog() const {
return upgrader_ui_ == nullptr || upgrader_ui_->can_close();
}
+namespace {
+void RunLaunchClosure(base::WeakPtr<crostini::CrostiniManager> crostini_manager,
+ base::OnceClosure launch_closure,
+ bool only_run_launch_closure_on_restart,
+ bool restart_required) {
+ if (!crostini_manager) {
+ return;
+ }
+ if (!restart_required) {
+ if (!only_run_launch_closure_on_restart) {
+ std::move(launch_closure).Run();
+ }
+ return;
+ }
+ crostini_manager->RestartCrostini(
+ crostini::kCrostiniDefaultVmName, crostini::kCrostiniDefaultContainerName,
+ base::BindOnce(
+ [](base::OnceClosure launch_closure,
+ crostini::CrostiniResult result) {
+ if (result != crostini::CrostiniResult::SUCCESS) {
+ LOG(ERROR)
+ << "Failed to restart crostini after upgrade. Error code: "
+ << static_cast<int>(result);
+ return;
+ }
+ std::move(launch_closure).Run();
+ },
+ std::move(launch_closure)));
+}
+} // namespace
+
void CrostiniUpgraderDialog::OnDialogShown(content::WebUI* webui) {
+ auto* crostini_manager =
+ crostini::CrostiniManager::GetForProfile(Profile::FromWebUI(webui));
+ crostini_manager->SetCrostiniDialogStatus(crostini::DialogType::UPGRADER,
+ true);
+ crostini_manager->UpgradePromptShown(
+ crostini::ContainerId(crostini::kCrostiniDefaultVmName,
+ crostini::kCrostiniDefaultContainerName));
+
upgrader_ui_ = static_cast<CrostiniUpgraderUI*>(webui->GetController());
- upgrader_ui_->set_launch_closure(std::move(launch_closure_));
+ upgrader_ui_->set_launch_callback(base::BindOnce(
+ &RunLaunchClosure, crostini_manager->GetWeakPtr(),
+ std::move(launch_closure_), only_run_launch_closure_on_restart_));
return SystemWebDialogDelegate::OnDialogShown(webui);
}
void CrostiniUpgraderDialog::OnCloseContents(content::WebContents* source,
bool* out_close_dialog) {
upgrader_ui_ = nullptr;
+ auto* crostini_manager = crostini::CrostiniManager::GetForProfile(
+ Profile::FromBrowserContext(source->GetBrowserContext()));
+ crostini_manager->SetCrostiniDialogStatus(crostini::DialogType::UPGRADER,
+ false);
return SystemWebDialogDelegate::OnCloseContents(source, out_close_dialog);
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h
index 5bda748394b..dc94be24912 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h
@@ -7,23 +7,30 @@
#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
-class Profile;
-
namespace chromeos {
class CrostiniUpgraderUI;
class CrostiniUpgraderDialog : public SystemWebDialogDelegate {
public:
- static void Show(Profile* profile, base::OnceClosure launch_closure);
+ // If a restart of Crostini is not required, the launch closure can be
+ // optionally dropped. e.g. when running the upgrader from Settings, if the
+ // user cancels before starting the upgrade, the launching of a Terminal is
+ // not desired. This contrasts to being propmpted for container upgrade from
+ // The app launcher, in which case the user could opt not to upgrade and the
+ // app should still be launched.
+ static void Show(base::OnceClosure launch_closure,
+ bool only_run_launch_closure_on_restart = false);
private:
- explicit CrostiniUpgraderDialog(base::OnceClosure launch_closure);
+ explicit CrostiniUpgraderDialog(base::OnceClosure launch_closure,
+ bool only_run_launch_closure_on_restart);
~CrostiniUpgraderDialog() override;
// SystemWebDialogDelegate:
void GetDialogSize(gfx::Size* size) const override;
bool ShouldShowCloseButton() const override;
+ bool ShouldCloseDialogOnEscape() const override;
void AdjustWidgetInitParams(views::Widget::InitParams* params) override;
bool CanCloseDialog() const override;
void OnDialogShown(content::WebUI* webui) override;
@@ -31,8 +38,8 @@ class CrostiniUpgraderDialog : public SystemWebDialogDelegate {
bool* out_close_dialog) override;
private:
- // Not owned.
- CrostiniUpgraderUI* upgrader_ui_ = nullptr;
+ CrostiniUpgraderUI* upgrader_ui_ = nullptr; // Not owned.
+ const bool only_run_launch_closure_on_restart_;
base::OnceClosure launch_closure_;
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
index 63baa53f4d2..5610cbf09cf 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc
@@ -7,22 +7,29 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/metrics/histogram_functions.h"
+#include "chrome/browser/chromeos/crostini/crostini_simple_types.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h"
+#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h"
+#include "content/public/browser/web_contents.h"
namespace chromeos {
CrostiniUpgraderPageHandler::CrostiniUpgraderPageHandler(
+ content::WebContents* web_contents,
crostini::CrostiniUpgraderUIDelegate* upgrader_ui_delegate,
mojo::PendingReceiver<chromeos::crostini_upgrader::mojom::PageHandler>
pending_page_handler,
mojo::PendingRemote<chromeos::crostini_upgrader::mojom::Page> pending_page,
base::OnceClosure close_dialog_callback,
- base::OnceClosure launch_closure)
- : upgrader_ui_delegate_{upgrader_ui_delegate},
+ base::OnceCallback<void(bool)> launch_callback)
+ : web_contents_{web_contents},
+ upgrader_ui_delegate_{upgrader_ui_delegate},
receiver_{this, std::move(pending_page_handler)},
page_{std::move(pending_page)},
close_dialog_callback_{std::move(close_dialog_callback)},
- launch_closure_{std::move(launch_closure)} {
+ launch_callback_{std::move(launch_callback)} {
upgrader_ui_delegate_->AddObserver(this);
}
@@ -30,29 +37,74 @@ CrostiniUpgraderPageHandler::~CrostiniUpgraderPageHandler() {
upgrader_ui_delegate_->RemoveObserver(this);
}
-void CrostiniUpgraderPageHandler::Backup() {
- upgrader_ui_delegate_->Backup();
+namespace {
+
+void Redisplay() {
+ CrostiniUpgraderDialog::Show(base::DoNothing());
+}
+
+} // namespace
+
+void CrostiniUpgraderPageHandler::OnBackupMaybeStarted(bool did_start) {
+ Redisplay();
+}
+
+void CrostiniUpgraderPageHandler::Backup(bool show_file_chooser) {
+ Redisplay();
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kDidBackup);
+ upgrader_ui_delegate_->Backup(
+ crostini::ContainerId(crostini::kCrostiniDefaultVmName,
+ crostini::kCrostiniDefaultContainerName),
+ show_file_chooser, web_contents_);
+}
+
+void CrostiniUpgraderPageHandler::StartPrechecks() {
+ upgrader_ui_delegate_->StartPrechecks();
}
void CrostiniUpgraderPageHandler::Upgrade() {
+ Redisplay();
upgrader_ui_delegate_->Upgrade(
crostini::ContainerId(crostini::kCrostiniDefaultVmName,
crostini::kCrostiniDefaultContainerName));
}
+void CrostiniUpgraderPageHandler::Restore() {
+ Redisplay();
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kDidRestore);
+ upgrader_ui_delegate_->Restore(
+ crostini::ContainerId(crostini::kCrostiniDefaultVmName,
+ crostini::kCrostiniDefaultContainerName),
+ web_contents_);
+}
+
void CrostiniUpgraderPageHandler::Cancel() {
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kUpgradeCanceled);
upgrader_ui_delegate_->Cancel();
}
void CrostiniUpgraderPageHandler::Launch() {
- std::move(launch_closure_).Run();
+ std::move(launch_callback_).Run(restart_required_);
}
void CrostiniUpgraderPageHandler::CancelBeforeStart() {
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kNotStarted);
+ restart_required_ = false;
upgrader_ui_delegate_->CancelBeforeStart();
+ if (launch_callback_) {
+ // Running launch closure - no upgrade wanted, no need to restart crostini.
+ Launch();
+ }
}
void CrostiniUpgraderPageHandler::Close() {
+ if (launch_callback_) {
+ Launch();
+ }
std::move(close_dialog_callback_).Run();
}
@@ -62,10 +114,16 @@ void CrostiniUpgraderPageHandler::OnUpgradeProgress(
}
void CrostiniUpgraderPageHandler::OnUpgradeSucceeded() {
+ Redisplay();
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kUpgradeSuccess);
page_->OnUpgradeSucceeded();
}
void CrostiniUpgraderPageHandler::OnUpgradeFailed() {
+ Redisplay();
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kUpgradeFailed);
page_->OnUpgradeFailed();
}
@@ -73,14 +131,44 @@ void CrostiniUpgraderPageHandler::OnBackupProgress(int percent) {
page_->OnBackupProgress(percent);
}
-void CrostiniUpgraderPageHandler::OnBackupSucceeded() {
- page_->OnBackupSucceeded();
+void CrostiniUpgraderPageHandler::OnBackupSucceeded(bool was_cancelled) {
+ Redisplay();
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kBackupSucceeded);
+ page_->OnBackupSucceeded(was_cancelled);
}
void CrostiniUpgraderPageHandler::OnBackupFailed() {
+ Redisplay();
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kBackupFailed);
page_->OnBackupFailed();
}
+void CrostiniUpgraderPageHandler::PrecheckStatus(
+ chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus status) {
+ page_->PrecheckStatus(status);
+}
+
+void CrostiniUpgraderPageHandler::OnRestoreProgress(int percent) {
+ page_->OnRestoreProgress(percent);
+}
+
+void CrostiniUpgraderPageHandler::OnRestoreSucceeded() {
+ Redisplay();
+ base::UmaHistogramEnumeration(
+ crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kRestoreSucceeded);
+ page_->OnRestoreSucceeded();
+}
+
+void CrostiniUpgraderPageHandler::OnRestoreFailed() {
+ Redisplay();
+ base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram,
+ crostini::UpgradeDialogEvent::kRestoreFailed);
+ page_->OnRestoreFailed();
+}
+
void CrostiniUpgraderPageHandler::OnCanceled() {
page_->OnCanceled();
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h
index 1fbe60cfcc1..edf98821f6e 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h
@@ -15,6 +15,10 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
+namespace content {
+class WebContents;
+} // namespace content
+
namespace chromeos {
class CrostiniUpgraderPageHandler
@@ -22,39 +26,54 @@ class CrostiniUpgraderPageHandler
public crostini::CrostiniUpgraderUIObserver {
public:
CrostiniUpgraderPageHandler(
+ content::WebContents* web_contents,
crostini::CrostiniUpgraderUIDelegate* upgrader_ui_delegate,
mojo::PendingReceiver<chromeos::crostini_upgrader::mojom::PageHandler>
pending_page_handler,
mojo::PendingRemote<chromeos::crostini_upgrader::mojom::Page>
pending_page,
base::OnceClosure close_dialog_callback,
- base::OnceClosure launch_closure);
+ base::OnceCallback<void(bool)> launch_callback);
~CrostiniUpgraderPageHandler() override;
// chromeos::crostini_upgrader::mojom::PageHandler:
- void Backup() override;
+ void Backup(bool show_file_chooser) override;
+ void StartPrechecks() override;
void Upgrade() override;
+ void Restore() override;
void Cancel() override;
void CancelBeforeStart() override;
void Close() override;
void Launch() override;
// CrostiniUpgraderUIObserver
+ void OnBackupMaybeStarted(bool did_start) override;
void OnBackupProgress(int percent) override;
- void OnBackupSucceeded() override;
+ void OnBackupSucceeded(bool was_cancelled) override;
void OnBackupFailed() override;
+ void PrecheckStatus(chromeos::crostini_upgrader::mojom::UpgradePrecheckStatus
+ status) override;
void OnUpgradeProgress(const std::vector<std::string>& messages) override;
void OnUpgradeSucceeded() override;
void OnUpgradeFailed() override;
+ void OnRestoreProgress(int percent) override;
+ void OnRestoreSucceeded() override;
+ void OnRestoreFailed() override;
void OnCanceled() override;
private:
- // Not owned.
- crostini::CrostiniUpgraderUIDelegate* upgrader_ui_delegate_;
+ // The chrome://crostini-upgrader WebUI that triggered the upgrade.
+ // Used to parent open/save dialogs.
+ content::WebContents* web_contents_; // Not owned.
+ crostini::CrostiniUpgraderUIDelegate* upgrader_ui_delegate_; // Not owned.
mojo::Receiver<chromeos::crostini_upgrader::mojom::PageHandler> receiver_;
mojo::Remote<chromeos::crostini_upgrader::mojom::Page> page_;
base::OnceClosure close_dialog_callback_;
- base::OnceClosure launch_closure_;
+ base::OnceCallback<void(bool)> launch_callback_;
+ // Will we need to restart the container as part of launch_callback?
+ // |restart_required_| is true unless the user cancels before starting the
+ // upgrade.
+ bool restart_required_ = true;
base::WeakPtrFactory<CrostiniUpgraderPageHandler> weak_ptr_factory_{this};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
index a86e6564a50..fde562c2df6 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
@@ -22,6 +22,8 @@
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_ui_data_source.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/text/bytes_formatting.h"
+#include "ui/base/webui/web_ui_util.h"
#include "ui/chromeos/devicetype_utils.h"
#include "ui/resources/grit/webui_resources.h"
#include "ui/strings/grit/ui_strings.h"
@@ -38,19 +40,26 @@ bool CrostiniUpgraderUI::IsEnabled() {
void AddStringResources(content::WebUIDataSource* source) {
static constexpr webui::LocalizedString kStrings[] = {
{"upgrade", IDS_CROSTINI_UPGRADER_UPGRADE_BUTTON},
+ {"retry", IDS_CROSTINI_INSTALLER_RETRY_BUTTON},
{"close", IDS_APP_CLOSE},
{"cancel", IDS_APP_CANCEL},
- {"launch", IDS_CROSTINI_UPGRADER_LAUNCH_BUTTON},
+ {"done", IDS_CROSTINI_UPGRADER_DONE_BUTTON},
+ {"restore", IDS_CROSTINI_UPGRADER_RESTORE_BUTTON},
{"learnMore", IDS_LEARN_MORE},
{"promptTitle", IDS_CROSTINI_UPGRADER_TITLE},
{"backingUpTitle", IDS_CROSTINI_UPGRADER_BACKING_UP_TITLE},
{"backupSucceededTitle", IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_TITLE},
+ {"prechecksFailedTitle", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_TITLE},
{"upgradingTitle", IDS_CROSTINI_UPGRADER_UPGRADING_TITLE},
+ {"restoreTitle", IDS_CROSTINI_UPGRADER_RESTORE_TITLE},
{"succeededTitle", IDS_CROSTINI_UPGRADER_SUCCEEDED_TITLE},
{"cancelingTitle", IDS_CROSTINI_UPGRADER_CANCELING_TITLE},
{"errorTitle", IDS_CROSTINI_UPGRADER_ERROR_TITLE},
+ {"precheckNoNetwork", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_NETWORK},
+ {"precheckNoPower", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_POWER},
+
{"promptMessage", IDS_CROSTINI_UPGRADER_BODY},
{"backingUpMessage", IDS_CROSTINI_UPGRADER_BACKING_UP_MESSAGE},
{"backupSucceededMessage",
@@ -58,6 +67,8 @@ void AddStringResources(content::WebUIDataSource* source) {
{"upgradingMessage", IDS_CROSTINI_UPGRADER_UPGRADING},
{"succeededMessage", IDS_CROSTINI_UPGRADER_SUCCEEDED},
{"cancelingMessage", IDS_CROSTINI_UPGRADER_CANCELING},
+ {"offerRestoreMessage", IDS_CROSTINI_UPGRADER_OFFER_RESTORE_MESSAGE},
+ {"restoreMessage", IDS_CROSTINI_UPGRADER_RESTORE_MESSAGE},
{"backupCheckboxMessage", IDS_CROSTINI_UPGRADER_BACKUP_CHECKBOX_MESSAGE},
{"backupChangeLocation", IDS_CROSTINI_UPGRADER_BACKUP_CHANGE_LOCATION},
@@ -71,6 +82,12 @@ void AddStringResources(content::WebUIDataSource* source) {
source->AddString("offlineError",
l10n_util::GetStringFUTF8(
IDS_CROSTINI_INSTALLER_OFFLINE_ERROR, device_name));
+ source->AddString("precheckNoSpace",
+ l10n_util::GetStringFUTF8(
+ IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_SPACE,
+ ui::FormatBytesWithUnits(
+ crostini::CrostiniUpgrader::kDiskRequired,
+ ui::DATA_UNITS_GIBIBYTE, /*show_units=*/true)));
}
CrostiniUpgraderUI::CrostiniUpgraderUI(content::WebUI* web_ui)
@@ -83,27 +100,26 @@ CrostiniUpgraderUI::CrostiniUpgraderUI(content::WebUI* web_ui)
source->AddResourcePath("images/linux_illustration.png",
IDR_LINUX_ILLUSTRATION);
- source->AddResourcePath("images/success_illustration.png",
- IDR_LINUX_ILLUSTRATION);
+ source->AddResourcePath("images/success_illustration.svg",
+ IDR_LINUX_SUCCESS_ILLUSTRATION);
source->AddResourcePath("images/error_illustration.png",
- IDR_PLUGIN_VM_LAUNCHER_ERROR);
+ IDR_PLUGIN_VM_INSTALLER_ERROR);
source->AddResourcePath("app.js", IDR_CROSTINI_UPGRADER_APP_JS);
source->AddResourcePath("browser_proxy.js",
IDR_CROSTINI_UPGRADER_BROWSER_PROXY_JS);
source->AddResourcePath("crostini_upgrader.mojom-lite.js",
IDR_CROSTINI_UPGRADER_MOJO_LITE_JS);
+ source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER);
+ source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER);
source->SetDefaultResource(IDR_CROSTINI_UPGRADER_INDEX_HTML);
source->UseStringsJs();
source->EnableReplaceI18nInJS();
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
-
- AddHandlerToRegistry(base::BindRepeating(
- &CrostiniUpgraderUI::BindPageHandlerFactory, base::Unretained(this)));
}
CrostiniUpgraderUI::~CrostiniUpgraderUI() = default;
-void CrostiniUpgraderUI::BindPageHandlerFactory(
+void CrostiniUpgraderUI::BindInterface(
mojo::PendingReceiver<
chromeos::crostini_upgrader::mojom::PageHandlerFactory>
pending_receiver) {
@@ -121,13 +137,14 @@ void CrostiniUpgraderUI::CreatePageHandler(
DCHECK(pending_page.is_valid());
page_handler_ = std::make_unique<CrostiniUpgraderPageHandler>(
+ web_ui()->GetWebContents(),
crostini::CrostiniUpgrader::GetForProfile(Profile::FromWebUI(web_ui())),
std::move(pending_page_handler), std::move(pending_page),
// Using Unretained(this) because |page_handler_| will not out-live
// |this|.
base::BindOnce(&CrostiniUpgraderUI::OnWebUICloseDialog,
base::Unretained(this)),
- std::move(launch_closure_));
+ std::move(launch_callback_));
}
void CrostiniUpgraderUI::OnWebUICloseDialog() {
@@ -137,4 +154,6 @@ void CrostiniUpgraderUI::OnWebUICloseDialog() {
ui::MojoWebDialogUI::CloseDialog(nullptr);
}
+WEB_UI_CONTROLLER_TYPE_IMPL(CrostiniUpgraderUI)
+
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h
index 5b2151309e6..6126283abd6 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_CROSTINI_UPGRADER_CROSTINI_UPGRADER_UI_H_
#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CROSTINI_UPGRADER_CROSTINI_UPGRADER_UI_H_
+#include "base/callback.h"
#include "base/macros.h"
#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -27,16 +28,18 @@ class CrostiniUpgraderUI
~CrostiniUpgraderUI() override;
bool can_close() { return can_close_; }
- void set_launch_closure(base::OnceClosure(launch_closure)) {
- launch_closure_ = std::move(launch_closure);
+ void set_launch_callback(base::OnceCallback<void(bool)>(launch_callback)) {
+ launch_callback_ = std::move(launch_callback);
}
- private:
- void BindPageHandlerFactory(
- mojo::PendingReceiver<
- chromeos::crostini_upgrader::mojom::PageHandlerFactory>
- pending_receiver);
+ // Instantiates implementor of the
+ // chromeos::crostini_upgrader::mojom::PageHandlerFactory mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(mojo::PendingReceiver<
+ chromeos::crostini_upgrader::mojom::PageHandlerFactory>
+ pending_receiver);
+ private:
// chromeos::crostini_upgrader::mojom::PageHandlerFactory:
void CreatePageHandler(
mojo::PendingRemote<chromeos::crostini_upgrader::mojom::Page>
@@ -51,10 +54,12 @@ class CrostiniUpgraderUI
page_factory_receiver_{this};
// Not owned. Passed to |page_handler_|
- base::OnceClosure launch_closure_;
+ base::OnceCallback<void(bool)> launch_callback_;
bool can_close_ = false;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(CrostiniUpgraderUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
index 52894b68f0e..0611cef1174 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc
@@ -42,9 +42,9 @@ void CryptohomeWebUIHandler::OnPageLoaded(const base::ListValue* args) {
base::PostTaskAndReplyWithResult(
FROM_HERE, {BrowserThread::IO},
- base::Bind(&crypto::IsTPMTokenReady, base::Closure()),
- base::Bind(&CryptohomeWebUIHandler::DidGetNSSUtilInfoOnUIThread,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&crypto::IsTPMTokenReady, base::Closure()),
+ base::BindOnce(&CryptohomeWebUIHandler::DidGetNSSUtilInfoOnUIThread,
+ weak_ptr_factory_.GetWeakPtr()));
}
void CryptohomeWebUIHandler::DidGetNSSUtilInfoOnUIThread(
diff --git a/chromium/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
index 857d5816fdf..39b9f40b465 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
@@ -28,6 +28,7 @@
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "chrome/browser/chromeos/drive/drive_integration_service.h"
#include "chrome/browser/chromeos/drive/file_system_util.h"
@@ -407,10 +408,8 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler {
// Propagate the amount of local free space in bytes.
base::FilePath home_path;
if (base::PathService::Get(base::DIR_HOME, &home_path)) {
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&base::SysInfo::AmountOfFreeDiskSpace, home_path),
base::BindOnce(&DriveInternalsWebUIHandler::OnGetFreeDiskSpace,
weak_ptr_factory_.GetWeakPtr()));
@@ -502,10 +501,8 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler {
"updateOtherServiceLogsUrl",
base::Value(net::FilePathToFileURL(log_path.DirName()).spec()));
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&GetServiceLogContents, log_path,
service_log_file_inode_, last_sent_line_number_),
base::BindOnce(&DriveInternalsWebUIHandler::OnServiceLogRead,
@@ -535,10 +532,8 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler {
const base::FilePath root_path =
drive::util::GetCacheRootPath(profile()).DirName();
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&GetGCacheContents, root_path),
base::BindOnce(&DriveInternalsWebUIHandler::OnGetGCacheContents,
weak_ptr_factory_.GetWeakPtr()));
@@ -625,10 +620,8 @@ class LogsZipper : public download::AllDownloadItemNotifier::Observer {
drive_internals_(std::move(drive_internals)) {}
void Start() {
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&LogsZipper::EnumerateLogFiles, logs_directory_,
zip_path_),
base::BindOnce(&LogsZipper::ZipLogFiles, base::Unretained(this)));
@@ -684,9 +677,8 @@ class LogsZipper : public download::AllDownloadItemNotifier::Observer {
}
void CleanUp() {
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(base::IgnoreResult(&base::DeleteFile), zip_path_,
false));
download_notifier_.reset();
diff --git a/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.cc
new file mode 100644
index 00000000000..8e0d635e3b8
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.cc
@@ -0,0 +1,346 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/image_fetcher/image_fetcher_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chromeos/components/account_manager/account_manager.h"
+#include "chromeos/components/account_manager/account_manager_factory.h"
+#include "components/image_fetcher/core/image_fetcher_service.h"
+#include "components/image_fetcher/core/request_metadata.h"
+#include "components/signin/public/base/avatar_icon_util.h"
+#include "content/public/browser/storage_partition.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/web_ui_util.h"
+#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
+#include "ui/gfx/image/image.h"
+
+namespace chromeos {
+
+namespace {
+constexpr char kImageFetcherUmaClientName[] =
+ "EduAccountLoginProfileImageFetcher";
+constexpr char kObfuscatedGaiaIdKey[] = "obfuscatedGaiaId";
+constexpr net::NetworkTrafficAnnotationTag traffic_annotation =
+ net::DefineNetworkTrafficAnnotation(
+ "edu_account_login_profile_image_fetcher",
+ R"(
+ semantics {
+ sender: "Profile image fetcher for EDU account login flow"
+ description:
+ "Retrieves profile images for user's parent accounts in EDU account"
+ "login flow."
+ trigger: "Triggered when child user opens account addition flow."
+ data: "Account picture URL of GAIA accounts."
+ destination: GOOGLE_OWNED_SERVICE
+ }
+ policy {
+ cookies_allowed: NO
+ setting: "This feature cannot be disabled by settings."
+ policy_exception_justification: "Not implemented."
+ })");
+} // namespace
+
+EduAccountLoginHandler::EduAccountLoginHandler(
+ const base::RepeatingClosure& close_dialog_closure)
+ : close_dialog_closure_(close_dialog_closure) {}
+
+EduAccountLoginHandler::~EduAccountLoginHandler() {
+ close_dialog_closure_.Run();
+}
+
+EduAccountLoginHandler::ProfileImageFetcher::ProfileImageFetcher(
+ image_fetcher::ImageFetcher* image_fetcher,
+ const std::map<std::string, GURL>& profile_image_urls,
+ base::OnceCallback<void(std::map<std::string, gfx::Image> profile_images)>
+ callback)
+ : image_fetcher_(image_fetcher),
+ profile_image_urls_(profile_image_urls),
+ callback_(std::move(callback)) {}
+
+EduAccountLoginHandler::ProfileImageFetcher::~ProfileImageFetcher() = default;
+
+void EduAccountLoginHandler::ProfileImageFetcher::FetchProfileImages() {
+ for (const auto& profile_image_url : profile_image_urls_) {
+ FetchProfileImage(profile_image_url.first, profile_image_url.second);
+ }
+}
+
+void EduAccountLoginHandler::ProfileImageFetcher::FetchProfileImage(
+ const std::string& obfuscated_gaia_id,
+ const GURL& profile_image_url) {
+ if (!profile_image_url.is_valid()) {
+ OnImageFetched(obfuscated_gaia_id, gfx::Image(),
+ image_fetcher::RequestMetadata());
+ return;
+ }
+
+ image_fetcher::ImageFetcherParams params(traffic_annotation,
+ kImageFetcherUmaClientName);
+ GURL image_url_with_size(signin::GetAvatarImageURLWithOptions(
+ profile_image_url, signin::kAccountInfoImageSize,
+ true /* no_silhouette */));
+ image_fetcher_->FetchImage(
+ image_url_with_size,
+ base::BindRepeating(
+ &EduAccountLoginHandler::ProfileImageFetcher::OnImageFetched,
+ weak_ptr_factory_.GetWeakPtr(), obfuscated_gaia_id),
+ std::move(params));
+}
+
+void EduAccountLoginHandler::ProfileImageFetcher::OnImageFetched(
+ const std::string& obfuscated_gaia_id,
+ const gfx::Image& image,
+ const image_fetcher::RequestMetadata& metadata) {
+ fetched_profile_images_[obfuscated_gaia_id] = std::move(image);
+ if (fetched_profile_images_.size() == profile_image_urls_.size()) {
+ std::move(callback_).Run(std::move(fetched_profile_images_));
+ }
+}
+
+void EduAccountLoginHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "getParents",
+ base::BindRepeating(&EduAccountLoginHandler::HandleGetParents,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "parentSignin",
+ base::BindRepeating(&EduAccountLoginHandler::HandleParentSignin,
+ base::Unretained(this)));
+}
+
+void EduAccountLoginHandler::OnJavascriptDisallowed() {
+ family_fetcher_.reset();
+ access_token_fetcher_.reset();
+ gaia_auth_fetcher_.reset();
+ profile_image_fetcher_.reset();
+ get_parents_callback_id_.clear();
+ parent_signin_callback_id_.clear();
+}
+
+void EduAccountLoginHandler::HandleGetParents(const base::ListValue* args) {
+ AllowJavascript();
+
+ CHECK_EQ(args->GetList().size(), 1u);
+
+ if (!get_parents_callback_id_.empty()) {
+ // HandleGetParents call is already in progress, reject the callback.
+ RejectJavascriptCallback(args->GetList()[0], base::Value());
+ return;
+ }
+ get_parents_callback_id_ = args->GetList()[0].GetString();
+
+ FetchFamilyMembers();
+}
+
+void EduAccountLoginHandler::HandleParentSignin(const base::ListValue* args) {
+ const base::Value::ConstListView& args_list = args->GetList();
+ CHECK_EQ(args_list.size(), 3u);
+ CHECK(args_list[0].is_string());
+
+ if (!parent_signin_callback_id_.empty()) {
+ // HandleParentSignin call is already in progress, reject the callback.
+ RejectJavascriptCallback(args_list[0], base::Value());
+ return;
+ }
+ parent_signin_callback_id_ = args_list[0].GetString();
+
+ const base::DictionaryValue* parent = nullptr;
+ args_list[1].GetAsDictionary(&parent);
+ CHECK(parent);
+ const base::Value* obfuscated_gaia_id_value =
+ parent->FindKey(kObfuscatedGaiaIdKey);
+ DCHECK(obfuscated_gaia_id_value);
+ std::string obfuscated_gaia_id = obfuscated_gaia_id_value->GetString();
+
+ std::string password;
+ args_list[2].GetAsString(&password);
+
+ FetchAccessToken(obfuscated_gaia_id, password);
+}
+
+void EduAccountLoginHandler::FetchFamilyMembers() {
+ DCHECK(!family_fetcher_);
+ Profile* profile = Profile::FromWebUI(web_ui());
+ chromeos::AccountManager* account_manager =
+ g_browser_process->platform_part()
+ ->GetAccountManagerFactory()
+ ->GetAccountManager(profile->GetPath().value());
+ DCHECK(account_manager);
+
+ family_fetcher_ = std::make_unique<FamilyInfoFetcher>(
+ this, IdentityManagerFactory::GetForProfile(profile),
+ account_manager->GetUrlLoaderFactory());
+ family_fetcher_->StartGetFamilyMembers();
+}
+
+void EduAccountLoginHandler::FetchParentImages(
+ base::ListValue parents,
+ std::map<std::string, GURL> profile_image_urls) {
+ DCHECK(!profile_image_fetcher_);
+ image_fetcher::ImageFetcher* fetcher =
+ ImageFetcherServiceFactory::GetForKey(
+ Profile::FromWebUI(web_ui())->GetProfileKey())
+ ->GetImageFetcher(image_fetcher::ImageFetcherConfig::kNetworkOnly);
+ profile_image_fetcher_ = std::make_unique<ProfileImageFetcher>(
+ fetcher, profile_image_urls,
+ base::BindOnce(&EduAccountLoginHandler::OnParentProfileImagesFetched,
+ base::Unretained(this), std::move(parents)));
+ profile_image_fetcher_->FetchProfileImages();
+}
+
+void EduAccountLoginHandler::FetchAccessToken(
+ const std::string& obfuscated_gaia_id,
+ const std::string& password) {
+ DCHECK(!access_token_fetcher_);
+ Profile* profile = Profile::FromWebUI(web_ui());
+ signin::IdentityManager* identity_manager =
+ IdentityManagerFactory::GetForProfile(profile);
+ OAuth2AccessTokenManager::ScopeSet scopes;
+ scopes.insert(GaiaConstants::kAccountsReauthOAuth2Scope);
+ access_token_fetcher_ =
+ std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
+ "EduAccountLoginHandler", identity_manager, scopes,
+ base::BindOnce(
+ &EduAccountLoginHandler::CreateReAuthProofTokenForParent,
+ base::Unretained(this), std::move(obfuscated_gaia_id),
+ std::move(password)),
+ signin::PrimaryAccountAccessTokenFetcher::Mode::kImmediate);
+}
+
+void EduAccountLoginHandler::FetchReAuthProofTokenForParent(
+ const std::string& child_oauth_access_token,
+ const std::string& parent_obfuscated_gaia_id,
+ const std::string& parent_credential) {
+ DCHECK(!gaia_auth_fetcher_);
+ Profile* profile = Profile::FromWebUI(web_ui());
+ chromeos::AccountManager* account_manager =
+ g_browser_process->platform_part()
+ ->GetAccountManagerFactory()
+ ->GetAccountManager(profile->GetPath().value());
+ DCHECK(account_manager);
+
+ gaia_auth_fetcher_ = std::make_unique<GaiaAuthFetcher>(
+ this, gaia::GaiaSource::kChrome, account_manager->GetUrlLoaderFactory());
+ gaia_auth_fetcher_->StartCreateReAuthProofTokenForParent(
+ child_oauth_access_token, parent_obfuscated_gaia_id, parent_credential);
+}
+
+void EduAccountLoginHandler::OnGetFamilyMembersSuccess(
+ const std::vector<FamilyInfoFetcher::FamilyMember>& members) {
+ family_fetcher_.reset();
+ base::ListValue parents;
+ std::map<std::string, GURL> profile_image_urls;
+
+ for (const auto& member : members) {
+ if (member.role != FamilyInfoFetcher::HEAD_OF_HOUSEHOLD &&
+ member.role != FamilyInfoFetcher::PARENT) {
+ continue;
+ }
+
+ base::DictionaryValue parent;
+ parent.SetStringKey("email", member.email);
+ parent.SetStringKey("displayName", member.display_name);
+ parent.SetStringKey(kObfuscatedGaiaIdKey, member.obfuscated_gaia_id);
+
+ parents.Append(std::move(parent));
+ profile_image_urls[member.obfuscated_gaia_id] =
+ GURL(member.profile_image_url);
+ }
+
+ FetchParentImages(std::move(parents), profile_image_urls);
+}
+
+void EduAccountLoginHandler::OnFailure(FamilyInfoFetcher::ErrorCode error) {
+ family_fetcher_.reset();
+ RejectJavascriptCallback(base::Value(get_parents_callback_id_),
+ base::ListValue());
+ get_parents_callback_id_.clear();
+}
+
+void EduAccountLoginHandler::OnParentProfileImagesFetched(
+ base::ListValue parents,
+ std::map<std::string, gfx::Image> profile_images) {
+ profile_image_fetcher_.reset();
+
+ for (auto& parent : parents.GetList()) {
+ const std::string* obfuscated_gaia_id =
+ parent.FindStringKey(kObfuscatedGaiaIdKey);
+ DCHECK(obfuscated_gaia_id);
+ std::string profile_image;
+ if (profile_images[*obfuscated_gaia_id].IsEmpty()) {
+ gfx::ImageSkia default_icon =
+ *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+ IDR_LOGIN_DEFAULT_USER);
+
+ profile_image = webui::GetBitmapDataUrl(
+ default_icon.GetRepresentation(1.0f).GetBitmap());
+ } else {
+ profile_image = webui::GetBitmapDataUrl(
+ profile_images[*obfuscated_gaia_id].AsBitmap());
+ }
+ parent.SetStringKey("profileImage", profile_image);
+ }
+
+ ResolveJavascriptCallback(base::Value(get_parents_callback_id_), parents);
+ get_parents_callback_id_.clear();
+}
+
+void EduAccountLoginHandler::CreateReAuthProofTokenForParent(
+ const std::string& parent_obfuscated_gaia_id,
+ const std::string& parent_credential,
+ GoogleServiceAuthError error,
+ signin::AccessTokenInfo access_token_info) {
+ access_token_fetcher_.reset();
+ if (error.state() != GoogleServiceAuthError::NONE) {
+ LOG(ERROR)
+ << "Could not get access token to create ReAuthProofToken for parent"
+ << error.ToString();
+ base::DictionaryValue result;
+ result.SetBoolKey("isWrongPassword", false);
+ RejectJavascriptCallback(base::Value(parent_signin_callback_id_), result);
+ parent_signin_callback_id_.clear();
+ return;
+ }
+
+ FetchReAuthProofTokenForParent(access_token_info.token,
+ parent_obfuscated_gaia_id, parent_credential);
+}
+
+void EduAccountLoginHandler::OnReAuthProofTokenSuccess(
+ const std::string& reauth_proof_token) {
+ gaia_auth_fetcher_.reset();
+ ResolveJavascriptCallback(base::Value(parent_signin_callback_id_),
+ base::Value(reauth_proof_token));
+ parent_signin_callback_id_.clear();
+}
+
+void EduAccountLoginHandler::OnReAuthProofTokenFailure(
+ const GaiaAuthConsumer::ReAuthProofTokenStatus error) {
+ LOG(ERROR) << "Failed to fetch ReAuthProofToken for the parent, error="
+ << static_cast<int>(error);
+ gaia_auth_fetcher_.reset();
+
+ base::DictionaryValue result;
+ result.SetBoolKey(
+ "isWrongPassword",
+ error == GaiaAuthConsumer::ReAuthProofTokenStatus::kInvalidGrant);
+ RejectJavascriptCallback(base::Value(parent_signin_callback_id_), result);
+ parent_signin_callback_id_.clear();
+}
+
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.h b/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.h
new file mode 100644
index 00000000000..88b968d36e5
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.h
@@ -0,0 +1,149 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_EDU_ACCOUNT_LOGIN_HANDLER_CHROMEOS_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_EDU_ACCOUNT_LOGIN_HANDLER_CHROMEOS_H_
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/values.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/supervised_user/child_accounts/family_info_fetcher.h"
+#include "components/image_fetcher/core/image_fetcher.h"
+#include "components/signin/public/identity_manager/access_token_info.h"
+#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
+#include "content/public/browser/web_ui_message_handler.h"
+#include "google_apis/gaia/gaia_auth_consumer.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+
+namespace chromeos {
+
+// Handler for EDU account login flow.
+class EduAccountLoginHandler : public content::WebUIMessageHandler,
+ public FamilyInfoFetcher::Consumer,
+ public GaiaAuthConsumer {
+ public:
+ explicit EduAccountLoginHandler(
+ const base::RepeatingClosure& close_dialog_closure);
+ ~EduAccountLoginHandler() override;
+ EduAccountLoginHandler(const EduAccountLoginHandler&) = delete;
+ EduAccountLoginHandler& operator=(const EduAccountLoginHandler&) = delete;
+
+ private:
+ class ProfileImageFetcher {
+ public:
+ // Create a new instance to fetch a set of images.
+ // |profile_image_urls| is a map from obfuscated Gaia id to profile image
+ // url. After all images are fetched, |callback| will be resolved with a
+ // map from obfuscated Gaia id to gfx::Image. If image cannot be fetched
+ // an empty gfx::Image() will be returned.
+ ProfileImageFetcher(
+ image_fetcher::ImageFetcher* image_fetcher,
+ const std::map<std::string, GURL>& profile_image_urls,
+ base::OnceCallback<
+ void(std::map<std::string, gfx::Image> profile_images)> callback);
+ ProfileImageFetcher(const ProfileImageFetcher&) = delete;
+ ProfileImageFetcher& operator=(const ProfileImageFetcher&) = delete;
+ ~ProfileImageFetcher();
+
+ // Start fetching profile images.
+ void FetchProfileImages();
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(EduAccountLoginHandlerTest,
+ ProfileImageFetcherTest);
+
+ // Called for each profile provided in |profile_image_urls_|. If
+ // |profile_image_url| is valid - fetches the image. Otherwise calls
+ // |OnImageFetched| with an empty image.
+ void FetchProfileImage(const std::string& obfuscated_gaia_id,
+ const GURL& profile_image_url);
+
+ // Called for each profile provided in |profile_image_urls_|. After all
+ // images are fetched resolves |callback_| with profile images.
+ void OnImageFetched(const std::string& obfuscated_gaia_id,
+ const gfx::Image& image,
+ const image_fetcher::RequestMetadata& metadata);
+
+ image_fetcher::ImageFetcher* image_fetcher_ = nullptr;
+ const std::map<std::string, GURL> profile_image_urls_;
+ base::OnceCallback<void(std::map<std::string, gfx::Image> profile_images)>
+ callback_;
+ std::map<std::string, gfx::Image> fetched_profile_images_;
+ base::WeakPtrFactory<ProfileImageFetcher> weak_ptr_factory_{this};
+ };
+
+ FRIEND_TEST_ALL_PREFIXES(EduAccountLoginHandlerTest, HandleGetParentsSuccess);
+ FRIEND_TEST_ALL_PREFIXES(EduAccountLoginHandlerTest, HandleGetParentsFailure);
+ FRIEND_TEST_ALL_PREFIXES(EduAccountLoginHandlerTest,
+ HandleParentSigninSuccess);
+ FRIEND_TEST_ALL_PREFIXES(EduAccountLoginHandlerTest,
+ HandleParentSigninAccessTokenFailure);
+ FRIEND_TEST_ALL_PREFIXES(EduAccountLoginHandlerTest,
+ HandleParentSigninReAuthProofTokenFailure);
+ FRIEND_TEST_ALL_PREFIXES(EduAccountLoginHandlerTest, ProfileImageFetcherTest);
+
+ // content::WebUIMessageHandler:
+ void RegisterMessages() override;
+ void OnJavascriptDisallowed() override;
+
+ void HandleGetParents(const base::ListValue* args);
+ void HandleCloseDialog(const base::ListValue* args);
+ void HandleParentSignin(const base::ListValue* args);
+
+ virtual void FetchFamilyMembers();
+ virtual void FetchParentImages(
+ base::ListValue parents,
+ std::map<std::string, GURL> profile_image_urls);
+ virtual void FetchAccessToken(const std::string& obfuscated_gaia_id,
+ const std::string& password);
+
+ virtual void FetchReAuthProofTokenForParent(
+ const std::string& child_oauth_access_token,
+ const std::string& parent_obfuscated_gaia_id,
+ const std::string& parent_credential);
+
+ // FamilyInfoFetcher::Consumer implementation.
+ void OnGetFamilyMembersSuccess(
+ const std::vector<FamilyInfoFetcher::FamilyMember>& members) override;
+ void OnFailure(FamilyInfoFetcher::ErrorCode error) override;
+
+ // ProfileImageFetcher callback
+ void OnParentProfileImagesFetched(
+ base::ListValue parents,
+ std::map<std::string, gfx::Image> profile_images);
+
+ // signin::PrimaryAccountAccessTokenFetcher callback
+ void CreateReAuthProofTokenForParent(
+ const std::string& parent_obfuscated_gaia_id,
+ const std::string& parent_credential,
+ GoogleServiceAuthError error,
+ signin::AccessTokenInfo access_token_info);
+
+ // GaiaAuthConsumer overrides.
+ void OnReAuthProofTokenSuccess(
+ const std::string& reauth_proof_token) override;
+ void OnReAuthProofTokenFailure(
+ const GaiaAuthConsumer::ReAuthProofTokenStatus error) override;
+
+ // Used for getting parent RAPT token.
+ std::unique_ptr<GaiaAuthFetcher> gaia_auth_fetcher_;
+
+ // Used for getting child access token.
+ std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
+ access_token_fetcher_;
+ base::RepeatingClosure close_dialog_closure_;
+ std::unique_ptr<FamilyInfoFetcher> family_fetcher_;
+
+ std::unique_ptr<ProfileImageFetcher> profile_image_fetcher_;
+ std::string get_parents_callback_id_;
+ std::string parent_signin_callback_id_;
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_EDU_ACCOUNT_LOGIN_HANDLER_CHROMEOS_H_
diff --git a/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_unittest.cc b/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_unittest.cc
new file mode 100644
index 00000000000..c8a2beaed80
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_unittest.cc
@@ -0,0 +1,363 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.h"
+
+#include <memory>
+
+#include "base/bind_helpers.h"
+#include "base/json/json_writer.h"
+#include "base/test/bind_test_util.h"
+#include "base/values.h"
+#include "components/image_fetcher/core/mock_image_fetcher.h"
+#include "components/image_fetcher/core/request_metadata.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "content/public/test/test_web_ui.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/web_ui_util.h"
+#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_unittest_util.h"
+
+using testing::_;
+
+namespace chromeos {
+
+namespace {
+
+constexpr char kFakeParentGaiaId[] = "someObfuscatedGaiaId";
+constexpr char kFakeParentGaiaId2[] = "anotherObfuscatedGaiaId";
+constexpr char kFakeParentCredential[] = "someParentCredential";
+constexpr char kFakeAccessToken[] = "someAccessToken";
+
+std::vector<FamilyInfoFetcher::FamilyMember> GetFakeFamilyMembers() {
+ std::vector<FamilyInfoFetcher::FamilyMember> members;
+ members.push_back(FamilyInfoFetcher::FamilyMember(
+ kFakeParentGaiaId, FamilyInfoFetcher::HEAD_OF_HOUSEHOLD, "Homer Simpson",
+ "homer@simpson.com", "http://profile.url/homer",
+ "http://profile.url/homer/image"));
+ members.push_back(FamilyInfoFetcher::FamilyMember(
+ kFakeParentGaiaId2, FamilyInfoFetcher::PARENT, "Marge Simpson",
+ std::string(), "http://profile.url/marge", std::string()));
+ members.push_back(FamilyInfoFetcher::FamilyMember(
+ "obfuscatedGaiaId3", FamilyInfoFetcher::CHILD, "Lisa Simpson",
+ "lisa@gmail.com", std::string(), "http://profile.url/lisa/image"));
+ members.push_back(FamilyInfoFetcher::FamilyMember(
+ "obfuscatedGaiaId4", FamilyInfoFetcher::CHILD, "Bart Simpson",
+ "bart@bart.bart", std::string(), std::string()));
+ members.push_back(FamilyInfoFetcher::FamilyMember(
+ "obfuscatedGaiaId5", FamilyInfoFetcher::MEMBER, std::string(),
+ std::string(), std::string(), std::string()));
+ return members;
+}
+
+std::map<std::string, GURL> GetFakeProfileImageUrlMap() {
+ return {
+ {kFakeParentGaiaId, GURL("http://profile.url/homer/image")},
+ {kFakeParentGaiaId2, GURL()},
+ };
+}
+
+gfx::Image GetFakeImage() {
+ return ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+ IDR_LOGIN_DEFAULT_USER);
+}
+
+std::map<std::string, gfx::Image> GetFakeProfileImageMap() {
+ return {
+ {kFakeParentGaiaId, GetFakeImage()},
+ {kFakeParentGaiaId2, gfx::Image()},
+ };
+}
+
+base::ListValue GetFakeParentsWithoutImage() {
+ base::ListValue parents;
+
+ base::DictionaryValue parent1;
+ parent1.SetStringKey("email", "homer@simpson.com");
+ parent1.SetStringKey("displayName", "Homer Simpson");
+ parent1.SetStringKey("obfuscatedGaiaId", kFakeParentGaiaId);
+ parents.Append(std::move(parent1));
+
+ base::DictionaryValue parent2;
+ parent2.SetStringKey("email", std::string());
+ parent2.SetStringKey("displayName", "Marge Simpson");
+ parent2.SetStringKey("obfuscatedGaiaId", kFakeParentGaiaId2);
+ parents.Append(std::move(parent2));
+
+ return parents;
+}
+
+base::ListValue GetFakeParentsWithImage() {
+ base::ListValue parents = GetFakeParentsWithoutImage();
+ std::map<std::string, gfx::Image> profile_images = GetFakeProfileImageMap();
+
+ for (auto& parent : parents.GetList()) {
+ const std::string* obfuscated_gaia_id =
+ parent.FindStringKey("obfuscatedGaiaId");
+ DCHECK(obfuscated_gaia_id);
+ std::string profile_image;
+ if (profile_images[*obfuscated_gaia_id].IsEmpty()) {
+ gfx::ImageSkia default_icon =
+ *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+ IDR_LOGIN_DEFAULT_USER);
+
+ profile_image = webui::GetBitmapDataUrl(
+ default_icon.GetRepresentation(1.0f).GetBitmap());
+ } else {
+ profile_image = webui::GetBitmapDataUrl(
+ profile_images[*obfuscated_gaia_id].AsBitmap());
+ }
+ parent.SetStringKey("profileImage", profile_image);
+ }
+
+ return parents;
+}
+
+base::DictionaryValue GetFakeParent() {
+ base::DictionaryValue parent;
+ parent.SetStringKey("email", "homer@simpson.com");
+ parent.SetStringKey("displayName", "Homer Simpson");
+ parent.SetStringKey("profileImageUrl", "http://profile.url/homer/image");
+ parent.SetStringKey("obfuscatedGaiaId", kFakeParentGaiaId);
+ return parent;
+}
+
+class MockEduAccountLoginHandler : public EduAccountLoginHandler {
+ public:
+ explicit MockEduAccountLoginHandler(
+ const base::RepeatingClosure& close_dialog_closure)
+ : EduAccountLoginHandler(close_dialog_closure) {}
+ using EduAccountLoginHandler::set_web_ui;
+
+ MOCK_METHOD(void, FetchFamilyMembers, (), (override));
+ MOCK_METHOD(void,
+ FetchAccessToken,
+ (const std::string& obfuscated_gaia_id,
+ const std::string& password),
+ (override));
+ MOCK_METHOD(void,
+ FetchReAuthProofTokenForParent,
+ (const std::string& child_oauth_access_token,
+ const std::string& parent_obfuscated_gaia_id,
+ const std::string& parent_credential),
+ (override));
+ MOCK_METHOD(void,
+ FetchParentImages,
+ (base::ListValue parents,
+ (std::map<std::string, GURL> profile_image_urls)),
+ (override));
+};
+} // namespace
+
+class EduAccountLoginHandlerTest : public testing::Test {
+ public:
+ EduAccountLoginHandlerTest() {}
+
+ void SetUp() override {
+ mock_image_fetcher_ = std::make_unique<image_fetcher::MockImageFetcher>();
+ handler_ = std::make_unique<MockEduAccountLoginHandler>(base::DoNothing());
+ handler_->set_web_ui(web_ui());
+ }
+
+ void VerifyJavascriptCallbackResolved(
+ const content::TestWebUI::CallData& data,
+ const std::string& event_name,
+ bool success = true) {
+ EXPECT_EQ("cr.webUIResponse", data.function_name());
+
+ std::string callback_id;
+ ASSERT_TRUE(data.arg1()->GetAsString(&callback_id));
+ EXPECT_EQ(event_name, callback_id);
+
+ bool callback_success = false;
+ ASSERT_TRUE(data.arg2()->GetAsBoolean(&callback_success));
+ EXPECT_EQ(success, callback_success);
+ }
+
+ image_fetcher::MockImageFetcher* mock_image_fetcher() const {
+ return mock_image_fetcher_.get();
+ }
+
+ MockEduAccountLoginHandler* handler() const { return handler_.get(); }
+
+ content::TestWebUI* web_ui() { return &web_ui_; }
+
+ private:
+ std::unique_ptr<image_fetcher::MockImageFetcher> mock_image_fetcher_;
+ std::unique_ptr<MockEduAccountLoginHandler> handler_;
+ content::TestWebUI web_ui_;
+};
+
+TEST_F(EduAccountLoginHandlerTest, HandleGetParentsSuccess) {
+ constexpr char callback_id[] = "handle-get-parents-callback";
+ base::ListValue list_args;
+ list_args.AppendString(callback_id);
+
+ EXPECT_CALL(*handler(), FetchFamilyMembers());
+ handler()->HandleGetParents(&list_args);
+
+ EXPECT_CALL(*handler(), FetchParentImages(_, GetFakeProfileImageUrlMap()));
+ // Simulate successful fetching of family members -> expect FetchParentImages
+ // to be called.
+ handler()->OnGetFamilyMembersSuccess(GetFakeFamilyMembers());
+
+ // Simulate successful fetching of the images -> expect JavascriptCallack to
+ // be resolved.
+ handler()->OnParentProfileImagesFetched(GetFakeParentsWithoutImage(),
+ GetFakeProfileImageMap());
+
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ VerifyJavascriptCallbackResolved(data, callback_id);
+
+ ASSERT_EQ(GetFakeParentsWithImage(), *data.arg3());
+}
+
+TEST_F(EduAccountLoginHandlerTest, HandleGetParentsFailure) {
+ constexpr char callback_id[] = "handle-get-parents-callback";
+ base::ListValue list_args;
+ list_args.AppendString(callback_id);
+
+ EXPECT_CALL(*handler(), FetchFamilyMembers());
+ handler()->HandleGetParents(&list_args);
+
+ // Simulate failed fetching of family members.
+ handler()->OnFailure(FamilyInfoFetcher::ErrorCode::NETWORK_ERROR);
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ VerifyJavascriptCallbackResolved(data, callback_id, false /*success*/);
+
+ ASSERT_EQ(base::ListValue(), *data.arg3());
+}
+
+TEST_F(EduAccountLoginHandlerTest, HandleParentSigninSuccess) {
+ handler()->AllowJavascriptForTesting();
+
+ constexpr char callback_id[] = "handle-parent-signin-callback";
+ base::ListValue list_args;
+ list_args.AppendString(callback_id);
+ list_args.Append(GetFakeParent());
+ list_args.Append(kFakeParentCredential);
+
+ EXPECT_CALL(*handler(),
+ FetchAccessToken(kFakeParentGaiaId, kFakeParentCredential));
+ handler()->HandleParentSignin(&list_args);
+
+ EXPECT_CALL(*handler(),
+ FetchReAuthProofTokenForParent(
+ kFakeAccessToken, kFakeParentGaiaId, kFakeParentCredential));
+ handler()->CreateReAuthProofTokenForParent(
+ kFakeParentGaiaId, kFakeParentCredential,
+ GoogleServiceAuthError(GoogleServiceAuthError::NONE),
+ signin::AccessTokenInfo(kFakeAccessToken,
+ base::Time::Now() + base::TimeDelta::FromHours(1),
+ "id_token"));
+
+ constexpr char fake_rapt[] = "fakeReauthProofToken";
+ // Simulate successful fetching of ReAuthProofToken.
+ handler()->OnReAuthProofTokenSuccess(fake_rapt);
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ VerifyJavascriptCallbackResolved(data, callback_id);
+
+ ASSERT_EQ(base::Value(fake_rapt), *data.arg3());
+}
+
+TEST_F(EduAccountLoginHandlerTest, HandleParentSigninAccessTokenFailure) {
+ handler()->AllowJavascriptForTesting();
+
+ constexpr char callback_id[] = "handle-parent-signin-callback";
+ base::ListValue list_args;
+ list_args.AppendString(callback_id);
+ list_args.Append(GetFakeParent());
+ list_args.Append(kFakeParentCredential);
+
+ EXPECT_CALL(*handler(),
+ FetchAccessToken(kFakeParentGaiaId, kFakeParentCredential));
+ handler()->HandleParentSignin(&list_args);
+
+ handler()->CreateReAuthProofTokenForParent(
+ kFakeParentGaiaId, kFakeParentCredential,
+ GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR),
+ signin::AccessTokenInfo());
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ VerifyJavascriptCallbackResolved(data, callback_id, false /*success*/);
+
+ base::DictionaryValue result;
+ result.SetBoolKey("isWrongPassword", false);
+ ASSERT_EQ(result, *data.arg3());
+}
+
+TEST_F(EduAccountLoginHandlerTest, HandleParentSigninReAuthProofTokenFailure) {
+ handler()->AllowJavascriptForTesting();
+
+ constexpr char callback_id[] = "handle-parent-signin-callback";
+ base::ListValue list_args;
+ list_args.AppendString(callback_id);
+ list_args.Append(GetFakeParent());
+ list_args.Append(kFakeParentCredential);
+
+ EXPECT_CALL(*handler(),
+ FetchAccessToken(kFakeParentGaiaId, kFakeParentCredential));
+ handler()->HandleParentSignin(&list_args);
+
+ EXPECT_CALL(*handler(),
+ FetchReAuthProofTokenForParent(
+ kFakeAccessToken, kFakeParentGaiaId, kFakeParentCredential));
+ handler()->CreateReAuthProofTokenForParent(
+ kFakeParentGaiaId, kFakeParentCredential,
+ GoogleServiceAuthError(GoogleServiceAuthError::NONE),
+ signin::AccessTokenInfo(kFakeAccessToken,
+ base::Time::Now() + base::TimeDelta::FromHours(1),
+ "id_token"));
+
+ // Simulate failed fetching of ReAuthProofToken.
+ handler()->OnReAuthProofTokenFailure(
+ GaiaAuthConsumer::ReAuthProofTokenStatus::kInvalidGrant);
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ VerifyJavascriptCallbackResolved(data, callback_id, false);
+
+ base::DictionaryValue result;
+ result.SetBoolKey("isWrongPassword", true);
+ ASSERT_EQ(result, *data.arg3());
+}
+
+TEST_F(EduAccountLoginHandlerTest, ProfileImageFetcherTest) {
+ std::map<std::string, gfx::Image> expected_profile_images =
+ GetFakeProfileImageMap();
+
+ // Expect callback to be called with all images in GetFakeProfileImageMap.
+ auto callback = base::BindLambdaForTesting(
+ [&](std::map<std::string, gfx::Image> profile_images) {
+ EXPECT_EQ(expected_profile_images.size(), profile_images.size());
+
+ for (const auto& profile_image_pair : profile_images) {
+ gfx::Image expected_image =
+ expected_profile_images[profile_image_pair.first];
+ EXPECT_TRUE(gfx::test::AreImagesEqual(expected_image,
+ profile_image_pair.second));
+ }
+ });
+
+ // Expect to be called 1 time (only for image with URL). For profile with
+ // empty image URL - default gfx::Image() should be returned.
+ EXPECT_CALL(*mock_image_fetcher(), FetchImageAndData_(_, _, _, _)).Times(1);
+
+ auto profile_image_fetcher =
+ std::make_unique<EduAccountLoginHandler::ProfileImageFetcher>(
+ mock_image_fetcher(), GetFakeProfileImageUrlMap(), callback);
+ profile_image_fetcher->FetchProfileImages();
+
+ // Simulate successful image fetching (for image with URL) -> expect the
+ // callback to be called.
+ profile_image_fetcher->OnImageFetched(kFakeParentGaiaId, GetFakeImage(),
+ image_fetcher::RequestMetadata());
+}
+
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc
index 655134c118a..2f9c7d1eb4c 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc
@@ -57,10 +57,6 @@ void SetLocalizedStrings(Profile* profile,
l10n_util::GetStringUTF16(IDS_FIRST_RUN_HELP_STEP_FINISH_BUTTON));
localized_strings->SetString(
"nextButton", l10n_util::GetStringUTF16(IDS_FIRST_RUN_NEXT_BUTTON));
- localized_strings->SetBoolean(
- "transitionsEnabled",
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kEnableFirstRunUITransitions));
localized_strings->SetString(
"accessibleTitle",
l10n_util::GetStringUTF16(IDS_FIRST_RUN_STEP_ACCESSIBLE_TITLE));
diff --git a/chromium/chrome/browser/ui/webui/chromeos/image_source.cc b/chromium/chrome/browser/ui/webui/chromeos/image_source.cc
index 2ad02f4ce3e..cd1d5e2d04f 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/image_source.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/image_source.cc
@@ -16,6 +16,7 @@
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/chromeos/login/users/avatar/user_image_loader.h"
@@ -40,8 +41,8 @@ void ImageLoaded(content::URLDataSource::GotDataCallback got_data_callback,
} // namespace
ImageSource::ImageSource() {
- task_runner_ = base::CreateSequencedTaskRunner(
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
}
@@ -64,9 +65,8 @@ void ImageSource::StartDataRequest(
const base::FilePath asset_dir(chrome::kChromeOSAssetPath);
const base::FilePath image_path = asset_dir.AppendASCII(path);
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&base::PathExists, image_path),
base::BindOnce(&ImageSource::StartDataRequestAfterPathExists,
weak_factory_.GetWeakPtr(), image_path,
diff --git a/chromium/chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.cc
index c91925636af..02e8de7122f 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.cc
@@ -30,6 +30,7 @@
#include "content/public/browser/web_ui_data_source.h"
#include "net/base/url_util.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/strings/grit/ui_strings.h"
diff --git a/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc
index d341aac11e6..43f44e8bbe9 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc
@@ -155,18 +155,16 @@ InternetConfigDialogUI::InternetConfigDialogUI(content::WebUI* web_ui)
#endif
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
-
- // Add Mojo bindings to this WebUI so that Mojo calls can occur in JavaScript.
- AddHandlerToRegistry(base::BindRepeating(
- &InternetConfigDialogUI::BindCrosNetworkConfig, base::Unretained(this)));
}
InternetConfigDialogUI::~InternetConfigDialogUI() {}
-void InternetConfigDialogUI::BindCrosNetworkConfig(
+void InternetConfigDialogUI::BindInterface(
mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
receiver) {
ash::GetNetworkConfigService(std::move(receiver));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(InternetConfigDialogUI)
+
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.h
index a95f0f75897..f3d3dfcaf9f 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.h
@@ -54,12 +54,15 @@ class InternetConfigDialogUI : public ui::MojoWebDialogUI {
public:
explicit InternetConfigDialogUI(content::WebUI* web_ui);
~InternetConfigDialogUI() override;
-
- private:
- void BindCrosNetworkConfig(
+ // Instantiates implementor of the mojom::CrosNetworkConfig mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
receiver);
+ private:
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(InternetConfigDialogUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.cc
index 02ea2ac9977..59ff9f6636a 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.cc
@@ -153,18 +153,16 @@ InternetDetailDialogUI::InternetDetailDialogUI(content::WebUI* web_ui)
IDR_INTERNET_DETAIL_DIALOG_JS);
#endif
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
-
- // Add Mojo bindings to this WebUI so that Mojo calls can occur in JavaScript.
- AddHandlerToRegistry(base::BindRepeating(
- &InternetDetailDialogUI::BindCrosNetworkConfig, base::Unretained(this)));
}
InternetDetailDialogUI::~InternetDetailDialogUI() {}
-void InternetDetailDialogUI::BindCrosNetworkConfig(
+void InternetDetailDialogUI::BindInterface(
mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
receiver) {
ash::GetNetworkConfigService(std::move(receiver));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(InternetDetailDialogUI)
+
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.h
index fe91980b879..e84b1cbf9d0 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/internet_detail_dialog.h
@@ -50,11 +50,15 @@ class InternetDetailDialogUI : public ui::MojoWebDialogUI {
explicit InternetDetailDialogUI(content::WebUI* web_ui);
~InternetDetailDialogUI() override;
- private:
- void BindCrosNetworkConfig(
+ // Instantiates implementor of the mojom::CrosNetworkConfig mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
receiver);
+ private:
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(InternetDetailDialogUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
index 57a8d683416..afba0db4fb2 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
@@ -65,14 +65,12 @@ void AppLaunchSplashScreenHandler::DeclareLocalizedValues(
const base::string16 product_os_name =
l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME);
- builder->Add(
- "shortcutInfo",
- l10n_util::GetStringFUTF16(IDS_APP_START_BAILOUT_SHORTCUT_FORMAT,
- product_os_name));
-
- builder->Add(
- "productName",
- l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME));
+ builder->Add("shortcutInfo",
+ l10n_util::GetStringFUTF16(IDS_APP_START_BAILOUT_SHORTCUT_FORMAT,
+ product_os_name));
+
+ builder->Add("productName",
+ l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME));
}
void AppLaunchSplashScreenHandler::Initialize() {
@@ -111,8 +109,7 @@ void AppLaunchSplashScreenHandler::RegisterMessages() {
&AppLaunchSplashScreenHandler::HandleNetworkConfigRequested);
}
-void AppLaunchSplashScreenHandler::Hide() {
-}
+void AppLaunchSplashScreenHandler::Hide() {}
void AppLaunchSplashScreenHandler::ToggleNetworkConfig(bool visible) {
CallJS("login.AppLaunchSplashScreen.toggleNetworkConfig", visible);
@@ -127,6 +124,13 @@ void AppLaunchSplashScreenHandler::UpdateAppLaunchState(AppLaunchState state) {
SetLaunchText(
l10n_util::GetStringUTF8(GetProgressMessageFromState(state_)));
}
+
+ // When we are asked to initialize network, we should remember that this app
+ // requires network.
+ if (state_ == AppLaunchState::APP_LAUNCH_STATE_PREPARING_NETWORK) {
+ network_required_ = true;
+ }
+
UpdateState(NetworkError::ERROR_REASON_UPDATE);
}
@@ -135,13 +139,14 @@ void AppLaunchSplashScreenHandler::SetDelegate(Delegate* delegate) {
}
void AppLaunchSplashScreenHandler::ShowNetworkConfigureUI() {
+ network_config_shown_ = true;
+
NetworkStateInformer::State state = network_state_informer_->state();
- if (state == NetworkStateInformer::ONLINE) {
- online_state_ = true;
- if (!network_config_requested_) {
- delegate_->OnNetworkStateChanged(true);
- return;
- }
+
+ // We should not block users when the network was not required by the
+ // controller.
+ if (!network_required_) {
+ state = NetworkStateInformer::ONLINE;
}
const std::string network_path = network_state_informer_->network_path();
@@ -197,16 +202,16 @@ void AppLaunchSplashScreenHandler::OnNetworkReady() {
void AppLaunchSplashScreenHandler::UpdateState(
NetworkError::ErrorReason reason) {
- if (!delegate_ || (state_ != APP_LAUNCH_STATE_PREPARING_NETWORK &&
- state_ != APP_LAUNCH_STATE_NETWORK_WAIT_TIMEOUT)) {
+ if (!delegate_)
return;
- }
-
bool new_online_state =
network_state_informer_->state() == NetworkStateInformer::ONLINE;
delegate_->OnNetworkStateChanged(new_online_state);
- online_state_ = new_online_state;
+ // Redraw network configure UI when the network state changes.
+ if (network_config_shown_) {
+ ShowNetworkConfigureUI();
+ }
}
void AppLaunchSplashScreenHandler::PopulateAppInfo(
@@ -222,8 +227,14 @@ void AppLaunchSplashScreenHandler::PopulateAppInfo(
IDR_PRODUCT_LOGO_128);
}
+ // Display app domain if present.
+ if (!app.url.is_empty()) {
+ app.url = app.url.GetOrigin();
+ }
+
out_info->SetString("name", app.name);
out_info->SetString("iconURL", webui::GetBitmapDataUrl(*app.icon.bitmap()));
+ out_info->SetString("url", app.url.spec());
}
void AppLaunchSplashScreenHandler::SetLaunchText(const std::string& text) {
@@ -233,12 +244,16 @@ void AppLaunchSplashScreenHandler::SetLaunchText(const std::string& text) {
int AppLaunchSplashScreenHandler::GetProgressMessageFromState(
AppLaunchState state) {
switch (state) {
+ case APP_LAUNCH_STATE_PREPARING_PROFILE:
+ return IDS_APP_START_PREPARING_PROFILE_MESSAGE;
case APP_LAUNCH_STATE_PREPARING_NETWORK:
return IDS_APP_START_NETWORK_WAIT_MESSAGE;
case APP_LAUNCH_STATE_INSTALLING_APPLICATION:
return IDS_APP_START_APP_WAIT_MESSAGE;
case APP_LAUNCH_STATE_WAITING_APP_WINDOW:
return IDS_APP_START_WAIT_FOR_APP_WINDOW_MESSAGE;
+ case APP_LAUNCH_STATE_WAITING_APP_WINDOW_INSTALL_FAILED:
+ return IDS_APP_START_WAIT_FOR_APP_WINDOW_INSTALL_FAILED_MESSAGE;
case APP_LAUNCH_STATE_NETWORK_WAIT_TIMEOUT:
return IDS_APP_START_NETWORK_WAIT_TIMEOUT_MESSAGE;
case APP_LAUNCH_STATE_SHOWING_NETWORK_CONFIGURE_UI:
@@ -262,21 +277,18 @@ void AppLaunchSplashScreenHandler::HandleCancelAppLaunch() {
}
void AppLaunchSplashScreenHandler::HandleNetworkConfigRequested() {
- if (!delegate_ || network_config_done_)
+ if (!delegate_)
return;
-
- network_config_requested_ = true;
delegate_->OnNetworkConfigRequested();
}
void AppLaunchSplashScreenHandler::HandleContinueAppLaunch() {
- DCHECK(online_state_);
- if (delegate_ && online_state_) {
- network_config_requested_ = false;
- network_config_done_ = true;
- delegate_->OnNetworkConfigFinished();
- Show();
- }
+ if (!delegate_)
+ return;
+
+ network_config_shown_ = false;
+ delegate_->OnNetworkConfigFinished();
+ Show();
}
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
index 09690d5b2d7..b34bb34d47e 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
@@ -45,9 +45,11 @@ class AppLaunchSplashScreenView {
};
enum AppLaunchState {
+ APP_LAUNCH_STATE_PREPARING_PROFILE,
APP_LAUNCH_STATE_PREPARING_NETWORK,
APP_LAUNCH_STATE_INSTALLING_APPLICATION,
APP_LAUNCH_STATE_WAITING_APP_WINDOW,
+ APP_LAUNCH_STATE_WAITING_APP_WINDOW_INSTALL_FAILED,
APP_LAUNCH_STATE_NETWORK_WAIT_TIMEOUT,
APP_LAUNCH_STATE_SHOWING_NETWORK_CONFIGURE_UI,
};
@@ -124,19 +126,15 @@ class AppLaunchSplashScreenHandler
Delegate* delegate_ = nullptr;
bool show_on_init_ = false;
- AppLaunchState state_ = APP_LAUNCH_STATE_PREPARING_NETWORK;
+ AppLaunchState state_ = APP_LAUNCH_STATE_PREPARING_PROFILE;
scoped_refptr<NetworkStateInformer> network_state_informer_;
ErrorScreen* error_screen_;
- // True if we are online.
- bool online_state_ = false;
-
- // True if we have network config screen was already shown before.
- bool network_config_done_ = false;
-
- // True if we have manually requested network config screen.
- bool network_config_requested_ = false;
+ // Whether network configure UI is being shown.
+ bool network_config_shown_ = false;
+ // Whether the network is required in order to proceed with app launch.
+ bool network_required_ = false;
DISALLOW_COPY_AND_ASSIGN(AppLaunchSplashScreenHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.cc
deleted file mode 100644
index 3cf432e74d3..00000000000
--- a/chromium/chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.cc
+++ /dev/null
@@ -1,120 +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 "chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.h"
-
-#include <memory>
-
-#include "base/values.h"
-#include "chrome/browser/chromeos/login/arc_kiosk_controller.h"
-#include "chrome/grit/chrome_unscaled_resources.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/login/localized_values_builder.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/base/webui/web_ui_util.h"
-#include "ui/gfx/image/image_skia.h"
-
-namespace chromeos {
-
-constexpr StaticOobeScreenId ArcKioskSplashScreenView::kScreenId;
-
-ArcKioskSplashScreenHandler::ArcKioskSplashScreenHandler(
- JSCallsContainer* js_calls_container)
- : BaseScreenHandler(kScreenId, js_calls_container) {}
-
-ArcKioskSplashScreenHandler::~ArcKioskSplashScreenHandler() {
- if (controller_)
- controller_->OnDeletingSplashScreenView();
-}
-
-void ArcKioskSplashScreenHandler::DeclareLocalizedValues(
- ::login::LocalizedValuesBuilder* builder) {
- builder->Add("arcKioskStartMessage", IDS_APP_START_APP_WAIT_MESSAGE);
-
- const base::string16 product_os_name =
- l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_OS_NAME);
- builder->Add("arcKioskShortcutInfo",
- l10n_util::GetStringFUTF16(IDS_APP_START_BAILOUT_SHORTCUT_FORMAT,
- product_os_name));
- builder->Add("arcKioskProductName", product_os_name);
-}
-
-void ArcKioskSplashScreenHandler::Initialize() {
- if (!show_on_init_)
- return;
- show_on_init_ = false;
- Show();
-}
-
-void ArcKioskSplashScreenHandler::Show() {
- if (!page_is_ready()) {
- show_on_init_ = true;
- return;
- }
-
- base::DictionaryValue data;
- // |data| will take ownership of |app_info|.
- std::unique_ptr<base::DictionaryValue> app_info =
- std::make_unique<base::DictionaryValue>();
- PopulateAppInfo(app_info.get());
- data.Set("appInfo", std::move(app_info));
- ShowScreenWithData(kScreenId, &data);
-}
-
-void ArcKioskSplashScreenHandler::RegisterMessages() {
- AddCallback("cancelArcKioskLaunch",
- &ArcKioskSplashScreenHandler::HandleCancelArcKioskLaunch);
-}
-
-void ArcKioskSplashScreenHandler::UpdateArcKioskState(ArcKioskState state) {
- if (!page_is_ready())
- return;
- SetLaunchText(l10n_util::GetStringUTF8(GetProgressMessageFromState(state)));
-}
-
-void ArcKioskSplashScreenHandler::SetDelegate(ArcKioskController* controller) {
- controller_ = controller;
-}
-
-void ArcKioskSplashScreenHandler::PopulateAppInfo(
- base::DictionaryValue* out_info) {
- out_info->SetString("name", l10n_util::GetStringUTF8(IDS_SHORT_PRODUCT_NAME));
- out_info->SetString(
- "iconURL",
- webui::GetBitmapDataUrl(*ui::ResourceBundle::GetSharedInstance()
- .GetImageSkiaNamed(IDR_PRODUCT_LOGO_128)
- ->bitmap()));
-}
-
-void ArcKioskSplashScreenHandler::SetLaunchText(const std::string& text) {
- CallJS("login.ArcKioskSplashScreen.updateArcKioskMessage", text);
-}
-
-int ArcKioskSplashScreenHandler::GetProgressMessageFromState(
- ArcKioskState state) {
- switch (state) {
- case ArcKioskState::STARTING_SESSION:
- return IDS_SYNC_SETUP_SPINNER_TITLE;
- case ArcKioskState::WAITING_APP_LAUNCH:
- return IDS_APP_START_APP_WAIT_MESSAGE;
- case ArcKioskState::WAITING_APP_WINDOW:
- return IDS_APP_START_WAIT_FOR_APP_WINDOW_MESSAGE;
- default:
- NOTREACHED();
- break;
- }
- return IDS_SYNC_SETUP_SPINNER_TITLE;
-}
-
-void ArcKioskSplashScreenHandler::HandleCancelArcKioskLaunch() {
- if (!controller_) {
- LOG(WARNING) << "No delegate set to handle cancel app launch";
- return;
- }
- controller_->OnCancelArcKioskLaunch();
-}
-
-} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.h
deleted file mode 100644
index 2eccabc7924..00000000000
--- a/chromium/chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.h
+++ /dev/null
@@ -1,85 +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 CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ARC_KIOSK_SPLASH_SCREEN_HANDLER_H_
-#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ARC_KIOSK_SPLASH_SCREEN_HANDLER_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
-
-namespace base {
-class DictionaryValue;
-}
-
-namespace chromeos {
-
-class ArcKioskController;
-
-// Interface for UI implementations of the ArcKioskSplashScreen.
-class ArcKioskSplashScreenView {
- public:
- enum class ArcKioskState {
- STARTING_SESSION,
- WAITING_APP_LAUNCH,
- WAITING_APP_WINDOW,
- };
-
- constexpr static StaticOobeScreenId kScreenId{"arc-kiosk-splash"};
-
- ArcKioskSplashScreenView() = default;
-
- virtual ~ArcKioskSplashScreenView() = default;
-
- // Shows the contents of the screen.
- virtual void Show() = 0;
-
- // Set the current ARC kiosk state.
- virtual void UpdateArcKioskState(ArcKioskState state) = 0;
-
- // Sets screen this view belongs to.
- virtual void SetDelegate(ArcKioskController* controller) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ArcKioskSplashScreenView);
-};
-
-// A class that handles the WebUI hooks for the ARC kiosk splash screen.
-class ArcKioskSplashScreenHandler : public BaseScreenHandler,
- public ArcKioskSplashScreenView {
- public:
- using TView = ArcKioskSplashScreenView;
-
- explicit ArcKioskSplashScreenHandler(JSCallsContainer* js_calls_container);
- ~ArcKioskSplashScreenHandler() override;
-
- private:
- // BaseScreenHandler implementation:
- void DeclareLocalizedValues(
- ::login::LocalizedValuesBuilder* builder) override;
- void Initialize() override;
-
- // WebUIMessageHandler implementation:
- void RegisterMessages() override;
-
- // ArcKioskSplashScreenView implementation:
- void Show() override;
- void UpdateArcKioskState(ArcKioskState state) override;
- void SetDelegate(ArcKioskController* controller) override;
-
- void PopulateAppInfo(base::DictionaryValue* out_info);
- void SetLaunchText(const std::string& text);
- int GetProgressMessageFromState(ArcKioskState state);
- void HandleCancelArcKioskLaunch();
-
- ArcKioskController* controller_ = nullptr;
- bool show_on_init_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(ArcKioskSplashScreenHandler);
-};
-
-} // namespace chromeos
-
-#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_ARC_KIOSK_SPLASH_SCREEN_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.cc
index 31de0cd5dfb..bc8d272106e 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.cc
@@ -28,6 +28,7 @@
#include "components/consent_auditor/consent_auditor.h"
#include "components/login/localized_values_builder.h"
#include "components/prefs/pref_service.h"
+#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/web_contents.h"
@@ -114,7 +115,6 @@ void ArcTermsOfServiceScreenHandler::DeclareLocalizedValues(
IDS_ARC_OOBE_TERMS_DESCRIPTION);
builder->Add("arcTermsOfServiceLoading", IDS_ARC_OOBE_TERMS_LOADING);
builder->Add("arcTermsOfServiceError", IDS_ARC_OOBE_TERMS_LOAD_ERROR);
- builder->Add("arcTermsOfServiceSkipButton", IDS_ARC_OOBE_TERMS_BUTTON_SKIP);
builder->Add("arcTermsOfServiceRetryButton", IDS_ARC_OOBE_TERMS_BUTTON_RETRY);
builder->Add("arcTermsOfServiceAcceptButton",
IDS_ARC_OOBE_TERMS_BUTTON_ACCEPT);
@@ -123,35 +123,84 @@ void ArcTermsOfServiceScreenHandler::DeclareLocalizedValues(
builder->Add("arcTermsOfServiceNextButton",
IDS_ARC_OPT_IN_DIALOG_BUTTON_NEXT);
builder->Add("arcPolicyLink", IDS_ARC_OPT_IN_PRIVACY_POLICY_LINK);
- builder->Add("arcTextBackupRestore",
- is_child_account_ ? IDS_ARC_OPT_IN_DIALOG_BACKUP_RESTORE_CHILD
- : IDS_ARC_OPT_IN_DIALOG_BACKUP_RESTORE);
+ builder->Add("arcTextBackupRestore", is_child_account_
+ ? IDS_ARC_OOBE_BACKUP_RESTORE_CHILD
+ : IDS_ARC_OOBE_BACKUP_RESTORE);
builder->Add("arcTextLocationService",
- is_child_account_ ? IDS_ARC_OPT_IN_LOCATION_SETTING_CHILD
- : IDS_ARC_OPT_IN_LOCATION_SETTING);
- builder->Add("arcTextPaiService", IDS_ARC_OPT_IN_PAI);
+ is_child_account_ ? IDS_ARC_OOBE_LOCATION_SETTING_CHILD
+ : IDS_ARC_OOBE_LOCATION_SETTING);
+ builder->Add("arcTextPaiService", IDS_ARC_OOBE_PAI);
builder->Add("arcTextGoogleServiceConfirmation",
IDS_ARC_OPT_IN_GOOGLE_SERVICE_CONFIRMATION);
builder->Add("arcTextReviewSettings", IDS_ARC_REVIEW_SETTINGS);
+ builder->Add("arcTextMetricsEnabled",
+ IDS_ARC_OOBE_TERMS_DIALOG_METRICS_ENABLED);
+ builder->Add("arcTextMetricsDisabled",
+ IDS_ARC_OOBE_TERMS_DIALOG_METRICS_DISABLED);
builder->Add("arcTextMetricsManagedEnabled",
IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_ENABLED);
+ builder->Add("arcTextMetricsManagedDisabled",
+ IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_DISABLED);
+ builder->Add("arcTextMetricsEnabledChild",
+ IDS_ARC_OOBE_TERMS_DIALOG_METRICS_ENABLED_CHILD);
+ builder->Add("arcTextMetricsDisabledChild",
+ IDS_ARC_OOBE_TERMS_DIALOG_METRICS_DISABLED_CHILD);
+ builder->Add("arcTextMetricsManagedEnabledChild",
+ IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_ENABLED_CHILD);
+ builder->Add("arcTextMetricsManagedDisabledChild",
+ IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_DISABLED_CHILD);
builder->Add("arcTextMetricsDemoApps", IDS_ARC_OOBE_TERMS_DIALOG_DEMO_APPS);
builder->Add("arcAcceptAndContinueGoogleServiceConfirmation",
IDS_ARC_OPT_IN_ACCEPT_AND_CONTINUE_GOOGLE_SERVICE_CONFIRMATION);
- builder->Add("arcLearnMoreStatistics",
- is_child_account_ ? IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_CHILD
- : IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS);
- builder->Add("arcLearnMoreLocationService",
+ builder->Add("arcLearnMoreStatisticsTitle",
+ IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_TITLE);
+ builder->Add("arcLearnMoreStatisticsP1",
+ is_child_account_ ? IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_CHILD_P1
+ : IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_P1);
+ builder->Add("arcLearnMoreStatisticsP2",
+ is_child_account_ ? IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_CHILD_P2
+ : IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_P2);
+ builder->Add("arcLearnMoreStatisticsP3",
+ is_child_account_ ? IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_CHILD_P3
+ : IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_P3);
+ builder->Add("arcLearnMoreStatisticsP4",
+ is_child_account_ ? IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_CHILD_P4
+ : IDS_ARC_OPT_IN_LEARN_MORE_STATISTICS_P4);
+ builder->Add("arcLearnMoreLocationServiceTitle",
+ IDS_ARC_OPT_IN_LEARN_MORE_LOCATION_SERVICES_TITLE);
+ builder->Add("arcLearnMoreLocationServiceP1",
is_child_account_
- ? IDS_ARC_OPT_IN_LEARN_MORE_LOCATION_SERVICES_CHILD
- : IDS_ARC_OPT_IN_LEARN_MORE_LOCATION_SERVICES);
- builder->Add("arcLearnMoreBackupAndRestore",
+ ? IDS_ARC_OPT_IN_LEARN_MORE_LOCATION_SERVICES_CHILD_P1
+ : IDS_ARC_OPT_IN_LEARN_MORE_LOCATION_SERVICES_P1);
+ builder->Add("arcLearnMoreLocationServiceP2",
is_child_account_
- ? IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_CHILD
- : IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE);
- builder->Add("arcLearnMorePaiService", IDS_ARC_OPT_IN_LEARN_MORE_PAI_SERVICE);
+ ? IDS_ARC_OPT_IN_LEARN_MORE_LOCATION_SERVICES_CHILD_P2
+ : IDS_ARC_OPT_IN_LEARN_MORE_LOCATION_SERVICES_P2);
+ builder->Add("arcLearnMoreBackupAndRestoreTitle",
+ IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_TITLE);
+ builder->Add("arcLearnMoreBackupAndRestoreP1",
+ IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_P1);
+ builder->Add("arcLearnMoreBackupAndRestoreP2",
+ IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_P2);
+ builder->Add("arcLearnMoreBackupAndRestoreP3",
+ IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_P3);
+ builder->Add("arcLearnMoreBackupAndRestoreP4",
+ IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_P4);
+ builder->Add("arcLearnMoreBackupAndRestoreP5",
+ IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_P5);
+ builder->Add("arcLearnMoreBackupAndRestoreChildP1",
+ IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_CHILD_P1);
+ builder->Add("arcLearnMoreBackupAndRestoreChildP2",
+ IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_CHILD_P2);
+ builder->Add("arcLearnMoreBackupAndRestoreChildP3",
+ IDS_ARC_OPT_IN_LEARN_MORE_BACKUP_AND_RESTORE_CHILD_P3);
+ builder->Add("arcLearnMorePaiServiceTitle",
+ IDS_ARC_OPT_IN_LEARN_MORE_PAI_SERVICE_TITLE);
+ builder->Add("arcLearnMorePaiService", IDS_ARC_OOBE_LEARN_MORE_PAI_SERVICE);
builder->Add("arcOverlayClose", IDS_ARC_OOBE_TERMS_POPUP_HELP_CLOSE_BUTTON);
+ builder->Add("oobeModalDialogClose", IDS_CHROMEOS_OOBE_CLOSE_DIALOG);
builder->Add("arcOverlayLoading", IDS_ARC_POPUP_HELP_LOADING);
+ builder->Add("arcLearnMoreText", IDS_ARC_OPT_IN_DIALOG_LEARN_MORE_LINK_TEXT);
}
void ArcTermsOfServiceScreenHandler::OnMetricsModeChanged(bool enabled,
@@ -171,27 +220,24 @@ void ArcTermsOfServiceScreenHandler::OnMetricsModeChanged(bool enabled,
// managed flag.
const bool owner_profile = !owner.is_valid() || user->GetAccountId() == owner;
- int message_id;
+ std::string message;
if (owner_profile && !managed) {
if (is_child_account_) {
- message_id = enabled ? IDS_ARC_OOBE_TERMS_DIALOG_METRICS_ENABLED_CHILD
- : IDS_ARC_OOBE_TERMS_DIALOG_METRICS_DISABLED_CHILD;
+ message = enabled ? "arcTextMetricsEnabledChild"
+ : "arcTextMetricsDisabledChild";
} else {
- message_id = enabled ? IDS_ARC_OOBE_TERMS_DIALOG_METRICS_ENABLED
- : IDS_ARC_OOBE_TERMS_DIALOG_METRICS_DISABLED;
+ message = enabled ? "arcTextMetricsEnabled" : "arcTextMetricsDisabled";
}
} else {
if (is_child_account_) {
- message_id =
- enabled ? IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_ENABLED_CHILD
- : IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_DISABLED_CHILD;
+ message = enabled ? "arcTextMetricsManagedEnabledChild"
+ : "arcTextMetricsManagedDisabledChild";
} else {
- message_id = enabled ? IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_ENABLED
- : IDS_ARC_OOBE_TERMS_DIALOG_METRICS_MANAGED_DISABLED;
+ message = enabled ? "arcTextMetricsManagedEnabled"
+ : "arcTextMetricsManagedDisabled";
}
}
- CallJS("login.ArcTermsOfServiceScreen.setMetricsMode",
- l10n_util::GetStringUTF16(message_id), true);
+ CallJS("login.ArcTermsOfServiceScreen.setMetricsMode", message, true);
}
void ArcTermsOfServiceScreenHandler::OnBackupAndRestoreModeChanged(
@@ -277,19 +323,19 @@ void ArcTermsOfServiceScreenHandler::DoShow() {
// ToS then prefs::kArcEnabled is automatically reset in ArcSessionManager.
arc::SetArcPlayStoreEnabledForProfile(profile, true);
- // Hide the Skip button if the ToS screen can not be skipped during OOBE.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- chromeos::switches::kEnableArcOobeOptinNoSkip) ||
- arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile)) {
- CallJS("login.ArcTermsOfServiceScreen.hideSkipButton");
- }
+ // Hide the Skip button in the ToS screen.
+ // TODO(crbug.com/1059048) Remove this when the ToS screen no longer has
+ // the skip button altogether. We call it all the time now so we can
+ // remove a Chrome OS flag.
+ CallJS("login.ArcTermsOfServiceScreen.hideSkipButton");
action_taken_ = false;
ShowScreen(kScreenId);
arc_managed_ = arc::IsArcPlayStoreEnabledPreferenceManagedForProfile(profile);
- CallJS("login.ArcTermsOfServiceScreen.setArcManaged", arc_managed_);
+ CallJS("login.ArcTermsOfServiceScreen.setArcManaged", arc_managed_,
+ is_child_account_);
MaybeLoadPlayStoreToS(true);
StartNetworkAndTimeZoneObserving();
@@ -328,8 +374,11 @@ void ArcTermsOfServiceScreenHandler::RecordConsents(
consent_auditor::ConsentAuditor* consent_auditor =
ConsentAuditorFactory::GetForProfile(profile);
auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
- DCHECK(identity_manager->HasPrimaryAccount());
- const CoreAccountId account_id = identity_manager->GetPrimaryAccountId();
+ // The account may or may not have consented to browser sync.
+ DCHECK(
+ identity_manager->HasPrimaryAccount(signin::ConsentLevel::kNotRequired));
+ const CoreAccountId account_id =
+ identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kNotRequired);
ArcPlayTermsOfServiceConsent play_consent;
play_consent.set_status(tos_accepted ? UserConsentTypes::GIVEN
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
index 2e9b0f79190..0875097cdfe 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
@@ -64,17 +64,14 @@ AssistantOptInFlowScreenHandler::~AssistantOptInFlowScreenHandler() {
void AssistantOptInFlowScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) {
- builder->Add("locale", g_browser_process->GetApplicationLocale());
builder->Add("assistantLogo", IDS_ASSISTANT_LOGO);
- builder->Add("assistantOptinLoading", IDS_ASSISTANT_VALUE_PROP_LOADING);
+ builder->Add("assistantOptinLoading", IDS_ASSISTANT_OPT_IN_LOADING);
builder->Add("assistantOptinLoadErrorTitle",
- IDS_ASSISTANT_VALUE_PROP_LOAD_ERROR_TITLE);
+ IDS_ASSISTANT_OPT_IN_LOAD_ERROR_TITLE);
builder->Add("assistantOptinLoadErrorMessage",
- IDS_ASSISTANT_VALUE_PROP_LOAD_ERROR_MESSAGE);
- builder->Add("assistantOptinSkipButton",
- IDS_ASSISTANT_VALUE_PROP_SKIP_BUTTON);
- builder->Add("assistantOptinRetryButton",
- IDS_ASSISTANT_VALUE_PROP_RETRY_BUTTON);
+ IDS_ASSISTANT_OPT_IN_LOAD_ERROR_MESSAGE);
+ builder->Add("assistantOptinSkipButton", IDS_ASSISTANT_OPT_IN_SKIP_BUTTON);
+ builder->Add("assistantOptinRetryButton", IDS_ASSISTANT_OPT_IN_RETRY_BUTTON);
builder->Add("assistantUserImage", IDS_ASSISTANT_OOBE_USER_IMAGE);
builder->Add("assistantVoiceMatchTitle", IDS_ASSISTANT_VOICE_MATCH_TITLE);
builder->Add("assistantVoiceMatchMessage", IDS_ASSISTANT_VOICE_MATCH_MESSAGE);
@@ -278,6 +275,12 @@ void AssistantOptInFlowScreenHandler::OnDialogClosed() {
}
}
+void AssistantOptInFlowScreenHandler::OnAssistantSettingsEnabled(bool enabled) {
+ // Close the opt-in screen is the Assistant is disabled.
+ if (!enabled)
+ HandleFlowFinished();
+}
+
void AssistantOptInFlowScreenHandler::OnAssistantStatusChanged(
ash::mojom::AssistantState state) {
if (state != ash::mojom::AssistantState::NOT_READY) {
@@ -332,6 +335,14 @@ void AssistantOptInFlowScreenHandler::OnGetSettingsResponse(
UMA_HISTOGRAM_TIMES("Assistant.OptInFlow.GetSettingsRequestTime",
time_since_request_sent);
+ if (ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
+ assistant::prefs::kAssistantDisabledByPolicy)) {
+ DVLOG(1) << "Assistant is disabled by domain policy. Skip Assistant "
+ "opt-in flow.";
+ HandleFlowFinished();
+ return;
+ }
+
assistant::SettingsUi settings_ui;
if (!settings_ui.ParseFromString(settings)) {
LOG(ERROR) << "Failed to parse get settings response.";
@@ -573,7 +584,7 @@ void AssistantOptInFlowScreenHandler::HandleFlowFinished() {
UMA_HISTOGRAM_EXACT_LINEAR("Assistant.OptInFlow.LoadingTimeoutCount",
loading_timeout_counter_, 10);
if (screen_)
- screen_->OnUserAction(kFlowFinished);
+ screen_->HandleUserAction(kFlowFinished);
else
CallJS("login.AssistantOptInFlowScreen.closeDialog");
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h
index bad0ee1c62b..5a43ecbce36 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h
@@ -96,6 +96,7 @@ class AssistantOptInFlowScreenHandler
void Initialize() override;
// ash::AssistantStateObserver:
+ void OnAssistantSettingsEnabled(bool enabled) override;
void OnAssistantStatusChanged(ash::mojom::AssistantState state) override;
// Connect to assistant settings manager.
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h
index 7ac15fc624b..619e5b9ab61 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h
@@ -9,7 +9,6 @@
#include "base/macros.h"
#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen_view.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
-#include "content/public/browser/web_ui.h"
namespace chromeos {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/base_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/base_screen_handler.cc
index bf93f4d53d3..e102a083897 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/base_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/base_screen_handler.cc
@@ -32,7 +32,7 @@ void BaseScreenHandler::RegisterMessages() {
void BaseScreenHandler::HandleUserAction(const std::string& action_id) {
if (base_screen_)
- base_screen_->OnUserAction(action_id);
+ base_screen_->HandleUserAction(action_id);
}
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
index 590afb648a2..95159a1980f 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -6,16 +6,17 @@
#include <type_traits>
+#include "ash/public/ash_interfaces.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/event_rewriter_controller.h"
#include "ash/public/cpp/shelf_config.h"
#include "ash/public/cpp/tablet_mode.h"
-#include "ash/public/mojom/constants.mojom.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "build/branding_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
@@ -53,10 +54,7 @@
#include "components/prefs/pref_service.h"
#include "components/strings/grit/components_strings.h"
#include "components/version_info/version_info.h"
-#include "content/public/browser/system_connector.h"
#include "google_apis/google_api_keys.h"
-#include "services/service_manager/public/cpp/connector.h"
-#include "ui/accessibility/accessibility_switches.h"
#include "ui/aura/window_tree_host.h"
#include "ui/display/screen.h"
#include "ui/events/event_sink.h"
@@ -101,12 +99,8 @@ CoreOobeHandler::CoreOobeHandler(JSCallsContainer* js_calls_container)
ash::TabletMode::Get()->AddObserver(this);
- // |connector| may be null in tests.
- auto* connector = content::GetSystemConnector();
- if (connector) {
- connector->Connect(ash::mojom::kServiceName,
- cros_display_config_.BindNewPipeAndPassReceiver());
- }
+ ash::BindCrosDisplayConfigController(
+ cros_display_config_.BindNewPipeAndPassReceiver());
OobeConfiguration::Get()->AddAndFireObserver(this);
}
@@ -169,7 +163,7 @@ void CoreOobeHandler::DeclareLocalizedValues(
void CoreOobeHandler::Initialize() {
UpdateA11yState();
UpdateOobeUIVisibility();
-#if defined(OFFICIAL_BUILD)
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
version_info_updater_.StartUpdate(true);
#else
version_info_updater_.StartUpdate(false);
@@ -208,8 +202,8 @@ void CoreOobeHandler::RegisterMessages() {
&CoreOobeHandler::HandleEnableDockedMagnifier);
AddCallback("setDeviceRequisition",
&CoreOobeHandler::HandleSetDeviceRequisition);
- AddRawCallback("skipToLoginForTesting",
- &CoreOobeHandler::HandleSkipToLoginForTesting);
+ AddCallback("skipToLoginForTesting",
+ &CoreOobeHandler::HandleSkipToLoginForTesting);
AddCallback("skipToUpdateForTesting",
&CoreOobeHandler::HandleSkipToUpdateForTesting);
AddCallback("launchHelpApp", &CoreOobeHandler::HandleLaunchHelpApp);
@@ -225,6 +219,9 @@ void CoreOobeHandler::RegisterMessages() {
AddCallback("setupDemoMode", &CoreOobeHandler::HandleSetupDemoMode);
AddCallback("startDemoModeSetupForTesting",
&CoreOobeHandler::HandleStartDemoModeSetupForTesting);
+
+ AddCallback("hideOobeDialog", &CoreOobeHandler::HandleHideOobeDialog);
+ AddCallback("updateOobeUIState", &CoreOobeHandler::HandleUpdateOobeUIState);
}
void CoreOobeHandler::ShowSignInError(
@@ -383,6 +380,11 @@ void CoreOobeHandler::HandleEnableDockedMagnifier(bool enabled) {
MagnificationManager::Get()->SetDockedMagnifierEnabled(enabled);
}
+void CoreOobeHandler::HandleHideOobeDialog() {
+ if (LoginDisplayHost::default_host())
+ LoginDisplayHost::default_host()->HideOobeDialog();
+}
+
void CoreOobeHandler::HandleSetDeviceRequisition(
const std::string& requisition) {
policy::BrowserPolicyConnectorChromeOS* connector =
@@ -406,18 +408,9 @@ void CoreOobeHandler::HandleSetDeviceRequisition(
}
}
-void CoreOobeHandler::HandleSkipToLoginForTesting(const base::ListValue* args) {
- LoginScreenContext context;
-
- // Parse |args|.
- if (args->GetSize() > 0) {
- std::string email;
- if (args->GetString(0, &email))
- context.set_email(email);
- }
-
+void CoreOobeHandler::HandleSkipToLoginForTesting() {
if (WizardController::default_controller())
- WizardController::default_controller()->SkipToLoginForTesting(context);
+ WizardController::default_controller()->SkipToLoginForTesting();
}
void CoreOobeHandler::HandleSkipToUpdateForTesting() {
@@ -479,10 +472,6 @@ void CoreOobeHandler::UpdateA11yState() {
AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
a11y_info.SetBoolean("selectToSpeakEnabled",
AccessibilityManager::Get()->IsSelectToSpeakEnabled());
- a11y_info.SetBoolean(
- "enableExperimentalA11yFeatures",
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- ::switches::kEnableExperimentalAccessibilityFeatures));
DCHECK(MagnificationManager::Get());
a11y_info.SetBoolean("screenMagnifierEnabled",
MagnificationManager::Get()->IsMagnifierEnabled());
@@ -672,6 +661,13 @@ void CoreOobeHandler::HandleStartDemoModeSetupForTesting(
}
}
+void CoreOobeHandler::HandleUpdateOobeUIState(int state) {
+ if (LoginDisplayHost::default_host()) {
+ auto dialog_state = static_cast<ash::OobeDialogState>(state);
+ LoginDisplayHost::default_host()->UpdateOobeDialogState(dialog_state);
+ }
+}
+
void CoreOobeHandler::InitDemoModeDetection() {
demo_mode_detector_.InitDetection();
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
index 4971a157908..44940f99887 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
@@ -180,11 +180,12 @@ class CoreOobeHandler : public BaseWebUIHandler,
void HandleEnableSpokenFeedback(bool /* enabled */);
void HandleEnableSelectToSpeak(bool /* enabled */);
void HandleEnableDockedMagnifier(bool /* enabled */);
+ void HandleHideOobeDialog();
void HandleInitialized();
void HandleSkipUpdateEnrollAfterEula();
void HandleUpdateCurrentScreen(const std::string& screen);
void HandleSetDeviceRequisition(const std::string& requisition);
- void HandleSkipToLoginForTesting(const base::ListValue* args);
+ void HandleSkipToLoginForTesting();
void HandleSkipToUpdateForTesting();
void HandleLaunchHelpApp(double help_topic_id);
void HandleToggleResetScreen();
@@ -198,6 +199,7 @@ class CoreOobeHandler : public BaseWebUIHandler,
// Handles demo mode setup for tests. Accepts 'online' and 'offline' as
// |demo_config|.
void HandleStartDemoModeSetupForTesting(const std::string& demo_config);
+ void HandleUpdateOobeUIState(int state);
// Shows the reset screen if |is_reset_allowed| and updates the
// tpm_firmware_update in settings.
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.cc
index 0d3868e0730..8dd97791667 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.cc
@@ -10,6 +10,7 @@
#include "chrome/browser/chromeos/login/oobe_screen.h"
#include "chrome/browser/chromeos/login/screens/demo_setup_screen.h"
#include "chrome/grit/generated_resources.h"
+#include "chromeos/constants/chromeos_features.h"
#include "components/login/localized_values_builder.h"
namespace chromeos {
@@ -51,6 +52,12 @@ void DemoSetupScreenHandler::OnSetupFailed(
DemoSetupController::DemoSetupError::RecoveryMethod::kPowerwash);
}
+void DemoSetupScreenHandler::SetCurrentSetupStep(
+ DemoSetupController::DemoSetupStep current_step) {
+ CallJS("login.DemoSetupScreen.setCurrentSetupStep",
+ DemoSetupController::GetDemoSetupStepString(current_step));
+}
+
void DemoSetupScreenHandler::OnSetupSucceeded() {
CallJS("login.DemoSetupScreen.onSetupSucceeded");
}
@@ -67,6 +74,21 @@ void DemoSetupScreenHandler::DeclareLocalizedValues(
IDS_OOBE_DEMO_SETUP_ERROR_SCREEN_RETRY_BUTTON_LABEL);
builder->Add("demoSetupErrorScreenPowerwashButtonLabel",
IDS_LOCAL_STATE_ERROR_POWERWASH_BUTTON);
+
+ builder->Add("demoSetupProgressStepDownload",
+ IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_DOWNLOAD);
+ builder->Add("demoSetupProgressStepEnroll",
+ IDS_OOBE_DEMO_SETUP_PROGRESS_STEP_ENROLL);
+}
+
+void DemoSetupScreenHandler::GetAdditionalParameters(
+ base::DictionaryValue* parameters) {
+ parameters->SetBoolKey(
+ "showStepsInDemoModeSetup",
+ base::FeatureList::IsEnabled(features::kShowStepsInDemoModeSetup));
+
+ parameters->SetPath("demoSetupSteps",
+ DemoSetupController::GetDemoSetupSteps());
}
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h
index 5362c7ca6c5..e21cadb510f 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/demo_setup_screen_handler.h
@@ -28,6 +28,10 @@ class DemoSetupScreenView {
// Sets view and screen.
virtual void Bind(DemoSetupScreen* screen) = 0;
+ // Updates current setup step.
+ virtual void SetCurrentSetupStep(
+ DemoSetupController::DemoSetupStep current_step) = 0;
+
// Handles successful setup.
virtual void OnSetupSucceeded() = 0;
@@ -36,7 +40,7 @@ class DemoSetupScreenView {
const DemoSetupController::DemoSetupError& error) = 0;
};
-// WebUI implementation of DemoSetupScreenView. It controlls UI, receives UI
+// WebUI implementation of DemoSetupScreenView. It controls UI, receives UI
// events and notifies the Delegate.
class DemoSetupScreenHandler : public BaseScreenHandler,
public DemoSetupScreenView {
@@ -50,6 +54,8 @@ class DemoSetupScreenHandler : public BaseScreenHandler,
void Show() override;
void Hide() override;
void Bind(DemoSetupScreen* screen) override;
+ void SetCurrentSetupStep(
+ DemoSetupController::DemoSetupStep current_step) override;
void OnSetupFailed(const DemoSetupController::DemoSetupError& error) override;
void OnSetupSucceeded() override;
@@ -58,6 +64,9 @@ class DemoSetupScreenHandler : public BaseScreenHandler,
void DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) override;
+ // BaseWebUIHandler:
+ void GetAdditionalParameters(base::DictionaryValue* parameters) override;
+
private:
DemoSetupScreen* screen_ = nullptr;
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app_test.cc b/chromium/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app_test.cc
index d939dacac13..ae95efbe5a7 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app_test.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/discover/modules/discover_module_launch_help_app_test.cc
@@ -17,8 +17,8 @@ IN_PROC_BROWSER_TEST_F(DiscoverModuleLaunchHelpAppTest, ShowHelpTab) {
base::RunLoop run_loop;
- base::ActionCallback on_user_action =
- base::BindLambdaForTesting([&](const std::string& action) {
+ base::ActionCallback on_user_action = base::BindLambdaForTesting(
+ [&](const std::string& action, base::TimeTicks action_time) {
if (action == "ShowHelpTab")
run_loop.Quit();
});
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
index b75aaa8b7cf..bcd552e1741 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/encryption_migration_screen_handler.cc
@@ -16,6 +16,7 @@
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "base/time/tick_clock.h"
@@ -39,11 +40,9 @@
#include "components/login/localized_values_builder.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/system_connector.h"
+#include "content/public/browser/device_service.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "services/device/public/mojom/constants.mojom.h"
#include "services/device/public/mojom/wake_lock_provider.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/text/bytes_formatting.h"
#include "ui/chromeos/devicetype_utils.h"
@@ -520,12 +519,11 @@ void EncryptionMigrationScreenHandler::UpdateUIState(UIState state) {
}
void EncryptionMigrationScreenHandler::CheckAvailableStorage() {
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
- free_disk_space_fetcher_,
- base::Bind(&EncryptionMigrationScreenHandler::OnGetAvailableStorage,
- weak_ptr_factory_.GetWeakPtr()));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(free_disk_space_fetcher_),
+ base::BindOnce(&EncryptionMigrationScreenHandler::OnGetAvailableStorage,
+ weak_ptr_factory_.GetWeakPtr()));
}
void EncryptionMigrationScreenHandler::OnGetAvailableStorage(int64_t size) {
@@ -624,16 +622,10 @@ device::mojom::WakeLock* EncryptionMigrationScreenHandler::GetWakeLock() {
mojo::PendingReceiver<device::mojom::WakeLock> receiver =
wake_lock_.BindNewPipeAndPassReceiver();
- // Service manager connection might be not initialized in some testing
- // contexts.
- if (!content::GetSystemConnector())
- return wake_lock_.get();
-
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
mojo::Remote<device::mojom::WakeLockProvider> wake_lock_provider;
- content::GetSystemConnector()->Connect(
- device::mojom::kServiceName,
+ content::GetDeviceService().BindWakeLockProvider(
wake_lock_provider.BindNewPipeAndPassReceiver());
wake_lock_provider->GetWakeLockWithoutContext(
device::mojom::WakeLockType::kPreventAppSuspension,
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
index 8104726c649..90fb5125c55 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -28,8 +28,8 @@
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
-#include "chrome/browser/chromeos/policy/enrollment_status_chromeos.h"
#include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h"
+#include "chrome/browser/policy/enrollment_status.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h"
#include "chrome/grit/generated_resources.h"
@@ -52,7 +52,6 @@ namespace {
// Enrollment step names.
const char kEnrollmentStepSignin[] = "signin";
const char kEnrollmentStepAdJoin[] = "ad-join";
-const char kEnrollmentStepPickLicense[] = "license";
const char kEnrollmentStepSuccess[] = "success";
const char kEnrollmentStepWorking[] = "working";
@@ -119,13 +118,6 @@ bool IsProxyError(NetworkStateInformer::State state,
reason == NetworkError::ERROR_REASON_PROXY_CONNECTION_FAILED;
}
-// Returns the enterprise display domain after enrollment, or an empty string.
-std::string GetEnterpriseDisplayDomain() {
- policy::BrowserPolicyConnectorChromeOS* connector =
- g_browser_process->platform_part()->browser_policy_connector_chromeos();
- return connector->GetEnterpriseDisplayDomain();
-}
-
constexpr struct {
const char* id;
int title_id;
@@ -198,24 +190,20 @@ EnrollmentScreenHandler::~EnrollmentScreenHandler() {
void EnrollmentScreenHandler::RegisterMessages() {
AddCallback("toggleFakeEnrollment",
&EnrollmentScreenHandler::HandleToggleFakeEnrollment);
- AddCallback("oauthEnrollClose",
- &EnrollmentScreenHandler::HandleClose);
+ AddCallback("oauthEnrollClose", &EnrollmentScreenHandler::HandleClose);
AddCallback("oauthEnrollCompleteLogin",
&EnrollmentScreenHandler::HandleCompleteLogin);
AddCallback("oauthEnrollAdCompleteLogin",
&EnrollmentScreenHandler::HandleAdCompleteLogin);
AddCallback("oauthEnrollAdUnlockConfiguration",
&EnrollmentScreenHandler::HandleAdUnlockConfiguration);
- AddCallback("oauthEnrollRetry",
- &EnrollmentScreenHandler::HandleRetry);
+ AddCallback("oauthEnrollRetry", &EnrollmentScreenHandler::HandleRetry);
AddCallback("frameLoadingCompleted",
&EnrollmentScreenHandler::HandleFrameLoadingCompleted);
AddCallback("oauthEnrollAttributes",
&EnrollmentScreenHandler::HandleDeviceAttributesProvided);
AddCallback("oauthEnrollOnLearnMore",
&EnrollmentScreenHandler::HandleOnLearnMore);
- AddCallback("onLicenseTypeSelected",
- &EnrollmentScreenHandler::HandleLicenseTypeSelected);
}
// EnrollmentScreenHandler
@@ -236,20 +224,13 @@ void EnrollmentScreenHandler::Show() {
DoShow();
}
-void EnrollmentScreenHandler::Hide() {
-}
+void EnrollmentScreenHandler::Hide() {}
void EnrollmentScreenHandler::ShowSigninScreen() {
observe_network_failure_ = true;
ShowStep(kEnrollmentStepSignin);
}
-void EnrollmentScreenHandler::ShowLicenseTypeSelectionScreen(
- const base::DictionaryValue& license_types) {
- CallJS("login.OAuthEnrollmentScreen.setAvailableLicenseTypes", license_types);
- ShowStep(kEnrollmentStepPickLicense);
-}
-
void EnrollmentScreenHandler::ShowActiveDirectoryScreen(
const std::string& domain_join_config,
const std::string& machine_name,
@@ -355,10 +336,15 @@ void EnrollmentScreenHandler::ShowEnrollmentSpinnerScreen() {
ShowStep(kEnrollmentStepWorking);
}
-void EnrollmentScreenHandler::ShowAttestationBasedEnrollmentSuccessScreen(
- const std::string& enterprise_domain) {
- CallJS("login.OAuthEnrollmentScreen.showAttestationBasedEnrollmentSuccess",
- ui::GetChromeOSDeviceName(), enterprise_domain);
+void EnrollmentScreenHandler::SetEnterpriseDomainAndDeviceType(
+ const std::string& domain,
+ const base::string16& device_type) {
+ CallJS("login.OAuthEnrollmentScreen.setEnterpriseDomainAndDeviceType", domain,
+ device_type);
+}
+
+void EnrollmentScreenHandler::ShowEnrollmentSuccessScreen() {
+ ShowStep(kEnrollmentStepSuccess);
}
void EnrollmentScreenHandler::ShowAuthError(
@@ -401,12 +387,7 @@ void EnrollmentScreenHandler::ShowEnrollmentStatus(
policy::EnrollmentStatus status) {
switch (status.status()) {
case policy::EnrollmentStatus::SUCCESS:
- if (config_.is_mode_attestation()) {
- ShowAttestationBasedEnrollmentSuccessScreen(
- GetEnterpriseDisplayDomain());
- } else {
- ShowStep(kEnrollmentStepSuccess);
- }
+ ShowEnrollmentSuccessScreen();
return;
case policy::EnrollmentStatus::NO_STATE_KEYS:
ShowError(IDS_ENTERPRISE_ENROLLMENT_STATUS_NO_STATE_KEYS, false);
@@ -520,9 +501,6 @@ void EnrollmentScreenHandler::ShowEnrollmentStatus(
ShowError(IDS_ENTERPRISE_ENROLLMENT_ERROR_SAVE_DEVICE_CONFIGURATION,
false);
return;
- case policy::EnrollmentStatus::LICENSE_REQUEST_FAILED:
- ShowError(IDS_ENTERPRISE_ENROLLMENT_ERROR_LICENSE_REQUEST, false);
- return;
case policy::EnrollmentStatus::OFFLINE_POLICY_LOAD_FAILED:
case policy::EnrollmentStatus::OFFLINE_POLICY_DECODING_FAILED:
// OFFLINE_POLICY_LOAD_FAILED and OFFLINE_POLICY_DECODING_FAILED happen
@@ -546,16 +524,21 @@ void EnrollmentScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) {
builder->Add("oauthEnrollScreenTitle",
IDS_ENTERPRISE_ENROLLMENT_SCREEN_TITLE);
- builder->Add("oauthEnrollRetry", IDS_ENTERPRISE_ENROLLMENT_RETRY);
- builder->Add("oauthEnrollDone", IDS_ENTERPRISE_ENROLLMENT_DONE);
builder->Add("oauthEnrollNextBtn", IDS_OFFLINE_LOGIN_NEXT_BUTTON_TEXT);
builder->Add("oauthEnrollSkip", IDS_ENTERPRISE_ENROLLMENT_SKIP);
+ builder->Add("oauthEnrollDone", IDS_ENTERPRISE_ENROLLMENT_DONE);
+ builder->Add("oauthEnrollRetry", IDS_ENTERPRISE_ENROLLMENT_RETRY);
+ builder->Add("oauthEnrollManualEnrollment",
+ IDS_ENTERPRISE_ENROLLMENT_ENROLL_MANUALLY);
builder->AddF("oauthEnrollSuccess", IDS_ENTERPRISE_ENROLLMENT_SUCCESS,
ui::GetChromeOSDeviceName());
builder->Add("oauthEnrollSuccessTitle",
IDS_ENTERPRISE_ENROLLMENT_SUCCESS_TITLE);
+ builder->Add("oauthEnrollErrorTitle", IDS_ENTERPRISE_ENROLLMENT_ERROR_TITLE);
builder->Add("enrollmentSuccessIllustrationTitle",
IDS_ENTERPRISE_ENROLLMENT_SUCCESS_ILLUSTRATION_TITLE);
+ builder->Add("enrollmentErrorIllustrationTitle",
+ IDS_ENTERPRISE_ENROLLMENT_ERROR_ILLUSTRATION_TITLE);
builder->Add("oauthEnrollDeviceInformation",
IDS_ENTERPRISE_ENROLLMENT_DEVICE_INFORMATION);
builder->Add("oauthEnrollExplainAttributeLink",
@@ -569,7 +552,7 @@ void EnrollmentScreenHandler::DeclareLocalizedValues(
builder->Add("oauthEnrollWorking", IDS_ENTERPRISE_ENROLLMENT_WORKING_MESSAGE);
// Do not use AddF for this string as it will be rendered by the JS code.
builder->Add("oauthEnrollAbeSuccessDomain",
- IDS_ENTERPRISE_ENROLLMENT_SUCCESS_ABE_DOMAIN);
+ IDS_ENTERPRISE_ENROLLMENT_SUCCESS_DOMAIN);
builder->Add("oauthEnrollAbeSuccessSupport",
IDS_ENTERPRISE_ENROLLMENT_SUCCESS_ABE_SUPPORT);
@@ -597,19 +580,6 @@ void EnrollmentScreenHandler::DeclareLocalizedValues(
builder->Add("selectEncryption", IDS_AD_ENCRYPTION_SELECTION_SELECT);
builder->Add("selectConfiguration", IDS_AD_CONFIG_SELECTION_SELECT);
/* End of Active Directory strings */
-
- builder->Add("licenseSelectionCardTitle",
- IDS_ENTERPRISE_ENROLLMENT_LICENSE_SELECTION);
- builder->Add("licenseSelectionCardExplanation",
- IDS_ENTERPRISE_ENROLLMENT_LICENSE_SELECTION_EXPLANATION);
- builder->Add("perpetualLicenseTypeTitle",
- IDS_ENTERPRISE_ENROLLMENT_PERPETUAL_LICENSE_TYPE);
- builder->Add("annualLicenseTypeTitle",
- IDS_ENTERPRISE_ENROLLMENT_ANNUAL_LICENSE_TYPE);
- builder->Add("kioskLicenseTypeTitle",
- IDS_ENTERPRISE_ENROLLMENT_KIOSK_LICENSE_TYPE);
- builder->Add("licenseCountTemplate",
- IDS_ENTERPRISE_ENROLLMENT_LICENSES_REMAINING_TEMPLATE);
}
void EnrollmentScreenHandler::GetAdditionalParameters(
@@ -861,11 +831,6 @@ void EnrollmentScreenHandler::HandleOnLearnMore() {
help_app_->ShowHelpTopic(HelpAppLauncher::HELP_DEVICE_ATTRIBUTES);
}
-void EnrollmentScreenHandler::HandleLicenseTypeSelected(
- const std::string& licenseType) {
- controller_->OnLicenseTypeSelected(licenseType);
-}
-
void EnrollmentScreenHandler::ShowStep(const char* step) {
CallJS("login.OAuthEnrollmentScreen.showStep", std::string(step));
}
@@ -906,6 +871,7 @@ void EnrollmentScreenHandler::DoShowWithPartition(
GaiaUrls::GetInstance()->oauth2_chrome_client_id());
screen_data.SetString("enrollment_mode",
EnrollmentModeToUIMode(config_.mode));
+ screen_data.SetBoolean("is_enrollment_enforced", config_.is_forced());
screen_data.SetBoolean("attestationBased", config_.is_mode_attestation());
screen_data.SetString("management_domain", config_.management_domain);
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
index 2580ce653f0..b83224e3d25 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
@@ -69,19 +69,20 @@ class EnrollmentScreenHandler
// Implements EnrollmentScreenView:
void SetEnrollmentConfig(Controller* controller,
const policy::EnrollmentConfig& config) override;
+
+ void SetEnterpriseDomainAndDeviceType(
+ const std::string& domain,
+ const base::string16& device_type) override;
void Show() override;
void Hide() override;
void ShowSigninScreen() override;
- void ShowLicenseTypeSelectionScreen(
- const base::DictionaryValue& license_types) override;
void ShowActiveDirectoryScreen(const std::string& domain_join_config,
const std::string& machine_name,
const std::string& username,
authpolicy::ErrorType error) override;
void ShowAttributePromptScreen(const std::string& asset_id,
const std::string& location) override;
- void ShowAttestationBasedEnrollmentSuccessScreen(
- const std::string& enterprise_domain) override;
+ void ShowEnrollmentSuccessScreen() override;
void ShowEnrollmentSpinnerScreen() override;
void ShowAuthError(const GoogleServiceAuthError& error) override;
void ShowEnrollmentStatus(policy::EnrollmentStatus status) override;
@@ -117,8 +118,6 @@ class EnrollmentScreenHandler
void HandleDeviceAttributesProvided(const std::string& asset_id,
const std::string& location);
void HandleOnLearnMore();
- void HandleLicenseTypeSelected(const std::string& licenseType);
-
void UpdateStateInternal(NetworkError::ErrorReason reason, bool force_update);
void SetupAndShowOfflineMessage(NetworkStateInformer::State state,
NetworkError::ErrorReason reason);
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
index 1a2a0cd98a0..aa87c7a9018 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
@@ -75,6 +75,11 @@ std::string EulaScreenHandler::GetEulaOnlineUrl() {
g_browser_process->GetApplicationLocale().c_str());
}
+std::string EulaScreenHandler::GetAdditionalToSUrl() {
+ return base::StringPrintf(chrome::kAdditionalToSOnlineURLPath,
+ g_browser_process->GetApplicationLocale().c_str());
+}
+
void EulaScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) {
builder->Add("eulaScreenAccessibleTitle", IDS_EULA_SCREEN_ACCESSIBLE_TITLE);
@@ -107,9 +112,11 @@ void EulaScreenHandler::DeclareLocalizedValues(
// Online URL to use. May be overridden by tests.
builder->Add("eulaOnlineUrl", GetEulaOnlineUrl());
+ builder->Add("eulaAdditionalToSOnlineUrl", GetAdditionalToSUrl());
/* MD-OOBE */
builder->Add("oobeEulaSectionTitle", IDS_OOBE_EULA_SECTION_TITLE);
+ builder->Add("oobeEulaAditionalTerms", IDS_OOBE_EULA_ADDITIONAL_TERMS);
builder->Add("oobeEulaIframeLabel", IDS_OOBE_EULA_IFRAME_LABEL);
builder->Add("oobeEulaAcceptAndContinueButtonText",
IDS_OOBE_EULA_ACCEPT_AND_CONTINUE_BUTTON_TEXT);
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h
index 9a14d39cf33..bb724d1f659 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h
@@ -10,7 +10,6 @@
#include "base/memory/ref_counted.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
#include "components/login/secure_module_util_chromeos.h"
-#include "content/public/browser/web_ui.h"
namespace base {
class DictionaryValue;
@@ -75,6 +74,7 @@ class EulaScreenHandler : public EulaView, public BaseScreenHandler {
// Determines the online URL to use.
std::string GetEulaOnlineUrl();
static const char* eula_url_for_testing_;
+ std::string GetAdditionalToSUrl();
void UpdateLocalizedValues(::login::SecureModuleUsed secure_module_used);
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h
index 7a36649adf7..4dc7fb49bde 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h
@@ -37,6 +37,8 @@ class FakeUpdateRequiredScreenHandler : public UpdateRequiredView {
void SetEstimatedTimeLeftVisible(bool visible) override {}
void SetEstimatedTimeLeft(int seconds_left) override {}
void SetUIState(UpdateRequiredView::UIState ui_state) override;
+ void SetEnterpriseAndDeviceName(const std::string& enterpriseDomain,
+ const base::string16& deviceName) override {}
UpdateRequiredView::UIState ui_state_;
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
index 4d4380b17b7..14d58280bee 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
@@ -15,9 +15,7 @@
#include "chrome/grit/generated_resources.h"
#include "components/login/localized_values_builder.h"
#include "components/prefs/pref_service.h"
-#include "content/public/browser/system_connector.h"
-#include "services/device/public/mojom/constants.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
+#include "content/public/browser/device_service.h"
#include "ui/base/l10n/l10n_util.h"
namespace {
@@ -55,8 +53,8 @@ FingerprintSetupScreenHandler::FingerprintSetupScreenHandler(
: BaseScreenHandler(kScreenId, js_calls_container) {
set_user_acted_method_path("login.FingerprintSetupScreen.userActed");
- content::GetSystemConnector()->Connect(
- device::mojom::kServiceName, fp_service_.BindNewPipeAndPassReceiver());
+ content::GetDeviceService().BindFingerprint(
+ fp_service_.BindNewPipeAndPassReceiver());
fp_service_->AddFingerprintObserver(receiver_.BindNewPipeAndPassRemote());
}
@@ -94,6 +92,7 @@ void FingerprintSetupScreenHandler::DeclareLocalizedValues(
description_id =
IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_POWER_BUTTON_DESCRIPTION;
break;
+ case quick_unlock::FingerprintLocation::KEYBOARD_BOTTOM_LEFT:
case quick_unlock::FingerprintLocation::KEYBOARD_BOTTOM_RIGHT:
case quick_unlock::FingerprintLocation::KEYBOARD_TOP_RIGHT:
description_id =
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index 83a06a813d9..69ee8265d9b 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -25,6 +25,8 @@
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
+#include "base/timer/timer.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
@@ -62,10 +64,10 @@
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/installer/util/google_update_settings.h"
+#include "chromeos/components/security_token_pin/constants.h"
#include "chromeos/constants/chromeos_features.h"
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/constants/devicetype.h"
-#include "chromeos/constants/security_token_pin_types.h"
#include "chromeos/dbus/util/version_loader.h"
#include "chromeos/login/auth/challenge_response/cert_utils.h"
#include "chromeos/login/auth/cryptohome_key_constants.h"
@@ -73,6 +75,7 @@
#include "chromeos/login/auth/user_context.h"
#include "chromeos/network/onc/certificate_scope.h"
#include "chromeos/settings/cros_settings_names.h"
+#include "chromeos/strings/grit/chromeos_strings.h"
#include "components/login/localized_values_builder.h"
#include "components/policy/proto/chrome_device_policy.pb.h"
#include "components/prefs/pref_service.h"
@@ -121,6 +124,8 @@ enum class ChromeOSSamlApiUsed {
kMaxValue = kSamlApiNotUsed,
};
+constexpr base::TimeDelta kCookieDelay = base::TimeDelta::FromSeconds(20);
+
void RecordAPILogin(bool is_third_party_idp, bool is_api_used) {
ChromeOSSamlApiUsed login_type;
if (!is_third_party_idp) {
@@ -294,9 +299,9 @@ PinDialogManager* GetLoginScreenPinDialogManager() {
}
base::Value MakeSecurityTokenPinDialogParameters(
- SecurityTokenPinCodeType code_type,
+ security_token_pin::CodeType code_type,
bool enable_user_input,
- SecurityTokenPinErrorLabel error_label,
+ security_token_pin::ErrorLabel error_label,
int attempts_left) {
base::Value params(base::Value::Type::DICTIONARY);
params.SetIntKey("codeType", static_cast<int>(code_type));
@@ -461,9 +466,8 @@ void GaiaScreenHandler::OnSetCookieForLoadGaiaWithPartition(
&GaiaScreenHandler::LoadGaiaWithPartitionAndVersionAndConsent,
weak_factory_.GetWeakPtr(), context, partition_name,
base::Owned(version.release()), base::Owned(consent.release()));
- base::PostTaskAndReply(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
std::move(get_version_and_consent), std::move(load_gaia));
}
@@ -574,6 +578,8 @@ void GaiaScreenHandler::LoadGaiaWithPartitionAndVersionAndConsent(
}
public_saml_url_fetcher_.reset();
+ was_security_token_pin_canceled_ = false;
+
frame_state_ = FRAME_STATE_LOADING;
CallJS("login.GaiaSigninScreen.loadAuthExtension", params);
}
@@ -671,10 +677,8 @@ void GaiaScreenHandler::DeclareLocalizedValues(
IDS_SAML_SECURITY_TOKEN_PIN_DIALOG_TRY_AGAIN);
builder->Add("securityTokenPinDialogAttemptsLeft",
IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT);
- builder->Add("securityTokenPinDialogErrorRetry",
- IDS_REQUEST_PIN_DIALOG_ERROR_RETRY);
- builder->Add("securityTokenPinDialogErrorRetryAttempts",
- IDS_REQUEST_PIN_DIALOG_ERROR_RETRY_ATTEMPTS);
+ builder->Add("securityTokenPinDialogErrorAttempts",
+ IDS_REQUEST_PIN_DIALOG_ERROR_ATTEMPTS);
builder->Add("securityTokenPinDialogUnknownError",
IDS_REQUEST_PIN_DIALOG_UNKNOWN_ERROR);
builder->Add("securityTokenPinDialogUnknownInvalidPin",
@@ -719,9 +723,6 @@ void GaiaScreenHandler::RegisterMessages() {
AddRawCallback("showAddUser", &GaiaScreenHandler::HandleShowAddUser);
AddCallback("getIsSamlUserPasswordless",
&GaiaScreenHandler::HandleGetIsSamlUserPasswordless);
- AddCallback("hideOobeDialog", &GaiaScreenHandler::HandleHideOobeDialog);
- AddCallback("updateSigninUIState",
- &GaiaScreenHandler::HandleUpdateSigninUIState);
AddCallback("showGuestInOobe", &GaiaScreenHandler::HandleShowGuestInOobe);
AddCallback("samlStateChanged", &GaiaScreenHandler::HandleSamlStateChanged);
AddCallback("securityTokenPinEntered",
@@ -772,16 +773,24 @@ void GaiaScreenHandler::HandleAuthExtensionLoaded() {
}
void GaiaScreenHandler::HandleWebviewLoadAborted(int error_code) {
+ if (error_code == net::ERR_INVALID_AUTH_CREDENTIALS) {
+ // Silently ignore this error - it is used as an intermediate state for
+ // committed interstitials (see https://crbug.com/1049349 for details).
+ return;
+ }
if (error_code == net::ERR_ABORTED) {
LOG(WARNING) << "Ignoring Gaia webview error: "
<< net::ErrorToShortString(error_code);
return;
}
- if (error_code == net::ERR_TIMED_OUT &&
- is_security_token_pin_dialog_running()) {
- // Timeout errors are expected when the security token PIN is not entered by
- // the user on time. In that case, return the user back to the first sign-in
- // step instead of showing the network error screen.
+ if ((was_security_token_pin_canceled_ && error_code == net::ERR_FAILED) ||
+ (is_security_token_pin_dialog_running() &&
+ error_code == net::ERR_TIMED_OUT)) {
+ // Specific errors are expected when the security token PIN is aborted
+ // (either with a generic failure if the user canceled the dialog, or with a
+ // timeout error if the user didn't enter it on time). In that case, return
+ // the user back to the first sign-in step instead of showing the network
+ // error screen.
ReloadGaia(/*force_reload=*/true);
return;
}
@@ -838,7 +847,6 @@ void GaiaScreenHandler::DoAdAuth(
break;
}
case authpolicy::ERROR_PASSWORD_EXPIRED:
- DCHECK(active_directory_password_change_screen_handler_);
active_directory_password_change_screen_handler_->ShowScreen(username);
break;
case authpolicy::ERROR_PARSE_UPN_FAILED:
@@ -930,6 +938,11 @@ void GaiaScreenHandler::ContinueAuthenticationWhenCookiesAvailable() {
cookie_manager->AddCookieChangeListener(
GaiaUrls::GetInstance()->gaia_url(), kOAUTHCodeCookie,
oauth_code_listener_.BindNewPipeAndPassRemote());
+ cookie_waiting_timer_ = std::make_unique<base::OneShotTimer>();
+ cookie_waiting_timer_->Start(
+ FROM_HERE, kCookieDelay,
+ base::BindOnce(&GaiaScreenHandler::OnCookieWaitTimeout,
+ weak_factory_.GetWeakPtr()));
}
const net::CookieOptions cookie_options =
@@ -961,6 +974,7 @@ void GaiaScreenHandler::OnGetCookiesForCompleteAuthentication(
UserContext user_context = *pending_user_context_;
pending_user_context_.reset();
oauth_code_listener_.reset();
+ cookie_waiting_timer_.reset();
user_context.SetAuthCode(auth_code);
if (!gaps_cookie.empty())
@@ -969,6 +983,17 @@ void GaiaScreenHandler::OnGetCookiesForCompleteAuthentication(
LoginDisplayHost::default_host()->CompleteLogin(user_context);
}
+void GaiaScreenHandler::OnCookieWaitTimeout() {
+ DCHECK(pending_user_context_);
+ pending_user_context_.reset();
+ oauth_code_listener_.reset();
+ cookie_waiting_timer_.reset();
+ LoadAuthExtension(true /* force */, false /* offline */);
+ core_oobe_view_->ShowSignInError(
+ 0, l10n_util::GetStringUTF8(IDS_LOGIN_FATAL_ERROR_NO_AUTH_TOKEN),
+ std::string(), HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
+}
+
void GaiaScreenHandler::HandleCompleteLogin(const std::string& gaia_id,
const std::string& typed_email,
const std::string& password,
@@ -1035,16 +1060,10 @@ void GaiaScreenHandler::HandleGaiaUIReady() {
}
}
-void GaiaScreenHandler::HandleHideOobeDialog() {
- if (LoginDisplayHost::default_host())
- LoginDisplayHost::default_host()->HideOobeDialog();
-}
-
void GaiaScreenHandler::HandleShowAddUser(const base::ListValue* args) {
// TODO(xiaoyinh): Add trace event for gaia webui in views login screen.
- TRACE_EVENT_ASYNC_STEP_INTO0("ui", "ShowLoginWebUI",
- LoginDisplayHostWebUI::kShowLoginWebUIid,
- "ShowAddUser");
+ TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("ui", "ShowAddUser",
+ LoginDisplayHostWebUI::kShowLoginWebUIid);
std::string email;
// |args| can be null if it's OOBE.
@@ -1067,13 +1086,6 @@ void GaiaScreenHandler::HandleGetIsSamlUserPasswordless(
base::Value(is_saml_user_passwordless));
}
-void GaiaScreenHandler::HandleUpdateSigninUIState(int state) {
- if (LoginDisplayHost::default_host()) {
- auto dialog_state = static_cast<ash::OobeDialogState>(state);
- LoginDisplayHost::default_host()->UpdateOobeDialogState(dialog_state);
- }
-}
-
void GaiaScreenHandler::HandleShowGuestInOobe(bool show) {
ash::LoginScreen::Get()->ShowGuestButtonInOobe(show);
}
@@ -1108,6 +1120,7 @@ void GaiaScreenHandler::HandleSecurityTokenPinEntered(
return;
}
+ was_security_token_pin_canceled_ = user_input.empty();
if (user_input.empty()) {
security_token_pin_entered_callback_.Reset();
std::move(security_token_pin_dialog_closed_callback_).Run();
@@ -1298,9 +1311,9 @@ void GaiaScreenHandler::ShowSigninScreenForTest(const std::string& username,
void GaiaScreenHandler::ShowSecurityTokenPinDialog(
const std::string& /*caller_extension_name*/,
- SecurityTokenPinCodeType code_type,
+ security_token_pin::CodeType code_type,
bool enable_user_input,
- SecurityTokenPinErrorLabel error_label,
+ security_token_pin::ErrorLabel error_label,
int attempts_left,
const base::Optional<AccountId>& /*authenticating_user_account_id*/,
SecurityTokenPinEnteredCallback pin_entered_callback,
@@ -1530,8 +1543,9 @@ bool GaiaScreenHandler::BuildUserContextForGaiaSignIn(
extension_provided_client_cert_usage_observer_->ClientCertsWereUsed()) {
scoped_refptr<net::X509Certificate> saml_client_cert;
std::vector<ChallengeResponseKey::SignatureAlgorithm> signature_algorithms;
+ std::string extension_id;
if (!extension_provided_client_cert_usage_observer_->GetOnlyUsedClientCert(
- &saml_client_cert, &signature_algorithms)) {
+ &saml_client_cert, &signature_algorithms, &extension_id)) {
*error_message = l10n_util::GetStringUTF8(
IDS_CHALLENGE_RESPONSE_AUTH_MULTIPLE_CLIENT_CERTS_ERROR);
return false;
@@ -1543,6 +1557,7 @@ bool GaiaScreenHandler::BuildUserContextForGaiaSignIn(
IDS_CHALLENGE_RESPONSE_AUTH_INVALID_CLIENT_CERT_ERROR);
return false;
}
+ challenge_response_key.set_extension_id(extension_id);
user_context->GetMutableChallengeResponseKeys()->push_back(
challenge_response_key);
} else {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
index 8cf89428246..ff64497e598 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -18,6 +18,7 @@
#include "chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h"
#include "chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.h"
+#include "chromeos/components/security_token_pin/constants.h"
#include "chromeos/network/portal_detector/network_portal_detector.h"
#include "components/user_manager/user_type.h"
#include "net/base/net_errors.h"
@@ -28,6 +29,7 @@ class AccountId;
namespace base {
class DictionaryValue;
+class OneShotTimer;
} // namespace base
namespace network {
@@ -123,9 +125,9 @@ class GaiaScreenHandler : public BaseScreenHandler,
// SecurityTokenPinDialogHost:
void ShowSecurityTokenPinDialog(
const std::string& caller_extension_name,
- SecurityTokenPinCodeType code_type,
+ security_token_pin::CodeType code_type,
bool enable_user_input,
- SecurityTokenPinErrorLabel error_label,
+ security_token_pin::ErrorLabel error_label,
int attempts_left,
const base::Optional<AccountId>& authenticating_user_account_id,
SecurityTokenPinEnteredCallback pin_entered_callback,
@@ -227,12 +229,10 @@ class GaiaScreenHandler : public BaseScreenHandler,
void HandleIdentifierEntered(const std::string& account_identifier);
void HandleAuthExtensionLoaded();
- void HandleHideOobeDialog();
void HandleShowAddUser(const base::ListValue* args);
void HandleGetIsSamlUserPasswordless(const std::string& callback_id,
const std::string& typed_email,
const std::string& gaia_id);
- void HandleUpdateSigninUIState(int state);
// Allows WebUI to control the login shelf's guest button visibility during
// OOBE.
@@ -334,6 +334,8 @@ class GaiaScreenHandler : public BaseScreenHandler,
const net::CookieStatusList& cookies,
const net::CookieStatusList& excluded_cookies);
+ void OnCookieWaitTimeout();
+
bool is_security_token_pin_dialog_running() const {
return !security_token_pin_dialog_closed_callback_.is_null();
}
@@ -444,6 +446,9 @@ class GaiaScreenHandler : public BaseScreenHandler,
// Is non-empty iff the dialog is active.
SecurityTokenPinDialogClosedCallback
security_token_pin_dialog_closed_callback_;
+ // Whether the PIN dialog shown during the current authentication attempt was
+ // canceled by the user.
+ bool was_security_token_pin_canceled_ = false;
// Handler for |samlChallengeMachineKey| request.
std::unique_ptr<SamlChallengeKeyHandler> saml_challenge_key_handler_;
@@ -453,6 +458,7 @@ class GaiaScreenHandler : public BaseScreenHandler,
mojo::Receiver<network::mojom::CookieChangeListener> oauth_code_listener_{
this};
std::unique_ptr<UserContext> pending_user_context_;
+ std::unique_ptr<base::OneShotTimer> cookie_waiting_timer_;
base::WeakPtrFactory<GaiaScreenHandler> weak_factory_{this};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.cc
new file mode 100644
index 00000000000..2aeccdf9329
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.cc
@@ -0,0 +1,83 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h"
+
+#include "chrome/browser/chromeos/login/screens/gesture_navigation_screen.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/login/localized_values_builder.h"
+
+namespace chromeos {
+
+constexpr StaticOobeScreenId GestureNavigationScreenView::kScreenId;
+
+GestureNavigationScreenHandler::GestureNavigationScreenHandler(
+ JSCallsContainer* js_calls_container)
+ : BaseScreenHandler(kScreenId, js_calls_container) {
+ set_user_acted_method_path("login.GestureNavigationScreen.userActed");
+}
+
+GestureNavigationScreenHandler::~GestureNavigationScreenHandler() = default;
+
+void GestureNavigationScreenHandler::Show() {
+ if (!page_is_ready()) {
+ show_on_init_ = true;
+ return;
+ }
+
+ ShowScreen(kScreenId);
+}
+
+void GestureNavigationScreenHandler::Bind(GestureNavigationScreen* screen) {
+ screen_ = screen;
+ BaseScreenHandler::SetBaseScreen(screen);
+}
+
+void GestureNavigationScreenHandler::Hide() {}
+
+void GestureNavigationScreenHandler::DeclareLocalizedValues(
+ ::login::LocalizedValuesBuilder* builder) {
+ builder->Add("gestureNavigationIntroTitle",
+ IDS_OOBE_GESTURE_NAVIGATION_INTRO_TITLE);
+ builder->Add("gestureNavigationIntroNextButton",
+ IDS_OOBE_GESTURE_NAVIGATION_INTRO_NEXT_BUTTON);
+ builder->Add("gestureNavigationIntroGoHomeItem",
+ IDS_OOBE_GESTURE_NAVIGATION_INTRO_GO_HOME);
+ builder->Add("gestureNavigationIntroSwitchAppItem",
+ IDS_OOBE_GESTURE_NAVIGATION_INTRO_SWITCH_APP);
+ builder->Add("gestureNavigationIntroGoBackItem",
+ IDS_OOBE_GESTURE_NAVIGATION_INTRO_GO_BACK);
+ builder->Add("gestureNavigationHomeTitle",
+ IDS_OOBE_GESTURE_NAVIGATION_HOME_TITLE);
+ builder->Add("gestureNavigationHomeDescription",
+ IDS_OOBE_GESTURE_NAVIGATION_HOME_DESCRIPTION);
+ builder->Add("gestureNavigationBackTitle",
+ IDS_OOBE_GESTURE_NAVIGATION_BACK_TITLE);
+ builder->Add("gestureNavigationBackDescription",
+ IDS_OOBE_GESTURE_NAVIGATION_BACK_DESCRIPTION);
+ builder->Add("gestureNavigationOverviewTitle",
+ IDS_OOBE_GESTURE_NAVIGATION_OVERVIEW_TITLE);
+ builder->Add("gestureNavigationOverviewDescription",
+ IDS_OOBE_GESTURE_NAVIGATION_OVERVIEW_DESCRIPTION);
+}
+
+void GestureNavigationScreenHandler::Initialize() {
+ if (show_on_init_) {
+ Show();
+ show_on_init_ = false;
+ }
+}
+
+void GestureNavigationScreenHandler::RegisterMessages() {
+ AddCallback("handleGesturePageChange",
+ &GestureNavigationScreenHandler::HandleGesturePageChange);
+ BaseScreenHandler::RegisterMessages();
+}
+
+void GestureNavigationScreenHandler::HandleGesturePageChange(
+ const std::string& new_page) {
+ screen_->GesturePageChange(new_page);
+}
+
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h
new file mode 100644
index 00000000000..82af0f326dd
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h
@@ -0,0 +1,64 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_GESTURE_NAVIGATION_SCREEN_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_GESTURE_NAVIGATION_SCREEN_HANDLER_H_
+
+#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
+
+namespace chromeos {
+
+class GestureNavigationScreen;
+
+// Interface between gesture navigation screen and its representation.
+class GestureNavigationScreenView {
+ public:
+ constexpr static StaticOobeScreenId kScreenId{"gesture-navigation"};
+
+ virtual ~GestureNavigationScreenView() {}
+
+ virtual void Bind(GestureNavigationScreen* screen) = 0;
+ virtual void Show() = 0;
+ virtual void Hide() = 0;
+};
+
+// WebUI implementation of GestureNavigationScreenView.
+class GestureNavigationScreenHandler : public GestureNavigationScreenView,
+ public BaseScreenHandler {
+ public:
+ using TView = GestureNavigationScreenView;
+
+ explicit GestureNavigationScreenHandler(JSCallsContainer* js_calls_container);
+ ~GestureNavigationScreenHandler() override;
+
+ GestureNavigationScreenHandler(const GestureNavigationScreenHandler&) =
+ delete;
+ GestureNavigationScreenHandler operator=(
+ const GestureNavigationScreenHandler&) = delete;
+
+ // GestureNavigationScreenView:
+ void Bind(GestureNavigationScreen* screen) override;
+ void Show() override;
+ void Hide() override;
+
+ // BaseScreenHandler:
+ void DeclareLocalizedValues(
+ ::login::LocalizedValuesBuilder* builder) override;
+ void Initialize() override;
+ void RegisterMessages() override;
+
+ private:
+ // Called when the currently shown page for the gesture navigation screen is
+ // changed.
+ void HandleGesturePageChange(const std::string& new_page);
+
+ GestureNavigationScreen* screen_ = nullptr;
+
+ // If true, Initialize() will call Show().
+ bool show_on_init_ = false;
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_GESTURE_NAVIGATION_SCREEN_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc
index 2025c505a4d..b75bf1e45c5 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.cc
@@ -25,11 +25,8 @@ namespace chromeos {
constexpr StaticOobeScreenId HIDDetectionView::kScreenId;
HIDDetectionScreenHandler::HIDDetectionScreenHandler(
- JSCallsContainer* js_calls_container,
- CoreOobeView* core_oobe_view)
- : BaseScreenHandler(kScreenId, js_calls_container),
- core_oobe_view_(core_oobe_view) {
-}
+ JSCallsContainer* js_calls_container)
+ : BaseScreenHandler(kScreenId, js_calls_container) {}
HIDDetectionScreenHandler::~HIDDetectionScreenHandler() {
if (screen_)
@@ -41,7 +38,6 @@ void HIDDetectionScreenHandler::Show() {
show_on_init_ = true;
return;
}
- core_oobe_view_->InitDemoModeDetection();
PrefService* local_state = g_browser_process->local_state();
int num_of_times_dialog_was_shown = local_state->GetInteger(
@@ -87,9 +83,9 @@ void HIDDetectionScreenHandler::SetKeyboardPinCode(const std::string& value) {
CallJS("login.HIDDetectionScreen.setKeyboardPinCode", value);
}
-void HIDDetectionScreenHandler::SetNumKeysEnteredExpected(bool value) {
+void HIDDetectionScreenHandler::SetPinDialogVisible(bool value) {
num_keys_entered_expected_ = value;
- CallJS("login.HIDDetectionScreen.setNumKeysEnteredExpected", value);
+ CallJS("login.HIDDetectionScreen.setPinDialogVisible", value);
}
void HIDDetectionScreenHandler::SetNumKeysEnteredPinCode(int value) {
@@ -97,9 +93,10 @@ void HIDDetectionScreenHandler::SetNumKeysEnteredPinCode(int value) {
CallJS("login.HIDDetectionScreen.setNumKeysEnteredPinCode", value);
}
-void HIDDetectionScreenHandler::SetMouseDeviceName(const std::string& value) {
+void HIDDetectionScreenHandler::SetPointingDeviceName(
+ const std::string& value) {
mouse_device_name_ = value;
- CallJS("login.HIDDetectionScreen.setMouseDeviceName", value);
+ CallJS("login.HIDDetectionScreen.setPointingDeviceName", value);
}
void HIDDetectionScreenHandler::SetKeyboardDeviceName(
@@ -108,12 +105,6 @@ void HIDDetectionScreenHandler::SetKeyboardDeviceName(
CallJS("login.HIDDetectionScreen.setKeyboardDeviceName", value);
}
-void HIDDetectionScreenHandler::SetKeyboardDeviceLabel(
- const std::string& value) {
- keyboard_device_label_ = value;
- CallJS("login.HIDDetectionScreen.setKeyboardDeviceLabel", value);
-}
-
void HIDDetectionScreenHandler::SetContinueButtonEnabled(bool value) {
continue_button_enabled_ = value;
CallJS("login.HIDDetectionScreen.setContinueButtonEnabled", value);
@@ -132,16 +123,22 @@ void HIDDetectionScreenHandler::DeclareLocalizedValues(
IDS_HID_DETECTION_CONNECTED_USB_MOUSE);
builder->Add("hidDetectionPointingDeviceConnected",
IDS_HID_DETECTION_CONNECTED_POINTING_DEVICE);
+ builder->Add("hidDetectionKeyboardPairing",
+ IDS_HID_DETECTION_PAIRING_BLUETOOTH_KEYBOARD);
builder->Add("hidDetectionUSBKeyboardConnected",
IDS_HID_DETECTION_CONNECTED_USB_KEYBOARD);
builder->Add("hidDetectionBTMousePaired",
IDS_HID_DETECTION_PAIRED_BLUETOOTH_MOUSE);
builder->Add("hidDetectionBTEnterKey", IDS_HID_DETECTION_BLUETOOTH_ENTER_KEY);
-}
-
-void HIDDetectionScreenHandler::DeclareJSCallbacks() {
- AddCallback(
- "HIDDetectionOnContinue", &HIDDetectionScreenHandler::HandleOnContinue);
+ builder->Add("hidDetectionPinDialogTitle",
+ IDS_HID_DETECTION_PAIRING_BLUETOOTH_KEYBOARD_PIN_DIALOG_TITLE);
+ builder->Add("hidDetectionBluetoothPairingCode",
+ IDS_HID_DETECTION_BLUETOOTH_PAIRING_CODE);
+ builder->Add("hidDetectionBluetoothPairingCodeExplanation",
+ IDS_HID_DETECTION_BLUETOOTH_PAIRING_CODE_EXPLANATION);
+ builder->Add("hidDetectionBluetoothKeyboardPaired",
+ IDS_HID_DETECTION_PAIRED_BLUETOOTH_KEYBOARD);
+ builder->Add("oobeModalDialogClose", IDS_CHROMEOS_OOBE_CLOSE_DIALOG);
}
void HIDDetectionScreenHandler::Initialize() {
@@ -151,13 +148,6 @@ void HIDDetectionScreenHandler::Initialize() {
}
}
-void HIDDetectionScreenHandler::HandleOnContinue() {
- // Continue button pressed.
- core_oobe_view_->StopDemoModeDetection();
- if (screen_)
- screen_->OnContinueButtonClicked();
-}
-
// static
void HIDDetectionScreenHandler::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(prefs::kTimesHIDDialogShown, 0);
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h
index a7314136657..7a3d3cddd63 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h
@@ -12,11 +12,9 @@
#include "base/values.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
#include "components/prefs/pref_registry_simple.h"
-#include "content/public/browser/web_ui.h"
namespace chromeos {
-class CoreOobeView;
class HIDDetectionScreen;
// Interface between HID detection screen and its representation, either WebUI
@@ -40,11 +38,10 @@ class HIDDetectionView {
virtual void SetKeyboardState(const std::string& value) = 0;
virtual void SetMouseState(const std::string& value) = 0;
virtual void SetKeyboardPinCode(const std::string& value) = 0;
- virtual void SetNumKeysEnteredExpected(bool value) = 0;
+ virtual void SetPinDialogVisible(bool value) = 0;
virtual void SetNumKeysEnteredPinCode(int value) = 0;
- virtual void SetMouseDeviceName(const std::string& value) = 0;
+ virtual void SetPointingDeviceName(const std::string& value) = 0;
virtual void SetKeyboardDeviceName(const std::string& value) = 0;
- virtual void SetKeyboardDeviceLabel(const std::string& value) = 0;
virtual void SetContinueButtonEnabled(bool value) = 0;
};
@@ -55,8 +52,7 @@ class HIDDetectionScreenHandler
public:
using TView = HIDDetectionView;
- HIDDetectionScreenHandler(JSCallsContainer* js_calls_container,
- CoreOobeView* core_oobe_view);
+ HIDDetectionScreenHandler(JSCallsContainer* js_calls_container);
~HIDDetectionScreenHandler() override;
// HIDDetectionView implementation:
@@ -69,17 +65,15 @@ class HIDDetectionScreenHandler
void SetKeyboardState(const std::string& value) override;
void SetMouseState(const std::string& value) override;
void SetKeyboardPinCode(const std::string& value) override;
- void SetNumKeysEnteredExpected(bool value) override;
+ void SetPinDialogVisible(bool value) override;
void SetNumKeysEnteredPinCode(int value) override;
- void SetMouseDeviceName(const std::string& value) override;
+ void SetPointingDeviceName(const std::string& value) override;
void SetKeyboardDeviceName(const std::string& value) override;
- void SetKeyboardDeviceLabel(const std::string& value) override;
void SetContinueButtonEnabled(bool value) override;
// BaseScreenHandler implementation:
void DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) override;
- void DeclareJSCallbacks() override;
void Initialize() override;
// Registers the preference for derelict state.
@@ -107,9 +101,6 @@ class HIDDetectionScreenHandler
}
private:
- // JS messages handlers.
- void HandleOnContinue();
-
// Cached values that have been sent to JS. Used by tests.
std::string keyboard_state_;
std::string mouse_state_;
@@ -123,8 +114,6 @@ class HIDDetectionScreenHandler
HIDDetectionScreen* screen_ = nullptr;
- CoreOobeView* core_oobe_view_ = nullptr;
-
// If true, Initialize() will call Show().
bool show_on_init_ = false;
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h
index 4b296b97406..8a9d07f41d4 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h
@@ -9,7 +9,6 @@
#include "base/macros.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
-#include "content/public/browser/web_ui.h"
namespace chromeos {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.cc
index c4cae8f4460..c1a89cb6c35 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.cc
@@ -8,15 +8,12 @@
#include "base/bind.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/login/screens/kiosk_enable_screen.h"
#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/grit/generated_resources.h"
#include "components/login/localized_values_builder.h"
#include "components/strings/grit/components_strings.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
namespace chromeos {
@@ -24,11 +21,13 @@ constexpr StaticOobeScreenId KioskEnableScreenView::kScreenId;
KioskEnableScreenHandler::KioskEnableScreenHandler(
JSCallsContainer* js_calls_container)
- : BaseScreenHandler(kScreenId, js_calls_container) {}
+ : BaseScreenHandler(kScreenId, js_calls_container) {
+ set_user_acted_method_path("login.KioskEnableScreen.userActed");
+}
KioskEnableScreenHandler::~KioskEnableScreenHandler() {
- if (delegate_)
- delegate_->OnViewDestroyed(this);
+ if (screen_)
+ screen_->OnViewDestroyed(this);
}
void KioskEnableScreenHandler::Show() {
@@ -36,28 +35,13 @@ void KioskEnableScreenHandler::Show() {
show_on_init_ = true;
return;
}
-
- KioskAppManager::Get()->GetConsumerKioskAutoLaunchStatus(
- base::Bind(
- &KioskEnableScreenHandler::OnGetConsumerKioskAutoLaunchStatus,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void KioskEnableScreenHandler::OnGetConsumerKioskAutoLaunchStatus(
- KioskAppManager::ConsumerKioskAutoLaunchStatus status) {
- is_configurable_ =
- (status == KioskAppManager::CONSUMER_KIOSK_AUTO_LAUNCH_CONFIGURABLE);
- if (!is_configurable_) {
- LOG(WARNING) << "Consumer kiosk auto launch feature is not configurable!";
- return;
- }
-
ShowScreen(kScreenId);
}
-void KioskEnableScreenHandler::SetDelegate(KioskEnableScreen* delegate) {
- delegate_ = delegate;
- if (page_is_ready())
+void KioskEnableScreenHandler::SetScreen(KioskEnableScreen* screen) {
+ BaseScreenHandler::SetBaseScreen(screen);
+ screen_ = screen;
+ if (page_is_ready() && screen_)
Initialize();
}
@@ -75,7 +59,7 @@ void KioskEnableScreenHandler::DeclareLocalizedValues(
}
void KioskEnableScreenHandler::Initialize() {
- if (!page_is_ready() || !delegate_)
+ if (!page_is_ready() || !screen_)
return;
if (show_on_init_) {
@@ -84,41 +68,8 @@ void KioskEnableScreenHandler::Initialize() {
}
}
-void KioskEnableScreenHandler::RegisterMessages() {
- AddCallback("kioskOnClose", &KioskEnableScreenHandler::HandleOnClose);
- AddCallback("kioskOnEnable", &KioskEnableScreenHandler::HandleOnEnable);
-}
-
-void KioskEnableScreenHandler::HandleOnClose() {
- if (delegate_)
- delegate_->OnExit();
-}
-
-void KioskEnableScreenHandler::HandleOnEnable() {
- if (!is_configurable_) {
- NOTREACHED();
- if (delegate_)
- delegate_->OnExit();
- return;
- }
-
- KioskAppManager::Get()->EnableConsumerKioskAutoLaunch(
- base::Bind(&KioskEnableScreenHandler::OnEnableConsumerKioskAutoLaunch,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void KioskEnableScreenHandler::OnEnableConsumerKioskAutoLaunch(
- bool success) {
- if (!success)
- LOG(WARNING) << "Consumer kiosk mode can't be enabled!";
-
+void KioskEnableScreenHandler::ShowKioskEnabled(bool success) {
CallJS("login.KioskEnableScreen.onCompleted", success);
- if (success) {
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_KIOSK_ENABLED,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
- }
}
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h
index c6aa06760f7..9f32017e8a0 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h
@@ -24,7 +24,8 @@ class KioskEnableScreenView {
virtual ~KioskEnableScreenView() {}
virtual void Show() = 0;
- virtual void SetDelegate(KioskEnableScreen* delegate) = 0;
+ virtual void SetScreen(KioskEnableScreen* screen) = 0;
+ virtual void ShowKioskEnabled(bool success) = 0;
};
// WebUI implementation of KioskEnableScreenActor.
@@ -36,40 +37,22 @@ class KioskEnableScreenHandler : public KioskEnableScreenView,
explicit KioskEnableScreenHandler(JSCallsContainer* js_calls_container);
~KioskEnableScreenHandler() override;
- // KioskEnableScreenActor implementation:
+ // KioskEnableScreenView:
void Show() override;
- void SetDelegate(KioskEnableScreen* delegate) override;
+ void SetScreen(KioskEnableScreen* screen) override;
+ void ShowKioskEnabled(bool success) override;
// BaseScreenHandler implementation:
void DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) override;
void Initialize() override;
- // WebUIMessageHandler implementation:
- void RegisterMessages() override;
-
private:
- // JS messages handlers.
- void HandleOnClose();
- void HandleOnEnable();
-
- // Callback for KioskAppManager::EnableConsumerModeKiosk().
- void OnEnableConsumerKioskAutoLaunch(bool success);
-
- // Callback for KioskAppManager::GetConsumerKioskModeStatus().
- void OnGetConsumerKioskAutoLaunchStatus(
- KioskAppManager::ConsumerKioskAutoLaunchStatus status);
-
- KioskEnableScreen* delegate_ = nullptr;
+ KioskEnableScreen* screen_ = nullptr;
// Keeps whether screen should be shown right after initialization.
bool show_on_init_ = false;
- // True if machine's consumer kiosk mode is in a configurable state.
- bool is_configurable_ = false;
-
- base::WeakPtrFactory<KioskEnableScreenHandler> weak_ptr_factory_{this};
-
DISALLOW_COPY_AND_ASSIGN(KioskEnableScreenHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/l10n_util.cc b/chromium/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
index 7392dc3d99c..8fa827a081c 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/l10n_util.cc
@@ -23,6 +23,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/task_runner_util.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -345,6 +346,7 @@ std::string CalculateSelectedLanguage(const std::string& requested_locale,
}
void ResolveLanguageListInThreadPool(
+ const std::string& locale,
std::unique_ptr<chromeos::locale_util::LanguageSwitchResult>
language_switch_result,
const scoped_refptr<base::TaskRunner> task_runner,
@@ -353,14 +355,7 @@ void ResolveLanguageListInThreadPool(
base::BlockingType::MAY_BLOCK);
std::string selected_language;
- if (!language_switch_result) {
- if (!g_browser_process->GetApplicationLocale().empty()) {
- selected_language = g_browser_process->GetApplicationLocale();
- } else {
- selected_language =
- StartupCustomizationDocument::GetInstance()->initial_locale_default();
- }
- } else {
+ if (language_switch_result) {
if (language_switch_result->success) {
if (language_switch_result->requested_locale ==
language_switch_result->loaded_locale) {
@@ -373,19 +368,22 @@ void ResolveLanguageListInThreadPool(
} else {
selected_language = language_switch_result->loaded_locale;
}
+ } else {
+ selected_language = !locale.empty()
+ ? locale
+ : StartupCustomizationDocument::GetInstance()
+ ->initial_locale_default();
}
const std::string selected_code =
- selected_language.empty() ? g_browser_process->GetApplicationLocale()
- : selected_language;
+ selected_language.empty() ? locale : selected_language;
const std::string list_locale =
- language_switch_result ? language_switch_result->loaded_locale
- : g_browser_process->GetApplicationLocale();
+ language_switch_result ? language_switch_result->loaded_locale : locale;
std::unique_ptr<base::ListValue> language_list(
chromeos::GetUILanguageList(nullptr, selected_code));
task_runner->PostTask(
- FROM_HERE, base::BindOnce(resolved_callback, base::Passed(&language_list),
+ FROM_HERE, base::BindOnce(resolved_callback, std::move(language_list),
list_locale, selected_language));
}
@@ -430,10 +428,11 @@ void ResolveUILanguageList(
const UILanguageListResolvedCallback& callback) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- base::PostTask(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock()},
base::BindOnce(&ResolveLanguageListInThreadPool,
- base::Passed(&language_switch_result),
+ g_browser_process->GetApplicationLocale(),
+ std::move(language_switch_result),
base::SequencedTaskRunnerHandle::Get(), callback));
}
@@ -585,10 +584,9 @@ void GetKeyboardLayoutsForLocale(
// thread.
std::string (*get_application_locale)(const std::string&, bool) =
&l10n_util::GetApplicationLocale;
- base::PostTaskAndReplyWithResult(
+ base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(get_application_locale, locale,
false /* set_icu_locale */),
base::BindOnce(&GetKeyboardLayoutsForResolvedLocale, locale, callback));
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc
index 01da3bd96db..c21f11bee12 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.cc
@@ -4,12 +4,29 @@
#include "chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h"
+#include "ash/public/cpp/ash_pref_names.h"
+#include "base/command_line.h"
+#include "base/metrics/histogram_functions.h"
#include "chrome/browser/chromeos/login/screens/marketing_opt_in_screen.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/grit/generated_resources.h"
+#include "chromeos/constants/chromeos_switches.h"
#include "components/login/localized_values_builder.h"
+#include "components/prefs/pref_service.h"
+#include "ui/chromeos/devicetype_utils.h"
namespace chromeos {
+namespace {
+
+void RecordShowShelfNavigationButtonsValueChange(bool enabled) {
+ base::UmaHistogramBoolean(
+ "Accessibility.CrosShelfNavigationButtonsInTabletModeChanged.OOBE",
+ enabled);
+}
+
+} // namespace
+
constexpr StaticOobeScreenId MarketingOptInScreenView::kScreenId;
MarketingOptInScreenHandler::MarketingOptInScreenHandler(
@@ -17,20 +34,36 @@ MarketingOptInScreenHandler::MarketingOptInScreenHandler(
: BaseScreenHandler(kScreenId, js_calls_container) {
}
-MarketingOptInScreenHandler::~MarketingOptInScreenHandler() {}
+MarketingOptInScreenHandler::~MarketingOptInScreenHandler() {
+ if (a11y_nav_buttons_toggle_metrics_reporter_timer_.IsRunning())
+ a11y_nav_buttons_toggle_metrics_reporter_timer_.FireNow();
+}
void MarketingOptInScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) {
builder->Add("marketingOptInScreenTitle",
IDS_LOGIN_MARKETING_OPT_IN_SCREEN_TITLE);
- builder->Add("marketingOptInScreenSubtitle",
- IDS_LOGIN_MARKETING_OPT_IN_SCREEN_SUBTITLE);
- builder->Add("marketingOptInGetPlayUpdates",
- IDS_LOGIN_MARKETING_OPT_IN_SCREEN_GET_PLAY_UPDATES);
- builder->Add("marketingOptInGetChromebookUpdates",
- IDS_LOGIN_MARKETING_OPT_IN_SCREEN_GET_CHROMEBOOK_UPDATES);
+ builder->AddF("marketingOptInScreenSubtitle",
+ IDS_LOGIN_MARKETING_OPT_IN_SCREEN_SUBTITLE,
+ ui::GetChromeOSDeviceName());
+ builder->AddF("marketingOptInScreenSubtitleWithDeviceName",
+ IDS_LOGIN_MARKETING_OPT_IN_SCREEN_SUBTITLE_WITH_DEVICE_NAME,
+ ui::GetChromeOSDeviceName());
+ builder->Add(
+ "marketingOptInGetChromebookUpdates",
+ IDS_LOGIN_MARKETING_OPT_IN_SCREEN_GET_CHROMEBOOK_UPDATES_SIGN_ME_UP);
builder->Add("marketingOptInScreenAllSet",
IDS_LOGIN_MARKETING_OPT_IN_SCREEN_ALL_SET);
+ builder->Add("marketingOptInA11yButtonLabel",
+ IDS_MARKETING_OPT_IN_ACCESSIBILITY_BUTTON_LABEL);
+ builder->Add("finalA11yPageTitle", IDS_MARKETING_OPT_IN_ACCESSIBILITY_TITLE);
+ builder->Add("finalA11yPageNavButtonSettingTitle",
+ IDS_MARKETING_OPT_IN_ACCESSIBILITY_NAV_BUTTON_SETTING_TITLE);
+ builder->Add(
+ "finalA11yPageNavButtonSettingDescription",
+ IDS_MARKETING_OPT_IN_ACCESSIBILITY_NAV_BUTTON_SETTING_DESCRIPTION);
+ builder->Add("finalA11yPageDoneButtonTitle",
+ IDS_MARKETING_OPT_IN_ACCESSIBILITY_DONE_BUTTON);
}
void MarketingOptInScreenHandler::Bind(MarketingOptInScreen* screen) {
@@ -42,19 +75,59 @@ void MarketingOptInScreenHandler::Show() {
ShowScreen(kScreenId);
}
-void MarketingOptInScreenHandler::Hide() {}
+void MarketingOptInScreenHandler::Hide() {
+ if (a11y_nav_buttons_toggle_metrics_reporter_timer_.IsRunning())
+ a11y_nav_buttons_toggle_metrics_reporter_timer_.FireNow();
+}
+
+void MarketingOptInScreenHandler::UpdateA11ySettingsButtonVisibility(
+ bool shown) {
+ CallJS("login.MarketingOptInScreen.updateA11ySettingsButtonVisibility",
+ shown);
+}
+
+void MarketingOptInScreenHandler::UpdateA11yShelfNavigationButtonToggle(
+ bool enabled) {
+ CallJS("login.MarketingOptInScreen.updateA11yNavigationButtonToggle",
+ enabled);
+}
+
+void MarketingOptInScreenHandler::SetOptInVisibility(bool visible) {
+ CallJS("login.MarketingOptInScreen.setOptInVisibility", visible);
+}
+
+void MarketingOptInScreenHandler::SetEmailToggleState(bool checked) {
+ CallJS("login.MarketingOptInScreen.setEmailToggleState", checked);
+}
void MarketingOptInScreenHandler::Initialize() {}
void MarketingOptInScreenHandler::RegisterMessages() {
- AddCallback("login.MarketingOptInScreen.allSet",
- &MarketingOptInScreenHandler::HandleAllSet);
+ AddCallback("login.MarketingOptInScreen.onGetStarted",
+ &MarketingOptInScreenHandler::HandleOnGetStarted);
+ AddCallback(
+ "login.MarketingOptInScreen.setA11yNavigationButtonsEnabled",
+ &MarketingOptInScreenHandler::HandleSetA11yNavigationButtonsEnabled);
+}
+
+void MarketingOptInScreenHandler::GetAdditionalParameters(
+ base::DictionaryValue* parameters) {
+ BaseScreenHandler::GetAdditionalParameters(parameters);
+}
+
+void MarketingOptInScreenHandler::HandleOnGetStarted(
+ bool chromebook_email_opt_in) {
+ screen_->OnGetStarted(chromebook_email_opt_in);
}
-void MarketingOptInScreenHandler::HandleAllSet(
- bool play_communications_opt_in,
- bool tips_communications_opt_in) {
- screen_->OnAllSet(play_communications_opt_in, tips_communications_opt_in);
+void MarketingOptInScreenHandler::HandleSetA11yNavigationButtonsEnabled(
+ bool enabled) {
+ ProfileManager::GetActiveUserProfile()->GetPrefs()->SetBoolean(
+ ash::prefs::kAccessibilityTabletModeShelfNavigationButtonsEnabled,
+ enabled);
+ a11y_nav_buttons_toggle_metrics_reporter_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(10),
+ base::BindOnce(&RecordShowShelfNavigationButtonsValueChange, enabled));
}
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
index e7310c4b44d..a4898e6ba0b 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/marketing_opt_in_screen_handler.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_MARKETING_OPT_IN_SCREEN_HANDLER_H_
#include "base/macros.h"
+#include "base/timer/timer.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
namespace chromeos {
@@ -28,6 +29,19 @@ class MarketingOptInScreenView {
// Hides the contents of the screen.
virtual void Hide() = 0;
+
+ // Sets whether the a11y Settings button is visible.
+ virtual void UpdateA11ySettingsButtonVisibility(bool shown) = 0;
+
+ // Sets whether the a11y setting for showing shelf navigation buttons is
+ // toggled on or off.
+ virtual void UpdateA11yShelfNavigationButtonToggle(bool enabled) = 0;
+
+ // Sets the visibility of the marketing email opt-in
+ virtual void SetOptInVisibility(bool visible) = 0;
+
+ // Updates the toggle state for the email opt-in
+ virtual void SetEmailToggleState(bool checked) = 0;
};
// The sole implementation of the MarketingOptInScreenView, using WebUI.
@@ -47,18 +61,29 @@ class MarketingOptInScreenHandler : public BaseScreenHandler,
void Bind(MarketingOptInScreen* screen) override;
void Show() override;
void Hide() override;
+ void UpdateA11ySettingsButtonVisibility(bool shown) override;
+ void UpdateA11yShelfNavigationButtonToggle(bool enabled) override;
+ void SetOptInVisibility(bool visible) override;
+ void SetEmailToggleState(bool checked) override;
private:
// BaseScreenHandler:
void Initialize() override;
void RegisterMessages() override;
+ void GetAdditionalParameters(base::DictionaryValue* parameters) override;
- // WebUI event handler.
- void HandleAllSet(bool play_communications_opt_in,
- bool tips_communications_opt_in);
+ // WebUI event handlers.
+ void HandleOnGetStarted(bool chromebook_email_opt_in);
+ void HandleSetA11yNavigationButtonsEnabled(bool enabled);
MarketingOptInScreen* screen_ = nullptr;
+ // Timer to record user changed value for the accessibility setting to turn
+ // shelf navigation buttons on in tablet mode. The metric is recorded with 10
+ // second delay to avoid overreporting when the user keeps toggling the
+ // setting value in the screen UI.
+ base::OneShotTimer a11y_nav_buttons_toggle_metrics_reporter_timer_;
+
DISALLOW_COPY_AND_ASSIGN(MarketingOptInScreenHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
index 818c818751e..9423ee9eb01 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
@@ -6,7 +6,7 @@
#include <stdint.h>
-#include "ash/public/mojom/constants.mojom.h"
+#include "ash/public/ash_interfaces.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/strings/string_number_conversions.h"
@@ -14,8 +14,6 @@
#include "chrome/browser/ui/ash/ash_util.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/system_connector.h"
-#include "services/service_manager/public/cpp/connector.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/devices/touchscreen_device.h"
@@ -42,12 +40,8 @@ bool IsWhiteListedVendorId(uint16_t vendor_id) {
} // namespace
OobeDisplayChooser::OobeDisplayChooser() {
- // |connector| may be null in tests.
- auto* connector = content::GetSystemConnector();
- if (connector) {
- connector->Connect(ash::mojom::kServiceName,
- cros_display_config_.BindNewPipeAndPassReceiver());
- }
+ ash::BindCrosDisplayConfigController(
+ cros_display_config_.BindNewPipeAndPassReceiver());
}
OobeDisplayChooser::~OobeDisplayChooser() {}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.h b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.h
index fc9cf2a9e22..d6b373c8126 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.h
@@ -32,6 +32,7 @@ class OobeDisplayChooser : public ui::InputDeviceEventObserver {
void set_cros_display_config_for_test(
mojo::PendingRemote<ash::mojom::CrosDisplayConfigController>
cros_display_config) {
+ cros_display_config_.reset();
cros_display_config_.Bind(std::move(cros_display_config));
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index fa4f5fd178f..7ccd1bb578b 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -41,7 +41,6 @@
#include "chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/app_downloading_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h"
-#include "chrome/browser/ui/webui/chromeos/login/arc_kiosk_splash_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/arc_terms_of_service_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/auto_enrollment_check_screen_handler.h"
@@ -58,6 +57,7 @@
#include "chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/kiosk_autolaunch_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/kiosk_enable_screen_handler.h"
@@ -114,7 +114,6 @@ namespace chromeos {
namespace {
const char* kKnownDisplayTypes[] = {OobeUI::kAppLaunchSplashDisplay,
- OobeUI::kArcKioskSplashDisplay,
OobeUI::kDiscoverDisplay,
OobeUI::kGaiaSigninDisplay,
OobeUI::kLoginDisplay,
@@ -142,6 +141,7 @@ constexpr char kRecommendAppListViewJSPath[] = "recommend_app_list_view.js";
constexpr char kLogo24PX1XSvgPath[] = "logo_24px-1x.svg";
constexpr char kLogo24PX2XSvgPath[] = "logo_24px-2x.svg";
constexpr char kSyncConsentIcons[] = "sync-consent-icons.html";
+constexpr char kArcAppDownloadingVideoPath[] = "res/arc_app_dowsnloading.mp4";
#endif
// Adds various product logo resources.
@@ -180,6 +180,10 @@ void AddArcScreensResources(content::WebUIDataSource* source) {
IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_JS);
source->AddResourcePath(kRecommendAppListViewHTMLPath,
IDR_ARC_SUPPORT_RECOMMEND_APP_LIST_VIEW_HTML);
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ source->AddResourcePath(kArcAppDownloadingVideoPath,
+ IDR_OOBE_ARC_APPS_DOWNLOADING_VIDEO);
+#endif
}
void AddAssistantScreensResources(content::WebUIDataSource* source) {
@@ -190,6 +194,22 @@ void AddAssistantScreensResources(content::WebUIDataSource* source) {
source->OverrideContentSecurityPolicyWorkerSrc("worker-src blob: 'self';");
}
+void AddGestureNavigationResources(content::WebUIDataSource* source) {
+ source->AddResourcePath("gesture_go_home.json",
+ IDR_GESTURE_NAVIGATION_GO_HOME_ANIMATION);
+ source->AddResourcePath("gesture_go_back.json",
+ IDR_GESTURE_NAVIGATION_GO_BACK_ANIMATION);
+ source->AddResourcePath("gesture_hotseat_overview.json",
+ IDR_GESTURE_NAVIGATION_HOTSEAT_OVERVIEW_ANIMATION);
+ source->OverrideContentSecurityPolicyWorkerSrc("worker-src blob: 'self';");
+}
+
+void AddMarketingOptInResources(content::WebUIDataSource* source) {
+ source->AddResourcePath("all_set.json",
+ IDR_MARKETING_OPT_IN_ALL_SET_ANIMATION);
+ source->OverrideContentSecurityPolicyWorkerSrc("worker-src blob: 'self';");
+}
+
void AddFingerprintResources(content::WebUIDataSource* source) {
int animation_id;
bool is_lottie_animation = false;
@@ -198,6 +218,9 @@ void AddFingerprintResources(content::WebUIDataSource* source) {
is_lottie_animation = true;
animation_id = IDR_LOGIN_FINGER_PRINT_TABLET_ANIMATION;
break;
+ case quick_unlock::FingerprintLocation::KEYBOARD_BOTTOM_LEFT:
+ animation_id = IDR_LOGIN_FINGERPRINT_SCANNER_LAPTOP_BOTTOM_LEFT_ANIMATION;
+ break;
case quick_unlock::FingerprintLocation::KEYBOARD_BOTTOM_RIGHT:
animation_id =
IDR_LOGIN_FINGERPRINT_SCANNER_LAPTOP_BOTTOM_RIGHT_ANIMATION;
@@ -281,6 +304,8 @@ content::WebUIDataSource* CreateOobeUIDataSource(
AddSyncConsentResources(source);
AddArcScreensResources(source);
AddAssistantScreensResources(source);
+ AddGestureNavigationResources(source);
+ AddMarketingOptInResources(source);
source->AddResourcePath(kKeyboardUtilsJSPath, IDR_KEYBOARD_UTILS_JS);
source->OverrideContentSecurityPolicyObjectSrc(
@@ -323,7 +348,6 @@ void DisablePolymer2(content::URLDataSource* shared_source) {
// static
const char OobeUI::kAppLaunchSplashDisplay[] = "app-launch-splash";
-const char OobeUI::kArcKioskSplashDisplay[] = "arc-kiosk-splash";
const char OobeUI::kDiscoverDisplay[] = "discover";
const char OobeUI::kGaiaSigninDisplay[] = "gaia-signin";
const char OobeUI::kLockDisplay[] = "lock";
@@ -373,8 +397,8 @@ void OobeUI::ConfigureOobeDisplay() {
AddScreenHandler(std::make_unique<AutoEnrollmentCheckScreenHandler>(
js_calls_container_.get()));
- AddScreenHandler(std::make_unique<HIDDetectionScreenHandler>(
- js_calls_container_.get(), core_handler_));
+ AddScreenHandler(
+ std::make_unique<HIDDetectionScreenHandler>(js_calls_container_.get()));
AddScreenHandler(
std::make_unique<ErrorScreenHandler>(js_calls_container_.get()));
@@ -412,27 +436,21 @@ void OobeUI::ConfigureOobeDisplay() {
AddScreenHandler(std::make_unique<FingerprintSetupScreenHandler>(
js_calls_container_.get()));
+ AddScreenHandler(std::make_unique<GestureNavigationScreenHandler>(
+ js_calls_container_.get()));
+
AddScreenHandler(
std::make_unique<MarketingOptInScreenHandler>(js_calls_container_.get()));
- policy::BrowserPolicyConnectorChromeOS* connector =
- g_browser_process->platform_part()->browser_policy_connector_chromeos();
- ActiveDirectoryPasswordChangeScreenHandler*
- active_directory_password_change_screen_handler = nullptr;
- // Create Active Directory password change screen for corresponding devices
- // only.
- if (connector->IsActiveDirectoryManaged()) {
- auto password_change_handler =
- std::make_unique<ActiveDirectoryPasswordChangeScreenHandler>(
- js_calls_container_.get(), core_handler_);
- active_directory_password_change_screen_handler =
- password_change_handler.get();
- AddScreenHandler(std::move(password_change_handler));
- }
+ auto password_change_handler =
+ std::make_unique<ActiveDirectoryPasswordChangeScreenHandler>(
+ js_calls_container_.get(), core_handler_);
AddScreenHandler(std::make_unique<GaiaScreenHandler>(
js_calls_container_.get(), core_handler_, network_state_informer_,
- active_directory_password_change_screen_handler));
+ password_change_handler.get()));
+
+ AddScreenHandler(std::move(password_change_handler));
auto signin_screen_handler = std::make_unique<SigninScreenHandler>(
js_calls_container_.get(), network_state_informer_, error_screen,
@@ -444,9 +462,6 @@ void OobeUI::ConfigureOobeDisplay() {
js_calls_container_.get(), network_state_informer_, error_screen));
AddScreenHandler(
- std::make_unique<ArcKioskSplashScreenHandler>(js_calls_container_.get()));
-
- AddScreenHandler(
std::make_unique<DeviceDisabledScreenHandler>(js_calls_container_.get()));
AddScreenHandler(std::make_unique<EncryptionMigrationScreenHandler>(
@@ -491,7 +506,7 @@ void OobeUI::ConfigureOobeDisplay() {
oobe_display_chooser_ = std::make_unique<OobeDisplayChooser>();
}
-void OobeUI::BindMultiDeviceSetup(
+void OobeUI::BindInterface(
mojo::PendingReceiver<multidevice_setup::mojom::MultiDeviceSetup>
receiver) {
multidevice_setup::MultiDeviceSetupService* service =
@@ -501,7 +516,7 @@ void OobeUI::BindMultiDeviceSetup(
service->BindMultiDeviceSetup(std::move(receiver));
}
-void OobeUI::BindPrivilegedHostDeviceSetter(
+void OobeUI::BindInterface(
mojo::PendingReceiver<multidevice_setup::mojom::PrivilegedHostDeviceSetter>
receiver) {
multidevice_setup::MultiDeviceSetupService* service =
@@ -511,7 +526,7 @@ void OobeUI::BindPrivilegedHostDeviceSetter(
service->BindPrivilegedHostDeviceSetter(std::move(receiver));
}
-void OobeUI::BindCrosNetworkConfig(
+void OobeUI::BindInterface(
mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
receiver) {
ash::GetNetworkConfigService(std::move(receiver));
@@ -553,13 +568,6 @@ OobeUI::OobeUI(content::WebUI* web_ui, const GURL& url)
GURL("chrome://resources/polymer/v1_0/polymer/polymer.html"),
base::BindOnce(DisablePolymer2));
}
-
- AddHandlerToRegistry(base::BindRepeating(&OobeUI::BindMultiDeviceSetup,
- base::Unretained(this)));
- AddHandlerToRegistry(base::BindRepeating(
- &OobeUI::BindPrivilegedHostDeviceSetter, base::Unretained(this)));
- AddHandlerToRegistry(base::BindRepeating(&OobeUI::BindCrosNetworkConfig,
- base::Unretained(this)));
}
OobeUI::~OobeUI() {
@@ -580,6 +588,7 @@ void OobeUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) {
handler->GetLocalizedStrings(localized_strings);
const std::string& app_locale = g_browser_process->GetApplicationLocale();
webui::SetLoadTimeDataDefaults(app_locale, localized_strings);
+ localized_strings->SetString("app_locale", app_locale);
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
localized_strings->SetString("buildType", "chrome");
@@ -658,8 +667,7 @@ void OobeUI::ShowOobeUI(bool show) {
oobe_display_chooser_->TryToPlaceUiOnTouchDisplay();
}
-void OobeUI::ShowSigninScreen(const LoginScreenContext& context,
- SigninScreenHandlerDelegate* delegate,
+void OobeUI::ShowSigninScreen(SigninScreenHandlerDelegate* delegate,
NativeWindowDelegate* native_window_delegate) {
// Check our device mode.
policy::BrowserPolicyConnectorChromeOS* connector =
@@ -674,8 +682,7 @@ void OobeUI::ShowSigninScreen(const LoginScreenContext& context,
signin_screen_handler_->SetDelegate(delegate);
signin_screen_handler_->SetNativeWindowDelegate(native_window_delegate);
- LoginScreenContext actual_context(context);
- signin_screen_handler_->Show(actual_context, core_handler_->show_oobe_ui());
+ signin_screen_handler_->Show(core_handler_->show_oobe_ui());
}
void OobeUI::ForwardAccelerator(std::string accelerator_name) {
@@ -705,4 +712,6 @@ void OobeUI::SetLoginUserCount(int user_count) {
core_handler_->SetLoginUserCount(user_count);
}
+WEB_UI_CONTROLLER_TYPE_IMPL(OobeUI)
+
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
index 1ca5b98e8f0..a87658eadf2 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -17,7 +17,7 @@
#include "chrome/browser/chromeos/login/oobe_screen.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
#include "chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h"
-#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
+#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom-forward.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h" // nogncheck
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -29,7 +29,6 @@ class DictionaryValue;
namespace chromeos {
class ErrorScreen;
-class LoginScreenContext;
class NativeWindowDelegate;
class NetworkStateInformer;
class OobeDisplayChooser;
@@ -45,7 +44,6 @@ class OobeUI : public ui::MojoWebUIController {
// List of known types of OobeUI. Type added as path in chrome://oobe url, for
// example chrome://oobe/user-adding.
static const char kAppLaunchSplashDisplay[];
- static const char kArcKioskSplashDisplay[];
static const char kDiscoverDisplay[];
static const char kGaiaSigninDisplay[];
static const char kLockDisplay[];
@@ -89,8 +87,7 @@ class OobeUI : public ui::MojoWebUIController {
void ShowOobeUI(bool show);
// Shows the signin screen.
- void ShowSigninScreen(const LoginScreenContext& context,
- SigninScreenHandlerDelegate* delegate,
+ void ShowSigninScreen(SigninScreenHandlerDelegate* delegate,
NativeWindowDelegate* native_window_delegate);
// Forwards an accelerator to the webui to be handled.
@@ -145,6 +142,22 @@ class OobeUI : public ui::MojoWebUIController {
return nullptr;
}
+ // Instantiates implementor of the mojom::MultiDeviceSetup mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(
+ mojo::PendingReceiver<multidevice_setup::mojom::MultiDeviceSetup>
+ receiver);
+ // Instantiates implementor of the mojom::PrivilegedHostDeviceSetter mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
+ mojo::PendingReceiver<
+ multidevice_setup::mojom::PrivilegedHostDeviceSetter> receiver);
+ // Instantiates implementor of the mojom::CrosNetworkConfig mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
+ mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
+ receiver);
+
private:
void AddWebUIHandler(std::unique_ptr<BaseWebUIHandler> handler);
void AddScreenHandler(std::unique_ptr<BaseScreenHandler> handler);
@@ -153,17 +166,6 @@ class OobeUI : public ui::MojoWebUIController {
// display type.
void ConfigureOobeDisplay();
- // Adds Mojo receivers for this WebUIController.
- void BindMultiDeviceSetup(
- mojo::PendingReceiver<multidevice_setup::mojom::MultiDeviceSetup>
- receiver);
- void BindPrivilegedHostDeviceSetter(
- mojo::PendingReceiver<
- multidevice_setup::mojom::PrivilegedHostDeviceSetter> receiver);
- void BindCrosNetworkConfig(
- mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
- receiver);
-
// Type of UI.
std::string display_type_;
@@ -206,6 +208,8 @@ class OobeUI : public ui::MojoWebUIController {
// initialized.
std::unique_ptr<JSCallsContainer> js_calls_container_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(OobeUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
index 81873351f4b..473bd7311ce 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
@@ -119,9 +119,13 @@ void ResetScreenHandler::SetIsRollbackAvailable(bool value) {
CallJS("login.ResetScreen.setIsRollbackAvailable", value);
}
-void ResetScreenHandler::SetIsRollbackChecked(bool value) {
- is_rollback_checked_ = value;
- CallJS("login.ResetScreen.setIsRollbackChecked", value);
+// Only serve the request if the confirmation dialog isn't being shown.
+void ResetScreenHandler::SetIsRollbackRequested(bool value) {
+ if (is_showing_confirmation_dialog_)
+ return;
+
+ is_rollback_requested_ = value;
+ CallJS("login.ResetScreen.setIsRollbackRequested", value);
}
void ResetScreenHandler::SetIsTpmFirmwareUpdateAvailable(bool value) {
@@ -143,12 +147,13 @@ void ResetScreenHandler::SetTpmFirmwareUpdateMode(
CallJS("login.ResetScreen.setTpmFirmwareUpdateMode", static_cast<int>(value));
}
-void ResetScreenHandler::SetIsConfirmational(bool value) {
- CallJS("login.ResetScreen.setIsConfirmational", value);
+void ResetScreenHandler::SetShouldShowConfirmationDialog(bool value) {
+ is_showing_confirmation_dialog_ = value;
+ CallJS("login.ResetScreen.setShouldShowConfirmationDialog", value);
}
-void ResetScreenHandler::SetIsOfficialBuild(bool value) {
- CallJS("login.ResetScreen.setIsOfficialBuild", value);
+void ResetScreenHandler::SetConfirmationDialogClosed() {
+ is_showing_confirmation_dialog_ = false;
}
void ResetScreenHandler::SetScreenState(State value) {
@@ -168,8 +173,8 @@ bool ResetScreenHandler::GetIsRollbackAvailable() {
return is_rollback_available_;
}
-bool ResetScreenHandler::GetIsRollbackChecked() {
- return is_rollback_checked_;
+bool ResetScreenHandler::GetIsRollbackRequested() {
+ return is_rollback_requested_;
}
bool ResetScreenHandler::GetIsTpmFirmwareUpdateChecked() {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
index cdab74d6d39..a608bdfd652 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
@@ -9,7 +9,6 @@
#include "base/macros.h"
#include "chrome/browser/chromeos/tpm_firmware_update.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
-#include "content/public/browser/web_ui.h"
namespace chromeos {
@@ -36,19 +35,19 @@ class ResetView {
};
virtual void SetIsRollbackAvailable(bool value) = 0;
- virtual void SetIsRollbackChecked(bool value) = 0;
+ virtual void SetIsRollbackRequested(bool value) = 0;
virtual void SetIsTpmFirmwareUpdateAvailable(bool value) = 0;
virtual void SetIsTpmFirmwareUpdateChecked(bool value) = 0;
virtual void SetIsTpmFirmwareUpdateEditable(bool value) = 0;
virtual void SetTpmFirmwareUpdateMode(tpm_firmware_update::Mode value) = 0;
- virtual void SetIsConfirmational(bool value) = 0;
- virtual void SetIsOfficialBuild(bool value) = 0;
+ virtual void SetShouldShowConfirmationDialog(bool value) = 0;
+ virtual void SetConfirmationDialogClosed() = 0;
virtual void SetScreenState(State value) = 0;
virtual State GetScreenState() = 0;
virtual tpm_firmware_update::Mode GetTpmFirmwareUpdateMode() = 0;
virtual bool GetIsRollbackAvailable() = 0;
- virtual bool GetIsRollbackChecked() = 0;
+ virtual bool GetIsRollbackRequested() = 0;
virtual bool GetIsTpmFirmwareUpdateChecked() = 0;
};
@@ -73,18 +72,18 @@ class ResetScreenHandler : public ResetView,
void DeclareJSCallbacks() override;
void Initialize() override;
void SetIsRollbackAvailable(bool value) override;
- void SetIsRollbackChecked(bool value) override;
+ void SetIsRollbackRequested(bool value) override;
void SetIsTpmFirmwareUpdateAvailable(bool value) override;
void SetIsTpmFirmwareUpdateChecked(bool value) override;
void SetIsTpmFirmwareUpdateEditable(bool value) override;
void SetTpmFirmwareUpdateMode(tpm_firmware_update::Mode value) override;
- void SetIsConfirmational(bool value) override;
- void SetIsOfficialBuild(bool value) override;
+ void SetShouldShowConfirmationDialog(bool value) override;
+ void SetConfirmationDialogClosed() override;
void SetScreenState(State value) override;
State GetScreenState() override;
tpm_firmware_update::Mode GetTpmFirmwareUpdateMode() override;
bool GetIsRollbackAvailable() override;
- bool GetIsRollbackChecked() override;
+ bool GetIsRollbackRequested() override;
bool GetIsTpmFirmwareUpdateChecked() override;
private:
@@ -98,8 +97,9 @@ class ResetScreenHandler : public ResetView,
ResetView::State state_ = ResetView::State::kRestartRequired;
tpm_firmware_update::Mode mode_ = tpm_firmware_update::Mode::kNone;
bool is_rollback_available_ = false;
- bool is_rollback_checked_ = false;
+ bool is_rollback_requested_ = false;
bool is_tpm_firmware_update_checked_ = false;
+ bool is_showing_confirmation_dialog_ = false;
DISALLOW_COPY_AND_ASSIGN(ResetScreenHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.cc
index 485dbb82f2f..f9c0c9dbf51 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.cc
@@ -152,7 +152,7 @@ void SamlChallengeKeyHandler::ReturnResult(
}
std::string encoded_result_data;
- base::Base64Encode(result.data, &encoded_result_data);
+ base::Base64Encode(result.challenge_response, &encoded_result_data);
js_result.SetKey(kSuccessField, base::Value(result.IsSuccess()));
js_result.SetKey(kResponseField, base::Value(encoded_result_data));
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index 2e34b2bb0c8..be5053b0acd 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -218,10 +218,6 @@ std::string GetNetworkName(const std::string& service_path) {
} // namespace
-// LoginScreenContext implementation ------------------------------------------
-
-LoginScreenContext::LoginScreenContext() = default;
-
// SigninScreenHandler implementation ------------------------------------------
SigninScreenHandler::SigninScreenHandler(
@@ -298,13 +294,6 @@ SigninScreenHandler::~SigninScreenHandler() {
network_state_informer_->RemoveObserver(this);
proximity_auth::ScreenlockBridge::Get()->SetLockHandler(nullptr);
proximity_auth::ScreenlockBridge::Get()->SetFocusedUser(EmptyAccountId());
- // TODO(https://crbug.com/1033572) Quick fix to close feedback form when login
- // was performed.
- login_feedback_.reset();
- extensions::FeedbackPrivateDelegate* feedback_private_delegate =
- extensions::ExtensionsAPIClient::Get()->GetFeedbackPrivateDelegate();
- feedback_private_delegate->UnloadFeedbackExtension(
- Profile::FromWebUI(web_ui()));
}
void SigninScreenHandler::DeclareLocalizedValues(
@@ -492,16 +481,12 @@ void SigninScreenHandler::RegisterMessages() {
AddCallback("sendFeedback", &SigninScreenHandler::HandleSendFeedback);
}
-void SigninScreenHandler::Show(const LoginScreenContext& context,
- bool oobe_ui) {
+void SigninScreenHandler::Show(bool oobe_ui) {
CHECK(delegate_);
// Just initialize internal fields from context and call ShowImpl().
oobe_ui_ = oobe_ui;
- std::string email;
- email = context.email();
- gaia_screen_handler_->set_populated_email(email);
ShowImpl();
histogram_helper_->OnScreenShow();
}
@@ -529,11 +514,6 @@ void SigninScreenHandler::UpdateState(NetworkError::ErrorReason reason) {
UpdateStateInternal(reason, force_update);
}
-void SigninScreenHandler::SetFocusPODCallbackForTesting(
- base::Closure callback) {
- test_focus_pod_callback_ = callback;
-}
-
void SigninScreenHandler::SetOfflineTimeoutForTesting(
base::TimeDelta offline_timeout) {
is_offline_timeout_for_test_set_ = true;
@@ -1267,8 +1247,8 @@ void SigninScreenHandler::HandleLoginVisible(const std::string& source) {
chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
content::NotificationService::AllSources(),
content::NotificationService::NoDetails());
- TRACE_EVENT_ASYNC_END0("ui", "ShowLoginWebUI",
- LoginDisplayHostWebUI::kShowLoginWebUIid);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("ui", "ShowLoginWebUI",
+ LoginDisplayHostWebUI::kShowLoginWebUIid);
}
webui_visible_ = true;
if (preferences_changed_delayed_)
@@ -1340,8 +1320,6 @@ void SigninScreenHandler::HandleFocusPod(const AccountId& account_id,
if (delegate_ && !is_same_pod_focused)
delegate_->CheckUserStatus(account_id);
- if (!test_focus_pod_callback_.is_null())
- test_focus_pod_callback_.Run();
focused_pod_account_id_ = std::make_unique<AccountId>(account_id);
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index 6195aa7c0d3..f2b6b19f830 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -59,19 +59,6 @@ class NativeWindowDelegate;
class User;
class UserContext;
-// Helper class to pass initial parameters to the login screen.
-class LoginScreenContext {
- public:
- LoginScreenContext();
-
- void set_email(const std::string& email) { email_ = email; }
- const std::string& email() const { return email_; }
-
- private:
- // Optional email to prefill in gaia signin.
- std::string email_;
-};
-
// An interface for WebUILoginDisplay to call SigninScreenHandler.
class LoginDisplayWebUIHandler {
public:
@@ -204,7 +191,7 @@ class SigninScreenHandler
input_method::InputMethodManager::State* ime_state);
// Shows the sign in screen.
- void Show(const LoginScreenContext& context, bool oobe_ui);
+ void Show(bool oobe_ui);
// Sets delegate to be used by the handler. It is guaranteed that valid
// delegate is set before Show() method will be called.
@@ -228,8 +215,6 @@ class SigninScreenHandler
void OnWallpaperColorsChanged() override;
void OnWallpaperBlurChanged() override;
- void SetFocusPODCallbackForTesting(base::Closure callback);
-
// To avoid spurious error messages on flaky networks, the offline message is
// only shown if the network is offline for a threshold number of seconds.
// This method provides an ability to reduce the threshold to zero, allowing
@@ -414,10 +399,6 @@ class SigninScreenHandler
// Callback invoked after the feedback is finished.
void OnFeedbackFinished();
- // Callback invoked after the feedback sent from the unrecoverable cryptohome
- // page is finished.
- void OnUnrecoverableCryptohomeFeedbackFinished();
-
// Called when the cros property controlling allowed input methods changes.
void OnAllowedInputMethodsChanged();
@@ -492,9 +473,6 @@ class SigninScreenHandler
// Input Method Engine state used at signin screen.
scoped_refptr<input_method::InputMethodManager::State> ime_state_;
- // This callback captures "focusPod finished" event for tests.
- base::Closure test_focus_pod_callback_;
-
// True if SigninScreenHandler has already been added to OobeUI observers.
bool oobe_ui_observer_added_ = false;
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/signin_userlist_unittest.cc b/chromium/chrome/browser/ui/webui/chromeos/login/signin_userlist_unittest.cc
index 205688cf91b..6eb50149d50 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/signin_userlist_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/signin_userlist_unittest.cc
@@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "chrome/browser/chromeos/login/screens/user_selection_screen.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
@@ -23,15 +24,13 @@
namespace {
-const size_t kMaxUsers = 18; // same as in user_selection_screen.cc
+const size_t kMaxUsers = 50; // same as in user_selection_screen.cc
const char* kOwner = "owner@gmail.com";
const char* kUsersPublic[] = {"public0@gmail.com", "public1@gmail.com"};
-const char* kUsers[] = {
- "a0@gmail.com", "a1@gmail.com", "a2@gmail.com", "a3@gmail.com",
- "a4@gmail.com", "a5@gmail.com", "a6@gmail.com", "a7@gmail.com",
- "a8@gmail.com", "a9@gmail.com", "a10@gmail.com", "a11@gmail.com",
- "a12@gmail.com", "a13@gmail.com", "a14@gmail.com", "a15@gmail.com",
- "a16@gmail.com", "a17@gmail.com", kOwner, "a18@gmail.com"};
+
+std::string GenerateUserEmail(int number) {
+ return "a" + base::NumberToString(number) + "@gmail.com";
+}
} // namespace
@@ -60,8 +59,13 @@ class SigninPrepareUserListTest : public testing::Test,
fake_user_manager_->AddPublicAccountUser(
AccountId::FromUserEmail(kUsersPublic[i]));
- for (size_t i = 0; i < base::size(kUsers); ++i)
- fake_user_manager_->AddUser(AccountId::FromUserEmail(kUsers[i]));
+ for (size_t i = 0; i < kMaxUsers + 1; ++i) {
+ fake_user_manager_->AddUser(
+ AccountId::FromUserEmail(GenerateUserEmail(i)));
+ // Insert owner second to last.
+ if (i == kMaxUsers - 1)
+ fake_user_manager_->AddUser(AccountId::FromUserEmail(kOwner));
+ }
fake_user_manager_->set_owner_id(AccountId::FromUserEmail(kOwner));
}
@@ -106,7 +110,7 @@ TEST_F(SigninPrepareUserListTest, AlwaysKeepOwnerInList) {
true /* is_signin_to_add */);
EXPECT_EQ(kMaxUsers, users_to_send.size());
- EXPECT_EQ("a18@gmail.com",
+ EXPECT_EQ(GenerateUserEmail(kMaxUsers),
users_to_send.back()->GetAccountId().GetUserEmail());
EXPECT_EQ(kOwner,
users_to_send[kMaxUsers - 2]->GetAccountId().GetUserEmail());
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
index 61911ecd475..8b92640d17c 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
@@ -10,6 +10,7 @@
#include "chromeos/constants/chromeos_features.h"
#include "components/login/localized_values_builder.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/chromeos/devicetype_utils.h"
namespace {
@@ -29,13 +30,20 @@ void GetConsentIDs(const std::unordered_set<int>& known_ids,
// characters, so we must use base::ReplaceSubstrings* rather than
// base::ReplaceChars.
// TODO(alemate): Find a more elegant solution.
- std::string sanitized_string =
- base::UTF16ToUTF8(l10n_util::GetStringUTF16(id));
+ base::string16 raw_string;
+ if (id == IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME) {
+ raw_string = ui::SubstituteChromeOSDeviceType(
+ IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME);
+ } else {
+ raw_string = l10n_util::GetStringUTF16(id);
+ }
+ std::string sanitized_string = base::UTF16ToUTF8(raw_string);
base::ReplaceSubstringsAfterOffset(&sanitized_string, 0,
"\u00A0" /* NBSP */, "&nbsp;");
known_strings[sanitized_string] = id;
}
+
// The strings returned by the WebUI are not free-form, they must belong into
// a pre-determined set of strings (stored in |string_to_grd_id_map_|). As
// this has privacy and legal implications, CHECK the integrity of the strings
@@ -101,6 +109,19 @@ void SyncConsentScreenHandler::DeclareLocalizedValues(
RememberLocalizedValue("syncConsentAcceptAndContinue",
IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT_AND_CONTINUE,
builder);
+
+ // SplitSyncConsent strings. The version of the dialog to show is chosen
+ // after the WebUI is loaded, so always supply both sets of strings.
+ RememberLocalizedValue("osSyncConsentTitle", IDS_LOGIN_OS_SYNC_CONSENT_TITLE,
+ builder);
+ known_string_ids_.insert(IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME);
+ builder->AddF("osSyncConsentToggleName",
+ IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_NAME,
+ ui::GetChromeOSDeviceName());
+ RememberLocalizedValue("osSyncConsentToggleDescription",
+ IDS_LOGIN_OS_SYNC_CONSENT_TOGGLE_DESCRIPTION, builder);
+ RememberLocalizedValue("osSyncConsentContinue",
+ IDS_LOGIN_OS_SYNC_CONSENT_CONTINUE, builder);
}
void SyncConsentScreenHandler::Bind(SyncConsentScreen* screen) {
@@ -131,15 +152,15 @@ void SyncConsentScreenHandler::RegisterMessages() {
void SyncConsentScreenHandler::GetAdditionalParameters(
base::DictionaryValue* parameters) {
- parameters->SetBoolean("splitSettingsSync",
- chromeos::features::IsSplitSettingsSyncEnabled());
+ parameters->SetBoolean("splitSyncConsent",
+ chromeos::features::IsSplitSyncConsentEnabled());
BaseScreenHandler::GetAdditionalParameters(parameters);
}
void SyncConsentScreenHandler::HandleContinueAndReview(
const login::StringList& consent_description,
const std::string& consent_confirmation) {
- DCHECK(!chromeos::features::IsSplitSettingsSyncEnabled());
+ DCHECK(!chromeos::features::IsSplitSyncConsentEnabled());
std::vector<int> consent_description_ids;
int consent_confirmation_id;
GetConsentIDs(known_string_ids_, consent_description, consent_confirmation,
@@ -158,7 +179,7 @@ void SyncConsentScreenHandler::HandleContinueAndReview(
void SyncConsentScreenHandler::HandleContinueWithDefaults(
const login::StringList& consent_description,
const std::string& consent_confirmation) {
- DCHECK(!chromeos::features::IsSplitSettingsSyncEnabled());
+ DCHECK(!chromeos::features::IsSplitSyncConsentEnabled());
std::vector<int> consent_description_ids;
int consent_confirmation_id;
GetConsentIDs(known_string_ids_, consent_description, consent_confirmation,
@@ -178,7 +199,7 @@ void SyncConsentScreenHandler::HandleOsSyncAcceptAndContinue(
const login::StringList& consent_description,
const std::string& consent_confirmation,
bool enable_os_sync) {
- DCHECK(chromeos::features::IsSplitSettingsSyncEnabled());
+ DCHECK(chromeos::features::IsSplitSyncConsentEnabled());
std::vector<int> consent_description_ids;
int consent_confirmation_id;
GetConsentIDs(known_string_ids_, consent_description, consent_confirmation,
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.cc
index e384545e198..241a06360c0 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.cc
@@ -40,6 +40,7 @@ TermsOfServiceScreenHandler::TermsOfServiceScreenHandler(
CoreOobeView* core_oobe_view)
: BaseScreenHandler(kScreenId, js_calls_container),
core_oobe_view_(core_oobe_view) {
+ set_user_acted_method_path("login.TermsOfServiceScreen.userActed");
}
TermsOfServiceScreenHandler::~TermsOfServiceScreenHandler() {
@@ -47,13 +48,6 @@ TermsOfServiceScreenHandler::~TermsOfServiceScreenHandler() {
screen_->OnViewDestroyed(this);
}
-void TermsOfServiceScreenHandler::RegisterMessages() {
- AddCallback("termsOfServiceBack",
- &TermsOfServiceScreenHandler::HandleBack);
- AddCallback("termsOfServiceAccept",
- &TermsOfServiceScreenHandler::HandleAccept);
-}
-
void TermsOfServiceScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) {
builder->Add("termsOfServiceScreenHeading",
@@ -71,7 +65,8 @@ void TermsOfServiceScreenHandler::DeclareLocalizedValues(
IDS_TERMS_OF_SERVICE_SCREEN_ACCEPT_BUTTON);
}
-void TermsOfServiceScreenHandler::SetDelegate(TermsOfServiceScreen* screen) {
+void TermsOfServiceScreenHandler::SetScreen(TermsOfServiceScreen* screen) {
+ BaseScreenHandler::SetBaseScreen(screen);
screen_ = screen;
}
@@ -127,6 +122,10 @@ void TermsOfServiceScreenHandler::OnLoadSuccess(
UpdateTermsOfServiceInUI();
}
+bool TermsOfServiceScreenHandler::AreTermsLoaded() {
+ return !load_error_ && !terms_of_service_.empty();
+}
+
void TermsOfServiceScreenHandler::Initialize() {
if (show_on_init_) {
Show();
@@ -192,23 +191,4 @@ void TermsOfServiceScreenHandler::UpdateTermsOfServiceInUI() {
CallJS("login.TermsOfServiceScreen.setTermsOfService", terms_of_service_);
}
-void TermsOfServiceScreenHandler::HandleBack() {
- if (screen_)
- screen_->OnDecline();
-}
-
-void TermsOfServiceScreenHandler::HandleAccept() {
- if (!screen_)
- return;
-
- // If the Terms of Service have not been successfully downloaded, the "accept
- // and continue" button should not be accessible. If the user managed to
- // activate it somehow anway, do not treat this as acceptance of the Terms
- // and Conditions and end the session instead, as if the user had declined.
- if (terms_of_service_.empty())
- screen_->OnDecline();
- else
- screen_->OnAccept();
-}
-
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h
index 06e6b91f965..a2a4e0386b3 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h
@@ -26,7 +26,7 @@ class TermsOfServiceScreenView {
virtual ~TermsOfServiceScreenView() {}
// Sets screen this view belongs to.
- virtual void SetDelegate(TermsOfServiceScreen* screen) = 0;
+ virtual void SetScreen(TermsOfServiceScreen* screen) = 0;
// Shows the contents of the screen.
virtual void Show() = 0;
@@ -44,6 +44,9 @@ class TermsOfServiceScreenView {
// Called when the download of the Terms of Service is successful. Shows the
// downloaded |terms_of_service| to the user.
virtual void OnLoadSuccess(const std::string& terms_of_service) = 0;
+
+ // Whether TOS are successfully loaded.
+ virtual bool AreTermsLoaded() = 0;
};
// The sole implementation of the TermsOfServiceScreenView, using WebUI.
@@ -56,20 +59,18 @@ class TermsOfServiceScreenHandler : public BaseScreenHandler,
CoreOobeView* core_oobe_view);
~TermsOfServiceScreenHandler() override;
- // content::WebUIMessageHandler:
- void RegisterMessages() override;
-
// BaseScreenHandler:
void DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) override;
// TermsOfServiceScreenView:
- void SetDelegate(TermsOfServiceScreen* screen) override;
+ void SetScreen(TermsOfServiceScreen* screen) override;
void Show() override;
void Hide() override;
void SetDomain(const std::string& domain) override;
void OnLoadError() override;
void OnLoadSuccess(const std::string& terms_of_service) override;
+ bool AreTermsLoaded() override;
private:
// BaseScreenHandler:
@@ -92,14 +93,6 @@ class TermsOfServiceScreenHandler : public BaseScreenHandler,
// nothing if the download is still in progress.
void UpdateTermsOfServiceInUI();
- // Called when the user declines the Terms of Service by clicking the "back"
- // button.
- void HandleBack();
-
- // Called when the user accepts the Terms of Service by clicking the "accept
- // and continue" button.
- void HandleAccept();
-
TermsOfServiceScreen* screen_ = nullptr;
CoreOobeView* core_oobe_view_ = nullptr;
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.cc
index d02af35140b..d938229bbd9 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.cc
@@ -33,20 +33,19 @@ UpdateRequiredScreenHandler::~UpdateRequiredScreenHandler() {
void UpdateRequiredScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) {
- builder->Add("updateRequiredMessage",
- IDS_UPDATE_REQUIRED_LOGIN_SCREEN_MESSAGE);
+ builder->Add("updateRequiredTitle", IDS_UPDATE_REQUIRED_SCREEN_TITLE);
+ builder->Add("updateRequiredMessage", IDS_UPDATE_REQUIRED_SCREEN_MESSAGE);
builder->Add("errorMessage",
IDS_BROWSER_SHARING_ERROR_DIALOG_TEXT_INTERNAL_ERROR);
- builder->Add("eolMessage",
- ui::SubstituteChromeOSDeviceType(IDS_EOL_NOTIFICATION_EOL));
- builder->Add("selectNetworkButtonCaption", IDS_APP_START_CONFIGURE_NETWORK);
- builder->Add("updateButtonCaption",
- IDS_SETTINGS_ABOUT_PAGE_CHECK_FOR_UPDATES);
+ builder->Add("eolTitle", IDS_UPDATE_REQUIRED_SCREEN_EOL_TITLE);
+ builder->Add("eolMessage", IDS_UPDATE_REQUIRED_SCREEN_EOL_MESSAGE);
+ builder->Add("selectNetworkButtonCaption",
+ IDS_UPDATE_REQUIRED_SCREEN_OPEN_NETWORK_SETTINGS);
+ builder->Add("updateButtonCaption", IDS_UPDATE_REQUIRED_SCREEN_START_UPDATE);
builder->Add("rebootNeededMessage", IDS_UPDATE_COMPLETED);
-
builder->Add("checkingForUpdatesTitle", IDS_CHECKING_FOR_UPDATES);
builder->Add("updatingTitle", IDS_UPDATING_SCREEN_TITLE);
-
+ builder->Add("updatingMessage", IDS_UPDATE_REQUIRED_UPDATING_MESSAGE);
builder->Add("downloading", IDS_DOWNLOADING);
builder->Add("downloadingTimeLeftLong", IDS_DOWNLOADING_TIME_LEFT_LONG);
builder->Add("downloadingTimeLeftStatusOneHour",
@@ -59,11 +58,13 @@ void UpdateRequiredScreenHandler::DeclareLocalizedValues(
"updateOverCellularPromptTitle",
ui::SubstituteChromeOSDeviceType(IDS_UPDATE_OVER_CELLULAR_PROMPT_TITLE));
builder->Add("updateOverCellularPromptMessage",
- IDS_UPDATE_OVER_CELLULAR_PROMPT_MESSAGE);
+ IDS_UPDATE_REQUIRED_SCREEN_METERED_MESSAGE);
builder->Add("AcceptUpdateOverCellularButton",
- IDS_OFFERS_CONSENT_INFOBAR_ENABLE_BUTTON);
+ IDS_UPDATE_REQUIRED_SCREEN_ALLOW_METERED);
builder->Add("RejectUpdateOverCellularButton",
IDS_OFFERS_CONSENT_INFOBAR_DISABLE_BUTTON);
+ builder->Add("noNetworkMessage",
+ IDS_UPDATE_REQUIRED_SCREEN_NO_NETWORK_MESSAGE);
}
void UpdateRequiredScreenHandler::Initialize() {
@@ -73,6 +74,13 @@ void UpdateRequiredScreenHandler::Initialize() {
}
}
+void UpdateRequiredScreenHandler::SetEnterpriseAndDeviceName(
+ const std::string& enterpriseDomain,
+ const base::string16& deviceName) {
+ CallJS("login.UpdateRequiredScreen.setEnterpriseAndDeviceName",
+ enterpriseDomain, deviceName);
+}
+
void UpdateRequiredScreenHandler::Show() {
if (!page_is_ready()) {
show_on_init_ = true;
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h
index cd52e9f012d..48bffc48e60 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h
@@ -28,7 +28,8 @@ class UpdateRequiredView {
UPDATE_COMPLETED_NEED_REBOOT, // Update successful, manual reboot is
// needed.
UPDATE_ERROR, // An error has occurred.
- EOL // End of Life message.
+ EOL_REACHED, // End of Life reached message.
+ UPDATE_NO_NETWORK // No network available to update
};
constexpr static StaticOobeScreenId kScreenId{"update-required"};
@@ -61,6 +62,9 @@ class UpdateRequiredView {
virtual void SetEstimatedTimeLeft(int seconds_left) = 0;
// Set the UI state of the screen.
virtual void SetUIState(UpdateRequiredView::UIState ui_state) = 0;
+ // Set enterprise and device name to be used in strings in the UI.
+ virtual void SetEnterpriseAndDeviceName(const std::string& enterpriseDomain,
+ const base::string16& deviceName) = 0;
};
class UpdateRequiredScreenHandler : public UpdateRequiredView,
@@ -84,6 +88,8 @@ class UpdateRequiredScreenHandler : public UpdateRequiredView,
void SetEstimatedTimeLeftVisible(bool visible) override;
void SetEstimatedTimeLeft(int seconds_left) override;
void SetUIState(UpdateRequiredView::UIState ui_state) override;
+ void SetEnterpriseAndDeviceName(const std::string& enterpriseDomain,
+ const base::string16& deviceName) override;
// BaseScreenHandler:
void DeclareLocalizedValues(
@@ -95,6 +101,9 @@ class UpdateRequiredScreenHandler : public UpdateRequiredView,
// If true, Initialize() will call Show().
bool show_on_init_ = false;
+ // The domain name for which update required screen is being shown.
+ std::string domain_;
+
DISALLOW_COPY_AND_ASSIGN(UpdateRequiredScreenHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc
index a46b2fa6282..55b4f1b0cad 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/values.h"
+#include "build/branding_buildflags.h"
#include "chrome/browser/chromeos/login/oobe_screen.h"
#include "chrome/browser/chromeos/login/screens/update_screen.h"
#include "chrome/grit/chromium_strings.h"
@@ -97,7 +98,7 @@ void UpdateScreenHandler::DeclareLocalizedValues(
IDS_DOWNLOADING_TIME_LEFT_STATUS_MINUTES);
builder->Add("downloadingTimeLeftSmall", IDS_DOWNLOADING_TIME_LEFT_SMALL);
-#if !defined(OFFICIAL_BUILD)
+#if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
builder->Add("cancelUpdateHint", IDS_UPDATE_CANCEL);
builder->Add("cancelledUpdateMessage", IDS_UPDATE_CANCELLED);
#else
diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h
index 11ab9916896..c66ca8105d5 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h
@@ -8,7 +8,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
-#include "content/public/browser/web_ui.h"
namespace chromeos {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/machine_learning/BUILD.gn b/chromium/chrome/browser/ui/webui/chromeos/machine_learning/BUILD.gn
index 3adbd9c1354..770038b0f32 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/machine_learning/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/chromeos/machine_learning/BUILD.gn
@@ -5,11 +5,7 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "machine_learning_internals_page_handler.mojom",
- ]
+ sources = [ "machine_learning_internals_page_handler.mojom" ]
- deps = [
- "//chromeos/services/machine_learning/public/mojom",
- ]
+ deps = [ "//chromeos/services/machine_learning/public/mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.cc
index 18ff22fb323..ace92dd56d2 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.cc
@@ -49,14 +49,13 @@ MachineLearningInternalsUI::MachineLearningInternalsUI(
source->SetDefaultResource(IDR_MACHINE_LEARNING_INTERNALS_HTML);
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
- AddHandlerToRegistry(base::BindRepeating(
- &MachineLearningInternalsUI::BindMachineLearningInternalsPageHandler,
- base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(MachineLearningInternalsUI)
+
MachineLearningInternalsUI::~MachineLearningInternalsUI() = default;
-void MachineLearningInternalsUI::BindMachineLearningInternalsPageHandler(
+void MachineLearningInternalsUI::BindInterface(
mojo::PendingReceiver<mojom::PageHandler> receiver) {
page_handler_ = std::make_unique<MachineLearningInternalsPageHandler>(
std::move(receiver));
diff --git a/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.h b/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.h
index da44a735e5f..2da4dc87fc0 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/macros.h"
-#include "chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_page_handler.mojom.h"
+#include "chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_page_handler.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -23,12 +23,15 @@ class MachineLearningInternalsUI : public ui::MojoWebUIController {
explicit MachineLearningInternalsUI(content::WebUI* web_ui);
~MachineLearningInternalsUI() override;
- private:
- void BindMachineLearningInternalsPageHandler(
- mojo::PendingReceiver<mojom::PageHandler> receiver);
+ // Instantiates the implementor of the mojom::PageHandler mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(mojo::PendingReceiver<mojom::PageHandler> receiver);
+ private:
std::unique_ptr<MachineLearningInternalsPageHandler> page_handler_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(MachineLearningInternalsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc
index 09462a48fe7..09cb31f141e 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.cc
@@ -5,6 +5,7 @@
#include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h"
#include "ash/public/cpp/shell_window_ids.h"
+#include "ash/public/cpp/window_backdrop.h"
#include "ash/public/cpp/window_properties.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
@@ -58,8 +59,8 @@ void MultiDeviceSetupDialog::Show() {
// Remove the black backdrop behind the dialog window which appears in tablet
// and full-screen mode.
- window->SetProperty(ash::kBackdropWindowMode,
- ash::BackdropWindowMode::kDisabled);
+ ash::WindowBackdrop::Get(window)->SetBackdropMode(
+ ash::WindowBackdrop::BackdropMode::kDisabled);
}
// static
@@ -127,15 +128,11 @@ MultiDeviceSetupDialogUI::MultiDeviceSetupDialogUI(content::WebUI* web_ui)
web_ui->AddMessageHandler(std::make_unique<MultideviceSetupHandler>());
web_ui->AddMessageHandler(std::make_unique<MetricsHandler>());
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
-
- // Add Mojo bindings to this WebUI so that Mojo calls can occur in JavaScript.
- AddHandlerToRegistry(base::BindRepeating(
- &MultiDeviceSetupDialogUI::BindMultiDeviceSetup, base::Unretained(this)));
}
MultiDeviceSetupDialogUI::~MultiDeviceSetupDialogUI() = default;
-void MultiDeviceSetupDialogUI::BindMultiDeviceSetup(
+void MultiDeviceSetupDialogUI::BindInterface(
mojo::PendingReceiver<chromeos::multidevice_setup::mojom::MultiDeviceSetup>
receiver) {
MultiDeviceSetupService* service =
@@ -145,6 +142,8 @@ void MultiDeviceSetupDialogUI::BindMultiDeviceSetup(
service->BindMultiDeviceSetup(std::move(receiver));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(MultiDeviceSetupDialogUI)
+
} // namespace multidevice_setup
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h
index e4671891542..18a4359bdf0 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h
@@ -11,7 +11,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
-#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
+#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/web_dialogs/web_dialog_ui.h"
@@ -60,11 +60,15 @@ class MultiDeviceSetupDialogUI : public ui::MojoWebDialogUI {
explicit MultiDeviceSetupDialogUI(content::WebUI* web_ui);
~MultiDeviceSetupDialogUI() override;
- private:
- void BindMultiDeviceSetup(
+ // Instantiates implementor of the mojom::MultiDeviceSetup mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<
chromeos::multidevice_setup::mojom::MultiDeviceSetup> receiver);
+ private:
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupDialogUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.cc
index a034584a75a..113bcca5617 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_localized_strings_provider.cc
@@ -23,6 +23,7 @@
#include "content/public/browser/web_ui_data_source.h"
#include "services/service_manager/public/cpp/connector.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
#include "ui/chromeos/devicetype_utils.h"
namespace chromeos {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
index 76217f7b804..13fe503151a 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
@@ -18,6 +18,7 @@
#include "content/public/browser/web_ui_data_source.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
namespace chromeos {
namespace network_element {
@@ -31,6 +32,7 @@ constexpr webui::LocalizedString kElementLocalizedStrings[] = {
{"OncTypeTether", IDS_NETWORK_TYPE_TETHER},
{"OncTypeVPN", IDS_NETWORK_TYPE_VPN},
{"OncTypeWiFi", IDS_NETWORK_TYPE_WIFI},
+ {"ipAddressNotAvailable", IDS_NETWORK_IP_ADDRESS_NA},
{"networkListItemConnected", IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED},
{"networkListItemConnecting", IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING},
{"networkListItemConnectingTo", IDS_NETWORK_LIST_CONNECTING_TO},
@@ -69,6 +71,13 @@ constexpr webui::LocalizedString kElementLocalizedStrings[] = {
{"networkListItemNotConnected", IDS_NETWORK_LIST_NOT_CONNECTED},
{"networkListItemNoNetwork", IDS_NETWORK_LIST_NO_NETWORK},
{"vpnNameTemplate", IDS_NETWORK_LIST_THIRD_PARTY_VPN_NAME_TEMPLATE},
+ {"networkIconLabelEthernet", IDS_NETWORK_ICON_LABEL_ETHERNET},
+ {"networkIconLabelVpn", IDS_NETWORK_ICON_LABEL_VPN},
+ {"networkIconLabelOff", IDS_NETWORK_ICON_LABEL_NETWORK_OFF},
+ {"networkIconLabelNoNetwork", IDS_NETWORK_ICON_LABEL_NO_NETWORK},
+ {"networkIconLabelConnecting", IDS_NETWORK_ICON_LABEL_CONNECTING},
+ {"networkIconLabelNotConnected", IDS_NETWORK_ICON_LABEL_NOT_CONNECTED},
+ {"networkIconLabelSignalStrength", IDS_NETWORK_ICON_LABEL_SIGNAL_STRENGTH},
};
} // namespace
@@ -197,7 +206,6 @@ void AddOncLocalizedStrings(content::WebUIDataSource* html_source) {
void AddDetailsLocalizedStrings(content::WebUIDataSource* html_source) {
static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"loading", IDS_SETTINGS_LOADING},
{"hidePassword", IDS_SETTINGS_PASSWORD_HIDE},
{"showPassword", IDS_SETTINGS_PASSWORD_SHOW},
{"networkProxy", IDS_SETTINGS_INTERNET_NETWORK_PROXY_PROXY},
diff --git a/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h b/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h
index 3bdb0f473ac..5b9abb40867 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h
@@ -16,8 +16,10 @@ class WebUIDataSource;
namespace chromeos {
namespace network_element {
-// Adds the strings needed for network elements to |html_source|. String ids
-// correspond to ids in ui/webui/resources/cr_components/chromeos/network/.
+// This file contains functions to add localized strings used by
+// components in ui/webui/resources/cr_components/chromeos/network/.
+
+// Adds the strings needed for network elements to |html_source|.
void AddLocalizedStrings(content::WebUIDataSource* html_source);
// Same as AddLocalizedStrings but for a LocalizedValuesBuilder.
diff --git a/chromium/chrome/browser/ui/webui/chromeos/network_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/network_ui.cc
index 53c1cfdcb95..b0957822cff 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/network_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -190,7 +190,7 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler {
}
NetworkHandler::Get()->network_device_handler()->GetDeviceProperties(
device->path(),
- base::Bind(
+ base::BindOnce(
&NetworkConfigMessageHandler::GetShillDevicePropertiesSuccess,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&NetworkConfigMessageHandler::ErrorCallback,
@@ -400,15 +400,15 @@ NetworkUI::NetworkUI(content::WebUI* web_ui)
content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
html);
- AddHandlerToRegistry(base::BindRepeating(&NetworkUI::BindCrosNetworkConfig,
- base::Unretained(this)));
}
NetworkUI::~NetworkUI() {}
-void NetworkUI::BindCrosNetworkConfig(
+void NetworkUI::BindInterface(
mojo::PendingReceiver<network_config::mojom::CrosNetworkConfig> receiver) {
ash::GetNetworkConfigService(std::move(receiver));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(NetworkUI)
+
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/network_ui.h b/chromium/chrome/browser/ui/webui/chromeos/network_ui.h
index a9eb0ab1919..8e4fc290ebd 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/network_ui.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/network_ui.h
@@ -24,10 +24,14 @@ class NetworkUI : public ui::MojoWebUIController {
static void GetLocalizedStrings(base::DictionaryValue* localized_strings);
- private:
- void BindCrosNetworkConfig(
+ // Instantiates implementor of the mojom::CrosNetworkConfig mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<network_config::mojom::CrosNetworkConfig> receiver);
+ private:
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(NetworkUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/power_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/power_ui.cc
index 6fc8c5a84ab..3205d20dacf 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/power_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/power_ui.cc
@@ -28,6 +28,7 @@
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
+#include "ui/base/webui/web_ui_util.h"
namespace chromeos {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/set_time_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/set_time_ui.cc
index c95a763cd59..cc12e4bb71f 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/set_time_ui.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/set_time_ui.cc
@@ -33,6 +33,7 @@
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
+#include "ui/base/webui/web_ui_util.h"
#include "ui/resources/grit/webui_resources.h"
namespace chromeos {
@@ -143,8 +144,8 @@ class SetTimeMessageHandler : public content::WebUIMessageHandler,
}
ash::LoginScreen::Get()->ShowParentAccessWidget(
account_id,
- base::BindRepeating(&SetTimeMessageHandler::OnParentAccessValidation,
- weak_factory_.GetWeakPtr()),
+ base::BindOnce(&SetTimeMessageHandler::OnParentAccessValidation,
+ weak_factory_.GetWeakPtr()),
ash::ParentAccessRequestReason::kChangeTime,
!is_user_logged_in /* extra_dimmer */,
base::Time::FromDoubleT(seconds));
@@ -190,10 +191,9 @@ SetTimeUI::SetTimeUI(content::WebUI* web_ui) : WebDialogUI(web_ui) {
values.Set("timezoneList", chromeos::system::GetTimezoneList());
// If we are not logged in, we need to show the time zone dropdown.
- // Otherwise, we can leave |currentTimezoneId| blank.
+ values.SetBoolean("showTimezone", SetTimeDialog::ShouldShowTimezone());
std::string current_timezone_id;
- if (SetTimeDialog::ShouldShowTimezone())
- CrosSettings::Get()->GetString(kSystemTimezone, &current_timezone_id);
+ CrosSettings::Get()->GetString(kSystemTimezone, &current_timezone_id);
values.SetString("currentTimezoneId", current_timezone_id);
values.SetDouble("buildTime", base::GetBuildTime().ToJsTime());
diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.cc
index 4b31716cbeb..0e64776606e 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.cc
@@ -4,8 +4,10 @@
#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h"
+#include <utility>
+
+#include "base/bind.h"
#include "base/json/json_writer.h"
-#include "base/strings/string_number_conversions.h"
#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/browser_resources.h"
@@ -36,35 +38,57 @@ void AddSmbCredentialsDialogStrings(content::WebUIDataSource* html_source) {
}
}
-std::string GetDialogId(int32_t mount_id) {
- return chrome::kChromeUISmbCredentialsURL + base::NumberToString(mount_id);
+std::string GetDialogId(const std::string& mount_id) {
+ return chrome::kChromeUISmbCredentialsURL + mount_id;
+}
+
+SmbCredentialsDialog* GetDialog(const std::string& id) {
+ return static_cast<SmbCredentialsDialog*>(
+ SystemWebDialogDelegate::FindInstance(id));
}
} // namespace
// static
-void SmbCredentialsDialog::Show(int32_t mount_id,
- const std::string& share_path) {
+void SmbCredentialsDialog::Show(const std::string& mount_id,
+ const std::string& share_path,
+ RequestCallback callback) {
// If an SmbCredentialsDialog is already opened for |mount_id|, focus that
// dialog rather than opening a second one.
- auto* instance = SystemWebDialogDelegate::FindInstance(GetDialogId(mount_id));
- if (instance) {
- instance->Focus();
+ SmbCredentialsDialog* dialog = GetDialog(GetDialogId(mount_id));
+ if (dialog) {
+ // Replace the dialog's callback so that is responds to the most recent
+ // request.
+ dialog->callback_ = std::move(callback);
+ dialog->Focus();
return;
}
- SmbCredentialsDialog* dialog = new SmbCredentialsDialog(mount_id, share_path);
+ dialog = new SmbCredentialsDialog(mount_id, share_path, std::move(callback));
dialog->ShowSystemDialog();
}
-SmbCredentialsDialog::SmbCredentialsDialog(int32_t mount_id,
- const std::string& share_path)
+SmbCredentialsDialog::SmbCredentialsDialog(const std::string& mount_id,
+ const std::string& share_path,
+ RequestCallback callback)
: SystemWebDialogDelegate(GURL(GetDialogId(mount_id)),
base::string16() /* title */),
mount_id_(mount_id),
- share_path_(share_path) {}
+ share_path_(share_path),
+ callback_(std::move(callback)) {}
+
+SmbCredentialsDialog::~SmbCredentialsDialog() {
+ if (callback_) {
+ std::move(callback_).Run(true /* canceled */, std::string() /* username */,
+ std::string() /* password */);
+ }
+}
-SmbCredentialsDialog::~SmbCredentialsDialog() = default;
+void SmbCredentialsDialog::Respond(const std::string& username,
+ const std::string& password) {
+ DCHECK(callback_);
+ std::move(callback_).Run(false /* canceled */, username, password);
+}
void SmbCredentialsDialog::GetDialogSize(gfx::Size* size) const {
size->SetSize(SystemWebDialogDelegate::kDialogWidth,
@@ -89,18 +113,27 @@ SmbCredentialsDialogUI::SmbCredentialsDialogUI(content::WebUI* web_ui)
source->UseStringsJs();
source->SetDefaultResource(IDR_SMB_CREDENTIALS_DIALOG_CONTAINER_HTML);
- source->AddResourcePath("smb_credentials_dialog.html",
- IDR_SMB_CREDENTIALS_DIALOG_HTML);
source->AddResourcePath("smb_credentials_dialog.js",
IDR_SMB_CREDENTIALS_DIALOG_JS);
- web_ui->AddMessageHandler(
- std::make_unique<SmbHandler>(Profile::FromWebUI(web_ui)));
+ web_ui->AddMessageHandler(std::make_unique<SmbHandler>(
+ Profile::FromWebUI(web_ui),
+ base::BindOnce(&SmbCredentialsDialogUI::OnUpdateCredentials,
+ base::Unretained(this))));
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
}
SmbCredentialsDialogUI::~SmbCredentialsDialogUI() = default;
+void SmbCredentialsDialogUI::OnUpdateCredentials(const std::string& username,
+ const std::string& password) {
+ SmbCredentialsDialog* dialog =
+ GetDialog(web_ui()->GetWebContents()->GetLastCommittedURL().spec());
+ if (dialog) {
+ dialog->Respond(username, password);
+ }
+}
+
} // namespace smb_dialog
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h
index 91b96bc9158..b614f60c71c 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h
@@ -5,6 +5,9 @@
#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_SMB_SHARES_SMB_CREDENTIALS_DIALOG_H_
#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_SMB_SHARES_SMB_CREDENTIALS_DIALOG_H_
+#include <string>
+
+#include "base/callback.h"
#include "base/macros.h"
#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
#include "ui/web_dialogs/web_dialog_ui.h"
@@ -14,11 +17,25 @@ namespace smb_dialog {
class SmbCredentialsDialog : public SystemWebDialogDelegate {
public:
- // Shows the dialog.
- static void Show(int32_t mount_id, const std::string& share_path);
+ using RequestCallback = base::OnceCallback<void(bool canceled,
+ const std::string& username,
+ const std::string& password)>;
+
+ // Shows the dialog, and runs |callback| when the user responds with a
+ // username/password, or the dialog is closed. If a dialog is currently being
+ // shown for |mount_id|, the existing dialog will be focused and its callback
+ // will be replaced with |callback|.
+ static void Show(const std::string& mount_id,
+ const std::string& share_path,
+ RequestCallback callback);
+
+ // Respond to the dialog being show with a username/password.
+ void Respond(const std::string& username, const std::string& password);
protected:
- SmbCredentialsDialog(int32_t mount_id, const std::string& share_path);
+ SmbCredentialsDialog(const std::string& mount_id,
+ const std::string& share_path,
+ RequestCallback callback);
~SmbCredentialsDialog() override;
// ui::WebDialogDelegate
@@ -26,8 +43,9 @@ class SmbCredentialsDialog : public SystemWebDialogDelegate {
std::string GetDialogArgs() const override;
private:
- int32_t mount_id_;
- std::string share_path_;
+ const std::string mount_id_;
+ const std::string share_path_;
+ RequestCallback callback_;
DISALLOW_COPY_AND_ASSIGN(SmbCredentialsDialog);
};
@@ -37,6 +55,10 @@ class SmbCredentialsDialogUI : public ui::WebDialogUI {
explicit SmbCredentialsDialogUI(content::WebUI* web_ui);
~SmbCredentialsDialogUI() override;
+ private:
+ void OnUpdateCredentials(const std::string& username,
+ const std::string& password);
+
DISALLOW_COPY_AND_ASSIGN(SmbCredentialsDialogUI);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog_browsertest.cc b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog_browsertest.cc
new file mode 100644
index 00000000000..cfe05b16511
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog_browsertest.cc
@@ -0,0 +1,104 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h"
+
+#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+
+namespace chromeos {
+namespace smb_dialog {
+
+const char kMountId[] = "mount-id";
+const char kSharePath[] = "//test/share";
+
+class SmbCredentialsDialogTest : public InProcessBrowserTest {};
+
+IN_PROC_BROWSER_TEST_F(SmbCredentialsDialogTest, CloseDialog) {
+ content::WebContentsAddedObserver observer;
+
+ base::RunLoop run_loop;
+ SmbCredentialsDialog::Show(
+ kMountId, kSharePath,
+ base::BindLambdaForTesting([&run_loop](bool canceled,
+ const std::string& username,
+ const std::string& password) {
+ EXPECT_TRUE(canceled);
+ run_loop.Quit();
+ }));
+
+ content::WebContents* dialog_contents = observer.GetWebContents();
+ ASSERT_TRUE(content::WaitForLoadStop(dialog_contents));
+ EXPECT_EQ(dialog_contents->GetLastCommittedURL().host(),
+ chrome::kChromeUISmbCredentialsHost);
+ ASSERT_TRUE(
+ content::ExecuteScript(dialog_contents, "chrome.send('dialogClose');"));
+
+ run_loop.Run();
+}
+
+IN_PROC_BROWSER_TEST_F(SmbCredentialsDialogTest, ShowSameMountId) {
+ content::WebContentsAddedObserver observer;
+
+ base::RunLoop run_loop;
+ SmbCredentialsDialog::Show(
+ kMountId, kSharePath,
+ // This callback is replaced in the next call to Show() below, and
+ // therefore will never be run.
+ base::BindOnce([](bool canceled, const std::string& username,
+ const std::string& password) { FAIL(); }));
+ SmbCredentialsDialog::Show(
+ kMountId, kSharePath,
+ base::BindLambdaForTesting([&run_loop](bool canceled,
+ const std::string& username,
+ const std::string& password) {
+ EXPECT_TRUE(canceled);
+ run_loop.Quit();
+ }));
+
+ content::WebContents* dialog_contents = observer.GetWebContents();
+ ASSERT_TRUE(content::WaitForLoadStop(dialog_contents));
+ EXPECT_EQ(dialog_contents->GetLastCommittedURL().host(),
+ chrome::kChromeUISmbCredentialsHost);
+ ASSERT_TRUE(
+ content::ExecuteScript(dialog_contents, "chrome.send('dialogClose');"));
+
+ run_loop.Run();
+}
+
+IN_PROC_BROWSER_TEST_F(SmbCredentialsDialogTest, SubmitCredentials) {
+ content::WebContentsAddedObserver observer;
+
+ base::RunLoop run_loop;
+ SmbCredentialsDialog::Show(
+ kMountId, kSharePath,
+ base::BindLambdaForTesting([&run_loop](bool canceled,
+ const std::string& username,
+ const std::string& password) {
+ EXPECT_FALSE(canceled);
+ EXPECT_EQ(username, "my-username");
+ EXPECT_EQ(password, "my-password");
+ run_loop.Quit();
+ }));
+
+ content::WebContents* dialog_contents = observer.GetWebContents();
+ ASSERT_TRUE(content::WaitForLoadStop(dialog_contents));
+ EXPECT_EQ(dialog_contents->GetLastCommittedURL().host(),
+ chrome::kChromeUISmbCredentialsHost);
+ ASSERT_TRUE(content::ExecuteScript(dialog_contents,
+ R"xxx(
+const dialog = document.querySelector('smb-credentials-dialog');
+dialog.username_ = 'my-username';
+dialog.password_ = 'my-password';
+dialog.$$('.action-button').click();
+ )xxx"));
+
+ run_loop.Run();
+}
+
+} // namespace smb_dialog
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.cc
index 575a2855593..43c2ad753c7 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.cc
@@ -34,7 +34,10 @@ base::Value BuildShareList(const std::vector<smb_client::SmbUrl>& shares) {
} // namespace
-SmbHandler::SmbHandler(Profile* profile) : profile_(profile) {}
+SmbHandler::SmbHandler(Profile* profile,
+ UpdateCredentialsCallback update_cred_callback)
+ : profile_(profile),
+ update_cred_callback_(std::move(update_cred_callback)) {}
SmbHandler::~SmbHandler() = default;
@@ -136,20 +139,16 @@ void SmbHandler::HandleGatherSharesResponse(
void SmbHandler::HandleUpdateCredentials(const base::ListValue* args) {
CHECK_EQ(3U, args->GetSize());
- int32_t mount_id;
+ std::string mount_id;
std::string username;
std::string password;
- CHECK(args->GetInteger(0, &mount_id));
+ CHECK(args->GetString(0, &mount_id));
CHECK(args->GetString(1, &username));
CHECK(args->GetString(2, &password));
- smb_client::SmbService* const service = GetSmbService(profile_);
- if (!service) {
- return;
- }
-
- service->UpdateCredentials(mount_id, username, password);
+ DCHECK(update_cred_callback_);
+ std::move(update_cred_callback_).Run(username, password);
}
} // namespace smb_dialog
diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h
index ef94923201b..e08f720e548 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h
@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_SMB_SHARES_SMB_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_SMB_SHARES_SMB_HANDLER_H_
+#include <string>
+
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -20,7 +22,11 @@ using smb_client::SmbMountResult;
class SmbHandler : public content::WebUIMessageHandler {
public:
- explicit SmbHandler(Profile* profile);
+ using UpdateCredentialsCallback =
+ base::OnceCallback<void(const std::string& username,
+ const std::string& password)>;
+
+ SmbHandler(Profile* profile, UpdateCredentialsCallback update_cred_callback);
~SmbHandler() override;
private:
@@ -51,6 +57,7 @@ class SmbHandler : public content::WebUIMessageHandler {
bool host_discovery_done_ = false;
base::OnceClosure stored_mount_call_;
Profile* const profile_;
+ UpdateCredentialsCallback update_cred_callback_;
base::WeakPtrFactory<SmbHandler> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SmbHandler);
diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.cc
index 5bbece77c06..2aa8bca9516 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.cc
@@ -5,6 +5,8 @@
#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/chromeos/smb_client/smb_service.h"
+#include "chrome/browser/chromeos/smb_client/smb_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h"
#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.h"
@@ -64,19 +66,30 @@ SmbShareDialogUI::SmbShareDialogUI(content::WebUI* web_ui)
AddSmbSharesStrings(source);
+ Profile* const profile = Profile::FromWebUI(web_ui);
const user_manager::User* user =
- chromeos::ProfileHelper::Get()->GetUserByProfile(
- Profile::FromWebUI(web_ui));
+ chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
+
source->AddBoolean("isActiveDirectoryUser",
user && user->IsActiveDirectoryUser());
+ // Check if Kerberos was and still is enabled via policy at the creation time
+ // of SmbService. As a result, if Kerberos policy was enabled during a user
+ // session, SSO option will not be available/visible.
+ // TODO(crbug.com/1040138): subscribe to pref. changes in SmbService and setup
+ // Kerberos after it is enabled during a user session.
+ const chromeos::smb_client::SmbService* const smb_service =
+ chromeos::smb_client::SmbServiceFactory::Get(profile);
+ bool is_kerberos_enabled =
+ smb_service && smb_service->IsKerberosEnabledViaPolicy();
+ source->AddBoolean("isKerberosEnabled", is_kerberos_enabled);
+
source->UseStringsJs();
source->SetDefaultResource(IDR_SMB_SHARES_DIALOG_CONTAINER_HTML);
- source->AddResourcePath("smb_share_dialog.html", IDR_SMB_SHARES_DIALOG_HTML);
source->AddResourcePath("smb_share_dialog.js", IDR_SMB_SHARES_DIALOG_JS);
- web_ui->AddMessageHandler(
- std::make_unique<SmbHandler>(Profile::FromWebUI(web_ui)));
+ web_ui->AddMessageHandler(std::make_unique<SmbHandler>(
+ Profile::FromWebUI(web_ui), base::DoNothing()));
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.cc
index cfa4d21c238..dc49d9b1f3f 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.cc
@@ -7,6 +7,7 @@
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/webui/web_ui_util.h"
namespace chromeos {
namespace smb_dialog {
@@ -39,6 +40,8 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source) {
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_UNSUPPORTED_DEVICE_MESSAGE},
{"smbShareAddedMountExistsMessage",
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE},
+ {"smbShareAddedTooManyMountsMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_TOO_MANY_MOUNTS_MESSAGE},
{"smbShareAddedInvalidURLMessage",
IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE},
{"smbShareAddedInvalidSSOURLMessage",
diff --git a/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.cc
index 61589b9f592..95451db1bb1 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.cc
@@ -4,11 +4,15 @@
#include "chrome/browser/ui/webui/chromeos/sync/os_sync_handler.h"
+#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/ui/webui/settings/chromeos/pref_names.h"
+#include "components/prefs/pref_service.h"
+#include "components/sync/base/pref_names.h"
#include "components/sync/base/user_selectable_type.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/driver/sync_user_settings.h"
@@ -19,12 +23,17 @@ using syncer::SyncUserSettings;
using syncer::UserSelectableOsType;
using syncer::UserSelectableOsTypeSet;
+namespace {
+const char kWallpaperEnabledKey[] = "wallpaperEnabled";
+} // namespace
+
OSSyncHandler::OSSyncHandler(Profile* profile) : profile_(profile) {
DCHECK(profile_);
}
OSSyncHandler::~OSSyncHandler() {
RemoveSyncServiceObserver();
+ CommitFeatureEnabledPref();
}
void OSSyncHandler::RegisterMessages() {
@@ -37,6 +46,10 @@ void OSSyncHandler::RegisterMessages() {
base::BindRepeating(&OSSyncHandler::HandleDidNavigateAwayFromOsSyncPage,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
+ "SetOsSyncFeatureEnabled",
+ base::BindRepeating(&OSSyncHandler::HandleSetOsSyncFeatureEnabled,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
"SetOsSyncDatatypes",
base::BindRepeating(&OSSyncHandler::HandleSetOsSyncDatatypes,
base::Unretained(this)));
@@ -51,26 +64,32 @@ void OSSyncHandler::OnJavascriptDisallowed() {
}
void OSSyncHandler::OnStateChanged(syncer::SyncService* service) {
- PushSyncPrefs();
+ if (!is_setting_prefs_)
+ PushSyncPrefs();
}
void OSSyncHandler::HandleDidNavigateToOsSyncPage(const base::ListValue* args) {
AllowJavascript();
+ // Cache the feature enabled pref.
SyncService* service = GetSyncService();
-
- if (service && !sync_blocker_)
- sync_blocker_ = service->GetSetupInProgressHandle();
-
- // TODO(jamescook): Sort out consent/opt-in story, then SetSyncRequested()
- // here.
+ if (service)
+ feature_enabled_ = service->GetUserSettings()->IsOsSyncFeatureEnabled();
PushSyncPrefs();
}
void OSSyncHandler::HandleDidNavigateAwayFromOsSyncPage(
const base::ListValue* args) {
- sync_blocker_.reset();
+ CommitFeatureEnabledPref();
+}
+
+void OSSyncHandler::HandleSetOsSyncFeatureEnabled(const base::ListValue* args) {
+ CHECK_EQ(1u, args->GetSize());
+ CHECK(args->GetBoolean(0, &feature_enabled_));
+ should_commit_feature_enabled_ = true;
+ // Changing the feature enabled state may change toggle state.
+ PushSyncPrefs();
}
void OSSyncHandler::HandleSetOsSyncDatatypes(const base::ListValue* args) {
@@ -78,15 +97,19 @@ void OSSyncHandler::HandleSetOsSyncDatatypes(const base::ListValue* args) {
const base::DictionaryValue* result;
CHECK(args->GetDictionary(0, &result));
+ // Wallpaper sync status is stored directly to the profile's prefs.
+ bool wallpaper_synced;
+ CHECK(result->GetBoolean(kWallpaperEnabledKey, &wallpaper_synced));
+ profile_->GetPrefs()->SetBoolean(chromeos::settings::prefs::kSyncOsWallpaper,
+ wallpaper_synced);
+
// Start configuring the SyncService using the configuration passed to us from
// the JS layer.
syncer::SyncService* service = GetSyncService();
// If the sync engine has shutdown for some reason, just stop.
- if (!service || !service->IsEngineInitialized()) {
- sync_blocker_.reset();
+ if (!service || !service->IsEngineInitialized())
return;
- }
bool sync_all_os_types;
CHECK(result->GetBoolean("syncAllOsTypes", &sync_all_os_types));
@@ -105,13 +128,10 @@ void OSSyncHandler::HandleSetOsSyncDatatypes(const base::ListValue* args) {
// toggles for in-development features hidden by feature flags.
SyncUserSettings* settings = service->GetUserSettings();
selected_types.RetainAll(settings->GetRegisteredSelectableOsTypes());
- settings->SetSelectedOsTypes(sync_all_os_types, selected_types);
- // Update the enabled state last so that the selected types will be set before
- // pref observers are notified of the change.
- bool feature_enabled;
- CHECK(result->GetBoolean("featureEnabled", &feature_enabled));
- settings->SetOsSyncFeatureEnabled(feature_enabled);
+ // Don't send updates back to JS while processing values sent from JS.
+ base::AutoReset<bool> reset(&is_setting_prefs_, true);
+ settings->SetSelectedOsTypes(sync_all_os_types, selected_types);
// TODO(jamescook): Add metrics for selected types.
}
@@ -120,6 +140,16 @@ void OSSyncHandler::SetWebUIForTest(content::WebUI* web_ui) {
set_web_ui(web_ui);
}
+void OSSyncHandler::CommitFeatureEnabledPref() {
+ if (!should_commit_feature_enabled_)
+ return;
+ SyncService* service = GetSyncService();
+ if (!service)
+ return;
+ service->GetUserSettings()->SetOsSyncFeatureEnabled(feature_enabled_);
+ should_commit_feature_enabled_ = false;
+}
+
void OSSyncHandler::PushSyncPrefs() {
syncer::SyncService* service = GetSyncService();
// The sync service may be nullptr if it has been just disabled by policy.
@@ -128,8 +158,8 @@ void OSSyncHandler::PushSyncPrefs() {
base::DictionaryValue args;
SyncUserSettings* user_settings = service->GetUserSettings();
- args.SetBoolean("featureEnabled", user_settings->GetOsSyncFeatureEnabled());
// Tell the UI layer which data types are registered/enabled by the user.
+ args.SetBoolean("syncAllOsTypes", user_settings->IsSyncAllOsTypesEnabled());
UserSelectableOsTypeSet registered_types =
user_settings->GetRegisteredSelectableOsTypes();
UserSelectableOsTypeSet selected_types = user_settings->GetSelectedOsTypes();
@@ -138,18 +168,24 @@ void OSSyncHandler::PushSyncPrefs() {
std::string type_name = syncer::GetUserSelectableOsTypeName(type);
args.SetBoolean(type_name + "Registered", registered_types.Has(type));
args.SetBoolean(type_name + "Synced", selected_types.Has(type));
- // TODO(crbug.com/1020236): Add SyncUserSettings::GetForcedOsTypes() if we
- // decide to support Apps sync for supervised users.
- args.SetBoolean(type_name + "Enforced", false);
}
- args.SetBoolean("syncAllOsTypes", user_settings->IsSyncAllOsTypesEnabled());
- FireWebUIListener("os-sync-prefs-changed", args);
+
+ // Wallpaper sync status is fetched from prefs and is considered enabled if
+ // all OS types are enabled; this mimics behavior of GetSelectedOsTypes().
+ args.SetBoolean(kWallpaperEnabledKey,
+ user_settings->IsSyncAllOsTypesEnabled() ||
+ profile_->GetPrefs()->GetBoolean(
+ chromeos::settings::prefs::kSyncOsWallpaper));
+
+ FireWebUIListener("os-sync-prefs-changed", base::Value(feature_enabled_),
+ args);
}
syncer::SyncService* OSSyncHandler::GetSyncService() const {
- return profile_->IsSyncAllowed()
- ? ProfileSyncServiceFactory::GetForProfile(profile_)
- : nullptr;
+ const bool is_sync_allowed =
+ ProfileSyncServiceFactory::IsSyncAllowed(profile_);
+ return is_sync_allowed ? ProfileSyncServiceFactory::GetForProfile(profile_)
+ : nullptr;
}
void OSSyncHandler::AddSyncServiceObserver() {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.h b/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.h
index 8b3cc377e75..73dd52b7d77 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.h
+++ b/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler.h
@@ -19,7 +19,6 @@ class ListValue;
namespace syncer {
class SyncService;
-class SyncSetupInProgressHandle;
} // namespace syncer
// WebUI handler for JS/C++ communication for Chrome OS settings sync controls
@@ -41,11 +40,15 @@ class OSSyncHandler : public content::WebUIMessageHandler,
// Callbacks from the page. Visible for testing.
void HandleDidNavigateToOsSyncPage(const base::ListValue* args);
void HandleDidNavigateAwayFromOsSyncPage(const base::ListValue* args);
+ void HandleSetOsSyncFeatureEnabled(const base::ListValue* args);
void HandleSetOsSyncDatatypes(const base::ListValue* args);
void SetWebUIForTest(content::WebUI* web_ui);
private:
+ // Sets the OS sync feature enabled pref if the user changed the setting.
+ void CommitFeatureEnabledPref();
+
// Pushes the updated sync prefs to JavaScript.
void PushSyncPrefs();
@@ -57,8 +60,15 @@ class OSSyncHandler : public content::WebUIMessageHandler,
Profile* const profile_;
- // Prevents Sync from running until configuration is complete.
- std::unique_ptr<syncer::SyncSetupInProgressHandle> sync_blocker_;
+ // Cached copy of the OS sync feature enabled pref. Used to avoid turning on
+ // OS sync before the user is done configuring the toggles.
+ bool feature_enabled_ = false;
+
+ // Whether to commit the feature enabled state when the user closes the UI.
+ bool should_commit_feature_enabled_ = false;
+
+ // Prevents messages to JS layer while data type prefs are being set.
+ bool is_setting_prefs_ = false;
DISALLOW_COPY_AND_ASSIGN(OSSyncHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler_unittest.cc b/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler_unittest.cc
index 357103a604d..480e2165b9f 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/sync/os_sync_handler_unittest.cc
@@ -11,26 +11,24 @@
#include "base/values.h"
#include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/ui/webui/settings/chromeos/pref_names.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/test_chrome_web_ui_controller_factory.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
+#include "components/sync/base/pref_names.h"
#include "components/sync/base/user_selectable_type.h"
-#include "components/sync/driver/mock_sync_service.h"
-#include "components/sync/driver/sync_user_settings_mock.h"
+#include "components/sync/driver/test_sync_service.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/test/test_web_ui.h"
-#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::DictionaryValue;
+using content::TestWebUI;
+using syncer::SyncService;
using syncer::UserSelectableOsType;
using syncer::UserSelectableOsTypeSet;
using syncer::UserSelectableTypeSet;
-using ::testing::_;
-using ::testing::ByMove;
-using ::testing::Mock;
-using ::testing::Return;
namespace content {
class BrowserContext;
@@ -38,25 +36,23 @@ class BrowserContext;
namespace {
-enum FeatureConfig { FEATURE_ENABLED, FEATURE_DISABLED };
enum SyncAllConfig { SYNC_ALL_OS_TYPES, CHOOSE_WHAT_TO_SYNC };
// Creates a dictionary with the key/value pairs appropriate for a call to
// HandleSetOsSyncDatatypes().
-DictionaryValue CreateOsSyncPrefs(FeatureConfig feature,
- SyncAllConfig sync_all,
- UserSelectableOsTypeSet types) {
+DictionaryValue CreateOsSyncPrefs(SyncAllConfig sync_all,
+ UserSelectableOsTypeSet types,
+ bool wallpaper_enabled) {
DictionaryValue result;
- result.SetBoolean("featureEnabled", feature == FEATURE_ENABLED);
result.SetBoolean("syncAllOsTypes", sync_all == SYNC_ALL_OS_TYPES);
// Add all of our data types.
result.SetBoolean("osAppsSynced", types.Has(UserSelectableOsType::kOsApps));
result.SetBoolean("osPreferencesSynced",
types.Has(UserSelectableOsType::kOsPreferences));
- result.SetBoolean("printersSynced",
- types.Has(UserSelectableOsType::kPrinters));
result.SetBoolean("wifiConfigurationsSynced",
types.Has(UserSelectableOsType::kWifiConfigurations));
+ result.SetBoolean("wallpaperEnabled",
+ sync_all == SYNC_ALL_OS_TYPES || wallpaper_enabled);
return result;
}
@@ -75,21 +71,22 @@ void CheckBool(const DictionaryValue* dictionary,
// expected by the JS layer.
void CheckConfigDataTypeArguments(const DictionaryValue* dictionary,
SyncAllConfig config,
- UserSelectableOsTypeSet types) {
+ UserSelectableOsTypeSet types,
+ bool wallpaper_enabled) {
CheckBool(dictionary, "syncAllOsTypes", config == SYNC_ALL_OS_TYPES);
CheckBool(dictionary, "osAppsSynced",
types.Has(UserSelectableOsType::kOsApps));
CheckBool(dictionary, "osPreferencesSynced",
types.Has(UserSelectableOsType::kOsPreferences));
- CheckBool(dictionary, "printersSynced",
- types.Has(UserSelectableOsType::kPrinters));
CheckBool(dictionary, "wifiConfigurationsSynced",
types.Has(UserSelectableOsType::kWifiConfigurations));
+ CheckBool(dictionary, "wallpaperEnabled",
+ config == SYNC_ALL_OS_TYPES || wallpaper_enabled);
}
-std::unique_ptr<KeyedService> BuildMockSyncService(
+std::unique_ptr<KeyedService> BuildTestSyncService(
content::BrowserContext* context) {
- return std::make_unique<testing::NiceMock<syncer::MockSyncService>>();
+ return std::make_unique<syncer::TestSyncService>();
}
class TestWebUIProvider
@@ -102,7 +99,7 @@ class TestWebUIProvider
};
class OsSyncHandlerTest : public ChromeRenderViewHostTestHarness {
- public:
+ protected:
OsSyncHandlerTest() = default;
~OsSyncHandlerTest() override = default;
@@ -115,34 +112,10 @@ class OsSyncHandlerTest : public ChromeRenderViewHostTestHarness {
identity_test_env_adaptor_->identity_test_env()->SetPrimaryAccount(
"test@gmail.com");
- mock_sync_service_ = static_cast<syncer::MockSyncService*>(
+ sync_service_ = static_cast<syncer::TestSyncService*>(
ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
- profile(), base::BindRepeating(&BuildMockSyncService)));
-
- // Configure the sync service as enabled and syncing.
- ON_CALL(*mock_sync_service_, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
- ON_CALL(*mock_sync_service_, GetTransportState())
- .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE));
- ON_CALL(*mock_sync_service_, IsAuthenticatedAccountPrimary())
- .WillByDefault(Return(true));
- ON_CALL(*mock_sync_service_, GetSetupInProgressHandle())
- .WillByDefault(
- Return(ByMove(std::make_unique<syncer::SyncSetupInProgressHandle>(
- base::BindRepeating(
- &OsSyncHandlerTest::OnSetupInProgressHandleDestroyed,
- base::Unretained(this))))));
-
- // Configure user settings with the sync feature on and all types enabled.
- user_settings_ = mock_sync_service_->GetMockUserSettings();
- ON_CALL(*user_settings_, GetOsSyncFeatureEnabled())
- .WillByDefault(Return(true));
- ON_CALL(*user_settings_, IsSyncAllOsTypesEnabled())
- .WillByDefault(Return(true));
- ON_CALL(*user_settings_, GetSelectedOsTypes())
- .WillByDefault(Return(UserSelectableOsTypeSet::All()));
- ON_CALL(*user_settings_, GetRegisteredSelectableOsTypes())
- .WillByDefault(Return(UserSelectableOsTypeSet::All()));
+ profile(), base::BindRepeating(&BuildTestSyncService)));
+ user_settings_ = sync_service_->GetUserSettings();
handler_ = std::make_unique<OSSyncHandler>(profile());
handler_->SetWebUIForTest(&web_ui_);
@@ -160,60 +133,70 @@ class OsSyncHandlerTest : public ChromeRenderViewHostTestHarness {
GetIdentityTestEnvironmentFactories();
}
- void OnSetupInProgressHandleDestroyed() {
- in_progress_handle_destroyed_count_++;
- }
-
// Expects that an "os-sync-prefs-changed" event was sent to the WebUI and
// returns the data passed to that event.
- const DictionaryValue* ExpectOsSyncPrefsSent() {
- const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
+ void ExpectOsSyncPrefsSent(bool* feature_enabled,
+ const DictionaryValue** os_sync_prefs) {
+ const TestWebUI::CallData& call_data = *web_ui_.call_data().back();
EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
std::string event;
EXPECT_TRUE(call_data.arg1()->GetAsString(&event));
EXPECT_EQ(event, "os-sync-prefs-changed");
- const DictionaryValue* dictionary = nullptr;
- EXPECT_TRUE(call_data.arg2()->GetAsDictionary(&dictionary));
- return dictionary;
+ EXPECT_TRUE(call_data.arg2()->GetAsBoolean(feature_enabled));
+ EXPECT_TRUE(call_data.arg3()->GetAsDictionary(os_sync_prefs));
}
- void NotifySyncStateChanged() {
- handler_->OnStateChanged(mock_sync_service_);
+ void NotifySyncStateChanged() { handler_->OnStateChanged(sync_service_); }
+
+ bool GetWallperEnabledPref() {
+ return profile()->GetPrefs()->GetBoolean(
+ chromeos::settings::prefs::kSyncOsWallpaper);
}
- syncer::SyncUserSettingsMock* user_settings_ = nullptr;
- syncer::MockSyncService* mock_sync_service_ = nullptr;
+ void SetWallperEnabledPref(bool enabled) {
+ return profile()->GetPrefs()->SetBoolean(
+ chromeos::settings::prefs::kSyncOsWallpaper, enabled);
+ }
+
+ syncer::TestSyncService* sync_service_ = nullptr;
+ syncer::SyncUserSettings* user_settings_ = nullptr;
std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
identity_test_env_adaptor_;
- content::TestWebUI web_ui_;
+ TestWebUI web_ui_;
TestWebUIProvider test_web_ui_provider_;
std::unique_ptr<TestChromeWebUIControllerFactory> test_web_ui_factory_;
std::unique_ptr<OSSyncHandler> handler_;
-
- int in_progress_handle_destroyed_count_ = 0;
};
TEST_F(OsSyncHandlerTest, OsSyncPrefsSentOnNavigateToPage) {
+ user_settings_->SetOsSyncFeatureEnabled(true);
handler_->HandleDidNavigateToOsSyncPage(nullptr);
+
ASSERT_EQ(1U, web_ui_.call_data().size());
- ExpectOsSyncPrefsSent();
+ const TestWebUI::CallData& call_data = *web_ui_.call_data().back();
+
+ std::string event_name = call_data.arg1()->GetString();
+ EXPECT_EQ(event_name, "os-sync-prefs-changed");
+
+ bool feature_enabled = call_data.arg2()->GetBool();
+ EXPECT_TRUE(feature_enabled);
}
TEST_F(OsSyncHandlerTest, OsSyncPrefsWhenFeatureIsDisabled) {
- ON_CALL(*user_settings_, GetOsSyncFeatureEnabled())
- .WillByDefault(Return(false));
+ user_settings_->SetOsSyncFeatureEnabled(false);
handler_->HandleDidNavigateToOsSyncPage(nullptr);
- const DictionaryValue* os_sync_prefs = ExpectOsSyncPrefsSent();
- CheckBool(os_sync_prefs, "featureEnabled", false);
+
+ ASSERT_EQ(1U, web_ui_.call_data().size());
+ const TestWebUI::CallData& call_data = *web_ui_.call_data().back();
+ bool feature_enabled = call_data.arg2()->GetBool();
+ EXPECT_FALSE(feature_enabled);
}
TEST_F(OsSyncHandlerTest, OpenConfigPageBeforeSyncEngineInitialized) {
// Sync engine is stopped initially and will start up later.
- ON_CALL(*mock_sync_service_, GetTransportState())
- .WillByDefault(
- Return(syncer::SyncService::TransportState::START_DEFERRED));
+ sync_service_->SetTransportState(SyncService::TransportState::START_DEFERRED);
// Navigate to the page.
handler_->HandleDidNavigateToOsSyncPage(nullptr);
@@ -222,45 +205,65 @@ TEST_F(OsSyncHandlerTest, OpenConfigPageBeforeSyncEngineInitialized) {
EXPECT_EQ(0U, web_ui_.call_data().size());
// Now, act as if the SyncService has started up.
- ON_CALL(*mock_sync_service_, GetTransportState())
- .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE));
+ sync_service_->SetTransportState(SyncService::TransportState::ACTIVE);
NotifySyncStateChanged();
// Update for sync prefs is sent.
- EXPECT_EQ(1U, web_ui_.call_data().size());
- ExpectOsSyncPrefsSent();
-}
+ ASSERT_EQ(1U, web_ui_.call_data().size());
+ const TestWebUI::CallData& call_data = *web_ui_.call_data().back();
-TEST_F(OsSyncHandlerTest, NavigateAwayDestroysInProgressHandle) {
- handler_->HandleDidNavigateToOsSyncPage(nullptr);
- handler_->HandleDidNavigateAwayFromOsSyncPage(nullptr);
- EXPECT_EQ(1, in_progress_handle_destroyed_count_);
+ std::string event_name = call_data.arg1()->GetString();
+ EXPECT_EQ(event_name, "os-sync-prefs-changed");
}
-// Tests that signals not related to user intention to configure sync don't
-// trigger sync engine start.
+// Tests that transport state signals not related to user intention to
+// configure sync don't trigger sync engine start.
TEST_F(OsSyncHandlerTest, OnlyStartEngineWhenConfiguringSync) {
- ON_CALL(*mock_sync_service_, GetTransportState())
- .WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING));
- EXPECT_CALL(*user_settings_, SetSyncRequested(true)).Times(0);
+ user_settings_->SetSyncRequested(false);
+ sync_service_->SetTransportState(SyncService::TransportState::INITIALIZING);
NotifySyncStateChanged();
+ EXPECT_FALSE(user_settings_->IsSyncRequested());
}
-TEST_F(OsSyncHandlerTest, UserDisablesFeature) {
- base::ListValue list_args;
- list_args.Append(CreateOsSyncPrefs(FEATURE_DISABLED, SYNC_ALL_OS_TYPES,
- UserSelectableOsTypeSet::All()));
- EXPECT_CALL(*user_settings_, SetOsSyncFeatureEnabled(false));
- handler_->HandleSetOsSyncDatatypes(&list_args);
+TEST_F(OsSyncHandlerTest, UserEnablesFeatureThenNavigatesAway) {
+ // Open the page with the feature disabled.
+ user_settings_->SetOsSyncFeatureEnabled(false);
+ handler_->HandleDidNavigateToOsSyncPage(nullptr);
+
+ // Clicking "Turn on" doesn't set the pref yet.
+ base::ListValue args;
+ args.Append(base::Value(true)); // feature_enabled
+ handler_->HandleSetOsSyncFeatureEnabled(&args);
+ EXPECT_FALSE(user_settings_->IsOsSyncFeatureEnabled());
+
+ // The pref is set when the user navigates away.
+ handler_->HandleDidNavigateAwayFromOsSyncPage(nullptr);
+ EXPECT_TRUE(user_settings_->IsOsSyncFeatureEnabled());
+}
+
+TEST_F(OsSyncHandlerTest, UserEnablesFeatureThenClosesSettings) {
+ // Open the page with the feature disabled.
+ user_settings_->SetOsSyncFeatureEnabled(false);
+ handler_->HandleDidNavigateToOsSyncPage(nullptr);
+
+ // Clicking "Turn on" doesn't set the pref yet.
+ base::ListValue args;
+ args.Append(base::Value(true)); // feature_enabled
+ handler_->HandleSetOsSyncFeatureEnabled(&args);
+ EXPECT_FALSE(user_settings_->IsOsSyncFeatureEnabled());
+
+ // The pref is set when the settings window closes and destroys the handler.
+ handler_.reset();
+ EXPECT_TRUE(user_settings_->IsOsSyncFeatureEnabled());
}
TEST_F(OsSyncHandlerTest, TestSyncEverything) {
base::ListValue list_args;
- list_args.Append(CreateOsSyncPrefs(FEATURE_ENABLED, SYNC_ALL_OS_TYPES,
- UserSelectableOsTypeSet::All()));
- EXPECT_CALL(*user_settings_,
- SetSelectedOsTypes(/*sync_all_os_types=*/true, _));
+ list_args.Append(CreateOsSyncPrefs(SYNC_ALL_OS_TYPES,
+ UserSelectableOsTypeSet::All(),
+ /*wallpaper_enabled=*/true));
handler_->HandleSetOsSyncDatatypes(&list_args);
+ EXPECT_TRUE(user_settings_->IsSyncAllOsTypesEnabled());
}
// Walks through each user selectable type, and tries to sync just that single
@@ -269,59 +272,93 @@ TEST_F(OsSyncHandlerTest, TestSyncIndividualTypes) {
for (UserSelectableOsType type : UserSelectableOsTypeSet::All()) {
UserSelectableOsTypeSet types = {type};
base::ListValue list_args;
- list_args.Append(
- CreateOsSyncPrefs(FEATURE_ENABLED, CHOOSE_WHAT_TO_SYNC, types));
- EXPECT_CALL(*user_settings_, SetSelectedOsTypes(false, types));
+ list_args.Append(CreateOsSyncPrefs(CHOOSE_WHAT_TO_SYNC, types,
+ /*wallpaper_enabled=*/false));
handler_->HandleSetOsSyncDatatypes(&list_args);
- Mock::VerifyAndClearExpectations(mock_sync_service_);
+ EXPECT_FALSE(user_settings_->IsSyncAllOsTypesEnabled());
+ EXPECT_EQ(types, user_settings_->GetSelectedOsTypes());
}
+
+ // Special case for wallpaper.
+ base::ListValue list_args;
+ list_args.Append(CreateOsSyncPrefs(CHOOSE_WHAT_TO_SYNC, /*types=*/{},
+ /*wallpaper_enabled=*/true));
+ handler_->HandleSetOsSyncDatatypes(&list_args);
+ EXPECT_FALSE(user_settings_->IsSyncAllOsTypesEnabled());
+ EXPECT_TRUE(GetWallperEnabledPref());
}
TEST_F(OsSyncHandlerTest, TestSyncAllManually) {
base::ListValue list_args;
- list_args.Append(CreateOsSyncPrefs(FEATURE_ENABLED, CHOOSE_WHAT_TO_SYNC,
- UserSelectableOsTypeSet::All()));
- EXPECT_CALL(*user_settings_,
- SetSelectedOsTypes(false, UserSelectableOsTypeSet::All()));
+ list_args.Append(CreateOsSyncPrefs(CHOOSE_WHAT_TO_SYNC,
+ UserSelectableOsTypeSet::All(),
+ /*wallpaper_enabled=*/true));
handler_->HandleSetOsSyncDatatypes(&list_args);
+ EXPECT_FALSE(user_settings_->IsSyncAllOsTypesEnabled());
+ EXPECT_EQ(UserSelectableOsTypeSet::All(),
+ user_settings_->GetSelectedOsTypes());
+ EXPECT_TRUE(GetWallperEnabledPref());
}
TEST_F(OsSyncHandlerTest, ShowSetupSyncEverything) {
+ user_settings_->SetSelectedOsTypes(/*sync_all_os_types=*/true,
+ UserSelectableOsTypeSet::All());
+ SetWallperEnabledPref(true);
handler_->HandleDidNavigateToOsSyncPage(nullptr);
- const DictionaryValue* dictionary = ExpectOsSyncPrefsSent();
+ bool feature_enabled;
+ const DictionaryValue* dictionary;
+ ExpectOsSyncPrefsSent(&feature_enabled, &dictionary);
+ EXPECT_TRUE(feature_enabled);
CheckBool(dictionary, "syncAllOsTypes", true);
+ CheckBool(dictionary, "osAppsRegistered", true);
CheckBool(dictionary, "osPreferencesRegistered", true);
- CheckBool(dictionary, "printersRegistered", true);
CheckBool(dictionary, "wifiConfigurationsRegistered", true);
CheckConfigDataTypeArguments(dictionary, SYNC_ALL_OS_TYPES,
- UserSelectableOsTypeSet::All());
+ UserSelectableOsTypeSet::All(),
+ /*wallpaper_enabled=*/true);
}
TEST_F(OsSyncHandlerTest, ShowSetupManuallySyncAll) {
- ON_CALL(*user_settings_, IsSyncAllOsTypesEnabled())
- .WillByDefault(Return(false));
+ user_settings_->SetSelectedOsTypes(/*sync_all_os_types=*/false,
+ UserSelectableOsTypeSet::All());
+ SetWallperEnabledPref(true);
handler_->HandleDidNavigateToOsSyncPage(nullptr);
- const DictionaryValue* dictionary = ExpectOsSyncPrefsSent();
+ bool feature_enabled;
+ const DictionaryValue* dictionary;
+ ExpectOsSyncPrefsSent(&feature_enabled, &dictionary);
+ EXPECT_TRUE(feature_enabled);
CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC,
- UserSelectableOsTypeSet::All());
+ UserSelectableOsTypeSet::All(),
+ /*wallpaper_enabled=*/true);
}
TEST_F(OsSyncHandlerTest, ShowSetupSyncForAllTypesIndividually) {
for (UserSelectableOsType type : UserSelectableOsTypeSet::All()) {
- ON_CALL(*user_settings_, IsSyncAllOsTypesEnabled())
- .WillByDefault(Return(false));
UserSelectableOsTypeSet types(type);
- ON_CALL(*user_settings_, GetSelectedOsTypes()).WillByDefault(Return(types));
-
+ user_settings_->SetSelectedOsTypes(/*sync_all_os_types=*/false, types);
handler_->HandleDidNavigateToOsSyncPage(nullptr);
- const DictionaryValue* dictionary = ExpectOsSyncPrefsSent();
- CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, types);
- Mock::VerifyAndClearExpectations(mock_sync_service_);
+ bool feature_enabled;
+ const DictionaryValue* dictionary;
+ ExpectOsSyncPrefsSent(&feature_enabled, &dictionary);
+ EXPECT_TRUE(feature_enabled);
+ CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, types,
+ /*wallpaper_enabled=*/false);
}
+
+ // Special case for wallpaper.
+ user_settings_->SetSelectedOsTypes(/*sync_all_os_types=*/false, /*types=*/{});
+ SetWallperEnabledPref(true);
+ handler_->HandleDidNavigateToOsSyncPage(nullptr);
+ bool feature_enabled;
+ const DictionaryValue* dictionary;
+ ExpectOsSyncPrefsSent(&feature_enabled, &dictionary);
+ EXPECT_TRUE(feature_enabled);
+ CheckConfigDataTypeArguments(dictionary, CHOOSE_WHAT_TO_SYNC, /*types=*/{},
+ /*wallpaper_enabled=*/true);
}
} // namespace
diff --git a/chromium/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc
index f3f9c540083..fb2ddecaf69 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/sys_internals/sys_internals_message_handler.cc
@@ -17,6 +17,7 @@
#include "base/logging.h"
#include "base/process/process_metrics.h"
#include "base/system/sys_info.h"
+#include "base/task/thread_pool.h"
#include "content/public/browser/browser_thread.h"
namespace {
@@ -221,9 +222,8 @@ void SysInternalsMessageHandler::HandleGetSysInfo(const base::ListValue* args) {
}
base::Value callback_id = list[0].Clone();
- base::PostTaskAndReplyWithResult(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
- base::BindOnce(&GetSysInfo),
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()}, base::BindOnce(&GetSysInfo),
base::BindOnce(&SysInternalsMessageHandler::ReplySysInfo,
weak_ptr_factory_.GetWeakPtr(), std::move(callback_id)));
}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc b/chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc
index c23cac4ef3a..e90675f52de 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_browsertest.cc
@@ -18,6 +18,7 @@
#include "components/account_id/account_id.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_ui.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/common/web_preferences.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -99,17 +100,7 @@ IN_PROC_BROWSER_TEST_F(SystemWebDialogTest, InstanceTest) {
// https://crbug.com/855344.
}
-class SystemWebDialogTestWithSplitSettings : public SystemWebDialogTest {
- public:
- SystemWebDialogTestWithSplitSettings() {
- feature_list_.InitAndEnableFeature(chromeos::features::kSplitSettings);
- }
-
- private:
- base::test::ScopedFeatureList feature_list_;
-};
-
-IN_PROC_BROWSER_TEST_F(SystemWebDialogTestWithSplitSettings, FontSize) {
+IN_PROC_BROWSER_TEST_F(SystemWebDialogTest, FontSize) {
const content::WebPreferences kDefaultPrefs;
const int kDefaultFontSize = kDefaultPrefs.default_font_size;
const int kDefaultFixedFontSize = kDefaultPrefs.default_fixed_font_size;
@@ -134,7 +125,7 @@ IN_PROC_BROWSER_TEST_F(SystemWebDialogTestWithSplitSettings, FontSize) {
EXPECT_EQ(kDefaultFixedFontSize, dialog_prefs.default_fixed_font_size);
}
-IN_PROC_BROWSER_TEST_F(SystemWebDialogTestWithSplitSettings, PageZoom) {
+IN_PROC_BROWSER_TEST_F(SystemWebDialogTest, PageZoom) {
// Set the default browser page zoom to 150%.
double level = blink::PageZoomFactorToZoomLevel(1.5);
browser()->profile()->GetZoomLevelPrefs()->SetDefaultZoomLevelPref(level);
diff --git a/chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc b/chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc
index 3691bb400b0..69d0ad4f5e9 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.cc
@@ -12,7 +12,6 @@
#include "base/stl_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/views/chrome_web_dialog_view.h"
-#include "chromeos/constants/chromeos_features.h"
#include "components/session_manager/core/session_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/host_zoom_map.h"
@@ -173,17 +172,15 @@ std::string SystemWebDialogDelegate::GetDialogArgs() const {
void SystemWebDialogDelegate::OnDialogShown(content::WebUI* webui) {
webui_ = webui;
- if (features::IsSplitSettingsEnabled()) {
- // System dialogs don't use the browser's default page zoom. Their contents
- // stay at 100% to match the size of app list, shelf, status area, etc.
- auto* web_contents = webui_->GetWebContents();
- auto* rvh = web_contents->GetRenderViewHost();
- auto* zoom_map = content::HostZoomMap::GetForWebContents(web_contents);
- // Temporary means the lifetime of the WebContents.
- zoom_map->SetTemporaryZoomLevel(rvh->GetProcess()->GetID(),
- rvh->GetRoutingID(),
- blink::PageZoomFactorToZoomLevel(1.0));
- }
+ // System dialogs don't use the browser's default page zoom. Their contents
+ // stay at 100% to match the size of app list, shelf, status area, etc.
+ auto* web_contents = webui_->GetWebContents();
+ auto* rvh = web_contents->GetRenderViewHost();
+ auto* zoom_map = content::HostZoomMap::GetForWebContents(web_contents);
+ // Temporary means the lifetime of the WebContents.
+ zoom_map->SetTemporaryZoomLevel(rvh->GetProcess()->GetID(),
+ rvh->GetRoutingID(),
+ blink::PageZoomFactorToZoomLevel(1.0));
}
void SystemWebDialogDelegate::OnDialogClosed(const std::string& json_retval) {
diff --git a/chromium/chrome/browser/ui/webui/chromeos/terminal/OWNERS b/chromium/chrome/browser/ui/webui/chromeos/terminal/OWNERS
deleted file mode 100644
index 7cec5666d6e..00000000000
--- a/chromium/chrome/browser/ui/webui/chromeos/terminal/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-calamity@chromium.org
-joelhockey@chromium.org
-
-# COMPONENT: UI>Shell>Containers
diff --git a/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_source.cc b/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_source.cc
deleted file mode 100644
index a89867c8901..00000000000
--- a/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_source.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/chromeos/terminal/terminal_source.h"
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/memory/ref_counted_memory.h"
-#include "base/strings/string_util.h"
-#include "base/task/post_task.h"
-#include "base/task/task_traits.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/common/webui_url_constants.h"
-#include "net/base/mime_util.h"
-#include "third_party/zlib/google/compression_utils.h"
-
-namespace {
-// TODO(crbug.com/846546): Initially set to load crosh, but change to
-// terminal when it is available.
-constexpr base::FilePath::CharType kTerminalRoot[] =
- FILE_PATH_LITERAL("/usr/share/chromeos-assets/crosh_builtin");
-constexpr base::FilePath::CharType kDefaultFile[] =
- FILE_PATH_LITERAL("html/crosh.html");
-constexpr char kDefaultMime[] = "text/html";
-
-void ReadFile(const base::FilePath& path,
- content::URLDataSource::GotDataCallback callback) {
- std::string content;
- // First look for uncompressed resource, then try for gzipped file.
- bool result = base::ReadFileToString(path, &content);
- if (!result) {
- result =
- base::ReadFileToString(base::FilePath(path.value() + ".gz"), &content);
- std::string uncompressed;
- result = compression::GzipUncompress(content, &uncompressed);
- content = std::move(uncompressed);
- }
- // Allow missing files in <root>/_locales only.
- DCHECK(result || base::FilePath(kTerminalRoot)
- .Append("_locales")
- .AppendRelativePath(path, nullptr))
- << path;
- scoped_refptr<base::RefCountedString> response =
- base::RefCountedString::TakeString(&content);
- std::move(callback).Run(response.get());
-}
-} // namespace
-
-std::string TerminalSource::GetSource() {
- return chrome::kChromeUITerminalHost;
-}
-
-#if !BUILDFLAG(OPTIMIZE_WEBUI)
-bool TerminalSource::AllowCaching() {
- return false;
-}
-#endif
-
-void TerminalSource::StartDataRequest(
- const GURL& url,
- const content::WebContents::Getter& wc_getter,
- content::URLDataSource::GotDataCallback callback) {
- // TODO(crbug/1009127): Simplify usages of |path| since |url| is available.
- const std::string path = content::URLDataSource::URLToRequestPath(url);
- // Reparse path to strip any query or fragment, skip first '/' in path.
- std::string reparsed =
- GURL(chrome::kChromeUITerminalURL + path).path().substr(1);
- if (reparsed.empty())
- reparsed = kDefaultFile;
- base::FilePath file_path = base::FilePath(kTerminalRoot).Append(reparsed);
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
- base::BindOnce(&ReadFile, file_path, std::move(callback)));
-}
-
-std::string TerminalSource::GetMimeType(const std::string& path) {
- std::string mime_type(kDefaultMime);
- std::string ext = base::FilePath(path).Extension();
- if (!ext.empty())
- net::GetWellKnownMimeTypeFromExtension(ext.substr(1), &mime_type);
- return mime_type;
-}
-
-bool TerminalSource::ShouldServeMimeTypeAsContentTypeHeader() {
- // TerminalSource pages include js modules which require an explicit MimeType.
- return true;
-}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_source.h b/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_source.h
deleted file mode 100644
index 119ca1bd5ba..00000000000
--- a/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_source.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_TERMINAL_TERMINAL_SOURCE_H_
-#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_TERMINAL_TERMINAL_SOURCE_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "build/buildflag.h"
-#include "chrome/common/buildflags.h"
-#include "content/public/browser/url_data_source.h"
-#include "content/public/browser/web_contents.h"
-
-class TerminalSource : public content::URLDataSource {
- public:
- TerminalSource() = default;
- ~TerminalSource() override = default;
-
- private:
- std::string GetSource() override;
-#if !BUILDFLAG(OPTIMIZE_WEBUI)
- bool AllowCaching() override;
-#endif
-
- void StartDataRequest(
- const GURL& url,
- const content::WebContents::Getter& wc_getter,
- content::URLDataSource::GotDataCallback callback) override;
-
- std::string GetMimeType(const std::string& path) override;
-
- bool ShouldServeMimeTypeAsContentTypeHeader() override;
-
- DISALLOW_COPY_AND_ASSIGN(TerminalSource);
-};
-
-#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_TERMINAL_TERMINAL_SOURCE_H_
diff --git a/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_ui.cc
deleted file mode 100644
index 012f4a98466..00000000000
--- a/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_ui.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/chromeos/terminal/terminal_ui.h"
-
-#include <memory>
-
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/chromeos/terminal/terminal_source.h"
-#include "content/public/browser/url_data_source.h"
-
-TerminalUI::TerminalUI(content::WebUI* web_ui) : WebUIController(web_ui) {
- Profile* profile = Profile::FromWebUI(web_ui);
- content::URLDataSource::Add(profile, std::make_unique<TerminalSource>());
-}
diff --git a/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_ui.h b/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_ui.h
deleted file mode 100644
index d87b3f313e3..00000000000
--- a/chromium/chrome/browser/ui/webui/chromeos/terminal/terminal_ui.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_TERMINAL_TERMINAL_UI_H_
-#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_TERMINAL_TERMINAL_UI_H_
-
-#include "base/macros.h"
-#include "content/public/browser/web_ui_controller.h"
-
-class TerminalUI : public content::WebUIController {
- public:
- explicit TerminalUI(content::WebUI* web_ui);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TerminalUI);
-};
-
-#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_TERMINAL_TERMINAL_UI_H_
diff --git a/chromium/chrome/browser/ui/webui/chromeos/video_source.cc b/chromium/chrome/browser/ui/webui/chromeos/video_source.cc
index f3b5379aa2b..91b6ec01f2c 100644
--- a/chromium/chrome/browser/ui/webui/chromeos/video_source.cc
+++ b/chromium/chrome/browser/ui/webui/chromeos/video_source.cc
@@ -14,6 +14,7 @@
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -55,8 +56,8 @@ void VideoLoaded(content::URLDataSource::GotDataCallback got_data_callback,
} // namespace
VideoSource::VideoSource() {
- task_runner_ = base::CreateSequencedTaskRunner(
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE,
+ task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN});
}
@@ -78,9 +79,8 @@ void VideoSource::StartDataRequest(
const base::FilePath asset_dir(chrome::kChromeOSAssetPath);
const base::FilePath video_path = asset_dir.AppendASCII(path);
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&base::PathExists, video_path),
base::BindOnce(&VideoSource::StartDataRequestAfterPathExists,
weak_factory_.GetWeakPtr(), video_path,
diff --git a/chromium/chrome/browser/ui/webui/components/components_handler.cc b/chromium/chrome/browser/ui/webui/components/components_handler.cc
new file mode 100644
index 00000000000..1f1381b255f
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/components/components_handler.cc
@@ -0,0 +1,166 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/components/components_handler.h"
+
+#include "base/bind.h"
+#include "base/values.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/update_client/crx_update_item.h"
+#include "ui/base/l10n/l10n_util.h"
+
+ComponentsHandler::ComponentsHandler(
+ component_updater::ComponentUpdateService* component_updater)
+ : component_updater_(component_updater) {
+ DCHECK(component_updater_);
+}
+ComponentsHandler::~ComponentsHandler() = default;
+
+void ComponentsHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "requestComponentsData",
+ base::BindRepeating(&ComponentsHandler::HandleRequestComponentsData,
+ base::Unretained(this)));
+
+ web_ui()->RegisterMessageCallback(
+ "checkUpdate", base::BindRepeating(&ComponentsHandler::HandleCheckUpdate,
+ base::Unretained(this)));
+}
+
+void ComponentsHandler::OnJavascriptAllowed() {
+ observer_.Add(component_updater_);
+}
+
+void ComponentsHandler::OnJavascriptDisallowed() {
+ observer_.RemoveAll();
+}
+
+void ComponentsHandler::HandleRequestComponentsData(
+ const base::ListValue* args) {
+ AllowJavascript();
+ const base::Value& callback_id = args->GetList()[0];
+
+ base::DictionaryValue result;
+ result.Set("components", LoadComponents());
+ ResolveJavascriptCallback(callback_id, result);
+}
+
+// This function is called when user presses button from html UI.
+// TODO(shrikant): We need to make this button available based on current
+// state e.g. If component state is currently updating then we need to disable
+// button. (https://code.google.com/p/chromium/issues/detail?id=272540)
+void ComponentsHandler::HandleCheckUpdate(const base::ListValue* args) {
+ if (args->GetSize() != 1) {
+ NOTREACHED();
+ return;
+ }
+
+ std::string component_id;
+ if (!args->GetString(0, &component_id)) {
+ NOTREACHED();
+ return;
+ }
+
+ OnDemandUpdate(component_id);
+}
+
+void ComponentsHandler::OnEvent(Events event, const std::string& id) {
+ base::DictionaryValue parameters;
+ parameters.SetString("event", ComponentEventToString(event));
+ if (!id.empty()) {
+ if (event == Events::COMPONENT_UPDATED) {
+ update_client::CrxUpdateItem item;
+ if (component_updater_->GetComponentDetails(id, &item) && item.component)
+ parameters.SetString("version", item.component->version.GetString());
+ }
+ parameters.SetString("id", id);
+ }
+ FireWebUIListener("component-event", parameters);
+}
+
+base::string16 ComponentsHandler::ComponentEventToString(Events event) {
+ switch (event) {
+ case Events::COMPONENT_CHECKING_FOR_UPDATES:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_STARTED);
+ case Events::COMPONENT_WAIT:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_SLEEPING);
+ case Events::COMPONENT_UPDATE_FOUND:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_FOUND);
+ case Events::COMPONENT_UPDATE_READY:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_READY);
+ case Events::COMPONENT_UPDATED:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_UPDATED);
+ case Events::COMPONENT_NOT_UPDATED:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_NOTUPDATED);
+ case Events::COMPONENT_UPDATE_ERROR:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_UPDATE_ERROR);
+ case Events::COMPONENT_UPDATE_DOWNLOADING:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_DOWNLOADING);
+ }
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
+}
+
+base::string16 ComponentsHandler::ServiceStatusToString(
+ update_client::ComponentState state) {
+ // TODO(sorin): handle kDownloaded. For now, just handle it as kUpdating.
+ switch (state) {
+ case update_client::ComponentState::kNew:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_NEW);
+ case update_client::ComponentState::kChecking:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_CHECKING);
+ case update_client::ComponentState::kCanUpdate:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATE);
+ case update_client::ComponentState::kDownloadingDiff:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL_DIFF);
+ case update_client::ComponentState::kDownloading:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL);
+ case update_client::ComponentState::kUpdatingDiff:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDT_DIFF);
+ case update_client::ComponentState::kUpdating:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATING);
+ case update_client::ComponentState::kDownloaded:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DOWNLOADED);
+ case update_client::ComponentState::kUpdated:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATED);
+ case update_client::ComponentState::kUpToDate:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPTODATE);
+ case update_client::ComponentState::kUpdateError:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATE_ERROR);
+ case update_client::ComponentState::kUninstalled: // Fall through.
+ case update_client::ComponentState::kRun:
+ case update_client::ComponentState::kLastStatus:
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
+ }
+ return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
+}
+
+void ComponentsHandler::OnDemandUpdate(const std::string& component_id) {
+ component_updater_->GetOnDemandUpdater().OnDemandUpdate(
+ component_id, component_updater::OnDemandUpdater::Priority::FOREGROUND,
+ component_updater::Callback());
+}
+
+std::unique_ptr<base::ListValue> ComponentsHandler::LoadComponents() {
+ std::vector<std::string> component_ids;
+ component_ids = component_updater_->GetComponentIDs();
+
+ // Construct DictionaryValues to return to UI.
+ auto component_list = std::make_unique<base::ListValue>();
+ for (size_t j = 0; j < component_ids.size(); ++j) {
+ update_client::CrxUpdateItem item;
+ if (component_updater_->GetComponentDetails(component_ids[j], &item)) {
+ auto component_entry = std::make_unique<base::DictionaryValue>();
+ component_entry->SetString("id", component_ids[j]);
+ component_entry->SetString("status", ServiceStatusToString(item.state));
+ if (item.component) {
+ component_entry->SetString("name", item.component->name);
+ component_entry->SetString("version",
+ item.component->version.GetString());
+ }
+ component_list->Append(std::move(component_entry));
+ }
+ }
+
+ return component_list;
+}
diff --git a/chromium/chrome/browser/ui/webui/components/components_handler.h b/chromium/chrome/browser/ui/webui/components/components_handler.h
new file mode 100644
index 00000000000..5ed5d43d2a5
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/components/components_handler.h
@@ -0,0 +1,61 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_COMPONENTS_COMPONENTS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_COMPONENTS_COMPONENTS_HANDLER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/scoped_observer.h"
+#include "base/strings/string16.h"
+#include "components/component_updater/component_updater_service.h"
+#include "components/update_client/update_client.h"
+#include "content/public/browser/web_ui_message_handler.h"
+
+namespace base {
+class ListValue;
+}
+
+// The handler for Javascript messages for the chrome://components/ page.
+class ComponentsHandler : public content::WebUIMessageHandler,
+ public component_updater::ServiceObserver {
+ public:
+ ComponentsHandler(
+ component_updater::ComponentUpdateService* component_updater);
+ ComponentsHandler(const ComponentsHandler&) = delete;
+ ComponentsHandler& operator=(const ComponentsHandler&) = delete;
+ ~ComponentsHandler() override;
+
+ // WebUIMessageHandler implementation.
+ void RegisterMessages() override;
+ void OnJavascriptAllowed() override;
+ void OnJavascriptDisallowed() override;
+
+ // Callback for the "requestComponentsData" message.
+ void HandleRequestComponentsData(const base::ListValue* args);
+
+ // Callback for the "checkUpdate" message.
+ void HandleCheckUpdate(const base::ListValue* args);
+
+ // ServiceObserver implementation.
+ void OnEvent(Events event, const std::string& id) override;
+
+ private:
+ static base::string16 ComponentEventToString(Events event);
+ static base::string16 ServiceStatusToString(
+ update_client::ComponentState state);
+
+ std::unique_ptr<base::ListValue> LoadComponents();
+ void OnDemandUpdate(const std::string& component_id);
+
+ // Weak pointer; injected for testing.
+ component_updater::ComponentUpdateService* const component_updater_;
+
+ ScopedObserver<component_updater::ComponentUpdateService,
+ component_updater::ComponentUpdateService::Observer>
+ observer_{this};
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_COMPONENTS_COMPONENTS_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/components/components_handler_unittest.cc b/chromium/chrome/browser/ui/webui/components/components_handler_unittest.cc
new file mode 100644
index 00000000000..6f480a66a95
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/components/components_handler_unittest.cc
@@ -0,0 +1,34 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/components/components_handler.h"
+
+#include "components/component_updater/mock_component_updater_service.h"
+#include "content/public/test/test_web_ui.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class TestComponentsHandler : public ComponentsHandler {
+ public:
+ TestComponentsHandler(
+ component_updater::ComponentUpdateService* component_update_service)
+ : ComponentsHandler(component_update_service) {
+ set_web_ui(&test_web_ui_);
+ }
+
+ private:
+ content::TestWebUI test_web_ui_;
+};
+
+TEST(ComponentsHandlerTest, RemovesObserver) {
+ testing::NiceMock<component_updater::MockComponentUpdateService> mock_service;
+ EXPECT_CALL(mock_service, AddObserver(testing::_)).Times(1);
+ EXPECT_CALL(mock_service, RemoveObserver(testing::_)).Times(1);
+
+ {
+ TestComponentsHandler handler(&mock_service);
+ base::ListValue args;
+ args.AppendString("unused");
+ handler.HandleRequestComponentsData(&args);
+ }
+}
diff --git a/chromium/chrome/browser/ui/webui/components/components_ui.cc b/chromium/chrome/browser/ui/webui/components/components_ui.cc
new file mode 100644
index 00000000000..cddfc815037
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/components/components_ui.cc
@@ -0,0 +1,96 @@
+// 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 "chrome/browser/ui/webui/components/components_ui.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/components/components_handler.h"
+#include "chrome/browser/ui/webui/webui_util.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
+#include "chrome/grit/generated_resources.h"
+#include "chrome/grit/theme_resources.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/web_ui_util.h"
+
+#if defined(OS_CHROMEOS)
+#include "components/user_manager/user_manager.h"
+#endif
+
+namespace {
+
+content::WebUIDataSource* CreateComponentsUIHTMLSource(Profile* profile) {
+ content::WebUIDataSource* source =
+ content::WebUIDataSource::Create(chrome::kChromeUIComponentsHost);
+
+ source->OverrideContentSecurityPolicyScriptSrc(
+ "script-src chrome://resources 'self' 'unsafe-eval';");
+
+ static constexpr webui::LocalizedString kStrings[] = {
+ {"componentsTitle", IDS_COMPONENTS_TITLE},
+ {"componentsNoneInstalled", IDS_COMPONENTS_NONE_INSTALLED},
+ {"componentVersion", IDS_COMPONENTS_VERSION},
+ {"checkUpdate", IDS_COMPONENTS_CHECK_FOR_UPDATE},
+ {"noComponents", IDS_COMPONENTS_NO_COMPONENTS},
+ {"statusLabel", IDS_COMPONENTS_STATUS_LABEL},
+ {"checkingLabel", IDS_COMPONENTS_CHECKING_LABEL},
+ };
+ AddLocalizedStringsBulk(source, kStrings);
+
+ source->AddBoolean(
+ "isGuest",
+#if defined(OS_CHROMEOS)
+ user_manager::UserManager::Get()->IsLoggedInAsGuest() ||
+ user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()
+#else
+ profile->IsOffTheRecord()
+#endif
+ );
+ source->UseStringsJs();
+ source->AddResourcePath("components.js", IDR_COMPONENTS_COMPONENTS_JS);
+ source->SetDefaultResource(IDR_COMPONENTS_COMPONENTS_HTML);
+ return source;
+}
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// ComponentsUI
+//
+///////////////////////////////////////////////////////////////////////////////
+
+ComponentsUI::ComponentsUI(content::WebUI* web_ui) : WebUIController(web_ui) {
+ web_ui->AddMessageHandler(std::make_unique<ComponentsHandler>(
+ g_browser_process->component_updater()));
+
+ // Set up the chrome://components/ source.
+ Profile* profile = Profile::FromWebUI(web_ui);
+ content::WebUIDataSource::Add(profile, CreateComponentsUIHTMLSource(profile));
+}
+
+ComponentsUI::~ComponentsUI() {}
+
+// static
+base::RefCountedMemory* ComponentsUI::GetFaviconResourceBytes(
+ ui::ScaleFactor scale_factor) {
+ return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
+ IDR_PLUGINS_FAVICON, scale_factor);
+}
diff --git a/chromium/chrome/browser/ui/webui/components/components_ui.h b/chromium/chrome/browser/ui/webui/components/components_ui.h
new file mode 100644
index 00000000000..00b04799543
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/components/components_ui.h
@@ -0,0 +1,30 @@
+// 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 CHROME_BROWSER_UI_WEBUI_COMPONENTS_COMPONENTS_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_COMPONENTS_COMPONENTS_UI_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "ui/base/layout.h"
+
+namespace base {
+class RefCountedMemory;
+}
+
+class ComponentsUI : public content::WebUIController {
+ public:
+ explicit ComponentsUI(content::WebUI* web_ui);
+ ~ComponentsUI() override;
+
+ static base::RefCountedMemory* GetFaviconResourceBytes(
+ ui::ScaleFactor scale_factor);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ComponentsUI);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_COMPONENTS_COMPONENTS_UI_H_
diff --git a/chromium/chrome/browser/ui/webui/components_ui.cc b/chromium/chrome/browser/ui/webui/components_ui.cc
deleted file mode 100644
index 39f6cf92c40..00000000000
--- a/chromium/chrome/browser/ui/webui/components_ui.cc
+++ /dev/null
@@ -1,282 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/components_ui.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/values.h"
-#include "build/build_config.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/webui_util.h"
-#include "chrome/common/chrome_paths.h"
-#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
-#include "chrome/grit/generated_resources.h"
-#include "chrome/grit/theme_resources.h"
-#include "components/update_client/crx_update_item.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "content/public/browser/web_ui_message_handler.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-
-#if defined(OS_CHROMEOS)
-#include "components/user_manager/user_manager.h"
-#endif
-
-using content::WebUIMessageHandler;
-
-namespace {
-
-content::WebUIDataSource* CreateComponentsUIHTMLSource(Profile* profile) {
- content::WebUIDataSource* source =
- content::WebUIDataSource::Create(chrome::kChromeUIComponentsHost);
-
- source->OverrideContentSecurityPolicyScriptSrc(
- "script-src chrome://resources 'self' 'unsafe-eval';");
-
- static constexpr webui::LocalizedString kStrings[] = {
- {"componentsTitle", IDS_COMPONENTS_TITLE},
- {"componentsNoneInstalled", IDS_COMPONENTS_NONE_INSTALLED},
- {"componentVersion", IDS_COMPONENTS_VERSION},
- {"checkUpdate", IDS_COMPONENTS_CHECK_FOR_UPDATE},
- {"noComponents", IDS_COMPONENTS_NO_COMPONENTS},
- {"statusLabel", IDS_COMPONENTS_STATUS_LABEL},
- {"checkingLabel", IDS_COMPONENTS_CHECKING_LABEL},
- };
- AddLocalizedStringsBulk(source, kStrings);
-
- source->AddBoolean(
- "isGuest",
-#if defined(OS_CHROMEOS)
- user_manager::UserManager::Get()->IsLoggedInAsGuest() ||
- user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()
-#else
- profile->IsOffTheRecord()
-#endif
- );
- source->UseStringsJs();
- source->AddResourcePath("components.js", IDR_COMPONENTS_COMPONENTS_JS);
- source->SetDefaultResource(IDR_COMPONENTS_COMPONENTS_HTML);
- return source;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// ComponentsDOMHandler
-//
-////////////////////////////////////////////////////////////////////////////////
-
-// The handler for Javascript messages for the chrome://components/ page.
-class ComponentsDOMHandler : public WebUIMessageHandler {
- public:
- ComponentsDOMHandler();
- ~ComponentsDOMHandler() override {}
-
- // WebUIMessageHandler implementation.
- void RegisterMessages() override;
-
- // Callback for the "requestComponentsData" message.
- void HandleRequestComponentsData(const base::ListValue* args);
-
- // Callback for the "checkUpdate" message.
- void HandleCheckUpdate(const base::ListValue* args);
-
- private:
- content::NotificationRegistrar registrar_;
-
- DISALLOW_COPY_AND_ASSIGN(ComponentsDOMHandler);
-};
-
-ComponentsDOMHandler::ComponentsDOMHandler() {
-}
-
-void ComponentsDOMHandler::RegisterMessages() {
- web_ui()->RegisterMessageCallback(
- "requestComponentsData",
- base::BindRepeating(&ComponentsDOMHandler::HandleRequestComponentsData,
- base::Unretained(this)));
-
- web_ui()->RegisterMessageCallback(
- "checkUpdate",
- base::BindRepeating(&ComponentsDOMHandler::HandleCheckUpdate,
- base::Unretained(this)));
-}
-
-void ComponentsDOMHandler::HandleRequestComponentsData(
- const base::ListValue* args) {
- base::DictionaryValue result;
- result.Set("components", ComponentsUI::LoadComponents());
- web_ui()->CallJavascriptFunctionUnsafe("returnComponentsData", result);
-}
-
-// This function is called when user presses button from html UI.
-// TODO(shrikant): We need to make this button available based on current
-// state e.g. If component state is currently updating then we need to disable
-// button. (https://code.google.com/p/chromium/issues/detail?id=272540)
-void ComponentsDOMHandler::HandleCheckUpdate(const base::ListValue* args) {
- if (args->GetSize() != 1) {
- NOTREACHED();
- return;
- }
-
- std::string component_id;
- if (!args->GetString(0, &component_id)) {
- NOTREACHED();
- return;
- }
-
- ComponentsUI::OnDemandUpdate(component_id);
-}
-
-} // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// ComponentsUI
-//
-///////////////////////////////////////////////////////////////////////////////
-
-ComponentsUI::ComponentsUI(content::WebUI* web_ui) : WebUIController(web_ui) {
- web_ui->AddMessageHandler(std::make_unique<ComponentsDOMHandler>());
-
- // Set up the chrome://components/ source.
- Profile* profile = Profile::FromWebUI(web_ui);
- content::WebUIDataSource::Add(profile, CreateComponentsUIHTMLSource(profile));
- component_updater::ComponentUpdateService* cus =
- g_browser_process->component_updater();
- cus->AddObserver(this);
-}
-
-ComponentsUI::~ComponentsUI() {
- component_updater::ComponentUpdateService* cus =
- g_browser_process->component_updater();
- if (cus)
- cus->RemoveObserver(this);
-}
-
-// static
-void ComponentsUI::OnDemandUpdate(const std::string& component_id) {
- component_updater::ComponentUpdateService* cus =
- g_browser_process->component_updater();
- cus->GetOnDemandUpdater().OnDemandUpdate(
- component_id, component_updater::OnDemandUpdater::Priority::FOREGROUND,
- component_updater::Callback());
-}
-
-// static
-std::unique_ptr<base::ListValue> ComponentsUI::LoadComponents() {
- component_updater::ComponentUpdateService* cus =
- g_browser_process->component_updater();
- std::vector<std::string> component_ids;
- component_ids = cus->GetComponentIDs();
-
- // Construct DictionaryValues to return to UI.
- auto component_list = std::make_unique<base::ListValue>();
- for (size_t j = 0; j < component_ids.size(); ++j) {
- update_client::CrxUpdateItem item;
- if (cus->GetComponentDetails(component_ids[j], &item)) {
- auto component_entry = std::make_unique<base::DictionaryValue>();
- component_entry->SetString("id", component_ids[j]);
- component_entry->SetString("status", ServiceStatusToString(item.state));
- if (item.component) {
- component_entry->SetString("name", item.component->name);
- component_entry->SetString("version",
- item.component->version.GetString());
- }
- component_list->Append(std::move(component_entry));
- }
- }
-
- return component_list;
-}
-
-// static
-base::RefCountedMemory* ComponentsUI::GetFaviconResourceBytes(
- ui::ScaleFactor scale_factor) {
- return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
- IDR_PLUGINS_FAVICON, scale_factor);
-}
-
-base::string16 ComponentsUI::ComponentEventToString(Events event) {
- switch (event) {
- case Events::COMPONENT_CHECKING_FOR_UPDATES:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_STARTED);
- case Events::COMPONENT_WAIT:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_SLEEPING);
- case Events::COMPONENT_UPDATE_FOUND:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_FOUND);
- case Events::COMPONENT_UPDATE_READY:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_READY);
- case Events::COMPONENT_UPDATED:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_UPDATED);
- case Events::COMPONENT_NOT_UPDATED:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_NOTUPDATED);
- case Events::COMPONENT_UPDATE_ERROR:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_UPDATE_ERROR);
- case Events::COMPONENT_UPDATE_DOWNLOADING:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_EVT_STATUS_DOWNLOADING);
- }
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
-}
-
-base::string16 ComponentsUI::ServiceStatusToString(
- update_client::ComponentState state) {
- // TODO(sorin): handle kDownloaded. For now, just handle it as kUpdating.
- switch (state) {
- case update_client::ComponentState::kNew:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_NEW);
- case update_client::ComponentState::kChecking:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_CHECKING);
- case update_client::ComponentState::kCanUpdate:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATE);
- case update_client::ComponentState::kDownloadingDiff:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL_DIFF);
- case update_client::ComponentState::kDownloading:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DNL);
- case update_client::ComponentState::kUpdatingDiff:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDT_DIFF);
- case update_client::ComponentState::kUpdating:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATING);
- case update_client::ComponentState::kDownloaded:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_DOWNLOADED);
- case update_client::ComponentState::kUpdated:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATED);
- case update_client::ComponentState::kUpToDate:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPTODATE);
- case update_client::ComponentState::kUpdateError:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_SVC_STATUS_UPDATE_ERROR);
- case update_client::ComponentState::kUninstalled: // Fall through.
- case update_client::ComponentState::kRun:
- case update_client::ComponentState::kLastStatus:
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
- }
- return l10n_util::GetStringUTF16(IDS_COMPONENTS_UNKNOWN);
-}
-
-void ComponentsUI::OnEvent(Events event, const std::string& id) {
- base::DictionaryValue parameters;
- parameters.SetString("event", ComponentEventToString(event));
- if (!id.empty()) {
- if (event == Events::COMPONENT_UPDATED) {
- auto* component_updater = g_browser_process->component_updater();
- update_client::CrxUpdateItem item;
- if (component_updater->GetComponentDetails(id, &item) && item.component)
- parameters.SetString("version", item.component->version.GetString());
- }
- parameters.SetString("id", id);
- }
- web_ui()->CallJavascriptFunctionUnsafe("onComponentEvent", parameters);
-}
diff --git a/chromium/chrome/browser/ui/webui/components_ui.h b/chromium/chrome/browser/ui/webui/components_ui.h
deleted file mode 100644
index b391cd1b6da..00000000000
--- a/chromium/chrome/browser/ui/webui/components_ui.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_WEBUI_COMPONENTS_UI_H_
-#define CHROME_BROWSER_UI_WEBUI_COMPONENTS_UI_H_
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "components/component_updater/component_updater_service.h"
-#include "components/update_client/update_client.h"
-#include "content/public/browser/web_ui_controller.h"
-#include "ui/base/layout.h"
-
-namespace base {
-class ListValue;
-class RefCountedMemory;
-}
-
-class ComponentsUI : public content::WebUIController,
- public component_updater::ServiceObserver {
- public:
- explicit ComponentsUI(content::WebUI* web_ui);
- ~ComponentsUI() override;
-
- static void OnDemandUpdate(const std::string& component_id);
-
- static std::unique_ptr<base::ListValue> LoadComponents();
-
- static base::RefCountedMemory* GetFaviconResourceBytes(
- ui::ScaleFactor scale_factor);
-
- // ServiceObserver implementation.
- void OnEvent(Events event, const std::string& id) override;
-
- private:
- static base::string16 ComponentEventToString(Events event);
- static base::string16 ServiceStatusToString(
- update_client::ComponentState state);
- DISALLOW_COPY_AND_ASSIGN(ComponentsUI);
-};
-
-#endif // CHROME_BROWSER_UI_WEBUI_COMPONENTS_UI_H_
diff --git a/chromium/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc b/chromium/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc
index d7da4b11482..d7a42770c33 100644
--- a/chromium/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc
+++ b/chromium/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc
@@ -68,7 +68,7 @@ constexpr char kAllowedSameDirectory[] =
void AppendString(base::StringPiece input, std::string* output) {
if (!output->empty())
*output += ", ";
- input.AppendToString(output);
+ output->append(input.data(), input.size());
}
// Returns a string describing the current module blocking status: loaded or
diff --git a/chromium/chrome/browser/ui/webui/cookies_tree_model_util.cc b/chromium/chrome/browser/ui/webui/cookies_tree_model_util.cc
index 0873e01434c..c607734158d 100644
--- a/chromium/chrome/browser/ui/webui/cookies_tree_model_util.cc
+++ b/chromium/chrome/browser/ui/webui/cookies_tree_model_util.cc
@@ -19,7 +19,6 @@
#include "chrome/browser/browsing_data/cookies_tree_model.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/cache_storage_context.h"
-#include "content/public/browser/indexed_db_context.h"
#include "content/public/browser/service_worker_context.h"
#include "content/public/browser/storage_usage_info.h"
#include "extensions/buildflags/buildflags.h"
diff --git a/chromium/chrome/browser/ui/webui/crashes_ui.cc b/chromium/chrome/browser/ui/webui/crashes_ui.cc
index 121cac73034..dbb7da10e38 100644
--- a/chromium/chrome/browser/ui/webui/crashes_ui.cc
+++ b/chromium/chrome/browser/ui/webui/crashes_ui.cc
@@ -7,6 +7,8 @@
#include <stddef.h>
#include <memory>
+#include <string>
+#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -24,8 +26,8 @@
#include "chrome/common/url_constants.h"
#include "chrome/grit/chromium_strings.h"
#include "components/crash/core/browser/crashes_ui_util.h"
-#include "components/grit/components_resources.h"
#include "components/grit/components_scaled_resources.h"
+#include "components/grit/dev_ui_components_resources.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/web_contents.h"
@@ -41,7 +43,7 @@
#endif
#if defined(OS_LINUX)
-#include "components/crash/content/app/crashpad.h"
+#include "components/crash/core/app/crashpad.h"
#endif
using content::WebContents;
diff --git a/chromium/chrome/browser/ui/webui/device_log_ui.cc b/chromium/chrome/browser/ui/webui/device_log_ui.cc
index cc6913f18b9..fac445e2343 100644
--- a/chromium/chrome/browser/ui/webui/device_log_ui.cc
+++ b/chromium/chrome/browser/ui/webui/device_log_ui.cc
@@ -13,13 +13,14 @@
#include "base/values.h"
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "components/device_event_log/device_event_log.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
+#include "ui/base/webui/web_ui_util.h"
namespace chromeos {
@@ -71,8 +72,9 @@ DeviceLogUI::DeviceLogUI(content::WebUI* web_ui)
{"autoRefreshText", IDS_DEVICE_AUTO_REFRESH},
{"logRefreshText", IDS_DEVICE_LOG_REFRESH},
{"logClearText", IDS_DEVICE_LOG_CLEAR},
+ {"logClearTypesText", IDS_DEVICE_LOG_CLEAR_TYPES},
{"logNoEntriesText", IDS_DEVICE_LOG_NO_ENTRIES},
- {"logLevelShowText", IDS_DEVICE_LOG_LEVEL_SHOW},
+ {"logLevelLabel", IDS_DEVICE_LOG_LEVEL_LABEL},
{"logLevelErrorText", IDS_DEVICE_LOG_LEVEL_ERROR},
{"logLevelUserText", IDS_DEVICE_LOG_LEVEL_USER},
{"logLevelEventText", IDS_DEVICE_LOG_LEVEL_EVENT},
diff --git a/chromium/chrome/browser/ui/webui/devtools_ui_data_source.cc b/chromium/chrome/browser/ui/webui/devtools_ui_data_source.cc
index 0cfe18bc0cb..4a9faa8ce8c 100644
--- a/chromium/chrome/browser/ui/webui/devtools_ui_data_source.cc
+++ b/chromium/chrome/browser/ui/webui/devtools_ui_data_source.cc
@@ -14,6 +14,7 @@
#include "base/path_service.h"
#include "base/strings/strcat.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/devtools/devtools_ui_bindings.h"
#include "chrome/browser/devtools/url_constants.h"
#include "chrome/common/chrome_paths.h"
@@ -322,10 +323,9 @@ void DevToolsDataSource::StartFileRequest(const std::string& path,
base::FilePath full_path = base_path.AppendASCII(path);
CHECK(base_path.IsParent(full_path));
- base::PostTaskAndReplyWithResult(
+ base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE,
- {base::MayBlock(), base::ThreadPool(),
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
base::TaskPriority::USER_VISIBLE},
base::BindOnce(ReadFileForDevTools, std::move(full_path)),
std::move(callback));
diff --git a/chromium/chrome/browser/ui/webui/discards/BUILD.gn b/chromium/chrome/browser/ui/webui/discards/BUILD.gn
index cf71fc8ea10..ec52c2e0918 100644
--- a/chromium/chrome/browser/ui/webui/discards/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/discards/BUILD.gn
@@ -8,6 +8,7 @@ if (is_win || is_mac || is_desktop_linux || is_chromeos) {
mojom("mojo_bindings") {
sources = [
"discards.mojom",
+ "site_data.mojom",
]
public_deps = [
diff --git a/chromium/chrome/browser/ui/webui/discards/discards.mojom b/chromium/chrome/browser/ui/webui/discards/discards.mojom
index e326c896198..d4d0abab1bf 100644
--- a/chromium/chrome/browser/ui/webui/discards/discards.mojom
+++ b/chromium/chrome/browser/ui/webui/discards/discards.mojom
@@ -16,72 +16,6 @@ enum LifecycleUnitVisibility {
VISIBLE = 2,
};
-struct SiteCharacteristicsFeature {
- // The cumulative observation time for this feature in seconds, set to 0 once
- // this feature has been observed.
- int64 observation_duration;
- // The time at which this feature has been used (set to 0 if it hasn't been
- // used), in seconds since epoch.
- int64 use_timestamp;
-};
-
-struct SiteCharacteristicsPerformanceMeasurement {
- // A decaying average of the CPU usage measurements. Units: microseconds.
- float avg_cpu_usage_us;
- // A decaying average of the process footprint measurements. Units: kilobytes.
- float avg_footprint_kb;
- // A decaying average of the wall-clock load time duration of the tab.
- // Units: microseconds.
- float avg_load_duration_us;
-};
-
-struct SiteCharacteristicsDatabaseSize {
- // The total number of rows in the database, or -1 if the value is not
- // available.
- int64 num_rows;
-
- // The total size of the database on disk in kilobytes, or -1 if the value
- // is not available.
- int64 on_disk_size_kb;
-};
-
-// The data stored for a given origin, this should mirror the
-// SiteDataProto structure in
-// performance_manager/persistence/site_data/site_data.proto.
-struct SiteCharacteristicsDatabaseValue {
- // The last time this site has been in the loaded state, in seconds since
- // epoch.
- uint32 last_loaded;
-
- SiteCharacteristicsFeature updates_favicon_in_background;
- SiteCharacteristicsFeature updates_title_in_background;
- SiteCharacteristicsFeature uses_audio_in_background;
-
- // Load time performance measurement estimates. This maintains a decaying
- // average of the resource usage of a page until shortly after it becomes
- // idle.
- SiteCharacteristicsPerformanceMeasurement? load_time_estimates;
-};
-
-// Provides the key and miscellaneous in-memory only data pertaining to a
-// row that potentially exists in a database.
-struct SiteCharacteristicsDatabaseEntry {
- // The origin associated with this row.
- string origin;
-
- // This row is pending flush to disk.
- bool is_dirty;
-
- // NULL if the database entry doesn't exist on disk or in memory.
- SiteCharacteristicsDatabaseValue? value;
-};
-
-// Contains information about a specific DB instance.
-struct SiteCharacteristicsDatabase {
- // Contains the entries requested.
- array<SiteCharacteristicsDatabaseEntry> db_rows;
-};
-
// Discard related information about a single tab in a browser.
struct TabDiscardsInfo {
// The URL associated with the tab. This corresponds to GetLastCommittedURL,
@@ -141,29 +75,15 @@ interface DetailsProvider {
// each tab currently open in the browser, across all profiles.
GetTabDiscardsInfo() => (array<TabDiscardsInfo> infos);
- // Returns the in-memory entries and the entries for the requested origins.
- // Note that any entry may take some time to load from disk, and so there may
- // not be any data for a given entry until on the second or subsequent
- // requests.
- GetSiteCharacteristicsDatabase(
- array<string> explicitly_requested_origins) =>
- (SiteCharacteristicsDatabase? result);
-
- // Returns the size of the database in number of rows and kilobytes.
- // Note that this may be fairly expensive to acquire, and so shouldn't be
- // called frequently.
- GetSiteCharacteristicsDatabaseSize() =>
- (SiteCharacteristicsDatabaseSize? db_size);
-
// Sets the auto-discardable state of a tab, as specified by its stable
// |tab_id|, earlier returned by GetTabDiscardsInfo. Invokes a callback when
// the change has been made.
SetAutoDiscardable(int32 tab_id, bool is_auto_discardable) => ();
- // Discards a tab given its |tab_id|. If |urgent| is specified the unload
- // handlers will not be run, and the tab will be unloaded with prejudice.
+ // Discards a tab given its |tab_id|. The unload handlers will not be run, and
+ // the tab will be unloaded with prejudice.
// Invokes a callback when the discard is complete.
- DiscardById(int32 tab_id, bool urgent) => ();
+ DiscardById(int32 tab_id) => ();
// Freezes a tab given its |tab_id|.
FreezeById(int32 tab_id);
@@ -171,12 +91,11 @@ interface DetailsProvider {
// Loads a tab given its |tab_id|.
LoadById(int32 tab_id);
- // Discards the least important tab. If |urgent| is specified the unload
- // handlers will not be run, and the tab will be unloaded with prejudice.
+ // Discards the least important tab.
// This can fail to discard a tab if no tabs are currently considered
// eligible for discard. Invokes a callback when the discard is complete, or
// if the decision was made not to discard.
- Discard(bool urgent) => ();
+ Discard() => ();
};
// Represents the momentary state of a Page node.
@@ -203,7 +122,6 @@ struct ProcessInfo {
int64 id;
mojo_base.mojom.ProcessId pid;
- mojo_base.mojom.TimeDelta cumulative_cpu_usage;
uint64 private_footprint_kb;
};
diff --git a/chromium/chrome/browser/ui/webui/discards/discards_ui.cc b/chromium/chrome/browser/ui/webui/discards/discards_ui.cc
index e270478c985..22843d93c0b 100644
--- a/chromium/chrome/browser/ui/webui/discards/discards_ui.cc
+++ b/chromium/chrome/browser/ui/webui/discards/discards_ui.cc
@@ -17,8 +17,6 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/resource_coordinator/lifecycle_unit.h"
#include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h"
-#include "chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h"
-#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store.h"
#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h"
#include "chrome/browser/resource_coordinator/tab_activity_watcher.h"
#include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h"
@@ -26,6 +24,8 @@
#include "chrome/browser/resource_coordinator/time.h"
#include "chrome/browser/ui/webui/discards/discards.mojom.h"
#include "chrome/browser/ui/webui/discards/graph_dump_impl.h"
+#include "chrome/browser/ui/webui/discards/site_data.mojom-forward.h"
+#include "chrome/browser/ui/webui/discards/site_data_provider_impl.h"
#include "chrome/browser/ui/webui/favicon_source.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/browser_resources.h"
@@ -44,12 +44,11 @@
#include "url/gurl.h"
#include "url/origin.h"
-namespace {
+namespace resource_coordinator {
+class LocalSiteCharacteristicsDataStoreInspector;
+} // namespace resource_coordinator
-mojom::LifecycleUnitDiscardReason GetDiscardReason(bool urgent) {
- return urgent ? mojom::LifecycleUnitDiscardReason::URGENT
- : mojom::LifecycleUnitDiscardReason::PROACTIVE;
-}
+namespace {
discards::mojom::LifecycleUnitVisibility GetLifecycleUnitVisibility(
content::Visibility visibility) {
@@ -93,82 +92,13 @@ double GetSiteEngagementScore(content::WebContents* contents) {
return engagement_svc->GetDetails(nav_entry->GetURL()).total_score;
}
-discards::mojom::SiteCharacteristicsFeaturePtr ConvertFeatureFromProto(
- const SiteDataFeatureProto& proto) {
- discards::mojom::SiteCharacteristicsFeaturePtr feature =
- discards::mojom::SiteCharacteristicsFeature::New();
-
- if (proto.has_observation_duration()) {
- feature->observation_duration = proto.observation_duration();
- } else {
- feature->observation_duration = 0;
- }
-
- if (proto.has_use_timestamp()) {
- feature->use_timestamp = proto.use_timestamp();
- } else {
- feature->use_timestamp = 0;
- }
-
- return feature;
-}
-
-discards::mojom::SiteCharacteristicsDatabaseEntryPtr ConvertEntryFromProto(
- SiteDataProto* proto) {
- discards::mojom::SiteCharacteristicsDatabaseValuePtr value =
- discards::mojom::SiteCharacteristicsDatabaseValue::New();
-
- if (proto->has_last_loaded()) {
- value->last_loaded = proto->last_loaded();
- } else {
- value->last_loaded = 0;
- }
- value->updates_favicon_in_background =
- ConvertFeatureFromProto(proto->updates_favicon_in_background());
- value->updates_title_in_background =
- ConvertFeatureFromProto(proto->updates_title_in_background());
- value->uses_audio_in_background =
- ConvertFeatureFromProto(proto->uses_audio_in_background());
-
- if (proto->has_load_time_estimates()) {
- const auto& load_time_estimates_proto = proto->load_time_estimates();
- DCHECK(load_time_estimates_proto.has_avg_cpu_usage_us());
- DCHECK(load_time_estimates_proto.has_avg_footprint_kb());
-
- discards::mojom::SiteCharacteristicsPerformanceMeasurementPtr
- load_time_estimates =
- discards::mojom::SiteCharacteristicsPerformanceMeasurement::New();
- if (load_time_estimates_proto.has_avg_cpu_usage_us()) {
- load_time_estimates->avg_cpu_usage_us =
- load_time_estimates_proto.avg_cpu_usage_us();
- }
- if (load_time_estimates_proto.has_avg_footprint_kb()) {
- load_time_estimates->avg_footprint_kb =
- load_time_estimates_proto.avg_footprint_kb();
- }
- if (load_time_estimates_proto.has_avg_load_duration_us()) {
- load_time_estimates->avg_load_duration_us =
- load_time_estimates_proto.avg_load_duration_us();
- }
-
- value->load_time_estimates = std::move(load_time_estimates);
- }
-
- discards::mojom::SiteCharacteristicsDatabaseEntryPtr entry =
- discards::mojom::SiteCharacteristicsDatabaseEntry::New();
- entry->value = std::move(value);
- return entry;
-}
class DiscardsDetailsProviderImpl : public discards::mojom::DetailsProvider {
public:
// This instance is deleted when the supplied pipe is destroyed.
- DiscardsDetailsProviderImpl(
- resource_coordinator::LocalSiteCharacteristicsDataStoreInspector*
- data_store_inspector,
+ explicit DiscardsDetailsProviderImpl(
mojo::PendingReceiver<discards::mojom::DetailsProvider> receiver)
- : data_store_inspector_(data_store_inspector),
- receiver_(this, std::move(receiver)) {}
+ : receiver_(this, std::move(receiver)) {}
~DiscardsDetailsProviderImpl() override {}
@@ -206,13 +136,9 @@ class DiscardsDetailsProviderImpl : public discards::mojom::DetailsProvider {
info->can_freeze = lifecycle_unit->CanFreeze(&freeze_details);
info->cannot_freeze_reasons = freeze_details.GetFailureReasonStrings();
resource_coordinator::DecisionDetails discard_details;
- info->can_discard = lifecycle_unit->CanDiscard(
- mojom::LifecycleUnitDiscardReason::PROACTIVE, &discard_details);
info->cannot_discard_reasons = discard_details.GetFailureReasonStrings();
- info->discard_count = lifecycle_unit->GetDiscardCount();
- // This is only valid if the state is PENDING_DISCARD or DISCARD, but the
- // javascript code takes care of that.
info->discard_reason = lifecycle_unit->GetDiscardReason();
+ info->discard_count = lifecycle_unit->GetDiscardCount();
info->utility_rank = rank++;
const base::TimeTicks last_focused_time =
lifecycle_unit->GetLastFocusedTime();
@@ -244,11 +170,6 @@ class DiscardsDetailsProviderImpl : public discards::mojom::DetailsProvider {
std::move(callback).Run(std::move(infos));
}
- void GetSiteCharacteristicsDatabase(
- const std::vector<std::string>& explicitly_requested_origins,
- GetSiteCharacteristicsDatabaseCallback callback) override;
- void GetSiteCharacteristicsDatabaseSize(
- GetSiteCharacteristicsDatabaseSizeCallback callback) override;
void SetAutoDiscardable(int32_t id,
bool is_auto_discardable,
@@ -264,11 +185,10 @@ class DiscardsDetailsProviderImpl : public discards::mojom::DetailsProvider {
}
void DiscardById(int32_t id,
- bool urgent,
DiscardByIdCallback callback) override {
auto* lifecycle_unit = GetLifecycleUnitById(id);
if (lifecycle_unit)
- lifecycle_unit->Discard(GetDiscardReason(urgent));
+ lifecycle_unit->Discard(mojom::LifecycleUnitDiscardReason::URGENT);
std::move(callback).Run();
}
@@ -284,113 +204,19 @@ class DiscardsDetailsProviderImpl : public discards::mojom::DetailsProvider {
lifecycle_unit->Load();
}
- void Discard(bool urgent, DiscardCallback callback) override {
+ void Discard(DiscardCallback callback) override {
resource_coordinator::TabManager* tab_manager =
g_browser_process->GetTabManager();
- tab_manager->DiscardTab(GetDiscardReason(urgent));
+ tab_manager->DiscardTab(mojom::LifecycleUnitDiscardReason::URGENT);
std::move(callback).Run();
}
private:
- using LocalSiteCharacteristicsDataStoreInspector =
- resource_coordinator::LocalSiteCharacteristicsDataStoreInspector;
- using SiteCharacteristicsDataReader =
- resource_coordinator::SiteCharacteristicsDataReader;
- using SiteCharacteristicsDataStore =
- resource_coordinator::SiteCharacteristicsDataStore;
- using OriginToReaderMap =
- base::flat_map<std::string,
- std::unique_ptr<SiteCharacteristicsDataReader>>;
-
- // This map pins requested readers and their associated data in memory until
- // after the next read finishes. This is necessary to allow the database reads
- // to go through and populate the requested entries.
- OriginToReaderMap requested_origins_;
-
- LocalSiteCharacteristicsDataStoreInspector* data_store_inspector_;
mojo::Receiver<discards::mojom::DetailsProvider> receiver_;
DISALLOW_COPY_AND_ASSIGN(DiscardsDetailsProviderImpl);
};
-void DiscardsDetailsProviderImpl::GetSiteCharacteristicsDatabase(
- const std::vector<std::string>& explicitly_requested_origins,
- GetSiteCharacteristicsDatabaseCallback callback) {
- if (!data_store_inspector_) {
- // Early return with a nullptr if there's no inspector.
- std::move(callback).Run(nullptr);
- return;
- }
-
- // Move all previously explicitly requested origins to this local map.
- // Move any currently requested origins over to the member variable, or
- // populate them if they weren't previously requested.
- // The difference will remain in this map and go out of scope at the end of
- // this function.
- OriginToReaderMap prev_requested_origins;
- prev_requested_origins.swap(requested_origins_);
- SiteCharacteristicsDataStore* data_store =
- data_store_inspector_->GetDataStore();
- DCHECK(data_store);
- for (const std::string& origin : explicitly_requested_origins) {
- auto it = prev_requested_origins.find(origin);
- if (it == prev_requested_origins.end()) {
- GURL url(origin);
- requested_origins_[origin] =
- data_store->GetReaderForOrigin(url::Origin::Create(url));
- } else {
- requested_origins_[origin] = std::move(it->second);
- prev_requested_origins.erase(it);
- }
- }
-
- discards::mojom::SiteCharacteristicsDatabasePtr result =
- discards::mojom::SiteCharacteristicsDatabase::New();
- std::vector<url::Origin> in_memory_origins =
- data_store_inspector_->GetAllInMemoryOrigins();
- for (const url::Origin& origin : in_memory_origins) {
- // Get the data for this origin and convert it from proto to the
- // corresponding mojo structure.
- std::unique_ptr<SiteDataProto> proto;
- bool is_dirty = false;
- if (data_store_inspector_->GetDataForOrigin(origin, &is_dirty, &proto)) {
- auto entry = ConvertEntryFromProto(proto.get());
- entry->origin = origin.Serialize();
- entry->is_dirty = is_dirty;
- result->db_rows.push_back(std::move(entry));
- }
- }
-
- // Return the result.
- std::move(callback).Run(std::move(result));
-}
-
-void DiscardsDetailsProviderImpl::GetSiteCharacteristicsDatabaseSize(
- GetSiteCharacteristicsDatabaseSizeCallback callback) {
- if (!data_store_inspector_) {
- // Early return with a nullptr if there's no inspector.
- std::move(callback).Run(nullptr);
- return;
- }
-
- // Adapt the inspector callback to the mojom callback with this lambda.
- auto inspector_callback = base::BindOnce(
- [](GetSiteCharacteristicsDatabaseSizeCallback callback,
- base::Optional<int64_t> num_rows,
- base::Optional<int64_t> on_disk_size_kb) {
- discards::mojom::SiteCharacteristicsDatabaseSizePtr result =
- discards::mojom::SiteCharacteristicsDatabaseSize::New();
- result->num_rows = num_rows.has_value() ? num_rows.value() : -1;
- result->on_disk_size_kb =
- on_disk_size_kb.has_value() ? on_disk_size_kb.value() : -1;
-
- std::move(callback).Run(std::move(result));
- },
- std::move(callback));
-
- data_store_inspector_->GetDatabaseSize(std::move(inspector_callback));
-}
-
} // namespace
DiscardsUI::DiscardsUI(content::WebUI* web_ui)
@@ -420,6 +246,9 @@ DiscardsUI::DiscardsUI(content::WebUI* web_ui)
source->AddResourcePath(
"chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-lite.js",
IDR_DISCARDS_LIFECYCLE_UNIT_STATE_MOJOM_LITE_JS);
+ source->AddResourcePath(
+ "chrome/browser/ui/webui/discards/site_data.mojom-lite.js",
+ IDR_DISCARDS_SITE_DATA_MOJOM_LITE_JS);
// Add the mojo base dependency for the WebUI Graph Dump.
source->AddResourcePath(
@@ -435,24 +264,27 @@ DiscardsUI::DiscardsUI(content::WebUI* web_ui)
profile, std::make_unique<FaviconSource>(
profile, chrome::FaviconUrlFormat::kFavicon2));
- AddHandlerToRegistry(base::BindRepeating(
- &DiscardsUI::BindDiscardsDetailsProvider, base::Unretained(this)));
- AddHandlerToRegistry(base::BindRepeating(
- &DiscardsUI::BindDiscardsGraphDumpProvider, base::Unretained(this)));
-
data_store_inspector_ = resource_coordinator::
LocalSiteCharacteristicsDataStoreInspector::GetForProfile(profile);
}
+WEB_UI_CONTROLLER_TYPE_IMPL(DiscardsUI)
+
DiscardsUI::~DiscardsUI() {}
-void DiscardsUI::BindDiscardsDetailsProvider(
+void DiscardsUI::BindInterface(
mojo::PendingReceiver<discards::mojom::DetailsProvider> receiver) {
- ui_handler_ = std::make_unique<DiscardsDetailsProviderImpl>(
+ ui_handler_ =
+ std::make_unique<DiscardsDetailsProviderImpl>(std::move(receiver));
+}
+
+void DiscardsUI::BindInterface(
+ mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver) {
+ site_data_provider_ = std::make_unique<SiteDataProviderImpl>(
data_store_inspector_, std::move(receiver));
}
-void DiscardsUI::BindDiscardsGraphDumpProvider(
+void DiscardsUI::BindInterface(
mojo::PendingReceiver<discards::mojom::GraphDump> receiver) {
if (performance_manager::PerformanceManager::IsAvailable()) {
// Forward the interface receiver directly to the service.
diff --git a/chromium/chrome/browser/ui/webui/discards/discards_ui.h b/chromium/chrome/browser/ui/webui/discards/discards_ui.h
index fa360e2f090..f4543661a45 100644
--- a/chromium/chrome/browser/ui/webui/discards/discards_ui.h
+++ b/chromium/chrome/browser/ui/webui/discards/discards_ui.h
@@ -8,7 +8,8 @@
#include <memory>
#include "base/macros.h"
-#include "chrome/browser/ui/webui/discards/discards.mojom.h"
+#include "chrome/browser/ui/webui/discards/discards.mojom-forward.h"
+#include "chrome/browser/ui/webui/discards/site_data.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -23,16 +24,29 @@ class DiscardsUI : public ui::MojoWebUIController {
explicit DiscardsUI(content::WebUI* web_ui);
~DiscardsUI() override;
- private:
- void BindDiscardsDetailsProvider(
+ // Instantiates the implementor of the mojom::DetailsProvider mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<discards::mojom::DetailsProvider> receiver);
- void BindDiscardsGraphDumpProvider(
+
+ // Instantiates the implementor of the mojom::SiteDataProvider mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
+ mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver);
+
+ // Instantiates the implementor of the mojom::GraphDump mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<discards::mojom::GraphDump> receiver);
+ private:
std::unique_ptr<discards::mojom::DetailsProvider> ui_handler_;
+ std::unique_ptr<discards::mojom::SiteDataProvider> site_data_provider_;
resource_coordinator::LocalSiteCharacteristicsDataStoreInspector*
data_store_inspector_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(DiscardsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.cc b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.cc
index c48f8739da6..c5033d754e3 100644
--- a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.cc
+++ b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.cc
@@ -287,6 +287,11 @@ void DiscardsGraphDumpImpl::OnBeforeWorkerNodeRemoved(
SendDeletionNotification(worker_node);
}
+void DiscardsGraphDumpImpl::OnFinalResponseURLDetermined(
+ const performance_manager::WorkerNode* worker_node) {
+ SendWorkerNotification(worker_node, false);
+}
+
void DiscardsGraphDumpImpl::OnClientFrameAdded(
const performance_manager::WorkerNode* worker_node,
const performance_manager::FrameNode* client_frame_node) {
@@ -398,7 +403,6 @@ void DiscardsGraphDumpImpl::SendProcessNotification(
process_info->id = GetSerializationId(process);
process_info->pid = process->GetProcessId();
- process_info->cumulative_cpu_usage = process->GetCumulativeCpuUsage();
process_info->private_footprint_kb = process->GetPrivateFootprintKb();
if (created)
diff --git a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.h b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.h
index f52c963780a..d70ccaf1ea0 100644
--- a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.h
+++ b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.h
@@ -89,6 +89,9 @@ class DiscardsGraphDumpImpl : public discards::mojom::GraphDump,
void OnPriorityAndReasonChanged(
const performance_manager::FrameNode* frame_node,
const PriorityAndReason& previous_value) override {}
+ // Ignored.
+ void OnHadFormInteractionChanged(
+ const performance_manager::FrameNode* frame_node) override {}
// PageNodeObserver implementation:
void OnPageNodeAdded(const performance_manager::PageNode* page_node) override;
@@ -117,10 +120,10 @@ class DiscardsGraphDumpImpl : public discards::mojom::GraphDump,
void OnMainFrameUrlChanged(
const performance_manager::PageNode* page_node) override;
// Ignored.
- void OnPageAlmostIdleChanged(
- const performance_manager::PageNode* page_node) override {}
void OnMainFrameDocumentChanged(
const performance_manager::PageNode* page_node) override {}
+ void OnHadFormInteractionChanged(
+ const performance_manager::PageNode* page_node) override {}
void OnTitleUpdated(const performance_manager::PageNode* page_node) override {
} // Ignored.
void OnFaviconUpdated(
@@ -150,6 +153,8 @@ class DiscardsGraphDumpImpl : public discards::mojom::GraphDump,
const performance_manager::WorkerNode* worker_node) override;
void OnBeforeWorkerNodeRemoved(
const performance_manager::WorkerNode* worker_node) override;
+ void OnFinalResponseURLDetermined(
+ const performance_manager::WorkerNode* worker_node) override;
void OnClientFrameAdded(
const performance_manager::WorkerNode* worker_node,
const performance_manager::FrameNode* client_frame_node) override;
diff --git a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc
index 572f7f9cc32..f1b2e7d0945 100644
--- a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc
@@ -26,6 +26,8 @@ namespace {
using performance_manager::NodeBase;
+const std::string kHtmlMimeType = "text/html";
+
class TestChangeStream : public discards::mojom::GraphChangeStream {
public:
using FrameMap = std::map<int64_t, discards::mojom::FrameInfoPtr>;
@@ -158,9 +160,9 @@ TEST_F(DiscardsGraphDumpImplTest, ChangeStream) {
const GURL kExampleUrl("http://www.example.org");
int64_t next_navigation_id = 1;
mock_graph.page->OnMainFrameNavigationCommitted(
- false, now, next_navigation_id++, kExampleUrl);
+ false, now, next_navigation_id++, kExampleUrl, kHtmlMimeType);
mock_graph.other_page->OnMainFrameNavigationCommitted(
- false, now, next_navigation_id++, kExampleUrl);
+ false, now, next_navigation_id++, kExampleUrl, kHtmlMimeType);
auto* main_frame = mock_graph.page->GetMainFrameNodeImpl();
main_frame->OnNavigationCommitted(kExampleUrl, /* same_document */ false);
@@ -221,7 +223,7 @@ TEST_F(DiscardsGraphDumpImplTest, ChangeStream) {
// Test change notifications.
const GURL kAnotherURL("http://www.google.com/");
mock_graph.page->OnMainFrameNavigationCommitted(
- false, now, next_navigation_id++, kAnotherURL);
+ false, now, next_navigation_id++, kAnotherURL, kHtmlMimeType);
size_t child_frame_id =
NodeBase::GetSerializationId(mock_graph.child_frame.get());
diff --git a/chromium/chrome/browser/ui/webui/discards/site_data.mojom b/chromium/chrome/browser/ui/webui/discards/site_data.mojom
new file mode 100644
index 00000000000..1084c80fdff
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/discards/site_data.mojom
@@ -0,0 +1,90 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module discards.mojom;
+
+struct SiteCharacteristicsFeature {
+ // The cumulative observation time for this feature in seconds, set to 0 once
+ // this feature has been observed.
+ int64 observation_duration;
+ // The time at which this feature has been used (set to 0 if it hasn't been
+ // used), in seconds since epoch.
+ int64 use_timestamp;
+};
+
+struct SiteCharacteristicsPerformanceMeasurement {
+ // A decaying average of the CPU usage measurements. Units: microseconds.
+ float avg_cpu_usage_us;
+ // A decaying average of the process footprint measurements. Units: kilobytes.
+ float avg_footprint_kb;
+ // A decaying average of the wall-clock load time duration of the tab.
+ // Units: microseconds.
+ float avg_load_duration_us;
+};
+
+struct SiteCharacteristicsDatabaseSize {
+ // The total number of rows in the database, or -1 if the value is not
+ // available.
+ int64 num_rows;
+
+ // The total size of the database on disk in kilobytes, or -1 if the value
+ // is not available.
+ int64 on_disk_size_kb;
+};
+
+// The data stored for a given origin, this should mirror the
+// SiteDataProto structure in
+// performance_manager/persistence/site_data/site_data.proto.
+struct SiteCharacteristicsDatabaseValue {
+ // The last time this site has been in the loaded state, in seconds since
+ // epoch.
+ uint32 last_loaded;
+
+ SiteCharacteristicsFeature updates_favicon_in_background;
+ SiteCharacteristicsFeature updates_title_in_background;
+ SiteCharacteristicsFeature uses_audio_in_background;
+
+ // Load time performance measurement estimates. This maintains a decaying
+ // average of the resource usage of a page until shortly after it becomes
+ // idle.
+ SiteCharacteristicsPerformanceMeasurement? load_time_estimates;
+};
+
+// Provides the key and miscellaneous in-memory only data pertaining to a
+// row that potentially exists in a database.
+struct SiteCharacteristicsDatabaseEntry {
+ // The origin associated with this row.
+ string origin;
+
+ // This row is pending flush to disk.
+ bool is_dirty;
+
+ // NULL if the database entry doesn't exist on disk or in memory.
+ SiteCharacteristicsDatabaseValue? value;
+};
+
+// Contains information about a specific DB instance.
+struct SiteCharacteristicsDatabase {
+ // Contains the entries requested.
+ array<SiteCharacteristicsDatabaseEntry> db_rows;
+};
+
+// Interface for providing information about the site data database. Lives in
+// the browser process and is invoked in the renderer process via Javascript
+// code running in the chrome://discards WebUI.
+interface SiteDataProvider {
+ // Returns the in-memory entries and the entries for the requested origins.
+ // Note that any entry may take some time to load from disk, and so there may
+ // not be any data for a given entry until on the second or subsequent
+ // requests. The WebUI is expected to poll this function.
+ GetSiteCharacteristicsDatabase(
+ array<string> explicitly_requested_origins) =>
+ (SiteCharacteristicsDatabase? result);
+
+ // Returns the size of the database in number of rows and kilobytes.
+ // Note that this may be fairly expensive to acquire, and so shouldn't be
+ // called frequently.
+ GetSiteCharacteristicsDatabaseSize() =>
+ (SiteCharacteristicsDatabaseSize? db_size);
+};
diff --git a/chromium/chrome/browser/ui/webui/discards/site_data_provider_impl.cc b/chromium/chrome/browser/ui/webui/discards/site_data_provider_impl.cc
new file mode 100644
index 00000000000..8d701889fd7
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/discards/site_data_provider_impl.cc
@@ -0,0 +1,147 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/discards/site_data_provider_impl.h"
+
+#include "base/bind_helpers.h"
+#include "chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h"
+#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store.h"
+#include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h"
+
+namespace {
+
+discards::mojom::SiteCharacteristicsFeaturePtr ConvertFeatureFromProto(
+ const SiteDataFeatureProto& proto) {
+ discards::mojom::SiteCharacteristicsFeaturePtr feature =
+ discards::mojom::SiteCharacteristicsFeature::New();
+
+ if (proto.has_observation_duration())
+ feature->observation_duration = proto.observation_duration();
+
+ if (proto.has_use_timestamp())
+ feature->use_timestamp = proto.use_timestamp();
+
+ return feature;
+}
+
+discards::mojom::SiteCharacteristicsDatabaseEntryPtr ConvertEntryFromProto(
+ SiteDataProto* proto) {
+ discards::mojom::SiteCharacteristicsDatabaseValuePtr value =
+ discards::mojom::SiteCharacteristicsDatabaseValue::New();
+
+ if (proto->has_last_loaded())
+ value->last_loaded = proto->last_loaded();
+
+ value->updates_favicon_in_background =
+ ConvertFeatureFromProto(proto->updates_favicon_in_background());
+ value->updates_title_in_background =
+ ConvertFeatureFromProto(proto->updates_title_in_background());
+ value->uses_audio_in_background =
+ ConvertFeatureFromProto(proto->uses_audio_in_background());
+
+ if (proto->has_load_time_estimates()) {
+ const auto& load_time_estimates_proto = proto->load_time_estimates();
+ DCHECK(load_time_estimates_proto.has_avg_cpu_usage_us());
+ DCHECK(load_time_estimates_proto.has_avg_footprint_kb());
+
+ discards::mojom::SiteCharacteristicsPerformanceMeasurementPtr
+ load_time_estimates =
+ discards::mojom::SiteCharacteristicsPerformanceMeasurement::New();
+ if (load_time_estimates_proto.has_avg_cpu_usage_us()) {
+ load_time_estimates->avg_cpu_usage_us =
+ load_time_estimates_proto.avg_cpu_usage_us();
+ }
+ if (load_time_estimates_proto.has_avg_footprint_kb()) {
+ load_time_estimates->avg_footprint_kb =
+ load_time_estimates_proto.avg_footprint_kb();
+ }
+ if (load_time_estimates_proto.has_avg_load_duration_us()) {
+ load_time_estimates->avg_load_duration_us =
+ load_time_estimates_proto.avg_load_duration_us();
+ }
+
+ value->load_time_estimates = std::move(load_time_estimates);
+ }
+
+ discards::mojom::SiteCharacteristicsDatabaseEntryPtr entry =
+ discards::mojom::SiteCharacteristicsDatabaseEntry::New();
+ entry->value = std::move(value);
+ return entry;
+}
+
+} // namespace
+
+SiteDataProviderImpl::SiteDataProviderImpl(
+ resource_coordinator::LocalSiteCharacteristicsDataStoreInspector*
+ data_store_inspector,
+ mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver)
+ : data_store_inspector_(data_store_inspector),
+ receiver_(this, std::move(receiver)) {}
+
+SiteDataProviderImpl::~SiteDataProviderImpl() = default;
+
+void SiteDataProviderImpl::GetSiteCharacteristicsDatabase(
+ const std::vector<std::string>& explicitly_requested_origins,
+ GetSiteCharacteristicsDatabaseCallback callback) {
+ // Move all previously explicitly requested origins to this local map.
+ // Move any currently requested origins over to the member variable, or
+ // populate them if they weren't previously requested.
+ // The difference will remain in this map and go out of scope at the end of
+ // this function.
+ OriginToReaderMap prev_requested_origins;
+ prev_requested_origins.swap(requested_origins_);
+ resource_coordinator::SiteCharacteristicsDataStore* data_store =
+ data_store_inspector_->GetDataStore();
+ DCHECK(data_store);
+ for (const std::string& origin : explicitly_requested_origins) {
+ auto it = prev_requested_origins.find(origin);
+ if (it == prev_requested_origins.end()) {
+ GURL url(origin);
+ requested_origins_[origin] =
+ data_store->GetReaderForOrigin(url::Origin::Create(url));
+ } else {
+ requested_origins_[origin] = std::move(it->second);
+ }
+ }
+
+ discards::mojom::SiteCharacteristicsDatabasePtr result =
+ discards::mojom::SiteCharacteristicsDatabase::New();
+ std::vector<url::Origin> in_memory_origins =
+ data_store_inspector_->GetAllInMemoryOrigins();
+ for (const url::Origin& origin : in_memory_origins) {
+ // Get the data for this origin and convert it from proto to the
+ // corresponding mojo structure.
+ std::unique_ptr<SiteDataProto> proto;
+ bool is_dirty = false;
+ if (data_store_inspector_->GetDataForOrigin(origin, &is_dirty, &proto)) {
+ auto entry = ConvertEntryFromProto(proto.get());
+ entry->origin = origin.Serialize();
+ entry->is_dirty = is_dirty;
+ result->db_rows.push_back(std::move(entry));
+ }
+ }
+
+ // Return the result.
+ std::move(callback).Run(std::move(result));
+}
+
+void SiteDataProviderImpl::GetSiteCharacteristicsDatabaseSize(
+ GetSiteCharacteristicsDatabaseSizeCallback callback) {
+ // Adapt the inspector callback to the mojom callback with this lambda.
+ auto inspector_callback = base::BindOnce(
+ [](GetSiteCharacteristicsDatabaseSizeCallback callback,
+ base::Optional<int64_t> num_rows,
+ base::Optional<int64_t> on_disk_size_kb) {
+ discards::mojom::SiteCharacteristicsDatabaseSizePtr result =
+ discards::mojom::SiteCharacteristicsDatabaseSize::New();
+ result->num_rows = num_rows.has_value() ? num_rows.value() : -1;
+ result->on_disk_size_kb =
+ on_disk_size_kb.has_value() ? on_disk_size_kb.value() : -1;
+
+ std::move(callback).Run(std::move(result));
+ },
+ std::move(callback));
+
+ data_store_inspector_->GetDatabaseSize(std::move(inspector_callback));
+}
diff --git a/chromium/chrome/browser/ui/webui/discards/site_data_provider_impl.h b/chromium/chrome/browser/ui/webui/discards/site_data_provider_impl.h
new file mode 100644
index 00000000000..2d67c742cef
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/discards/site_data_provider_impl.h
@@ -0,0 +1,58 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_DISCARDS_SITE_DATA_PROVIDER_IMPL_H_
+#define CHROME_BROWSER_UI_WEBUI_DISCARDS_SITE_DATA_PROVIDER_IMPL_H_
+
+#include <map>
+#include <memory>
+
+#include "base/sequence_checker.h"
+#include "chrome/browser/ui/webui/discards/site_data.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace resource_coordinator {
+class LocalSiteCharacteristicsDataStoreInspector;
+class SiteCharacteristicsDataReader;
+} // namespace resource_coordinator
+
+class SiteDataProviderImpl : public discards::mojom::SiteDataProvider {
+ public:
+ SiteDataProviderImpl(
+ resource_coordinator::LocalSiteCharacteristicsDataStoreInspector*
+ data_store_inspector,
+ mojo::PendingReceiver<discards::mojom::SiteDataProvider> receiver);
+ ~SiteDataProviderImpl() override;
+ SiteDataProviderImpl(const SiteDataProviderImpl& other) = delete;
+ SiteDataProviderImpl& operator=(const SiteDataProviderImpl&) = delete;
+
+ void GetSiteCharacteristicsDatabase(
+ const std::vector<std::string>& explicitly_requested_origins,
+ GetSiteCharacteristicsDatabaseCallback callback) override;
+ void GetSiteCharacteristicsDatabaseSize(
+ GetSiteCharacteristicsDatabaseSizeCallback callback) override;
+
+ private:
+ using LocalSiteCharacteristicsDataStoreInspector =
+ resource_coordinator::LocalSiteCharacteristicsDataStoreInspector;
+ using SiteCharacteristicsDataReader =
+ resource_coordinator::SiteCharacteristicsDataReader;
+ using OriginToReaderMap =
+ std::map<std::string, std::unique_ptr<SiteCharacteristicsDataReader>>;
+
+ // This map pins requested readers and their associated data in memory until
+ // after the next read finishes. This is necessary to allow the database reads
+ // to go through and populate the requested entries.
+ OriginToReaderMap requested_origins_;
+
+ resource_coordinator::LocalSiteCharacteristicsDataStoreInspector*
+ data_store_inspector_ = nullptr;
+
+ mojo::Receiver<discards::mojom::SiteDataProvider> receiver_{this};
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_DISCARDS_SITE_DATA_PROVIDER_IMPL_H_
diff --git a/chromium/chrome/browser/ui/webui/domain_reliability_internals_ui.cc b/chromium/chrome/browser/ui/webui/domain_reliability_internals_ui.cc
index ad01bdc9b11..2a2e43e6b6b 100644
--- a/chromium/chrome/browser/ui/webui/domain_reliability_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/domain_reliability_internals_ui.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
diff --git a/chromium/chrome/browser/ui/webui/download_internals/download_internals_ui.cc b/chromium/chrome/browser/ui/webui/download_internals/download_internals_ui.cc
index 10c8baf3813..e63f09137ac 100644
--- a/chromium/chrome/browser/ui/webui/download_internals/download_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/download_internals/download_internals_ui.cc
@@ -9,7 +9,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/download_internals/download_internals_ui_message_handler.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
diff --git a/chromium/chrome/browser/ui/webui/downloads/BUILD.gn b/chromium/chrome/browser/ui/webui/downloads/BUILD.gn
index fae31c3fd7b..5e66ed80133 100644
--- a/chromium/chrome/browser/ui/webui/downloads/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/downloads/BUILD.gn
@@ -5,7 +5,5 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "downloads.mojom",
- ]
+ sources = [ "downloads.mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/downloads/OWNERS b/chromium/chrome/browser/ui/webui/downloads/OWNERS
index 23fd391d6d7..81029b10bbf 100644
--- a/chromium/chrome/browser/ui/webui/downloads/OWNERS
+++ b/chromium/chrome/browser/ui/webui/downloads/OWNERS
@@ -1,7 +1,5 @@
file://components/download/OWNERS
-dbeam@chromium.org
-
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/chrome/browser/ui/webui/downloads/downloads.mojom b/chromium/chrome/browser/ui/webui/downloads/downloads.mojom
index 4aa8113bce1..dfe2eaea6fd 100644
--- a/chromium/chrome/browser/ui/webui/downloads/downloads.mojom
+++ b/chromium/chrome/browser/ui/webui/downloads/downloads.mojom
@@ -47,6 +47,11 @@ interface PageHandler {
Cancel(string id);
ClearAll();
OpenDownloadsFolderRequiringGesture();
+
+ // Opens this download with the given |id| while it is being scanned by Safe
+ // Browsing. This completes the scan early. This requires a user gesture on
+ // the WebUI.
+ OpenDuringScanningRequiringGesture(string id);
};
interface Page {
diff --git a/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc b/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
index 1dd4c532238..f3c630fd91c 100644
--- a/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
+++ b/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.cc
@@ -38,7 +38,7 @@
#include "chrome/common/url_constants.h"
#include "components/download/public/common/download_item.h"
#include "components/prefs/pref_service.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/render_process_host.h"
@@ -71,6 +71,7 @@ enum DownloadsDOMEvent {
DOWNLOADS_DOM_EVENT_OPEN_FOLDER = 10,
DOWNLOADS_DOM_EVENT_RESUME = 11,
DOWNLOADS_DOM_EVENT_RETRY_DOWNLOAD = 12,
+ DOWNLOADS_DOM_EVENT_OPEN_DURING_SCANNING = 13,
DOWNLOADS_DOM_EVENT_MAX
};
@@ -214,8 +215,7 @@ void DownloadsDOMHandler::RetryDownload(const std::string& id) {
auto dl_params = std::make_unique<download::DownloadUrlParameters>(
url, render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRenderViewHost()->GetRoutingID(),
- render_frame_host->GetRoutingID(), traffic_annotation,
- file->GetNetworkIsolationKey());
+ render_frame_host->GetRoutingID(), traffic_annotation);
dl_params->set_content_initiated(true);
dl_params->set_initiator(url::Origin::Create(GURL("chrome://downloads")));
dl_params->set_download_source(download::DownloadSource::RETRY);
@@ -317,7 +317,7 @@ void DownloadsDOMHandler::RemoveDownloads(const DownloadVector& to_remove) {
IdSet ids;
for (auto* download : to_remove) {
- if (download->IsDangerous()) {
+ if (download->IsDangerous() || download->IsMixedContent()) {
// Don't allow users to revive dangerous downloads; just nuke 'em.
download->Remove();
continue;
@@ -355,6 +355,23 @@ void DownloadsDOMHandler::OpenDownloadsFolderRequiringGesture() {
}
}
+void DownloadsDOMHandler::OpenDuringScanningRequiringGesture(
+ const std::string& id) {
+ if (!GetWebUIWebContents()->HasRecentInteractiveInputEvent()) {
+ LOG(ERROR) << "OpenDownloadsFolderRequiringGesture received without recent "
+ "user interaction";
+ return;
+ }
+
+ CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_OPEN_DURING_SCANNING);
+ download::DownloadItem* download = GetDownloadByStringId(id);
+ if (download) {
+ DownloadItemModel model(download);
+ model.SetOpenWhenComplete(true);
+ model.CompleteSafeBrowsingScan();
+ }
+}
+
// DownloadsDOMHandler, private: --------------------------------------------
content::DownloadManager* DownloadsDOMHandler::GetMainNotifierManager() const {
@@ -402,6 +419,18 @@ void DownloadsDOMHandler::DangerPromptDone(
if (!item || item->IsDone())
return;
CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_SAVE_DANGEROUS);
+
+ // If a download is mixed content, validate that first. Is most cases, mixed
+ // content warnings will occur first, but in the worst case scenario, we show
+ // a dangerous warning twice. That's better than showing a mixed content
+ // warning, then dismissing the dangerous download warning. Since mixed
+ // content downloads triggering the UI are temporary and rare to begin with,
+ // this should very rarely occur.
+ if (item->IsMixedContent()) {
+ item->ValidateMixedContentDownload();
+ return;
+ }
+
item->ValidateDangerousDownload();
}
diff --git a/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.h b/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.h
index a66442d2c00..b91eca13de4 100644
--- a/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.h
+++ b/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler.h
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/download/download_danger_prompt.h"
-#include "chrome/browser/ui/webui/downloads/downloads.mojom.h"
+#include "chrome/browser/ui/webui/downloads/downloads.mojom-forward.h"
#include "chrome/browser/ui/webui/downloads/downloads_list_tracker.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -61,6 +61,7 @@ class DownloadsDOMHandler : public content::WebContentsObserver,
void Cancel(const std::string& id) override;
void ClearAll() override;
void OpenDownloadsFolderRequiringGesture() override;
+ void OpenDuringScanningRequiringGesture(const std::string& id) override;
protected:
// These methods are for mocking so that most of this class does not actually
diff --git a/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler_unittest.cc b/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler_unittest.cc
index 8b9d499e094..29caff3ed0c 100644
--- a/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/downloads/downloads_dom_handler_unittest.cc
@@ -15,7 +15,6 @@
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/mock_download_manager.h"
#include "content/public/test/test_web_ui.h"
-#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -92,6 +91,7 @@ TEST_F(DownloadsDOMHandlerTest, ClearAll) {
// Safe, in-progress items should be passed over.
testing::StrictMock<download::MockDownloadItem> in_progress;
EXPECT_CALL(in_progress, IsDangerous()).WillOnce(testing::Return(false));
+ EXPECT_CALL(in_progress, IsMixedContent()).WillOnce(testing::Return(false));
EXPECT_CALL(in_progress, IsTransient()).WillOnce(testing::Return(false));
EXPECT_CALL(in_progress, GetState())
.WillOnce(testing::Return(download::DownloadItem::IN_PROGRESS));
@@ -106,6 +106,7 @@ TEST_F(DownloadsDOMHandlerTest, ClearAll) {
// Completed items should be marked as hidden from the shelf.
testing::StrictMock<download::MockDownloadItem> completed;
EXPECT_CALL(completed, IsDangerous()).WillOnce(testing::Return(false));
+ EXPECT_CALL(completed, IsMixedContent()).WillOnce(testing::Return(false));
EXPECT_CALL(completed, IsTransient()).WillRepeatedly(testing::Return(false));
EXPECT_CALL(completed, GetState())
.WillOnce(testing::Return(download::DownloadItem::COMPLETE));
diff --git a/chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc b/chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
index 5b6896666c8..5fabbe1d591 100644
--- a/chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
+++ b/chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
@@ -75,6 +75,9 @@ const char* GetDangerTypeString(download::DownloadDangerType danger_type) {
return "DEEP_SCANNED_SAFE";
case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS:
return "DEEP_SCANNED_OPENED_DANGEROUS";
+ case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE:
+ return "BLOCKED_UNSUPPORTED_FILE_TYPE";
+ case download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING:
case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
@@ -272,6 +275,11 @@ downloads::mojom::DataPtr DownloadsListTracker::CreateDownloadData(
case download::DownloadItem::IN_PROGRESS: {
if (download_item->IsDangerous()) {
state = "DANGEROUS";
+ } else if (download_item->IsMixedContent()) {
+ state = "MIXED_CONTENT";
+ } else if (download_item->GetDangerType() ==
+ download::DOWNLOAD_DANGER_TYPE_ASYNC_SCANNING) {
+ state = "ASYNC_SCANNING";
} else if (download_item->IsPaused()) {
state = "PAUSED";
} else {
diff --git a/chromium/chrome/browser/ui/webui/downloads/downloads_ui.cc b/chromium/chrome/browser/ui/webui/downloads/downloads_ui.cc
index ef593e9194d..0f976c11afb 100644
--- a/chromium/chrome/browser/ui/webui/downloads/downloads_ui.cc
+++ b/chromium/chrome/browser/ui/webui/downloads/downloads_ui.cc
@@ -44,6 +44,7 @@
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/web_ui_util.h"
using content::BrowserContext;
using content::DownloadManager;
@@ -73,7 +74,7 @@ content::WebUIDataSource* CreateDownloadsUIHTMLSource(Profile* profile) {
bool requests_ap_verdicts =
safe_browsing::AdvancedProtectionStatusManagerFactory::GetForProfile(
profile)
- ->RequestsAdvancedProtectionVerdicts();
+ ->IsUnderAdvancedProtection();
source->AddBoolean("requestsApVerdicts", requests_ap_verdicts);
static constexpr webui::LocalizedString kStrings[] = {
@@ -122,6 +123,7 @@ content::WebUIDataSource* CreateDownloadsUIHTMLSource(Profile* profile) {
{"controlRemoveFromListAriaLabel", IDS_DOWNLOAD_LINK_REMOVE_ARIA_LABEL},
{"controlRetry", IDS_DOWNLOAD_LINK_RETRY},
{"controlledByUrl", IDS_DOWNLOAD_BY_EXTENSION_URL},
+ {"controlOpenNow", IDS_OPEN_DOWNLOAD_NOW},
{"toastClearedAll", IDS_DOWNLOAD_TOAST_CLEARED_ALL},
{"toastRemovedFromList", IDS_DOWNLOAD_TOAST_REMOVED_FROM_LIST},
{"undo", IDS_DOWNLOAD_UNDO},
@@ -137,7 +139,10 @@ content::WebUIDataSource* CreateDownloadsUIHTMLSource(Profile* profile) {
: IDS_BLOCK_REASON_UNCOMMON_DOWNLOAD);
source->AddLocalizedString("dangerSettingsDesc",
IDS_BLOCK_REASON_UNWANTED_DOWNLOAD);
-
+ source->AddLocalizedString("mixedContentDownloadDesc",
+ IDS_BLOCK_REASON_MIXED_CONTENT);
+ source->AddLocalizedString("asyncScanningDownloadDesc",
+ IDS_BLOCK_REASON_DEEP_SCANNING);
if (browser_defaults::kDownloadPageHasShowInFolder)
source->AddLocalizedString("controlShowInFolder", IDS_DOWNLOAD_LINK_SHOW);
@@ -185,11 +190,10 @@ DownloadsUI::DownloadsUI(content::WebUI* web_ui)
ManagedUIHandler::Initialize(web_ui, source);
content::WebUIDataSource::Add(profile, source);
content::URLDataSource::Add(profile, std::make_unique<ThemeSource>(profile));
-
- AddHandlerToRegistry(base::BindRepeating(&DownloadsUI::BindPageHandlerFactory,
- base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(DownloadsUI)
+
DownloadsUI::~DownloadsUI() = default;
// static
@@ -199,7 +203,7 @@ base::RefCountedMemory* DownloadsUI::GetFaviconResourceBytes(
IDR_DOWNLOADS_FAVICON, scale_factor);
}
-void DownloadsUI::BindPageHandlerFactory(
+void DownloadsUI::BindInterface(
mojo::PendingReceiver<downloads::mojom::PageHandlerFactory> receiver) {
page_factory_receiver_.reset();
diff --git a/chromium/chrome/browser/ui/webui/downloads/downloads_ui.h b/chromium/chrome/browser/ui/webui/downloads/downloads_ui.h
index ccb71d19076..0d3e2d6dd0c 100644
--- a/chromium/chrome/browser/ui/webui/downloads/downloads_ui.h
+++ b/chromium/chrome/browser/ui/webui/downloads/downloads_ui.h
@@ -30,10 +30,12 @@ class DownloadsUI : public ui::MojoWebUIController,
static base::RefCountedMemory* GetFaviconResourceBytes(
ui::ScaleFactor scale_factor);
- private:
- void BindPageHandlerFactory(
+ // Instantiates the implementor of the mojom::PageHandlerFactory mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<downloads::mojom::PageHandlerFactory> receiver);
+ private:
// downloads::mojom::PageHandlerFactory:
void CreatePageHandler(
mojo::PendingRemote<downloads::mojom::Page> page,
@@ -44,6 +46,8 @@ class DownloadsUI : public ui::MojoWebUIController,
mojo::Receiver<downloads::mojom::PageHandlerFactory> page_factory_receiver_{
this};
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(DownloadsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.cc b/chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.cc
index 03603cd5bfe..988985842be 100644
--- a/chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.cc
+++ b/chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.cc
@@ -16,7 +16,7 @@
#include "chrome/browser/engagement/site_engagement_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
@@ -91,15 +91,13 @@ SiteEngagementUI::SiteEngagementUI(content::WebUI* web_ui)
IDR_SITE_ENGAGEMENT_DETAILS_MOJOM_LITE_JS);
source->SetDefaultResource(IDR_SITE_ENGAGEMENT_HTML);
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source.release());
-
- AddHandlerToRegistry(
- base::BindRepeating(&SiteEngagementUI::BindSiteEngagementDetailsProvider,
- base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(SiteEngagementUI)
+
SiteEngagementUI::~SiteEngagementUI() {}
-void SiteEngagementUI::BindSiteEngagementDetailsProvider(
+void SiteEngagementUI::BindInterface(
mojo::PendingReceiver<mojom::SiteEngagementDetailsProvider> receiver) {
ui_handler_ = std::make_unique<SiteEngagementDetailsProviderImpl>(
Profile::FromWebUI(web_ui()), std::move(receiver));
diff --git a/chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.h b/chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.h
index 119a1229665..791fd7f299a 100644
--- a/chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.h
+++ b/chromium/chrome/browser/ui/webui/engagement/site_engagement_ui.h
@@ -6,7 +6,7 @@
#define CHROME_BROWSER_UI_WEBUI_ENGAGEMENT_SITE_ENGAGEMENT_UI_H_
#include "base/macros.h"
-#include "chrome/browser/engagement/site_engagement_details.mojom.h"
+#include "chrome/browser/engagement/site_engagement_details.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -16,12 +16,16 @@ class SiteEngagementUI : public ui::MojoWebUIController {
explicit SiteEngagementUI(content::WebUI* web_ui);
~SiteEngagementUI() override;
- private:
- void BindSiteEngagementDetailsProvider(
+ // Instantiates the implementor of the mojom::SiteEngagementDetailsProvider
+ // mojo interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<mojom::SiteEngagementDetailsProvider> receiver);
+ private:
std::unique_ptr<mojom::SiteEngagementDetailsProvider> ui_handler_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(SiteEngagementUI);
};
diff --git a/chromium/chrome/browser/ui/webui/explore_sites_internals/BUILD.gn b/chromium/chrome/browser/ui/webui/explore_sites_internals/BUILD.gn
index 2278f17b04b..80ac468a3d6 100644
--- a/chromium/chrome/browser/ui/webui/explore_sites_internals/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/explore_sites_internals/BUILD.gn
@@ -5,7 +5,5 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "explore_sites_internals.mojom",
- ]
+ sources = [ "explore_sites_internals.mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_page_handler.cc b/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_page_handler.cc
index b9a460ddfb3..0f6a2b188be 100644
--- a/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_page_handler.cc
+++ b/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_page_handler.cc
@@ -8,9 +8,9 @@
#include <vector>
#include "base/containers/flat_map.h"
-#include "chrome/browser/android/chrome_feature_list.h"
#include "chrome/browser/android/explore_sites/explore_sites_feature.h"
#include "chrome/browser/android/explore_sites/url_util.h"
+#include "chrome/browser/flags/android/chrome_feature_list.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals.mojom.h"
#include "components/language/core/browser/pref_names.h"
@@ -30,10 +30,6 @@ std::string GetChromeFlagsSetupString() {
return "Enabled";
case ExploreSitesVariation::EXPERIMENT:
return "Experiment";
- case ExploreSitesVariation::PERSONALIZED:
- return "Personalized";
- case ExploreSitesVariation::MOST_LIKELY:
- return "Most Likely";
case ExploreSitesVariation::DISABLED:
return "Disabled";
}
diff --git a/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.cc b/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.cc
index 803dc70251a..502ac7f8a17 100644
--- a/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.cc
@@ -6,8 +6,8 @@
#include "base/bind.h"
#include "build/build_config.h"
-#include "chrome/browser/android/chrome_feature_list.h"
#include "chrome/browser/android/explore_sites/explore_sites_service_factory.h"
+#include "chrome/browser/flags/android/chrome_feature_list.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals.mojom.h"
#include "chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_page_handler.h"
@@ -35,17 +35,13 @@ ExploreSitesInternalsUI::ExploreSitesInternalsUI(content::WebUI* web_ui)
explore_sites_service_ =
ExploreSitesServiceFactory::GetForBrowserContext(profile);
content::WebUIDataSource::Add(profile, source);
- // "BindExploreSitesInternalsPageHandler" will be invoked by
- // explore_sites_internals.js, which is only possible while this object is
- // alive, so this base::Unretained is safe.
- AddHandlerToRegistry(base::BindRepeating(
- &ExploreSitesInternalsUI::BindExploreSitesInternalsPageHandler,
- base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(ExploreSitesInternalsUI)
+
ExploreSitesInternalsUI::~ExploreSitesInternalsUI() {}
-void ExploreSitesInternalsUI::BindExploreSitesInternalsPageHandler(
+void ExploreSitesInternalsUI::BindInterface(
mojo::PendingReceiver<explore_sites_internals::mojom::PageHandler>
receiver) {
page_handler_ = std::make_unique<ExploreSitesInternalsPageHandler>(
diff --git a/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.h b/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.h
index 87fa86d06ec..4aa64b4ae1e 100644
--- a/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.h
+++ b/chromium/chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_ui.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/macros.h"
-#include "chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals.mojom.h"
+#include "chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals.mojom-forward.h"
#include "chrome/browser/ui/webui/explore_sites_internals/explore_sites_internals_page_handler.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -23,14 +23,18 @@ class ExploreSitesInternalsUI : public ui::MojoWebUIController {
explicit ExploreSitesInternalsUI(content::WebUI* web_ui);
~ExploreSitesInternalsUI() override;
- private:
- void BindExploreSitesInternalsPageHandler(
+ // Instantiates the implementor of the mojom::PageHandler mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<explore_sites_internals::mojom::PageHandler>
receiver);
+ private:
std::unique_ptr<ExploreSitesInternalsPageHandler> page_handler_;
ExploreSitesService* explore_sites_service_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(ExploreSitesInternalsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc b/chromium/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
index c70d287c4d4..8f200c7beb7 100644
--- a/chromium/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
+++ b/chromium/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
@@ -21,6 +21,7 @@
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/profiles/profile.h"
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/settings/cros_settings_names.h"
#include "components/crx_file/id_util.h"
diff --git a/chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.cc b/chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.cc
index e7d239f2ff7..3b391f2bc25 100644
--- a/chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.cc
@@ -10,6 +10,7 @@
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
#include "chrome/browser/extensions/activity_log/activity_log.h"
#include "chrome/browser/extensions/api/developer_private/developer_private_api.h"
#include "chrome/browser/extensions/chrome_test_extension_loader.h"
@@ -96,12 +97,6 @@ void ExtensionSettingsUIBrowserTest::SetAutoConfirmUninstall() {
extensions::ScopedTestDialogAutoConfirm::ACCEPT);
}
-void ExtensionSettingsUIBrowserTest::EnableErrorConsole() {
- error_console_override_ =
- std::make_unique<extensions::FeatureSwitch::ScopedOverride>(
- extensions::FeatureSwitch::error_console(), true);
-}
-
void ExtensionSettingsUIBrowserTest::SetDevModeEnabled(bool enabled) {
browser()->profile()->GetPrefs()->SetBoolean(
prefs::kExtensionsUIDeveloperMode, enabled);
@@ -203,7 +198,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsUIBrowserTest, ListenerRegistration) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL("chrome://extensions"),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
{
SCOPED_TRACE("With page loaded");
@@ -222,8 +217,15 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsUIBrowserTest, ListenerRegistration) {
}
}
+// Flaky on Windows: crbug.com/
+#if defined(OS_WIN)
+#define MAYBE_ActivityLogInactiveWithoutSwitch \
+ DISABLED_ActivityLogInactiveWithoutSwitch
+#else
+#define MAYBE_ActivityLogInactiveWithoutSwitch ActivityLogInactiveWithoutSwitch
+#endif // OS_WIN
IN_PROC_BROWSER_TEST_F(ExtensionSettingsUIBrowserTest,
- ActivityLogInactiveWithoutSwitch) {
+ MAYBE_ActivityLogInactiveWithoutSwitch) {
// Navigate to chrome://extensions which is a whitelisted URL for the
// chrome.activityLogPrivate API.
GURL extensions_url("chrome://extensions");
diff --git a/chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.h b/chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.h
index a74021ec537..f1f50ca37c7 100644
--- a/chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.h
+++ b/chromium/chrome/browser/ui/webui/extensions/extension_settings_browsertest.h
@@ -13,7 +13,6 @@
#include "chrome/test/base/web_ui_browser_test.h"
#include "extensions/browser/scoped_ignore_content_verifier_for_test.h"
#include "extensions/browser/test_management_policy.h"
-#include "extensions/common/feature_switch.h"
namespace extensions {
class Extension;
@@ -72,10 +71,6 @@ class ExtensionSettingsUIBrowserTest : public WebUIBrowserTest {
// Disable extension install verification.
extensions::ScopedInstallVerifierBypassForTest ignore_install_verification_;
- // Used to enable the error console.
- std::unique_ptr<extensions::FeatureSwitch::ScopedOverride>
- error_console_override_;
-
std::unique_ptr<extensions::ScopedTestDialogAutoConfirm>
uninstall_auto_confirm_;
diff --git a/chromium/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chromium/chrome/browser/ui/webui/extensions/extensions_ui.cc
index 9d525dc5b29..e8519afadf8 100644
--- a/chromium/chrome/browser/ui/webui/extensions/extensions_ui.cc
+++ b/chromium/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -10,10 +10,13 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/chrome_extension_browser_constants.h"
+#include "chrome/browser/extensions/extension_checkup.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/managed_ui_handler.h"
#include "chrome/browser/ui/webui/metrics_handler.h"
@@ -35,9 +38,11 @@
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "extensions/browser/extension_prefs.h"
+#include "extensions/common/extension_features.h"
#include "extensions/common/extension_urls.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/web_ui_util.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
@@ -69,6 +74,9 @@ content::WebUIDataSource* CreateMdExtensionsSource(Profile* profile,
webui::SetupBundledWebUIDataSource(source, "extensions.js",
IDR_EXTENSIONS_EXTENSIONS_ROLLUP_JS,
IDR_EXTENSIONS_EXTENSIONS_HTML);
+ source->AddResourcePath("checkup_image.svg", IDR_EXTENSIONS_CHECKUP_IMAGE);
+ source->AddResourcePath("checkup_image_dark.svg",
+ IDR_EXTENSIONS_CHECKUP_IMAGE_DARK);
#else
webui::SetupWebUIDataSource(
source, base::make_span(kExtensionsResources, kExtensionsResourcesSize),
@@ -235,6 +243,7 @@ content::WebUIDataSource* CreateMdExtensionsSource(Profile* profile,
{"shortcutScopeGlobal", IDS_EXTENSIONS_SHORTCUT_SCOPE_GLOBAL},
{"shortcutScopeLabel", IDS_EXTENSIONS_SHORTCUT_SCOPE_LABEL},
{"shortcutScopeInChrome", IDS_EXTENSIONS_SHORTCUT_SCOPE_IN_CHROME},
+ {"shortcutSet", IDS_EXTENSIONS_SHORTCUT_SET},
{"shortcutTypeAShortcut", IDS_EXTENSIONS_TYPE_A_SHORTCUT},
{"shortcutIncludeStartModifier", IDS_EXTENSIONS_INCLUDE_START_MODIFIER},
{"shortcutTooManyModifiers", IDS_EXTENSIONS_TOO_MANY_MODIFIERS},
@@ -307,6 +316,39 @@ content::WebUIDataSource* CreateMdExtensionsSource(Profile* profile,
source->AddBoolean(kShowActivityLogKey,
base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kEnableExtensionActivityLogging));
+
+ bool checkup_enabled =
+ base::FeatureList::IsEnabled(extensions_features::kExtensionsCheckup);
+ source->AddBoolean("showCheckup", checkup_enabled);
+ if (checkup_enabled) {
+ int title_id = 0;
+ int body1_id = 0;
+ int body2_id = 0;
+ switch (GetCheckupMessageFocus()) {
+ case CheckupMessage::PERFORMANCE:
+ title_id = IDS_EXTENSIONS_CHECKUP_BANNER_PERFORMANCE_TITLE;
+ body1_id = IDS_EXTENSIONS_CHECKUP_BANNER_PERFORMANCE_BODY1;
+ body2_id = IDS_EXTENSIONS_CHECKUP_BANNER_PERFORMANCE_BODY2;
+ break;
+ case CheckupMessage::PRIVACY:
+ title_id = IDS_EXTENSIONS_CHECKUP_BANNER_PRIVACY_TITLE;
+ body1_id = IDS_EXTENSIONS_CHECKUP_BANNER_PRIVACY_BODY1;
+ body2_id = IDS_EXTENSIONS_CHECKUP_BANNER_PRIVACY_BODY2;
+ break;
+ case CheckupMessage::NEUTRAL:
+ title_id = IDS_EXTENSIONS_CHECKUP_BANNER_NEUTRAL_TITLE;
+ body1_id = IDS_EXTENSIONS_CHECKUP_BANNER_NEUTRAL_BODY1;
+ body2_id = IDS_EXTENSIONS_CHECKUP_BANNER_NEUTRAL_BODY2;
+ break;
+ }
+ source->AddLocalizedString("checkupTitle", title_id);
+ source->AddLocalizedString("checkupBody1", body1_id);
+ source->AddLocalizedString("checkupBody2", body2_id);
+ } else {
+ source->AddString("checkupTitle", "");
+ source->AddString("checkupBody1", "");
+ source->AddString("checkupBody2", "");
+ }
source->AddString(kLoadTimeClassesKey, GetLoadTimeClasses(in_dev_mode));
return source;
@@ -315,7 +357,8 @@ content::WebUIDataSource* CreateMdExtensionsSource(Profile* profile,
} // namespace
ExtensionsUI::ExtensionsUI(content::WebUI* web_ui)
- : WebUIController(web_ui),
+ : WebContentsObserver(web_ui->GetWebContents()),
+ WebUIController(web_ui),
webui_load_timer_(web_ui->GetWebContents(),
"Extensions.WebUi.DocumentLoadedInMainFrameTime.MD",
"Extensions.WebUi.LoadCompletedInMainFrame.MD") {
@@ -354,7 +397,14 @@ ExtensionsUI::ExtensionsUI(content::WebUI* web_ui)
}
}
-ExtensionsUI::~ExtensionsUI() {}
+ExtensionsUI::~ExtensionsUI() {
+ if (timer_.has_value())
+ UMA_HISTOGRAM_LONG_TIMES("Extensions.Checkup.TimeSpent", timer_->Elapsed());
+}
+
+void ExtensionsUI::DidStopLoading() {
+ timer_ = base::ElapsedTimer();
+}
// static
base::RefCountedMemory* ExtensionsUI::GetFaviconResourceBytes(
diff --git a/chromium/chrome/browser/ui/webui/extensions/extensions_ui.h b/chromium/chrome/browser/ui/webui/extensions/extensions_ui.h
index 71e5e754f91..1ed8c8dd6b8 100644
--- a/chromium/chrome/browser/ui/webui/extensions/extensions_ui.h
+++ b/chromium/chrome/browser/ui/webui/extensions/extensions_ui.h
@@ -6,8 +6,10 @@
#define CHROME_BROWSER_UI_WEBUI_EXTENSIONS_EXTENSIONS_UI_H_
#include "base/macros.h"
+#include "base/timer/elapsed_timer.h"
#include "chrome/browser/ui/webui/webui_load_timer.h"
#include "components/prefs/pref_member.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_controller.h"
#include "ui/base/layout.h"
@@ -21,7 +23,8 @@ class PrefRegistrySyncable;
namespace extensions {
-class ExtensionsUI : public content::WebUIController {
+class ExtensionsUI : public content::WebContentsObserver,
+ public content::WebUIController {
public:
explicit ExtensionsUI(content::WebUI* web_ui);
~ExtensionsUI() override;
@@ -32,6 +35,9 @@ class ExtensionsUI : public content::WebUIController {
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
private:
+ // content::WebContentsObserver:
+ void DidStopLoading() override;
+
// Called when developer mode is toggled.
void OnDevModeChanged();
@@ -40,6 +46,9 @@ class ExtensionsUI : public content::WebUIController {
WebuiLoadTimer webui_load_timer_;
+ // Time the chrome://extensions page has been open.
+ base::Optional<base::ElapsedTimer> timer_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/favicon_source.cc b/chromium/chrome/browser/ui/webui/favicon_source.cc
index 111fed9a9fe..17eca9e53f0 100644
--- a/chromium/chrome/browser/ui/webui/favicon_source.cc
+++ b/chromium/chrome/browser/ui/webui/favicon_source.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
#include "chrome/browser/favicon/favicon_utils.h"
@@ -21,7 +21,11 @@
#include "components/favicon/core/history_ui_favicon_request_handler.h"
#include "components/favicon_base/favicon_url_parser.h"
#include "components/history/core/browser/top_sites.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/manifest.h"
#include "net/url_request/url_request.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/layout.h"
@@ -81,6 +85,7 @@ void FaviconSource::StartDataRequest(
const GURL& url,
const content::WebContents::Getter& wc_getter,
content::URLDataSource::GotDataCallback callback) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
const std::string path = content::URLDataSource::URLToRequestPath(url);
favicon::FaviconService* favicon_service =
FaviconServiceFactory::GetForProfile(profile_,
@@ -104,6 +109,18 @@ void FaviconSource::StartDataRequest(
return;
}
+ if (url_format_ == chrome::FaviconUrlFormat::kFaviconLegacy) {
+ const extensions::Extension* extension =
+ extensions::ExtensionRegistry::Get(profile_)
+ ->enabled_extensions()
+ .GetExtensionOrAppByURL(GetUnsafeRequestOrigin(wc_getter));
+ if (extension) {
+ base::UmaHistogramEnumeration("Extensions.FaviconResourceRequested",
+ extension->GetType(),
+ extensions::Manifest::NUM_LOAD_TYPES);
+ }
+ }
+
int desired_size_in_pixel =
std::ceil(parsed.size_in_dip * parsed.device_scale_factor);
@@ -167,7 +184,7 @@ void FaviconSource::StartDataRequest(
base::BindOnce(&FaviconSource::OnFaviconDataAvailable,
weak_ptr_factory_.GetWeakPtr(), std::move(callback),
parsed),
- favicon::FaviconRequestPlatform::kDesktop, parsed_history_ui_origin,
+ parsed_history_ui_origin,
/*icon_url_for_uma=*/
GURL(parsed.icon_url));
}
diff --git a/chromium/chrome/browser/ui/webui/favicon_source_unittest.cc b/chromium/chrome/browser/ui/webui/favicon_source_unittest.cc
index 78f08caf786..d9755279e48 100644
--- a/chromium/chrome/browser/ui/webui/favicon_source_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/favicon_source_unittest.cc
@@ -7,8 +7,11 @@
#include <memory>
#include <utility>
+#include "base/bind_helpers.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/strcat.h"
#include "base/test/bind_test_util.h"
+#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/favicon/favicon_service_factory.h"
#include "chrome/browser/favicon/history_ui_favicon_request_handler_factory.h"
#include "chrome/browser/profiles/profile.h"
@@ -21,6 +24,9 @@
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/web_contents_tester.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/common/extension_builder.h"
+#include "extensions/common/manifest.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/native_theme/test_native_theme.h"
@@ -47,12 +53,11 @@ class MockHistoryUiFaviconRequestHandler
MockHistoryUiFaviconRequestHandler() = default;
~MockHistoryUiFaviconRequestHandler() override = default;
- MOCK_METHOD6(
+ MOCK_METHOD5(
GetRawFaviconForPageURL,
void(const GURL& page_url,
int desired_size_in_pixel,
favicon_base::FaviconRawBitmapCallback callback,
- favicon::FaviconRequestPlatform request_platform,
favicon::HistoryUiFaviconRequestOrigin request_origin_for_uma,
const GURL& icon_url_for_uma));
@@ -122,10 +127,10 @@ class FaviconSourceTestBase : public testing::Test {
return kDummyTaskId;
});
ON_CALL(*mock_history_ui_favicon_request_handler_,
- GetRawFaviconForPageURL(_, _, _, _, _, _))
+ GetRawFaviconForPageURL(_, _, _, _, _))
.WillByDefault([](auto, auto,
favicon_base::FaviconRawBitmapCallback callback, auto,
- auto, auto) {
+ auto) {
std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
});
@@ -190,6 +195,44 @@ TEST_F(FaviconSourceTestWithLegacyFormat,
test_web_contents_getter_, base::BindRepeating(&Noop));
}
+TEST_F(FaviconSourceTestWithLegacyFormat,
+ ShouldRecordFaviconResourceHistogram_NonExtensionOrigin) {
+ base::HistogramTester tester;
+ source()->StartDataRequest(
+ GURL(base::StrCat({kDummyPrefix, "size/16@1x/https://www.google.com"})),
+ test_web_contents_getter_, base::DoNothing());
+ tester.ExpectBucketCount("Extensions.FaviconResourceRequested",
+ extensions::Manifest::TYPE_EXTENSION, 0);
+}
+
+TEST_F(FaviconSourceTestWithLegacyFormat,
+ ShouldRecordFaviconResourceHistogram_ExtensionOrigin) {
+ scoped_refptr<const extensions::Extension> extension =
+ extensions::ExtensionBuilder("one").Build();
+ extensions::ExtensionRegistry::Get(&profile_)->AddEnabled(extension);
+ content::WebContentsTester::For(test_web_contents_.get())
+ ->SetLastCommittedURL(extension->url());
+ base::HistogramTester tester;
+ source()->StartDataRequest(
+ GURL(base::StrCat({kDummyPrefix, "size/16@1x/https://www.google.com"})),
+ test_web_contents_getter_, base::DoNothing());
+ tester.ExpectBucketCount("Extensions.FaviconResourceRequested",
+ extensions::Manifest::TYPE_EXTENSION, 1);
+}
+
+TEST_F(FaviconSourceTestWithFavicon2Format,
+ ShouldNotRecordFaviconResourceHistogram) {
+ base::HistogramTester tester;
+ source()->StartDataRequest(
+ GURL(base::StrCat({kDummyPrefix, "size/16@1x/https://www.google.com"})),
+ test_web_contents_getter_, base::BindRepeating(&Noop));
+ std::unique_ptr<base::HistogramSamples> samples(
+ tester.GetHistogramSamplesSinceCreation(
+ "Extensions.FaviconResourceUsed"));
+ EXPECT_TRUE(samples);
+ EXPECT_EQ(0, samples->TotalCount());
+}
+
TEST_F(FaviconSourceTestWithFavicon2Format, DarkDefault) {
SetDarkMode(true);
EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON_DARK));
@@ -246,7 +289,7 @@ TEST_F(
EXPECT_CALL(
*mock_history_ui_favicon_request_handler_,
- GetRawFaviconForPageURL(GURL("https://www.google.com"), _, _, _, _, _))
+ GetRawFaviconForPageURL(GURL("https://www.google.com"), _, _, _, _))
.Times(1);
source()->StartDataRequest(
diff --git a/chromium/chrome/browser/ui/webui/feed_internals/BUILD.gn b/chromium/chrome/browser/ui/webui/feed_internals/BUILD.gn
index 846c29a4ccc..a4633c35f5a 100644
--- a/chromium/chrome/browser/ui/webui/feed_internals/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/feed_internals/BUILD.gn
@@ -5,11 +5,7 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "feed_internals.mojom",
- ]
+ sources = [ "feed_internals.mojom" ]
- public_deps = [
- "//url/mojom:url_mojom_gurl",
- ]
+ public_deps = [ "//url/mojom:url_mojom_gurl" ]
}
diff --git a/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc b/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc
index d511af87532..e8b0ad925e7 100644
--- a/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc
+++ b/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.cc
@@ -15,9 +15,10 @@
#include "chrome/browser/ui/webui/feed_internals/feed_internals.mojom.h"
#include "components/feed/content/feed_host_service.h"
#include "components/feed/content/feed_offline_host.h"
+#include "components/feed/core/common/pref_names.h"
+#include "components/feed/core/common/user_classifier.h"
#include "components/feed/core/feed_scheduler_host.h"
-#include "components/feed/core/pref_names.h"
-#include "components/feed/core/user_classifier.h"
+#include "components/feed/core/shared_prefs/pref_names.h"
#include "components/feed/feed_feature_list.h"
#include "components/offline_pages/core/prefetch/prefetch_prefs.h"
#include "components/offline_pages/core/prefetch/suggestions_provider.h"
@@ -34,15 +35,15 @@ feed_internals::mojom::TimePtr ToMojoTime(base::Time time) {
: feed_internals::mojom::Time::New(time.ToJsTime());
}
-std::string TriggerTypeToString(feed::FeedSchedulerHost::TriggerType* trigger) {
+std::string TriggerTypeToString(feed::TriggerType* trigger) {
if (trigger == nullptr)
return "Not set";
switch (*trigger) {
- case feed::FeedSchedulerHost::TriggerType::kNtpShown:
+ case feed::TriggerType::kNtpShown:
return "NTP Shown";
- case feed::FeedSchedulerHost::TriggerType::kForegrounded:
+ case feed::TriggerType::kForegrounded:
return "Foregrounded";
- case feed::FeedSchedulerHost::TriggerType::kFixedTimer:
+ case feed::TriggerType::kFixedTimer:
return "Fixed Timer";
}
}
diff --git a/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.cc b/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.cc
index 051f6fe93d7..dab3013f730 100644
--- a/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.cc
@@ -12,7 +12,7 @@
#include "chrome/browser/ui/webui/feed_internals/feed_internals.mojom.h"
#include "chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "content/public/browser/web_ui_data_source.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -28,15 +28,13 @@ FeedInternalsUI::FeedInternalsUI(content::WebUI* web_ui)
source->SetDefaultResource(IDR_FEED_INTERNALS_HTML);
content::WebUIDataSource::Add(profile_, source);
- // This class is the caller of the callback when an observer interface is
- // triggered. So this base::Unretained is safe.
- AddHandlerToRegistry(base::BindRepeating(
- &FeedInternalsUI::BindFeedInternalsPageHandler, base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(FeedInternalsUI)
+
FeedInternalsUI::~FeedInternalsUI() = default;
-void FeedInternalsUI::BindFeedInternalsPageHandler(
+void FeedInternalsUI::BindInterface(
mojo::PendingReceiver<feed_internals::mojom::PageHandler> receiver) {
page_handler_ = std::make_unique<FeedInternalsPageHandler>(
std::move(receiver),
diff --git a/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.h b/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.h
index 662b9bb65bd..01cc6bb45a8 100644
--- a/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.h
+++ b/chromium/chrome/browser/ui/webui/feed_internals/feed_internals_ui.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/macros.h"
-#include "chrome/browser/ui/webui/feed_internals/feed_internals.mojom.h"
+#include "chrome/browser/ui/webui/feed_internals/feed_internals.mojom-forward.h"
#include "chrome/browser/ui/webui/feed_internals/feed_internals_page_handler.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -27,14 +27,18 @@ class FeedInternalsUI : public ui::MojoWebUIController {
explicit FeedInternalsUI(content::WebUI* web_ui);
~FeedInternalsUI() override;
- private:
- void BindFeedInternalsPageHandler(
+ // Instantiates the implementor of the feed_internals::mojom::PageHandler mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<feed_internals::mojom::PageHandler> receiver);
+ private:
Profile* profile_;
std::unique_ptr<FeedInternalsPageHandler> page_handler_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(FeedInternalsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/flags_ui.cc b/chromium/chrome/browser/ui/webui/flags_ui.cc
index 6bce6f8dd26..6754133e497 100644
--- a/chromium/chrome/browser/ui/webui/flags_ui.cc
+++ b/chromium/chrome/browser/ui/webui/flags_ui.cc
@@ -37,15 +37,21 @@
#include "ui/base/resource/resource_bundle.h"
#if defined(OS_CHROMEOS)
+#include "base/command_line.h"
#include "base/system/sys_info.h"
#include "chrome/browser/chromeos/login/session/user_session_manager.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/owner_flags_storage.h"
+#include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/grit/generated_resources.h"
+#include "chromeos/constants/chromeos_switches.h"
#include "components/account_id/account_id.h"
+#include "components/infobars/core/simple_alert_infobar_delegate.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/user_manager/user_manager.h"
+#include "components/vector_icons/vector_icons.h"
#endif
using content::WebContents;
@@ -112,6 +118,17 @@ void FinishInitialization(base::WeakPtr<T> flags_ui,
new flags_ui::PrefServiceFlagsStorage(profile->GetPrefs()),
flags_ui::kGeneralAccessFlagsOnly);
}
+
+ // Show a warning info bar when kSafeMode switch is present.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ chromeos::switches::kSafeMode)) {
+ SimpleAlertInfoBarDelegate::Create(
+ InfoBarService::FromWebContents(flags_ui->web_ui()->GetWebContents()),
+ infobars::InfoBarDelegate::BAD_FLAGS_INFOBAR_DELEGATE,
+ &vector_icons::kWarningIcon,
+ l10n_util::GetStringUTF16(IDS_FLAGS_IGNORED_DUE_TO_CRASHY_CHROME),
+ /*auto_expire=*/false, /*should_animate=*/true);
+ }
}
#endif
diff --git a/chromium/chrome/browser/ui/webui/flags_ui_handler.cc b/chromium/chrome/browser/ui/webui/flags_ui_handler.cc
index 3661f832926..a340b551445 100644
--- a/chromium/chrome/browser/ui/webui/flags_ui_handler.cc
+++ b/chromium/chrome/browser/ui/webui/flags_ui_handler.cc
@@ -116,8 +116,10 @@ void FlagsUIHandler::HandleEnableExperimentalFeatureMessage(
std::string entry_internal_name;
std::string enable_str;
if (!args->GetString(0, &entry_internal_name) ||
- !args->GetString(1, &enable_str))
+ !args->GetString(1, &enable_str) || entry_internal_name.empty()) {
+ NOTREACHED();
return;
+ }
about_flags::SetFeatureEntryEnabled(flags_storage_.get(), entry_internal_name,
enable_str == "true");
diff --git a/chromium/chrome/browser/ui/webui/gcm_internals_ui.cc b/chromium/chrome/browser/ui/webui/gcm_internals_ui.cc
index 6fcce1ae41a..4449023832d 100644
--- a/chromium/chrome/browser/ui/webui/gcm_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/gcm_internals_ui.cc
@@ -20,7 +20,7 @@
#include "components/gcm_driver/gcm_internals_constants.h"
#include "components/gcm_driver/gcm_internals_helper.h"
#include "components/gcm_driver/gcm_profile_service.h"
-#include "components/grit/components_resources.h"
+#include "components/grit/dev_ui_components_resources.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
diff --git a/chromium/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chromium/chrome/browser/ui/webui/help/version_updater_chromeos.cc
index c93b9b199b2..090006fbca0 100644
--- a/chromium/chrome/browser/ui/webui/help/version_updater_chromeos.cc
+++ b/chromium/chrome/browser/ui/webui/help/version_updater_chromeos.cc
@@ -55,9 +55,6 @@ NetworkStatus GetNetworkStatus(bool interactive,
if (!network || !network->IsConnectedState()) // Offline state.
return NETWORK_STATUS_OFFLINE;
- if (network->type() == shill::kTypeBluetooth)
- return NETWORK_STATUS_DISALLOWED;
-
// Treats tethered networks as cellular networks.
if (network->IsUsingMobileData() &&
!help_utils_chromeos::IsUpdateOverCellularAllowed(interactive)) {
diff --git a/chromium/chrome/browser/ui/webui/help/version_updater_mac.mm b/chromium/chrome/browser/ui/webui/help/version_updater_mac.mm
index e339760732f..4550497b5ab 100644
--- a/chromium/chrome/browser/ui/webui/help/version_updater_mac.mm
+++ b/chromium/chrome/browser/ui/webui/help/version_updater_mac.mm
@@ -21,7 +21,7 @@
// updates. It will be created and managed by VersionUpdaterMac.
@interface KeystoneObserver : NSObject {
@private
- VersionUpdaterMac* versionUpdater_; // Weak.
+ VersionUpdaterMac* _versionUpdater; // Weak.
}
// Initialize an observer with an updater. The updater owns this object.
@@ -36,7 +36,7 @@
- (id)initWithUpdater:(VersionUpdaterMac*)updater {
if ((self = [super init])) {
- versionUpdater_ = updater;
+ _versionUpdater = updater;
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(handleStatusNotification:)
@@ -52,7 +52,7 @@
}
- (void)handleStatusNotification:(NSNotification*)notification {
- versionUpdater_->UpdateStatus([notification userInfo]);
+ _versionUpdater->UpdateStatus([notification userInfo]);
}
@end // @implementation KeystoneObserver
@@ -176,7 +176,6 @@ void VersionUpdaterMac::UpdateStatus(NSDictionary* dictionary) {
break;
case kAutoupdatePromoting:
-#if 1
// TODO(mark): KSRegistration currently handles the promotion
// synchronously, meaning that the main thread's loop doesn't spin,
// meaning that animations and other updates to the window won't occur
@@ -185,10 +184,6 @@ void VersionUpdaterMac::UpdateStatus(NSDictionary* dictionary) {
// visual feedback while promotion is in progress, but it should complete
// (or fail) very quickly. http://b/2290009.
return;
-#endif
- status = CHECKING;
- enable_promote_button = false;
- break;
case kAutoupdateRegisterFailed:
enable_promote_button = false;
diff --git a/chromium/chrome/browser/ui/webui/help/version_updater_win.cc b/chromium/chrome/browser/ui/webui/help/version_updater_win.cc
index 6467d6e1dca..f77d46664fd 100644
--- a/chromium/chrome/browser/ui/webui/help/version_updater_win.cc
+++ b/chromium/chrome/browser/ui/webui/help/version_updater_win.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/win/win_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/first_run/upgrade_util.h"
@@ -40,13 +41,11 @@ void VersionUpdaterWin::OnUpdateCheckComplete(
if (new_version.empty()) {
// Google Update says that no new version is available. Check to see if a
// restart is needed for a previously-applied update to take effect.
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
- base::Bind(&upgrade_util::IsUpdatePendingRestart),
- base::Bind(&VersionUpdaterWin::OnPendingRestartCheck,
- weak_factory_.GetWeakPtr()));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(&upgrade_util::IsUpdatePendingRestart),
+ base::BindOnce(&VersionUpdaterWin::OnPendingRestartCheck,
+ weak_factory_.GetWeakPtr()));
// Early exit since callback_ will be Run in OnPendingRestartCheck.
return;
}
diff --git a/chromium/chrome/browser/ui/webui/history/browsing_history_handler.cc b/chromium/chrome/browser/ui/webui/history/browsing_history_handler.cc
index 0e668084532..426bf5301ad 100644
--- a/chromium/chrome/browser/ui/webui/history/browsing_history_handler.cc
+++ b/chromium/chrome/browser/ui/webui/history/browsing_history_handler.cc
@@ -104,8 +104,8 @@ void GetDeviceNameAndType(const syncer::DeviceInfoTracker* tracker,
// Formats |entry|'s URL and title and adds them to |result|.
void SetHistoryEntryUrlAndTitle(
const BrowsingHistoryService::HistoryEntry& entry,
- base::DictionaryValue* result) {
- result->SetString("url", entry.url.spec());
+ base::Value* result) {
+ result->SetStringKey("url", entry.url.spec());
bool using_url_as_the_title = false;
base::string16 title_to_set(entry.title);
@@ -130,7 +130,7 @@ void SetHistoryEntryUrlAndTitle(
if (title_to_set.size() > kShortTitleLength)
title_to_set.resize(kShortTitleLength);
- result->SetString("title", title_to_set);
+ result->SetStringKey("title", title_to_set);
}
// Helper function to check if entry is present in user remote data (server-side
@@ -149,15 +149,15 @@ bool IsEntryInRemoteUserData(
return false;
}
-// Converts |entry| to a DictionaryValue to be owned by the caller.
-std::unique_ptr<base::DictionaryValue> HistoryEntryToValue(
+// Converts |entry| to a base::Value to be owned by the caller.
+base::Value HistoryEntryToValue(
const BrowsingHistoryService::HistoryEntry& entry,
BookmarkModel* bookmark_model,
Profile* profile,
const syncer::DeviceInfoTracker* tracker,
base::Clock* clock) {
- std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
- SetHistoryEntryUrlAndTitle(entry, result.get());
+ base::Value result(base::Value::Type::DICTIONARY);
+ SetHistoryEntryUrlAndTitle(entry, &result);
base::string16 domain = url_formatter::IDNToUnicode(entry.url.host());
// When the domain is empty, use the scheme instead. This allows for a
@@ -169,25 +169,24 @@ std::unique_ptr<base::DictionaryValue> HistoryEntryToValue(
// chrome/browser/resources/history/history.js in @typedef for
// HistoryEntry. Please update it whenever you add or remove
// any keys in result.
- result->SetString("domain", domain);
+ result.SetStringKey("domain", domain);
- result->SetString(
+ result.SetStringKey(
"fallbackFaviconText",
base::UTF16ToASCII(favicon::GetFallbackIconText(entry.url)));
- result->SetDouble("time", entry.time.ToJsTime());
+ result.SetDoubleKey("time", entry.time.ToJsTime());
// Pass the timestamps in a list.
- std::unique_ptr<base::ListValue> timestamps(new base::ListValue);
+ base::Value timestamps(base::Value::Type::LIST);
for (int64_t timestamp : entry.all_timestamps) {
- timestamps->AppendDouble(
- base::Time::FromInternalValue(timestamp).ToJsTime());
+ timestamps.Append(base::Time::FromInternalValue(timestamp).ToJsTime());
}
- result->Set("allTimestamps", std::move(timestamps));
+ result.SetKey("allTimestamps", std::move(timestamps));
// Always pass the short date since it is needed both in the search and in
// the monthly view.
- result->SetString("dateShort", base::TimeFormatShortDate(entry.time));
+ result.SetStringKey("dateShort", base::TimeFormatShortDate(entry.time));
base::string16 snippet_string;
base::string16 date_relative_day;
@@ -219,8 +218,8 @@ std::unique_ptr<base::DictionaryValue> HistoryEntryToValue(
std::string device_type;
if (!entry.client_id.empty())
GetDeviceNameAndType(tracker, entry.client_id, &device_name, &device_type);
- result->SetString("deviceName", device_name);
- result->SetString("deviceType", device_type);
+ result.SetStringKey("deviceName", device_name);
+ result.SetStringKey("deviceType", device_type);
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
SupervisedUserService* supervised_user_service = nullptr;
@@ -238,15 +237,15 @@ std::unique_ptr<base::DictionaryValue> HistoryEntryToValue(
}
#endif
- result->SetString("dateTimeOfDay", date_time_of_day);
- result->SetString("dateRelativeDay", date_relative_day);
- result->SetString("snippet", snippet_string);
- result->SetBoolean("starred", bookmark_model->IsBookmarked(entry.url));
- result->SetInteger("hostFilteringBehavior", host_filtering_behavior);
- result->SetBoolean("blockedVisit", is_blocked_visit);
- result->SetBoolean("isUrlInRemoteUserData", IsEntryInRemoteUserData(entry));
- result->SetString("remoteIconUrlForUma",
- entry.remote_icon_url_for_uma.spec());
+ result.SetStringKey("dateTimeOfDay", date_time_of_day);
+ result.SetStringKey("dateRelativeDay", date_relative_day);
+ result.SetStringKey("snippet", snippet_string);
+ result.SetBoolKey("starred", bookmark_model->IsBookmarked(entry.url));
+ result.SetIntKey("hostFilteringBehavior", host_filtering_behavior);
+ result.SetBoolKey("blockedVisit", is_blocked_visit);
+ result.SetBoolKey("isUrlInRemoteUserData", IsEntryInRemoteUserData(entry));
+ result.SetStringKey("remoteIconUrlForUma",
+ entry.remote_icon_url_for_uma.spec());
return result;
}
@@ -259,29 +258,35 @@ BrowsingHistoryHandler::BrowsingHistoryHandler()
BrowsingHistoryHandler::~BrowsingHistoryHandler() {}
+void BrowsingHistoryHandler::OnJavascriptAllowed() {
+ if (!browsing_history_service_ && initial_results_.is_none()) {
+ // Page was refreshed, so need to call StartQueryHistory here
+ StartQueryHistory();
+ }
+
+ for (auto& callback : deferred_callbacks_) {
+ std::move(callback).Run();
+ }
+ deferred_callbacks_.clear();
+}
+
void BrowsingHistoryHandler::OnJavascriptDisallowed() {
weak_factory_.InvalidateWeakPtrs();
+ browsing_history_service_ = nullptr;
+ initial_results_ = base::Value();
+ deferred_callbacks_.clear();
+ query_history_callback_id_.clear();
+ remove_visits_callback_.clear();
}
void BrowsingHistoryHandler::RegisterMessages() {
- Profile* profile = GetProfile();
- HistoryService* local_history = HistoryServiceFactory::GetForProfile(
- profile, ServiceAccessType::EXPLICIT_ACCESS);
- syncer::SyncService* sync_service =
- ProfileSyncServiceFactory::GetForProfile(profile);
- browsing_history_service_ = std::make_unique<BrowsingHistoryService>(
- this, local_history, sync_service);
-
// Create our favicon data source.
+ Profile* profile = GetProfile();
content::URLDataSource::Add(
profile, std::make_unique<FaviconSource>(
profile, chrome::FaviconUrlFormat::kFavicon2));
web_ui()->RegisterMessageCallback(
- "historyLoaded",
- base::BindRepeating(&BrowsingHistoryHandler::HandleHistoryLoaded,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
"queryHistory",
base::BindRepeating(&BrowsingHistoryHandler::HandleQueryHistory,
base::Unretained(this)));
@@ -304,28 +309,74 @@ void BrowsingHistoryHandler::RegisterMessages() {
base::Unretained(this)));
}
+void BrowsingHistoryHandler::StartQueryHistory() {
+ Profile* profile = GetProfile();
+ HistoryService* local_history = HistoryServiceFactory::GetForProfile(
+ profile, ServiceAccessType::EXPLICIT_ACCESS);
+ syncer::SyncService* sync_service =
+ ProfileSyncServiceFactory::GetForProfile(profile);
+ browsing_history_service_ = std::make_unique<BrowsingHistoryService>(
+ this, local_history, sync_service);
+
+ // 150 = RESULTS_PER_PAGE from chrome/browser/resources/history/constants.js
+ SendHistoryQuery(150, base::string16());
+}
+
void BrowsingHistoryHandler::HandleQueryHistory(const base::ListValue* args) {
+ AllowJavascript();
+ const base::Value& callback_id = args->GetList()[0];
+ if (!initial_results_.is_none()) {
+ ResolveJavascriptCallback(callback_id, std::move(initial_results_));
+ initial_results_ = base::Value();
+ return;
+ }
+
+ // Reset the query history continuation callback. Since it is repopulated in
+ // OnQueryComplete(), it cannot be reset earlier, as the early return above
+ // prevents the QueryHistory() call to the browsing history service.
query_history_continuation_.Reset();
+ // Cancel the previous query if it is still in flight.
+ if (!query_history_callback_id_.empty()) {
+ RejectJavascriptCallback(base::Value(query_history_callback_id_),
+ base::Value());
+ }
+ query_history_callback_id_ = callback_id.GetString();
+
// Parse the arguments from JavaScript. There are two required arguments:
// - the text to search for (may be empty)
// - the maximum number of results to return (may be 0, meaning that there
// is no maximum).
- base::string16 search_text = ExtractStringValue(args);
+ const base::Value& search_text = args->GetList()[1];
- history::QueryOptions options;
- if (!args->GetInteger(1, &options.max_count)) {
+ const base::Value& count = args->GetList()[2];
+ if (!count.is_int()) {
NOTREACHED() << "Failed to convert argument 2.";
return;
}
+ SendHistoryQuery(count.GetInt(), base::UTF8ToUTF16(search_text.GetString()));
+}
+
+void BrowsingHistoryHandler::SendHistoryQuery(int max_count,
+ const base::string16& query) {
+ history::QueryOptions options;
+ options.max_count = max_count;
options.duplicate_policy = history::QueryOptions::REMOVE_DUPLICATES_PER_DAY;
- browsing_history_service_->QueryHistory(search_text, options);
+ browsing_history_service_->QueryHistory(query, options);
}
void BrowsingHistoryHandler::HandleQueryHistoryContinuation(
const base::ListValue* args) {
- DCHECK(args->empty());
+ CHECK(args->GetList().size() == 1);
+ const base::Value& callback_id = args->GetList()[0];
+ // Cancel the previous query if it is still in flight.
+ if (!query_history_callback_id_.empty()) {
+ RejectJavascriptCallback(base::Value(query_history_callback_id_),
+ base::Value());
+ }
+ query_history_callback_id_ = callback_id.GetString();
+
DCHECK(query_history_continuation_);
std::move(query_history_continuation_).Run();
}
@@ -407,23 +458,33 @@ void BrowsingHistoryHandler::OnQueryComplete(
// Convert the result vector into a ListValue.
DCHECK(tracker);
- base::ListValue results_value;
+ base::Value results_value(base::Value::Type::LIST);
for (const BrowsingHistoryService::HistoryEntry& entry : results) {
- std::unique_ptr<base::Value> value(
+ results_value.Append(
HistoryEntryToValue(entry, bookmark_model, profile, tracker, clock_));
- results_value.Append(std::move(value));
}
- base::DictionaryValue results_info;
+ base::Value results_info(base::Value::Type::DICTIONARY);
// The items which are to be written into results_info_value_ are also
// described in chrome/browser/resources/history/history.js in @typedef for
// HistoryQuery. Please update it whenever you add or remove any keys in
// results_info_value_.
- results_info.SetString("term", query_results_info.search_text);
- results_info.SetBoolean("finished", query_results_info.reached_beginning);
+ results_info.SetStringKey("term", query_results_info.search_text);
+ results_info.SetBoolKey("finished", query_results_info.reached_beginning);
+
+ base::Value final_results(base::Value::Type::DICTIONARY);
+ final_results.SetKey("info", std::move(results_info));
+ final_results.SetKey("value", std::move(results_value));
+
+ if (query_history_callback_id_.empty()) {
+ // This can happen if JS isn't ready yet when the first query comes back.
+ initial_results_ = std::move(final_results);
+ return;
+ }
- web_ui()->CallJavascriptFunctionUnsafe("historyResult", results_info,
- results_value);
+ ResolveJavascriptCallback(base::Value(query_history_callback_id_),
+ std::move(final_results));
+ query_history_callback_id_.clear();
}
void BrowsingHistoryHandler::OnRemoveVisitsComplete() {
@@ -448,14 +509,6 @@ void BrowsingHistoryHandler::HistoryDeleted() {
}
}
-void BrowsingHistoryHandler::HandleHistoryLoaded(const base::ListValue* args) {
- AllowJavascript();
- for (auto& callback : deferred_callbacks_) {
- std::move(callback).Run();
- }
- deferred_callbacks_.clear();
-}
-
void BrowsingHistoryHandler::HasOtherFormsOfBrowsingHistory(
bool has_other_forms,
bool has_synced_results) {
diff --git a/chromium/chrome/browser/ui/webui/history/browsing_history_handler.h b/chromium/chrome/browser/ui/webui/history/browsing_history_handler.h
index 3b4c460ebd6..c473c8429a8 100644
--- a/chromium/chrome/browser/ui/webui/history/browsing_history_handler.h
+++ b/chromium/chrome/browser/ui/webui/history/browsing_history_handler.h
@@ -28,10 +28,11 @@ class BrowsingHistoryHandler : public content::WebUIMessageHandler,
~BrowsingHistoryHandler() override;
// WebUIMessageHandler implementation.
+ void OnJavascriptAllowed() override;
void OnJavascriptDisallowed() override;
void RegisterMessages() override;
- void HandleHistoryLoaded(const base::ListValue* args);
+ void StartQueryHistory();
// Handler for the "queryHistory" message.
void HandleQueryHistory(const base::ListValue* args);
@@ -67,6 +68,9 @@ class BrowsingHistoryHandler : public content::WebUIMessageHandler,
// outlive the BrowsingHistoryHandler instance.
void set_clock(base::Clock* clock) { clock_ = clock; }
+ protected:
+ virtual void SendHistoryQuery(int count, const base::string16& query);
+
private:
FRIEND_TEST_ALL_PREFIXES(BrowsingHistoryHandlerTest,
ObservingWebHistoryDeletions);
@@ -79,6 +83,10 @@ class BrowsingHistoryHandler : public content::WebUIMessageHandler,
std::vector<base::OnceClosure> deferred_callbacks_;
+ base::Value initial_results_;
+
+ std::string query_history_callback_id_;
+
base::OnceClosure query_history_continuation_;
std::string remove_visits_callback_;
diff --git a/chromium/chrome/browser/ui/webui/history/browsing_history_handler_unittest.cc b/chromium/chrome/browser/ui/webui/history/browsing_history_handler_unittest.cc
index 5ddd41d2705..63ec2886165 100644
--- a/chromium/chrome/browser/ui/webui/history/browsing_history_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/history/browsing_history_handler_unittest.cc
@@ -59,10 +59,20 @@ class BrowsingHistoryHandlerWithWebUIForTesting
test_clock_.SetNow(PretendNow());
}
+ void SendHistoryQuery(int count, const base::string16& query) override {
+ if (postpone_query_results_) {
+ return;
+ }
+ BrowsingHistoryHandler::SendHistoryQuery(count, query);
+ }
+
+ void PostponeResults() { postpone_query_results_ = true; }
+
base::SimpleTestClock* test_clock() { return &test_clock_; }
private:
base::SimpleTestClock test_clock_;
+ bool postpone_query_results_ = false;
DISALLOW_COPY_AND_ASSIGN(BrowsingHistoryHandlerWithWebUIForTesting);
};
@@ -99,8 +109,7 @@ class BrowsingHistoryHandlerTest : public ChromeRenderViewHostTestHarness {
};
}
- void VerifyHistoryDeletedFired() {
- const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ void VerifyHistoryDeletedFired(content::TestWebUI::CallData& data) {
EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
std::string event_fired;
ASSERT_TRUE(data.arg1()->GetAsString(&event_fired));
@@ -110,8 +119,10 @@ class BrowsingHistoryHandlerTest : public ChromeRenderViewHostTestHarness {
void InitializeWebUI(BrowsingHistoryHandlerWithWebUIForTesting& handler) {
// Send historyLoaded so that JS will be allowed.
base::Value init_args(base::Value::Type::LIST);
- init_args.Append("history-loaded-callback-id");
- handler.HandleHistoryLoaded(&base::Value::AsListValue(init_args));
+ init_args.Append("query-history-callback-id");
+ init_args.Append("");
+ init_args.Append(150);
+ handler.HandleQueryHistory(&base::Value::AsListValue(init_args));
}
syncer::TestSyncService* sync_service() { return sync_service_; }
@@ -151,14 +162,21 @@ TEST_F(BrowsingHistoryHandlerTest, ObservingWebHistoryDeletions) {
syncer::SyncService::TransportState::ACTIVE);
BrowsingHistoryHandlerWithWebUIForTesting handler(web_ui());
handler.RegisterMessages();
+ handler.StartQueryHistory();
InitializeWebUI(handler);
+ // QueryHistory triggers 2 calls to HasOtherFormsOfBrowsingHistory that fire
+ // before the callback is resolved if the sync service is active when the
+ // first query is sent. The handler should also resolve the initial
+ // queryHistory callback.
+ EXPECT_EQ(3U, web_ui()->call_data().size());
+
web_history_service()->ExpireHistoryBetween(
std::set<GURL>(), base::Time(), base::Time::Max(), callback,
PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
- EXPECT_EQ(1U, web_ui()->call_data().size());
- VerifyHistoryDeletedFired();
+ EXPECT_EQ(4U, web_ui()->call_data().size());
+ VerifyHistoryDeletedFired(*web_ui()->call_data().back());
}
// BrowsingHistoryHandler will be informed about WebHistoryService deletions
@@ -168,6 +186,7 @@ TEST_F(BrowsingHistoryHandlerTest, ObservingWebHistoryDeletions) {
syncer::SyncService::TransportState::INITIALIZING);
BrowsingHistoryHandlerWithWebUIForTesting handler(web_ui());
handler.RegisterMessages();
+ handler.StartQueryHistory();
sync_service()->SetTransportState(
syncer::SyncService::TransportState::ACTIVE);
sync_service()->FireStateChanged();
@@ -175,12 +194,20 @@ TEST_F(BrowsingHistoryHandlerTest, ObservingWebHistoryDeletions) {
web_history_service()->ExpireHistoryBetween(
std::set<GURL>(), base::Time(), base::Time::Max(), callback,
PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
+ EXPECT_EQ(4U, web_ui()->call_data().size());
- // Simulate initialization after history has been deleted.
+ // Simulate initialization after history has been deleted. The
+ // history-deleted event will happen before the historyResults() callback,
+ // since AllowJavascript is called before returning the results.
InitializeWebUI(handler);
- EXPECT_EQ(2U, web_ui()->call_data().size());
- VerifyHistoryDeletedFired();
+ // QueryHistory triggers 1 call to HasOtherFormsOfBrowsingHistory that fire
+ // before the callback is resolved if the sync service is inactive when the
+ // first query is sent. The handler should also have fired history-deleted
+ // and resolved the initial queryHistory callback.
+ EXPECT_EQ(7U, web_ui()->call_data().size());
+ VerifyHistoryDeletedFired(
+ *web_ui()->call_data()[web_ui()->call_data().size() - 2]);
}
// BrowsingHistoryHandler does not fire historyDeleted while a web history
@@ -190,7 +217,13 @@ TEST_F(BrowsingHistoryHandlerTest, ObservingWebHistoryDeletions) {
syncer::SyncService::TransportState::ACTIVE);
BrowsingHistoryHandlerWithWebUIForTesting handler(web_ui());
handler.RegisterMessages();
+ handler.StartQueryHistory();
InitializeWebUI(handler);
+ // QueryHistory triggers 2 calls to HasOtherFormsOfBrowsingHistory that fire
+ // before the callback is resolved if the sync service is active when the
+ // first query is sent. The handler should also resolve the initial
+ // queryHistory callback.
+ EXPECT_EQ(10U, web_ui()->call_data().size());
// Simulate a delete request.
base::Value args(base::Value::Type::LIST);
@@ -205,7 +238,7 @@ TEST_F(BrowsingHistoryHandlerTest, ObservingWebHistoryDeletions) {
args.Append(std::move(to_remove));
handler.HandleRemoveVisits(&base::Value::AsListValue(args));
- EXPECT_EQ(3U, web_ui()->call_data().size());
+ EXPECT_EQ(11U, web_ui()->call_data().size());
const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
EXPECT_EQ("cr.webUIResponse", data.function_name());
std::string callback_id;
@@ -224,13 +257,14 @@ TEST_F(BrowsingHistoryHandlerTest, ObservingWebHistoryDeletions) {
syncer::SyncService::TransportState::INITIALIZING);
BrowsingHistoryHandlerWithWebUIForTesting handler(web_ui());
handler.RegisterMessages();
+ handler.StartQueryHistory();
web_history_service()->ExpireHistoryBetween(
std::set<GURL>(), base::Time(), base::Time::Max(), callback,
PARTIAL_TRAFFIC_ANNOTATION_FOR_TESTS);
// No additional WebUI calls were made.
- EXPECT_EQ(3U, web_ui()->call_data().size());
+ EXPECT_EQ(11U, web_ui()->call_data().size());
}
}
@@ -253,18 +287,45 @@ TEST_F(BrowsingHistoryHandlerTest, MdTruncatesTitles) {
handler.OnQueryComplete({long_url_entry},
history::BrowsingHistoryService::QueryResultsInfo(),
base::OnceClosure());
+ InitializeWebUI(handler);
ASSERT_FALSE(web_ui()->call_data().empty());
- const base::ListValue* arg2;
- ASSERT_TRUE(web_ui()->call_data().front()->arg2()->GetAsList(&arg2));
+ // Request should be resolved successfully.
+ ASSERT_TRUE(web_ui()->call_data().front()->arg2()->GetBool());
+ const base::Value* arg3 = web_ui()->call_data().front()->arg3();
+ ASSERT_TRUE(arg3->is_dict());
+ const base::Value* list = arg3->FindListKey("value");
+ ASSERT_TRUE(list->is_list());
+
+ const base::Value& first_entry = list->GetList()[0];
+ ASSERT_TRUE(first_entry.is_dict());
- const base::DictionaryValue* first_entry;
- ASSERT_TRUE(arg2->GetDictionary(0, &first_entry));
+ const std::string* title = first_entry.FindStringKey("title");
+ ASSERT_TRUE(title);
- base::string16 title;
- ASSERT_TRUE(first_entry->GetString("title", &title));
+ ASSERT_EQ(0u, title->find("http://loooo"));
+ EXPECT_EQ(300u, title->size());
+}
+
+TEST_F(BrowsingHistoryHandlerTest, Reload) {
+ BrowsingHistoryHandlerWithWebUIForTesting handler(web_ui());
+ handler.RegisterMessages();
+ handler.PostponeResults();
+ handler.StartQueryHistory();
+ ASSERT_TRUE(web_ui()->call_data().empty());
+ InitializeWebUI(handler);
+ // Still empty, since no results are available yet.
+ ASSERT_TRUE(web_ui()->call_data().empty());
- ASSERT_EQ(0u, title.find(base::ASCIIToUTF16("http://loooo")));
- EXPECT_EQ(300u, title.size());
+ // Simulate page refresh and results being returned asynchronously.
+ handler.OnJavascriptDisallowed();
+ history::BrowsingHistoryService::HistoryEntry url_entry;
+ url_entry.url = GURL("https://www.chromium.org");
+ handler.OnQueryComplete({url_entry},
+ history::BrowsingHistoryService::QueryResultsInfo(),
+ base::OnceClosure());
+
+ // There should be no new Web UI calls, since JS is still disallowed.
+ ASSERT_TRUE(web_ui()->call_data().empty());
}
#endif
diff --git a/chromium/chrome/browser/ui/webui/history/foreign_session_handler.cc b/chromium/chrome/browser/ui/webui/history/foreign_session_handler.cc
index 658efd8fe85..e570fbeaf2a 100644
--- a/chromium/chrome/browser/ui/webui/history/foreign_session_handler.cc
+++ b/chromium/chrome/browser/ui/webui/history/foreign_session_handler.cc
@@ -122,7 +122,7 @@ base::Value SessionWindowToValue(const ::sessions::SessionWindow& window) {
base::Value tab_value = SessionTabToValue(*tab.get());
if (!tab_value.is_none()) {
modification_time = std::max(modification_time, tab->timestamp);
- tab_values.GetList().push_back(std::move(tab_value));
+ tab_values.Append(std::move(tab_value));
}
}
if (tab_values.GetList().empty())
@@ -223,21 +223,6 @@ sync_sessions::OpenTabsUIDelegate* ForeignSessionHandler::GetOpenTabsUIDelegate(
}
void ForeignSessionHandler::RegisterMessages() {
- Profile* profile = Profile::FromWebUI(web_ui());
-
- sync_sessions::SessionSyncService* service =
- SessionSyncServiceFactory::GetInstance()->GetForProfile(profile);
-
- // NOTE: The SessionSyncService can be null in tests.
- if (service) {
- // base::Unretained() is safe below because the subscription itself is a
- // class member field and handles destruction well.
- foreign_session_updated_subscription_ =
- service->SubscribeToForeignSessionsChanged(
- base::BindRepeating(&ForeignSessionHandler::OnForeignSessionUpdated,
- base::Unretained(this)));
- }
-
web_ui()->RegisterMessageCallback(
"deleteForeignSession",
base::BindRepeating(&ForeignSessionHandler::HandleDeleteForeignSession,
@@ -257,8 +242,34 @@ void ForeignSessionHandler::RegisterMessages() {
base::Unretained(this)));
}
+void ForeignSessionHandler::OnJavascriptAllowed() {
+ // This can happen if the page is refreshed.
+ if (initial_session_list_.is_none())
+ initial_session_list_ = GetForeignSessions();
+
+ Profile* profile = Profile::FromWebUI(web_ui());
+
+ sync_sessions::SessionSyncService* service =
+ SessionSyncServiceFactory::GetInstance()->GetForProfile(profile);
+
+ // NOTE: The SessionSyncService can be null in tests.
+ if (service) {
+ // base::Unretained() is safe below because the subscription itself is a
+ // class member field and handles destruction well.
+ foreign_session_updated_subscription_ =
+ service->SubscribeToForeignSessionsChanged(
+ base::BindRepeating(&ForeignSessionHandler::OnForeignSessionUpdated,
+ base::Unretained(this)));
+ }
+}
+
void ForeignSessionHandler::OnForeignSessionUpdated() {
- HandleGetForeignSessions(nullptr);
+ FireWebUIListener("foreign-sessions-changed",
+ std::move(GetForeignSessions()));
+}
+
+void ForeignSessionHandler::InitializeForeignSessions() {
+ initial_session_list_ = GetForeignSessions();
}
base::string16 ForeignSessionHandler::FormatSessionTime(
@@ -272,7 +283,18 @@ base::string16 ForeignSessionHandler::FormatSessionTime(
}
void ForeignSessionHandler::HandleGetForeignSessions(
- const base::ListValue* /*args*/) {
+ const base::ListValue* args) {
+ AllowJavascript();
+ CHECK(!initial_session_list_.is_none());
+ const base::Value& callback_id = args->GetList()[0];
+ ResolveJavascriptCallback(callback_id, std::move(initial_session_list_));
+
+ // Clear the initial list so that it will be reset in AllowJavascript if the
+ // page is refreshed.
+ initial_session_list_ = base::Value(base::Value::Type::NONE);
+}
+
+base::Value ForeignSessionHandler::GetForeignSessions() {
sync_sessions::OpenTabsUIDelegate* open_tabs =
GetOpenTabsUIDelegate(web_ui());
std::vector<const sync_sessions::SyncedSession*> sessions;
@@ -324,16 +346,15 @@ void ForeignSessionHandler::HandleGetForeignSessions(
base::Value window_data =
SessionWindowToValue(window_pair.second->wrapped_window);
if (!window_data.is_none()) {
- window_list.GetList().push_back(std::move(window_data));
+ window_list.Append(std::move(window_data));
}
}
session_data.SetKey("windows", std::move(window_list));
- session_list.GetList().push_back(std::move(session_data));
+ session_list.Append(std::move(session_data));
}
}
- web_ui()->CallJavascriptFunctionUnsafe("setForeignSessions",
- std::move(session_list));
+ return session_list;
}
void ForeignSessionHandler::HandleOpenForeignSession(
diff --git a/chromium/chrome/browser/ui/webui/history/foreign_session_handler.h b/chromium/chrome/browser/ui/webui/history/foreign_session_handler.h
index 4b6fc6ac4db..efd0a977f29 100644
--- a/chromium/chrome/browser/ui/webui/history/foreign_session_handler.h
+++ b/chromium/chrome/browser/ui/webui/history/foreign_session_handler.h
@@ -12,11 +12,15 @@
#include "base/callback_list.h"
#include "base/macros.h"
#include "base/time/time.h"
+#include "base/values.h"
#include "chrome/browser/sessions/session_service.h"
#include "components/sync_sessions/open_tabs_ui_delegate.h"
-#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_message_handler.h"
+namespace content {
+class WebUI;
+}
+
namespace user_prefs {
class PrefRegistrySyncable;
}
@@ -46,10 +50,13 @@ class ForeignSessionHandler : public content::WebUIMessageHandler {
public:
// WebUIMessageHandler implementation.
void RegisterMessages() override;
+ void OnJavascriptAllowed() override;
ForeignSessionHandler();
~ForeignSessionHandler() override;
+ void InitializeForeignSessions();
+
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
static void OpenForeignSessionTab(content::WebUI* web_ui,
@@ -69,6 +76,8 @@ class ForeignSessionHandler : public content::WebUIMessageHandler {
private:
void OnForeignSessionUpdated();
+ base::Value GetForeignSessions();
+
// Returns a string used to show the user when a session was last modified.
base::string16 FormatSessionTime(const base::Time& time);
@@ -94,6 +103,8 @@ class ForeignSessionHandler : public content::WebUIMessageHandler {
// the WebUI was present before the sessions data was visible.
base::TimeTicks load_attempt_time_;
+ base::Value initial_session_list_;
+
std::unique_ptr<base::CallbackList<void()>::Subscription>
foreign_session_updated_subscription_;
diff --git a/chromium/chrome/browser/ui/webui/history/history_ui.cc b/chromium/chrome/browser/ui/webui/history/history_ui.cc
index 14667902c84..bf1737935ce 100644
--- a/chromium/chrome/browser/ui/webui/history/history_ui.cc
+++ b/chromium/chrome/browser/ui/webui/history/history_ui.cc
@@ -36,9 +36,15 @@
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
namespace {
+#if !BUILDFLAG(OPTIMIZE_WEBUI)
+constexpr char kGeneratedPath[] =
+ "@out_folder@/gen/chrome/browser/resources/history/";
+#endif
+
constexpr char kIsUserSignedInKey[] = "isUserSignedIn";
constexpr char kShowMenuPromoKey[] = "showMenuPromo";
@@ -116,30 +122,20 @@ content::WebUIDataSource* CreateHistoryUIHTMLSource(Profile* profile) {
source->AddBoolean(kIsUserSignedInKey, IsUserSignedIn(profile));
#if BUILDFLAG(OPTIMIZE_WEBUI)
- source->AddResourcePath("app.html", IDR_HISTORY_APP_VULCANIZED_HTML);
- source->AddResourcePath("app.crisper.js", IDR_HISTORY_APP_CRISPER_JS);
- source->AddResourcePath("lazy_load.html",
- IDR_HISTORY_LAZY_LOAD_VULCANIZED_HTML);
- source->AddResourcePath("lazy_load.crisper.js",
- IDR_HISTORY_LAZY_LOAD_CRISPER_JS);
- source->AddResourcePath("constants.html", IDR_HISTORY_CONSTANTS_HTML);
- source->AddResourcePath("constants.js", IDR_HISTORY_CONSTANTS_JS);
- source->AddResourcePath("history.js", IDR_HISTORY_HISTORY_JS);
- source->AddResourcePath("history.js", IDR_HISTORY_HISTORY_JS);
+ webui::SetupBundledWebUIDataSource(source, "history.js",
+ IDR_HISTORY_HISTORY_ROLLUP_JS,
+ IDR_HISTORY_HISTORY_HTML);
+ source->AddResourcePath("lazy_load.js", IDR_HISTORY_LAZY_LOAD_ROLLUP_JS);
+ source->AddResourcePath("shared.rollup.js", IDR_HISTORY_SHARED_ROLLUP_JS);
source->AddResourcePath("images/sign_in_promo.svg",
IDR_HISTORY_IMAGES_SIGN_IN_PROMO_SVG);
source->AddResourcePath("images/sign_in_promo_dark.svg",
IDR_HISTORY_IMAGES_SIGN_IN_PROMO_DARK_SVG);
- source->AddResourcePath("strings.html", IDR_HISTORY_STRINGS_HTML);
#else
- // Add all history resources.
- for (size_t i = 0; i < kHistoryResourcesSize; ++i) {
- source->AddResourcePath(kHistoryResources[i].name,
- kHistoryResources[i].value);
- }
+ webui::SetupWebUIDataSource(
+ source, base::make_span(kHistoryResources, kHistoryResourcesSize),
+ kGeneratedPath, IDR_HISTORY_HISTORY_HTML);
#endif
- source->SetDefaultResource(IDR_HISTORY_HISTORY_HTML);
- source->UseStringsJs();
return source;
}
@@ -153,11 +149,19 @@ HistoryUI::HistoryUI(content::WebUI* web_ui) : WebUIController(web_ui) {
content::WebUIDataSource::Add(profile, data_source);
web_ui->AddMessageHandler(std::make_unique<webui::NavigationHandler>());
- web_ui->AddMessageHandler(std::make_unique<BrowsingHistoryHandler>());
+ auto browsing_history_handler = std::make_unique<BrowsingHistoryHandler>();
+ BrowsingHistoryHandler* browsing_history_handler_ptr =
+ browsing_history_handler.get();
+ web_ui->AddMessageHandler(std::move(browsing_history_handler));
+ browsing_history_handler_ptr->StartQueryHistory();
web_ui->AddMessageHandler(std::make_unique<MetricsHandler>());
- web_ui->AddMessageHandler(
- std::make_unique<browser_sync::ForeignSessionHandler>());
+ auto foreign_session_handler =
+ std::make_unique<browser_sync::ForeignSessionHandler>();
+ browser_sync::ForeignSessionHandler* foreign_session_handler_ptr =
+ foreign_session_handler.get();
+ web_ui->AddMessageHandler(std::move(foreign_session_handler));
+ foreign_session_handler_ptr->InitializeForeignSessions();
web_ui->AddMessageHandler(std::make_unique<HistoryLoginHandler>(
base::Bind(&HistoryUI::UpdateDataSource, base::Unretained(this))));
diff --git a/chromium/chrome/browser/ui/webui/history/navigation_handler.cc b/chromium/chrome/browser/ui/webui/history/navigation_handler.cc
index d0f06692632..036c575e22b 100644
--- a/chromium/chrome/browser/ui/webui/history/navigation_handler.cc
+++ b/chromium/chrome/browser/ui/webui/history/navigation_handler.cc
@@ -46,11 +46,9 @@ void NavigationHandler::HandleNavigateToUrl(const base::ListValue* args) {
bool middle_button = (button == 1.0);
WindowOpenDisposition disposition = ui::DispositionFromClick(
- middle_button, alt_key, ctrl_key, meta_key, shift_key);
- if (disposition == WindowOpenDisposition::CURRENT_TAB &&
- target_string == "_blank")
- disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
-
+ middle_button, alt_key, ctrl_key, meta_key, shift_key,
+ (target_string == "_blank") ? WindowOpenDisposition::NEW_FOREGROUND_TAB
+ : WindowOpenDisposition::CURRENT_TAB);
web_ui()->GetWebContents()->OpenURL(
content::OpenURLParams(GURL(url_string), content::Referrer(), disposition,
ui::PAGE_TRANSITION_LINK, false));
diff --git a/chromium/chrome/browser/ui/webui/identity_internals_ui.cc b/chromium/chrome/browser/ui/webui/identity_internals_ui.cc
index 5adab030eb4..7b10f4d9cd5 100644
--- a/chromium/chrome/browser/ui/webui/identity_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/identity_internals_ui.cc
@@ -185,7 +185,11 @@ std::string IdentityInternalsUIMessageHandler::GetStatus(
const extensions::IdentityTokenCacheValue& token_cache_value) {
switch (token_cache_value.status()) {
case extensions::IdentityTokenCacheValue::CACHE_STATUS_ADVICE:
- // Fallthrough to NOT FOUND case, as ADVICE is short lived.
+ case extensions::IdentityTokenCacheValue::CACHE_STATUS_REMOTE_CONSENT:
+ case extensions::IdentityTokenCacheValue::
+ CACHE_STATUS_REMOTE_CONSENT_APPROVED:
+ // Fallthrough to NOT FOUND case, as ADVICE, REMOTE_CONSENT and
+ // REMOTE_CONSENT_APPROVED are short lived.
case extensions::IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND:
return "Not Found";
case extensions::IdentityTokenCacheValue::CACHE_STATUS_TOKEN:
diff --git a/chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc
index 6a6d01d44a4..7a64f666416 100644
--- a/chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.cc
@@ -48,8 +48,8 @@ void IdentityInternalsUIBrowserTest::AddTokenToCache(
const std::vector<std::string>& scopes,
int time_to_live) {
extensions::IdentityTokenCacheValue token_cache_value =
- extensions::IdentityTokenCacheValue(token_id,
- base::TimeDelta::FromSeconds(time_to_live));
+ extensions::IdentityTokenCacheValue::CreateToken(
+ token_id, base::TimeDelta::FromSeconds(time_to_live));
extensions::ExtensionTokenKey key(
extension_id, CoreAccountId("account_id"),
std::set<std::string>(scopes.begin(), scopes.end()));
diff --git a/chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.js b/chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.js
index f71a7608c9d..863180e73b6 100644
--- a/chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.js
+++ b/chromium/chrome/browser/ui/webui/identity_internals_ui_browsertest.js
@@ -108,7 +108,7 @@ BaseIdentityInternalsWebUITest.prototype = {
// Test verifying chrome://identity-internals Web UI when the token cache is
// empty.
TEST_F('BaseIdentityInternalsWebUITest', 'emptyTokenCache', function() {
- var tokenListEntries = this.getTokens();
+ const tokenListEntries = this.getTokens();
expectEquals(0, tokenListEntries.length);
});
@@ -132,7 +132,7 @@ IdentityInternalsSingleTokenWebUITest.prototype = {
// Test for listing a token cache with a single token. It uses a known extension
// - the Chrome Web Store, in order to check the extension name.
TEST_F('IdentityInternalsSingleTokenWebUITest', 'getAllTokens', function() {
- var tokenListEntries = this.getTokens();
+ const tokenListEntries = this.getTokens();
expectEquals(1, tokenListEntries.length);
expectEquals('Web Store', this.getExtensionName(tokenListEntries[0]));
expectEquals('ahfgeienlihckogmohjhadlkjgocpleb',
@@ -141,7 +141,7 @@ TEST_F('IdentityInternalsSingleTokenWebUITest', 'getAllTokens', function() {
expectEquals('Token Present', this.getTokenStatus(tokenListEntries[0]));
expectLT(this.getExpirationTime(tokenListEntries[0]) - new Date(),
3600 * 1000);
- var scopes = this.getScopes(tokenListEntries[0]);
+ const scopes = this.getScopes(tokenListEntries[0]);
expectEquals(3, scopes.length);
expectEquals('store_scope1', scopes[0]);
expectEquals('store_scope2', scopes[1]);
@@ -152,8 +152,8 @@ TEST_F('IdentityInternalsSingleTokenWebUITest', 'getAllTokens', function() {
// correctly. They are implemented on the child class, because the parent does
// not have any tokens to display.
TEST_F('IdentityInternalsSingleTokenWebUITest', 'verifyGetters', function() {
- var tokenListEntries = document.querySelectorAll('#token-list > div');
- var actualTokens = this.getTokens();
+ const tokenListEntries = document.querySelectorAll('#token-list > div');
+ const actualTokens = this.getTokens();
expectEquals(tokenListEntries.length, actualTokens.length);
expectEquals(tokenListEntries[0], actualTokens[0]);
expectEquals(this.getExtensionName(tokenListEntries[0]),
@@ -169,11 +169,11 @@ TEST_F('IdentityInternalsSingleTokenWebUITest', 'verifyGetters', function() {
expectEquals(this.getExpirationTime(tokenListEntries[0]),
Date.parse(tokenListEntries[0].querySelector('.expiration-time')
.innerText.replace(' at ', ' ')));
- var scopes = tokenListEntries[0].querySelector('.scope-list')
- .innerHTML.split('<br>');
- var actualScopes = this.getScopes(tokenListEntries[0]);
+ const scopes =
+ tokenListEntries[0].querySelector('.scope-list').innerHTML.split('<br>');
+ const actualScopes = this.getScopes(tokenListEntries[0]);
expectEquals(scopes.length, actualScopes.length);
- for (var i = 0; i < scopes.length; i++) {
+ for (let i = 0; i < scopes.length; i++) {
expectEquals(scopes[i], actualScopes[i]);
}
});
@@ -199,7 +199,7 @@ IdentityInternalsMultipleTokensWebUITest.prototype = {
// are empty, because extensions are faked, and not present in the extension
// service.
TEST_F('IdentityInternalsMultipleTokensWebUITest', 'getAllTokens', function() {
- var tokenListEntries = this.getTokens();
+ const tokenListEntries = this.getTokens();
expectEquals(2, tokenListEntries.length);
expectEquals('', this.getExtensionName(tokenListEntries[0]));
expectEquals('extension0',
@@ -208,7 +208,7 @@ TEST_F('IdentityInternalsMultipleTokensWebUITest', 'getAllTokens', function() {
expectEquals('Token Present', this.getTokenStatus(tokenListEntries[0]));
expectLT(this.getExpirationTime(tokenListEntries[0]) - new Date(),
3600 * 1000);
- var scopes = this.getScopes(tokenListEntries[0]);
+ let scopes = this.getScopes(tokenListEntries[0]);
expectEquals(3, scopes.length);
expectEquals('scope_1_0', scopes[0]);
expectEquals('scope_2_0', scopes[1]);
@@ -220,7 +220,7 @@ TEST_F('IdentityInternalsMultipleTokensWebUITest', 'getAllTokens', function() {
expectEquals('Token Present', this.getTokenStatus(tokenListEntries[1]));
expectLT(this.getExpirationTime(tokenListEntries[1]) - new Date(),
3600 * 1000);
- var scopes = this.getScopes(tokenListEntries[1]);
+ scopes = this.getScopes(tokenListEntries[1]);
expectEquals(3, scopes.length);
expectEquals('scope_1_1', scopes[0]);
expectEquals('scope_2_1', scopes[1]);
@@ -243,18 +243,17 @@ IdentityInternalsWebUITestAsync.prototype = {
};
TEST_F('IdentityInternalsWebUITestAsync', 'revokeToken', function() {
- var tokenListBefore = this.getTokens();
+ const tokenListBefore = this.getTokens();
expectEquals(2, tokenListBefore.length);
- var tokenRevokeDone = identity_internals.tokenRevokeDone;
+ const tokenRevokeDone = identity_internals.tokenRevokeDone;
identity_internals.tokenRevokeDone = this.continueTest(
WhenTestDone.ALWAYS, function(accessTokens) {
tokenRevokeDone.call(identity_internals, accessTokens);
identity_internals.tokenRevokeDone = tokenRevokeDone;
- var tokenListAfter = this.getTokens();
+ const tokenListAfter = this.getTokens();
expectEquals(1, tokenListAfter.length);
expectEquals(this.getAccessToken(tokenListBefore[0]),
this.getAccessToken(tokenListAfter[0]));
}.bind(this));
this.getRevokeButton(tokenListBefore[1]).click();
});
-
diff --git a/chromium/chrome/browser/ui/webui/inspect_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/inspect_ui_browsertest.cc
index 8be94d29b34..93eed73eeb6 100644
--- a/chromium/chrome/browser/ui/webui/inspect_ui_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/inspect_ui_browsertest.cc
@@ -52,7 +52,7 @@ IN_PROC_BROWSER_TEST_F(InspectUITest, SharedWorker) {
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL(chrome::kChromeUIInspectURL),
WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
"testTargetListed", base::Value("#workers"),
diff --git a/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 06032adb281..f9e52ca32e9 100644
--- a/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -5,30 +5,37 @@
#include "chrome/browser/ui/webui/interstitials/interstitial_ui.h"
#include <memory>
+#include <utility>
#include "base/atomic_sequence_num.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/lookalikes/lookalike_url_blocking_page.h"
#include "chrome/browser/lookalikes/lookalike_url_controller_client.h"
-#include "chrome/browser/lookalikes/lookalike_url_interstitial_page.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/safe_browsing/safe_browsing_blocking_page.h"
#include "chrome/browser/safe_browsing/safe_browsing_service.h"
#include "chrome/browser/safe_browsing/test_safe_browsing_blocking_page_quiet.h"
#include "chrome/browser/safe_browsing/ui_manager.h"
-#include "chrome/browser/ssl/bad_clock_blocking_page.h"
-#include "chrome/browser/ssl/blocked_interception_blocking_page.h"
#include "chrome/browser/ssl/chrome_security_blocking_page_factory.h"
-#include "chrome/browser/ssl/mitm_software_blocking_page.h"
#include "chrome/common/buildflags.h"
#include "chrome/common/url_constants.h"
-#include "components/grit/components_resources.h"
-#include "components/safe_browsing/db/database_manager.h"
+#include "components/captive_portal/core/buildflags.h"
+#include "components/grit/dev_ui_components_resources.h"
+#include "components/lookalikes/lookalike_url_util.h"
+#include "components/safe_browsing/core/db/database_manager.h"
+#include "components/security_interstitials/content/bad_clock_blocking_page.h"
+#include "components/security_interstitials/content/blocked_interception_blocking_page.h"
+#include "components/security_interstitials/content/legacy_tls_blocking_page.h"
+#include "components/security_interstitials/content/mitm_software_blocking_page.h"
#include "components/security_interstitials/content/origin_policy_ui.h"
+#include "components/security_interstitials/content/unsafe_resource_util.h"
#include "components/security_interstitials/core/ssl_error_options_mask.h"
#include "components/security_interstitials/core/ssl_error_ui.h"
+#include "components/security_interstitials/core/unsafe_resource.h"
#include "content/public/browser/interstitial_page_delegate.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
@@ -48,7 +55,7 @@
#include "ui/base/webui/web_ui_util.h"
#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
-#include "chrome/browser/ssl/captive_portal_blocking_page.h"
+#include "components/security_interstitials/content/captive_portal_blocking_page.h"
#endif
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
@@ -107,7 +114,8 @@ class InterstitialHTMLSource : public content::URLDataSource {
DISALLOW_COPY_AND_ASSIGN(InterstitialHTMLSource);
};
-SSLBlockingPage* CreateSslBlockingPage(content::WebContents* web_contents) {
+std::unique_ptr<SSLBlockingPage> CreateSslBlockingPage(
+ content::WebContents* web_contents) {
// Random parameters for SSL blocking page.
int cert_error = net::ERR_CERT_CONTAINS_ERRORS;
GURL request_url("https://example.com");
@@ -115,22 +123,18 @@ SSLBlockingPage* CreateSslBlockingPage(content::WebContents* web_contents) {
bool strict_enforcement = false;
base::Time time_triggered_ = base::Time::NowFromSystemTime();
std::string url_param;
- if (net::GetValueForKeyInQuery(web_contents->GetURL(),
- "url",
- &url_param)) {
+ if (net::GetValueForKeyInQuery(web_contents->GetURL(), "url", &url_param)) {
if (GURL(url_param).is_valid()) {
request_url = GURL(url_param);
}
}
std::string overridable_param;
- if (net::GetValueForKeyInQuery(web_contents->GetURL(),
- "overridable",
+ if (net::GetValueForKeyInQuery(web_contents->GetURL(), "overridable",
&overridable_param)) {
overridable = overridable_param == "1";
}
std::string strict_enforcement_param;
- if (net::GetValueForKeyInQuery(web_contents->GetURL(),
- "strict_enforcement",
+ if (net::GetValueForKeyInQuery(web_contents->GetURL(), "strict_enforcement",
&strict_enforcement_param)) {
strict_enforcement = strict_enforcement_param == "1";
}
@@ -152,12 +156,13 @@ SSLBlockingPage* CreateSslBlockingPage(content::WebContents* web_contents) {
if (strict_enforcement)
options_mask |=
security_interstitials::SSLErrorOptionsMask::STRICT_ENFORCEMENT;
- return ChromeSecurityBlockingPageFactory::CreateSSLPage(
- web_contents, cert_error, ssl_info, request_url, options_mask,
- time_triggered_, GURL(), nullptr);
+ ChromeSecurityBlockingPageFactory blocking_page_factory;
+ return blocking_page_factory.CreateSSLPage(web_contents, cert_error, ssl_info,
+ request_url, options_mask,
+ time_triggered_, GURL(), nullptr);
}
-MITMSoftwareBlockingPage* CreateMITMSoftwareBlockingPage(
+std::unique_ptr<MITMSoftwareBlockingPage> CreateMITMSoftwareBlockingPage(
content::WebContents* web_contents) {
const int cert_error = net::ERR_CERT_AUTHORITY_INVALID;
const GURL request_url("https://example.com");
@@ -170,25 +175,41 @@ MITMSoftwareBlockingPage* CreateMITMSoftwareBlockingPage(
is_enterprise_managed = is_enterprise_managed_param == "1";
}
+ ChromeSecurityBlockingPageFactory blocking_page_factory;
+ blocking_page_factory.SetEnterpriseManagedForTesting(is_enterprise_managed);
+
net::SSLInfo ssl_info;
ssl_info.cert = ssl_info.unverified_cert = CreateFakeCert();
- return new MITMSoftwareBlockingPage(web_contents, cert_error, request_url,
- nullptr, ssl_info, mitm_software_name,
- is_enterprise_managed);
+ return blocking_page_factory.CreateMITMSoftwareBlockingPage(
+ web_contents, cert_error, request_url, nullptr, ssl_info,
+ mitm_software_name);
}
-BlockedInterceptionBlockingPage* CreateBlockedInterceptionBlockingPage(
- content::WebContents* web_contents) {
+std::unique_ptr<BlockedInterceptionBlockingPage>
+CreateBlockedInterceptionBlockingPage(content::WebContents* web_contents) {
const int cert_error = net::ERR_CERT_AUTHORITY_INVALID;
const GURL request_url("https://example.com");
net::SSLInfo ssl_info;
ssl_info.cert = ssl_info.unverified_cert = CreateFakeCert();
- return new BlockedInterceptionBlockingPage(web_contents, cert_error,
- request_url, nullptr, ssl_info);
+ ChromeSecurityBlockingPageFactory blocking_page_factory;
+ return blocking_page_factory.CreateBlockedInterceptionBlockingPage(
+ web_contents, cert_error, request_url, nullptr, ssl_info);
+}
+
+std::unique_ptr<LegacyTLSBlockingPage> CreateLegacyTLSBlockingPage(
+ content::WebContents* web_contents) {
+ const int cert_error = net::ERR_SSL_OBSOLETE_VERSION;
+ const GURL request_url("https://example.com");
+
+ net::SSLInfo ssl_info;
+ ssl_info.cert = ssl_info.unverified_cert = CreateFakeCert();
+ ChromeSecurityBlockingPageFactory blocking_page_factory;
+ return blocking_page_factory.CreateLegacyTLSBlockingPage(
+ web_contents, cert_error, request_url, nullptr, ssl_info);
}
-BadClockBlockingPage* CreateBadClockBlockingPage(
+std::unique_ptr<BadClockBlockingPage> CreateBadClockBlockingPage(
content::WebContents* web_contents) {
// Set up a fake clock error.
int cert_error = net::ERR_CERT_DATE_INVALID;
@@ -233,32 +254,31 @@ BadClockBlockingPage* CreateBadClockBlockingPage(
if (strict_enforcement)
options_mask |=
security_interstitials::SSLErrorOptionsMask::STRICT_ENFORCEMENT;
- return new BadClockBlockingPage(web_contents, cert_error, ssl_info,
- request_url, base::Time::Now(), clock_state,
- nullptr);
+ ChromeSecurityBlockingPageFactory blocking_page_factory;
+ return blocking_page_factory.CreateBadClockBlockingPage(
+ web_contents, cert_error, ssl_info, request_url, base::Time::Now(),
+ clock_state, nullptr);
}
-LookalikeUrlInterstitialPage* CreateLookalikeInterstitialPage(
+std::unique_ptr<LookalikeUrlBlockingPage> CreateLookalikeInterstitialPage(
content::WebContents* web_contents) {
GURL request_url("https://example.net");
GURL safe_url("https://example.com");
- return new LookalikeUrlInterstitialPage(
+ return std::make_unique<LookalikeUrlBlockingPage>(
web_contents, safe_url, ukm::kInvalidSourceId,
- LookalikeUrlInterstitialPage::MatchType::kNone,
+ LookalikeUrlMatchType::kNone,
std::make_unique<LookalikeUrlControllerClient>(web_contents, request_url,
safe_url));
}
-safe_browsing::SafeBrowsingBlockingPage* CreateSafeBrowsingBlockingPage(
- content::WebContents* web_contents) {
+std::unique_ptr<safe_browsing::SafeBrowsingBlockingPage>
+CreateSafeBrowsingBlockingPage(content::WebContents* web_contents) {
safe_browsing::SBThreatType threat_type =
safe_browsing::SB_THREAT_TYPE_URL_MALWARE;
GURL request_url("http://example.com");
std::string url_param;
- if (net::GetValueForKeyInQuery(web_contents->GetURL(),
- "url",
- &url_param)) {
+ if (net::GetValueForKeyInQuery(web_contents->GetURL(), "url", &url_param)) {
if (GURL(url_param).is_valid()) {
request_url = GURL(url_param);
}
@@ -267,9 +287,7 @@ safe_browsing::SafeBrowsingBlockingPage* CreateSafeBrowsingBlockingPage(
// TODO(mattm): add flag to change main_frame_url or add dedicated flag to
// test subresource interstitials.
std::string type_param;
- if (net::GetValueForKeyInQuery(web_contents->GetURL(),
- "type",
- &type_param)) {
+ if (net::GetValueForKeyInQuery(web_contents->GetURL(), "type", &type_param)) {
if (type_param == "malware") {
threat_type = safe_browsing::SB_THREAT_TYPE_URL_MALWARE;
} else if (type_param == "phishing") {
@@ -289,10 +307,9 @@ safe_browsing::SafeBrowsingBlockingPage* CreateSafeBrowsingBlockingPage(
resource.is_subresource = request_url != main_frame_url;
resource.is_subframe = false;
resource.threat_type = threat_type;
- resource.web_contents_getter =
- security_interstitials::UnsafeResource::GetWebContentsGetter(
- web_contents->GetMainFrame()->GetProcess()->GetID(),
- web_contents->GetMainFrame()->GetRoutingID());
+ resource.web_contents_getter = security_interstitials::GetWebContentsGetter(
+ web_contents->GetMainFrame()->GetProcess()->GetID(),
+ web_contents->GetMainFrame()->GetRoutingID());
resource.threat_source = g_browser_process->safe_browsing_service()
->database_manager()
->GetThreatSource();
@@ -304,13 +321,14 @@ safe_browsing::SafeBrowsingBlockingPage* CreateSafeBrowsingBlockingPage(
// creates a SafeBrowsingBlockingPage but does not actually show a real
// interstitial. Instead it extracts the html and displays it manually, so the
// parts which depend on the NavigationEntry are not hit.
- return safe_browsing::SafeBrowsingBlockingPage::CreateBlockingPage(
- g_browser_process->safe_browsing_service()->ui_manager().get(),
- web_contents, main_frame_url, resource, true);
+ return base::WrapUnique<safe_browsing::SafeBrowsingBlockingPage>(
+ safe_browsing::SafeBrowsingBlockingPage::CreateBlockingPage(
+ g_browser_process->safe_browsing_service()->ui_manager().get(),
+ web_contents, main_frame_url, resource, true));
}
-TestSafeBrowsingBlockingPageQuiet* CreateSafeBrowsingQuietBlockingPage(
- content::WebContents* web_contents) {
+std::unique_ptr<TestSafeBrowsingBlockingPageQuiet>
+CreateSafeBrowsingQuietBlockingPage(content::WebContents* web_contents) {
safe_browsing::SBThreatType threat_type =
safe_browsing::SB_THREAT_TYPE_URL_MALWARE;
GURL request_url("http://example.com");
@@ -341,10 +359,9 @@ TestSafeBrowsingBlockingPageQuiet* CreateSafeBrowsingQuietBlockingPage(
resource.is_subresource = request_url != main_frame_url;
resource.is_subframe = false;
resource.threat_type = threat_type;
- resource.web_contents_getter =
- security_interstitials::UnsafeResource::GetWebContentsGetter(
- web_contents->GetMainFrame()->GetProcess()->GetID(),
- web_contents->GetMainFrame()->GetRoutingID());
+ resource.web_contents_getter = security_interstitials::GetWebContentsGetter(
+ web_contents->GetMainFrame()->GetProcess()->GetID(),
+ web_contents->GetMainFrame()->GetRoutingID());
resource.threat_source = g_browser_process->safe_browsing_service()
->database_manager()
->GetThreatSource();
@@ -356,13 +373,14 @@ TestSafeBrowsingBlockingPageQuiet* CreateSafeBrowsingQuietBlockingPage(
// creates a SafeBrowsingBlockingPage but does not actually show a real
// interstitial. Instead it extracts the html and displays it manually, so the
// parts which depend on the NavigationEntry are not hit.
- return TestSafeBrowsingBlockingPageQuiet::CreateBlockingPage(
- g_browser_process->safe_browsing_service()->ui_manager().get(),
- web_contents, main_frame_url, resource, is_giant_webview);
+ return base::WrapUnique<TestSafeBrowsingBlockingPageQuiet>(
+ TestSafeBrowsingBlockingPageQuiet::CreateBlockingPage(
+ g_browser_process->safe_browsing_service()->ui_manager().get(),
+ web_contents, main_frame_url, resource, is_giant_webview));
}
#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
-CaptivePortalBlockingPage* CreateCaptivePortalBlockingPage(
+std::unique_ptr<CaptivePortalBlockingPage> CreateCaptivePortalBlockingPage(
content::WebContents* web_contents) {
bool is_wifi_connection = false;
GURL landing_url("https://captive.portal/login");
@@ -395,8 +413,9 @@ CaptivePortalBlockingPage* CreateCaptivePortalBlockingPage(
}
net::SSLInfo ssl_info;
ssl_info.cert = ssl_info.unverified_cert = CreateFakeCert();
- CaptivePortalBlockingPage* blocking_page =
- ChromeSecurityBlockingPageFactory::CreateCaptivePortalBlockingPage(
+ ChromeSecurityBlockingPageFactory blocking_page_factory;
+ std::unique_ptr<CaptivePortalBlockingPage> blocking_page =
+ blocking_page_factory.CreateCaptivePortalBlockingPage(
web_contents, request_url, landing_url, nullptr, ssl_info,
net::ERR_CERT_COMMON_NAME_INVALID);
blocking_page->OverrideWifiInfoForTesting(is_wifi_connection, wifi_ssid);
@@ -404,11 +423,12 @@ CaptivePortalBlockingPage* CreateCaptivePortalBlockingPage(
}
#endif
-security_interstitials::SecurityInterstitialPage*
+std::unique_ptr<security_interstitials::SecurityInterstitialPage>
CreateOriginPolicyInterstitialPage(content::WebContents* web_contents) {
- return security_interstitials::OriginPolicyUI::GetBlockingPage(
- network::OriginPolicyState::kCannotLoadPolicy, web_contents,
- GURL("https://example.com/broken/origin/policy"));
+ return base::WrapUnique<security_interstitials::SecurityInterstitialPage>(
+ security_interstitials::OriginPolicyUI::GetBlockingPage(
+ network::OriginPolicyState::kCannotLoadPolicy, web_contents,
+ GURL("https://example.com/broken/origin/policy")));
}
} // namespace
@@ -419,8 +439,7 @@ InterstitialUI::InterstitialUI(content::WebUI* web_ui)
std::make_unique<InterstitialHTMLSource>());
}
-InterstitialUI::~InterstitialUI() {
-}
+InterstitialUI::~InterstitialUI() = default;
// InterstitialHTMLSource
@@ -467,32 +486,32 @@ void InterstitialHTMLSource::StartDataRequest(
GURL(chrome::kChromeUIInterstitialURL).GetWithEmptyPath().Resolve(path);
std::string path_without_query = url.path();
if (path_without_query == "/ssl") {
- interstitial_delegate.reset(CreateSslBlockingPage(web_contents));
+ interstitial_delegate = CreateSslBlockingPage(web_contents);
} else if (path_without_query == "/mitm-software-ssl") {
- interstitial_delegate.reset(CreateMITMSoftwareBlockingPage(web_contents));
+ interstitial_delegate = CreateMITMSoftwareBlockingPage(web_contents);
} else if (path_without_query == "/blocked-interception") {
- interstitial_delegate.reset(
- CreateBlockedInterceptionBlockingPage(web_contents));
+ interstitial_delegate = CreateBlockedInterceptionBlockingPage(web_contents);
+ } else if (path_without_query == "/legacy-tls") {
+ interstitial_delegate = CreateLegacyTLSBlockingPage(web_contents);
} else if (path_without_query == "/safebrowsing") {
- interstitial_delegate.reset(CreateSafeBrowsingBlockingPage(web_contents));
+ interstitial_delegate = CreateSafeBrowsingBlockingPage(web_contents);
} else if (path_without_query == "/clock") {
- interstitial_delegate.reset(CreateBadClockBlockingPage(web_contents));
+ interstitial_delegate = CreateBadClockBlockingPage(web_contents);
} else if (path_without_query == "/lookalike") {
- interstitial_delegate.reset(CreateLookalikeInterstitialPage(web_contents));
+ interstitial_delegate = CreateLookalikeInterstitialPage(web_contents);
#if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
} else if (path_without_query == "/captiveportal") {
- interstitial_delegate.reset(CreateCaptivePortalBlockingPage(web_contents));
+ interstitial_delegate = CreateCaptivePortalBlockingPage(web_contents);
#endif
} else if (path_without_query == "/origin_policy") {
- interstitial_delegate.reset(
- CreateOriginPolicyInterstitialPage(web_contents));
+ interstitial_delegate = CreateOriginPolicyInterstitialPage(web_contents);
}
if (path_without_query == "/quietsafebrowsing") {
- TestSafeBrowsingBlockingPageQuiet* blocking_page =
+ std::unique_ptr<TestSafeBrowsingBlockingPageQuiet> blocking_page =
CreateSafeBrowsingQuietBlockingPage(web_contents);
- interstitial_delegate.reset(blocking_page);
html = blocking_page->GetHTML();
+ interstitial_delegate = std::move(blocking_page);
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
} else if (path_without_query == "/supervised_user") {
html = GetSupervisedUserInterstitialHTML(path);
diff --git a/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
index fb1809804c4..a0829a006b9 100644
--- a/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui_browsertest.cc
@@ -192,6 +192,11 @@ IN_PROC_BROWSER_TEST_F(InterstitialUITest, BlockedInterceptionInterstitial) {
base::ASCIIToUTF16("Anything you type"));
}
+IN_PROC_BROWSER_TEST_F(InterstitialUITest, LegacyTLSInterstitial) {
+ TestInterstitial(GURL("chrome://interstitials/legacy-tls"), "Privacy error",
+ base::ASCIIToUTF16("outdated security configuration"));
+}
+
// Tests that back button works after opening an interstitial from
// chrome://interstitials.
IN_PROC_BROWSER_TEST_F(InterstitialUITest, InterstitialBackButton) {
diff --git a/chromium/chrome/browser/ui/webui/interventions_internals/BUILD.gn b/chromium/chrome/browser/ui/webui/interventions_internals/BUILD.gn
index 424c3a9cb0b..cf7280f55a1 100644
--- a/chromium/chrome/browser/ui/webui/interventions_internals/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/interventions_internals/BUILD.gn
@@ -5,11 +5,7 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "interventions_internals.mojom",
- ]
+ sources = [ "interventions_internals.mojom" ]
- public_deps = [
- "//url/mojom:url_mojom_gurl",
- ]
+ public_deps = [ "//url/mojom:url_mojom_gurl" ]
}
diff --git a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc
index 7a6d49bbd45..b8bdba5f0af 100644
--- a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc
@@ -15,7 +15,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "components/previews/content/previews_ui_service.h"
#include "content/public/browser/web_ui_data_source.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
@@ -57,14 +57,13 @@ InterventionsInternalsUI::InterventionsInternalsUI(content::WebUI* web_ui)
}
content::WebUIDataSource::Add(profile, GetSource());
previews_ui_service_ = previews_service->previews_ui_service();
- AddHandlerToRegistry(base::BindRepeating(
- &InterventionsInternalsUI::BindInterventionsInternalsPageHandler,
- base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(InterventionsInternalsUI)
+
InterventionsInternalsUI::~InterventionsInternalsUI() {}
-void InterventionsInternalsUI::BindInterventionsInternalsPageHandler(
+void InterventionsInternalsUI::BindInterface(
mojo::PendingReceiver<mojom::InterventionsInternalsPageHandler> receiver) {
DCHECK(previews_ui_service_);
page_handler_ = std::make_unique<InterventionsInternalsPageHandler>(
diff --git a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.h b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.h
index 97143b00575..9d4bd6fdd19 100644
--- a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.h
+++ b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.h
@@ -6,7 +6,7 @@
#define CHROME_BROWSER_UI_WEBUI_INTERVENTIONS_INTERNALS_INTERVENTIONS_INTERNALS_UI_H_
#include "base/macros.h"
-#include "chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom.h"
+#include "chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom-forward.h"
#include "chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -21,15 +21,19 @@ class InterventionsInternalsUI : public ui::MojoWebUIController {
explicit InterventionsInternalsUI(content::WebUI* web_ui);
~InterventionsInternalsUI() override;
- private:
- void BindInterventionsInternalsPageHandler(
+ // Instantiates implementor of the mojom::InterventionsInternalsPageHandler
+ // mojo interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<mojom::InterventionsInternalsPageHandler> receiver);
+ private:
// The PreviewsUIService associated with this UI.
previews::PreviewsUIService* previews_ui_service_;
std::unique_ptr<InterventionsInternalsPageHandler> page_handler_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(InterventionsInternalsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/invalidations_message_handler.cc b/chromium/chrome/browser/ui/webui/invalidations_message_handler.cc
index 27b07ff974c..e4843d061d5 100644
--- a/chromium/chrome/browser/ui/webui/invalidations_message_handler.cc
+++ b/chromium/chrome/browser/ui/webui/invalidations_message_handler.cc
@@ -14,15 +14,13 @@
#include "components/invalidation/impl/profile_invalidation_provider.h"
#include "components/invalidation/public/invalidation_handler.h"
#include "components/invalidation/public/invalidation_service.h"
+#include "components/invalidation/public/topic_invalidation_map.h"
#include "content/public/browser/web_ui.h"
namespace invalidation {
class InvalidationLogger;
} // namespace invalidation
-namespace syncer {
-class ObjectIdInvalidationMap;
-} // namespace syncer
namespace {
@@ -70,8 +68,8 @@ void InvalidationsMessageHandler::HandleRequestDetailedStatus(
GetInvalidationProvider(Profile::FromWebUI(web_ui()));
if (invalidation_provider) {
invalidation_provider->GetInvalidationService()->RequestDetailedStatus(
- base::Bind(&InvalidationsMessageHandler::OnDetailedStatus,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindRepeating(&InvalidationsMessageHandler::OnDetailedStatus,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
@@ -100,15 +98,19 @@ void InvalidationsMessageHandler::OnStateChange(
base::Value(last_changed_timestamp.ToJsTime()));
}
-void InvalidationsMessageHandler::OnUpdateIds(
+void InvalidationsMessageHandler::OnUpdatedTopics(
const std::string& handler_name,
- const syncer::ObjectIdCountMap& ids) {
+ const syncer::TopicCountMap& topics) {
base::ListValue list_of_objects;
- for (auto it = ids.begin(); it != ids.end(); ++it) {
+ for (const auto& topic_item : topics) {
std::unique_ptr<base::DictionaryValue> dic(new base::DictionaryValue());
- dic->SetString("name", (it->first).name());
- dic->SetInteger("source", (it->first).source());
- dic->SetInteger("totalCount", it->second);
+ dic->SetString("name", topic_item.first);
+ // TODO(crbug.com/1056181): source has been deprecated and after Topic->
+ // ObjectID refactoring completely makes no sense. It needs to be cleaned
+ // up together with other ObjectID references in js counterpart. Pass 0
+ // temporary to avoid changes in js counterpart.
+ dic->SetInteger("source", 0);
+ dic->SetInteger("totalCount", topic_item.second);
list_of_objects.Append(std::move(dic));
}
web_ui()->CallJavascriptFunctionUnsafe("chrome.invalidations.updateIds",
@@ -119,7 +121,7 @@ void InvalidationsMessageHandler::OnDebugMessage(
const base::DictionaryValue& details) {}
void InvalidationsMessageHandler::OnInvalidation(
- const syncer::ObjectIdInvalidationMap& new_invalidations) {
+ const syncer::TopicInvalidationMap& new_invalidations) {
std::unique_ptr<base::ListValue> invalidations_list =
new_invalidations.ToValue();
web_ui()->CallJavascriptFunctionUnsafe(
diff --git a/chromium/chrome/browser/ui/webui/invalidations_message_handler.h b/chromium/chrome/browser/ui/webui/invalidations_message_handler.h
index f357963065c..c51938f5fb7 100644
--- a/chromium/chrome/browser/ui/webui/invalidations_message_handler.h
+++ b/chromium/chrome/browser/ui/webui/invalidations_message_handler.h
@@ -32,11 +32,11 @@ class InvalidationsMessageHandler
const std::multiset<std::string>& registered_handlers) override;
void OnStateChange(const syncer::InvalidatorState& new_state,
const base::Time& last_change_timestamp) override;
- void OnUpdateIds(const std::string& handler_name,
- const syncer::ObjectIdCountMap& ids_set) override;
+ void OnUpdatedTopics(const std::string& handler_name,
+ const syncer::TopicCountMap& topics_counts) override;
void OnDebugMessage(const base::DictionaryValue& details) override;
void OnInvalidation(
- const syncer::ObjectIdInvalidationMap& new_invalidations) override;
+ const syncer::TopicInvalidationMap& new_invalidations) override;
void OnDetailedStatus(const base::DictionaryValue& network_details) override;
// Implementation of WebUIMessageHandler.
diff --git a/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui.cc b/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui.cc
index 0113cab1ba8..79d76f9a1ec 100644
--- a/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui.cc
+++ b/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui.cc
@@ -20,6 +20,7 @@
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "printing/buildflags/buildflags.h"
+#include "ui/base/webui/web_ui_util.h"
namespace {
@@ -105,6 +106,7 @@ LocalDiscoveryUI::LocalDiscoveryUI(content::WebUI* web_ui)
void LocalDiscoveryUI::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterBooleanPref(prefs::kLocalDiscoveryEnabled, true);
registry->RegisterBooleanPref(
prefs::kLocalDiscoveryNotificationsEnabled,
#if defined(OS_WIN)
diff --git a/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc b/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
index 1a905066c73..2197f9a7844 100644
--- a/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
+++ b/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
@@ -211,6 +211,11 @@ void LocalDiscoveryUIHandler::HandleStart(const base::ListValue* args) {
void LocalDiscoveryUIHandler::HandleRegisterDevice(
const base::ListValue* args) {
+ if (IsUserProfileRestricted()) {
+ OnSetupError();
+ return;
+ }
+
std::string device;
bool rv = args->GetString(0, &device);
DCHECK(rv);
@@ -221,15 +226,16 @@ void LocalDiscoveryUIHandler::HandleRegisterDevice(
return;
}
- if (it->second.version < kCloudDevicesPrivetVersion) {
- privet_resolution_ = privet_http_factory_->CreatePrivetHTTP(device);
- privet_resolution_->Start(
- it->second.address,
- base::Bind(&LocalDiscoveryUIHandler::StartRegisterHTTP,
- base::Unretained(this)));
- } else {
+ if (it->second.version >= kCloudDevicesPrivetVersion) {
OnSetupError();
+ return;
}
+
+ privet_resolution_ = privet_http_factory_->CreatePrivetHTTP(device);
+ privet_resolution_->Start(
+ it->second.address,
+ base::Bind(&LocalDiscoveryUIHandler::StartRegisterHTTP,
+ base::Unretained(this)));
}
void LocalDiscoveryUIHandler::HandleCancelRegistration(
@@ -255,6 +261,11 @@ void LocalDiscoveryUIHandler::HandleRequestDeviceList(
void LocalDiscoveryUIHandler::HandleOpenCloudPrintURL(
const base::ListValue* args) {
+ // Opening of the Cloud Print URL should be disabled if the profile is
+ // restricted.
+ if (IsUserProfileRestricted())
+ return;
+
std::string id;
bool rv = args->GetString(0, &id);
DCHECK(rv);
@@ -481,9 +492,9 @@ void LocalDiscoveryUIHandler::ResetCurrentRegistration() {
void LocalDiscoveryUIHandler::CheckUserLoggedIn() {
base::Value logged_in_value(!GetSyncAccount().empty());
- base::Value is_supervised_value(IsUserSupervisedOrOffTheRecord());
+ base::Value is_restricted_value(IsUserProfileRestricted());
web_ui()->CallJavascriptFunctionUnsafe("local_discovery.setUserLoggedIn",
- logged_in_value, is_supervised_value);
+ logged_in_value, is_restricted_value);
}
void LocalDiscoveryUIHandler::CheckListingDone() {
@@ -528,9 +539,10 @@ std::unique_ptr<GCDApiFlow> LocalDiscoveryUIHandler::CreateApiFlow() {
return GCDApiFlow::Create(url_loader_factory, identity_manager);
}
-bool LocalDiscoveryUIHandler::IsUserSupervisedOrOffTheRecord() {
+bool LocalDiscoveryUIHandler::IsUserProfileRestricted() {
Profile* profile = Profile::FromWebUI(web_ui());
- return profile->IsSupervised() || profile->IsOffTheRecord();
+ return profile->IsSupervised() || profile->IsOffTheRecord() ||
+ !profile->GetPrefs()->GetBoolean(prefs::kLocalDiscoveryEnabled);
}
#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
diff --git a/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h b/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
index caf5a5b870d..952bd620c32 100644
--- a/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
+++ b/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
@@ -156,7 +156,7 @@ class LocalDiscoveryUIHandler
void CheckListingDone();
- bool IsUserSupervisedOrOffTheRecord();
+ bool IsUserProfileRestricted();
#if defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
void StartCloudPrintConnector();
diff --git a/chromium/chrome/browser/ui/webui/local_state/local_state_ui.cc b/chromium/chrome/browser/ui/webui/local_state/local_state_ui.cc
index bcba2ab0062..4b3779bc910 100644
--- a/chromium/chrome/browser/ui/webui/local_state/local_state_ui.cc
+++ b/chromium/chrome/browser/ui/webui/local_state/local_state_ui.cc
@@ -15,7 +15,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
diff --git a/chromium/chrome/browser/ui/webui/log_web_ui_url.cc b/chromium/chrome/browser/ui/webui/log_web_ui_url.cc
index 2c0253db04d..1969d60054f 100644
--- a/chromium/chrome/browser/ui/webui/log_web_ui_url.cc
+++ b/chromium/chrome/browser/ui/webui/log_web_ui_url.cc
@@ -10,14 +10,8 @@
#include "base/metrics/histogram_functions.h"
#include "chrome/common/url_constants.h"
#include "content/public/common/url_constants.h"
-#include "extensions/buildflags/buildflags.h"
#include "url/gurl.h"
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-#include "chrome/common/extensions/extension_constants.h"
-#include "extensions/common/constants.h"
-#endif
-
namespace webui {
const char kWebUICreatedForUrl[] = "WebUI.CreatedForUrl";
diff --git a/chromium/chrome/browser/ui/webui/management_ui.cc b/chromium/chrome/browser/ui/webui/management_ui.cc
index 9488e6a4df0..6bd451e3c24 100644
--- a/chromium/chrome/browser/ui/webui/management_ui.cc
+++ b/chromium/chrome/browser/ui/webui/management_ui.cc
@@ -16,11 +16,12 @@
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/theme_resources.h"
-#include "components/safe_browsing/common/safebrowsing_constants.h"
+#include "components/safe_browsing/core/common/safebrowsing_constants.h"
#include "components/strings/grit/components_strings.h"
#include "extensions/buildflags/buildflags.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/web_ui_util.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/browser_process.h"
@@ -57,8 +58,14 @@ content::WebUIDataSource* CreateManagementUIHtmlSource(Profile* profile) {
{kManagementReportNetworkInterfaces,
IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_INTERFACES},
{kManagementReportUsers, IDS_MANAGEMENT_REPORT_DEVICE_USERS},
+ {kManagementReportCrashReports, IDS_MANAGEMENT_REPORT_DEVICE_CRASH_REPORTS},
{kManagementPrinting, IDS_MANAGEMENT_REPORT_PRINTING},
{kManagementCrostini, IDS_MANAGEMENT_CROSTINI},
+ {kManagementCrostiniContainerConfiguration,
+ IDS_MANAGEMENT_CROSTINI_CONTAINER_CONFIGURATION},
+ {kManagementReportExtensions, IDS_MANAGEMENT_REPORT_EXTENSIONS},
+ {kManagementReportAndroidApplications,
+ IDS_MANAGEMENT_REPORT_ANDROID_APPLICATIONS},
#endif // defined(OS_CHROMEOS)
{"browserReporting", IDS_MANAGEMENT_BROWSER_REPORTING},
{"browserReportingExplanation",
diff --git a/chromium/chrome/browser/ui/webui/management_ui_handler.cc b/chromium/chrome/browser/ui/webui/management_ui_handler.cc
index 85acd3dd47f..d831e5152d9 100644
--- a/chromium/chrome/browser/ui/webui/management_ui_handler.cc
+++ b/chromium/chrome/browser/ui/webui/management_ui_handler.cc
@@ -14,6 +14,8 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
+#include "base/feature_list.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
@@ -22,9 +24,10 @@
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
@@ -36,6 +39,7 @@
#include "ui/base/webui/web_ui_util.h"
#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/crostini/crostini_features.h"
#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
@@ -131,8 +135,14 @@ const char kManagementReportHardwareStatus[] = "managementReportHardwareStatus";
const char kManagementReportNetworkInterfaces[] =
"managementReportNetworkInterfaces";
const char kManagementReportUsers[] = "managementReportUsers";
+const char kManagementReportCrashReports[] = "managementReportCrashReports";
+const char kManagementReportExtensions[] = "managementReportExtensions";
+const char kManagementReportAndroidApplications[] =
+ "managementReportAndroidApplications";
const char kManagementPrinting[] = "managementPrinting";
const char kManagementCrostini[] = "managementCrostini";
+const char kManagementCrostiniContainerConfiguration[] =
+ "managementCrostiniContainerConfiguration";
const char kAccountManagedInfo[] = "accountManagedInfo";
const char kDeviceManagedInfo[] = "deviceManagedInfo";
const char kOverview[] = "overview";
@@ -140,6 +150,8 @@ const char kOverview[] = "overview";
const char kCustomerLogo[] = "customerLogo";
+const char kPowerfulExtensionsCountHistogram[] = "Extensions.PowerfulCount";
+
namespace {
bool IsProfileManaged(Profile* profile) {
@@ -168,9 +180,13 @@ enum class DeviceReportingType {
kDeviceActivity,
kDeviceStatistics,
kDevice,
+ kCrashReport,
kLogs,
kPrint,
- kCrostini
+ kCrostini,
+ kUsername,
+ kExtensions,
+ kAndroidApplication
};
// Corresponds to DeviceReportingType in management_browser_proxy.js
@@ -184,12 +200,20 @@ std::string ToJSDeviceReportingType(const DeviceReportingType& type) {
return "device statistics";
case DeviceReportingType::kDevice:
return "device";
+ case DeviceReportingType::kCrashReport:
+ return "crash report";
case DeviceReportingType::kLogs:
return "logs";
case DeviceReportingType::kPrint:
return "print";
case DeviceReportingType::kCrostini:
return "crostini";
+ case DeviceReportingType::kUsername:
+ return "username";
+ case DeviceReportingType::kExtensions:
+ return "extension";
+ case DeviceReportingType::kAndroidApplication:
+ return "android application";
default:
NOTREACHED() << "Unknown device reporting type";
return "device";
@@ -241,6 +265,10 @@ void AddDeviceReportingInfo(base::Value* report_sources, Profile* profile) {
kManagementReportNetworkInterfaces,
DeviceReportingType::kDevice);
}
+ if (collector->ShouldReportCrashReportInfo()) {
+ AddDeviceReportingElement(report_sources, kManagementReportCrashReports,
+ DeviceReportingType::kCrashReport);
+ }
if (manager->GetSystemLogUploader()->upload_enabled()) {
AddDeviceReportingElement(report_sources, kManagementLogUploadEnabled,
DeviceReportingType::kLogs);
@@ -252,10 +280,31 @@ void AddDeviceReportingInfo(base::Value* report_sources, Profile* profile) {
DeviceReportingType::kPrint);
}
- if (profile->GetPrefs()->GetBoolean(
- crostini::prefs::kReportCrostiniUsageEnabled)) {
- AddDeviceReportingElement(report_sources, kManagementCrostini,
- DeviceReportingType::kCrostini);
+ if (crostini::CrostiniFeatures::Get()->IsAllowed(profile)) {
+ if (!profile->GetPrefs()
+ ->GetFilePath(crostini::prefs::kCrostiniAnsiblePlaybookFilePath)
+ .empty()) {
+ AddDeviceReportingElement(report_sources,
+ kManagementCrostiniContainerConfiguration,
+ DeviceReportingType::kCrostini);
+ } else if (profile->GetPrefs()->GetBoolean(
+ crostini::prefs::kReportCrostiniUsageEnabled)) {
+ AddDeviceReportingElement(report_sources, kManagementCrostini,
+ DeviceReportingType::kCrostini);
+ }
+ }
+
+ if (g_browser_process->local_state()->GetBoolean(
+ prefs::kCloudReportingEnabled) &&
+ base::FeatureList::IsEnabled(features::kEnterpriseReportingInChromeOS)) {
+ AddDeviceReportingElement(report_sources,
+ kManagementExtensionReportUsername,
+ DeviceReportingType::kUsername);
+ AddDeviceReportingElement(report_sources, kManagementReportExtensions,
+ DeviceReportingType::kExtensions);
+ AddDeviceReportingElement(report_sources,
+ kManagementReportAndroidApplications,
+ DeviceReportingType::kAndroidApplication);
}
}
#endif // defined(OS_CHROMEOS)
@@ -268,13 +317,14 @@ std::vector<base::Value> GetPermissionsForExtension(
return permission_messages;
extensions::PermissionIDSet permissions =
- extensions::PermissionMessageProvider::Get()->GetAllPermissionIDs(
- extension->permissions_data()->active_permissions(),
- extension->GetType());
+ extensions::PermissionMessageProvider::Get()
+ ->GetManagementUIPermissionIDs(
+ extension->permissions_data()->active_permissions(),
+ extension->GetType());
const extensions::PermissionMessages messages =
- extensions::PermissionMessageProvider::Get()
- ->GetPowerfulPermissionMessages(permissions);
+ extensions::PermissionMessageProvider::Get()->GetPermissionMessages(
+ permissions);
for (const auto& message : messages)
permission_messages.push_back(base::Value(message.message()));
@@ -516,9 +566,8 @@ void ManagementUIHandler::AddReportingInfo(base::Value* report_sources) {
}
}
-base::DictionaryValue ManagementUIHandler::GetContextualManagedData(
- Profile* profile) {
- base::DictionaryValue response;
+base::Value ManagementUIHandler::GetContextualManagedData(Profile* profile) {
+ base::Value response(base::Value::Type::DICTIONARY);
#if defined(OS_CHROMEOS)
std::string management_domain = GetDeviceDomain();
if (management_domain.empty())
@@ -526,26 +575,27 @@ base::DictionaryValue ManagementUIHandler::GetContextualManagedData(
#else
std::string management_domain = GetAccountDomain(profile);
- response.SetString("browserManagementNotice",
- l10n_util::GetStringFUTF16(
- managed_() ? IDS_MANAGEMENT_BROWSER_NOTICE
- : IDS_MANAGEMENT_NOT_MANAGED_NOTICE,
- base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
+ response.SetStringPath(
+ "browserManagementNotice",
+ l10n_util::GetStringFUTF16(
+ managed_() ? IDS_MANAGEMENT_BROWSER_NOTICE
+ : IDS_MANAGEMENT_NOT_MANAGED_NOTICE,
+ base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
#endif
if (management_domain.empty()) {
- response.SetString(
+ response.SetStringPath(
"extensionReportingTitle",
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED));
#if !defined(OS_CHROMEOS)
- response.SetString("pageSubtitle",
- l10n_util::GetStringUTF16(
- managed_() ? IDS_MANAGEMENT_SUBTITLE
- : IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
+ response.SetStringPath(
+ "pageSubtitle", l10n_util::GetStringUTF16(
+ managed_() ? IDS_MANAGEMENT_SUBTITLE
+ : IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
#else
const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
- response.SetString(
+ response.SetStringPath(
"pageSubtitle",
managed_()
? l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED,
@@ -556,13 +606,13 @@ base::DictionaryValue ManagementUIHandler::GetContextualManagedData(
#endif // !defined(OS_CHROMEOS)
} else {
- response.SetString(
+ response.SetStringPath(
"extensionReportingTitle",
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
base::UTF8ToUTF16(management_domain)));
#if !defined(OS_CHROMEOS)
- response.SetString(
+ response.SetStringPath(
"pageSubtitle",
managed_()
? l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
@@ -570,7 +620,7 @@ base::DictionaryValue ManagementUIHandler::GetContextualManagedData(
: l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
#else
const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
- response.SetString(
+ response.SetStringPath(
"pageSubtitle",
managed_()
? l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
@@ -581,11 +631,11 @@ base::DictionaryValue ManagementUIHandler::GetContextualManagedData(
l10n_util::GetStringUTF16(device_type)));
#endif // !defined(OS_CHROMEOS)
}
- response.SetBoolean("managed", managed_());
+ response.SetBoolPath("managed", managed_());
GetManagementStatus(profile, &response);
AsyncUpdateLogo();
if (!fetched_image_.empty())
- response.SetKey(kCustomerLogo, base::Value(fetched_image_));
+ response.SetPath(kCustomerLogo, base::Value(fetched_image_));
return response;
}
@@ -780,6 +830,11 @@ void ManagementUIHandler::HandleGetExtensions(const base::ListValue* args) {
base::Value powerful_extensions = GetPowerfulExtensions(extensions);
+ // The number of extensions to be reported in chrome://management with
+ // powerful permissions.
+ base::UmaHistogramCounts1000(kPowerfulExtensionsCountHistogram,
+ powerful_extensions.GetList().size());
+
ResolveJavascriptCallback(args->GetList()[0] /* callback_id */,
powerful_extensions);
}
diff --git a/chromium/chrome/browser/ui/webui/management_ui_handler.h b/chromium/chrome/browser/ui/webui/management_ui_handler.h
index 78fc6f597fe..a39859124bf 100644
--- a/chromium/chrome/browser/ui/webui/management_ui_handler.h
+++ b/chromium/chrome/browser/ui/webui/management_ui_handler.h
@@ -21,6 +21,7 @@
#include "content/public/browser/web_ui_message_handler.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/buildflags/buildflags.h"
+#include "extensions/common/extension_id.h"
#include "url/gurl.h"
#if defined(OS_CHROMEOS)
@@ -31,8 +32,12 @@ extern const char kManagementReportActivityTimes[];
extern const char kManagementReportHardwareStatus[];
extern const char kManagementReportNetworkInterfaces[];
extern const char kManagementReportUsers[];
+extern const char kManagementReportCrashReports[];
extern const char kManagementPrinting[];
extern const char kManagementCrostini[];
+extern const char kManagementCrostiniContainerConfiguration[];
+extern const char kManagementReportExtensions[];
+extern const char kManagementReportAndroidApplications[];
#endif // defined(OS_CHROMEOS)
extern const char kCloudReportingExtensionId[];
@@ -115,7 +120,7 @@ class ManagementUIHandler : public content::WebUIMessageHandler,
Profile* profile);
void AddReportingInfo(base::Value* report_sources);
- base::DictionaryValue GetContextualManagedData(Profile* profile);
+ base::Value GetContextualManagedData(Profile* profile);
base::Value GetThreatProtectionInfo(Profile* profile) const;
virtual policy::PolicyService* GetPolicyService() const;
virtual const extensions::Extension* GetEnabledExtension(
diff --git a/chromium/chrome/browser/ui/webui/management_ui_handler_unittest.cc b/chromium/chrome/browser/ui/webui/management_ui_handler_unittest.cc
index efd6cff8a0b..c5cf4a2e6f9 100644
--- a/chromium/chrome/browser/ui/webui/management_ui_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/management_ui_handler_unittest.cc
@@ -34,14 +34,14 @@ using testing::Return;
using testing::ReturnRef;
struct ContextualManagementSourceUpdate {
- base::string16* extension_reporting_title;
- base::string16* subtitle;
+ base::string16 extension_reporting_title;
+ base::string16 subtitle;
#if defined(OS_CHROMEOS)
- base::string16* management_overview;
+ base::string16 management_overview;
#else
- base::string16* browser_management_notice;
+ base::string16 browser_management_notice;
#endif // defined(OS_CHROMEOS)
- bool* managed;
+ bool managed;
};
class TestManagementUIHandler : public ManagementUIHandler {
@@ -55,7 +55,7 @@ class TestManagementUIHandler : public ManagementUIHandler {
cloud_reporting_extension_exists_ = enable;
}
- base::DictionaryValue GetContextualManagedDataForTesting(Profile* profile) {
+ base::Value GetContextualManagedDataForTesting(Profile* profile) {
return GetContextualManagedData(profile);
}
@@ -121,224 +121,211 @@ class ManagementUIHandlerTests : public testing::Test {
std::make_unique<base::Value>(value), nullptr);
}
- void ExtractContextualSourceUpdate(
- const base::DictionaryValue& data,
- const ContextualManagementSourceUpdate& extracted) {
- data.GetString("extensionReportingTitle",
- extracted.extension_reporting_title);
- data.GetString("pageSubtitle", extracted.subtitle);
+ base::string16 ExtractPathFromDict(const base::Value& data,
+ const std::string path) {
+ const std::string* buf = data.FindStringPath(path);
+ if (!buf)
+ return base::string16();
+ return base::UTF8ToUTF16(*buf);
+ }
+
+ void ExtractContextualSourceUpdate(const base::Value& data) {
+ extracted_.extension_reporting_title =
+ ExtractPathFromDict(data, "extensionReportingTitle");
+ extracted_.subtitle = ExtractPathFromDict(data, "pageSubtitle");
#if defined(OS_CHROMEOS)
- data.GetString("overview", extracted.management_overview);
+ extracted_.management_overview = ExtractPathFromDict(data, "overview");
#else
- data.GetString("browserManagementNotice",
- extracted.browser_management_notice);
+ extracted_.browser_management_notice =
+ ExtractPathFromDict(data, "browserManagementNotice");
#endif // defined(OS_CHROMEOS)
- data.GetBoolean("managed", extracted.managed);
+ base::Optional<bool> managed = data.FindBoolPath("managed");
+ extracted_.managed = managed.has_value() && managed.value();
+ }
+
+ void PrepareProfileAndHandler() {
+ PrepareProfileAndHandler(std::string(), false, true, false,
+ "devicedomain.com");
+ }
+
+ void PrepareProfileAndHandler(const std::string& profile_name,
+ bool override_policy_connector_is_managed,
+ bool use_account,
+ bool use_device) {
+ PrepareProfileAndHandler(profile_name, override_policy_connector_is_managed,
+ use_account, use_device, "devicedomain.com");
+ }
+
+ void PrepareProfileAndHandler(const std::string& profile_name,
+ bool override_policy_connector_is_managed,
+ bool use_account,
+ bool use_device,
+ const std::string& device_domain) {
+ TestingProfile::Builder builder;
+ builder.SetProfileName(profile_name);
+ if (override_policy_connector_is_managed) {
+ builder.OverridePolicyConnectorIsManagedForTesting(true);
+ }
+ profile_ = builder.Build();
+ handler_.SetAccountManagedForTesting(use_account);
+ handler_.SetDeviceManagedForTesting(use_device);
+#if defined(OS_CHROMEOS)
+ handler_.SetDeviceDomain(device_domain);
+#endif
+ base::Value data =
+ handler_.GetContextualManagedDataForTesting(profile_.get());
+ ExtractContextualSourceUpdate(data);
}
+ bool GetManaged() const { return extracted_.managed; }
+
+#if defined(OS_CHROMEOS)
+ base::string16 GetManagementOverview() const {
+ return extracted_.management_overview;
+ }
+#else
+ base::string16 GetBrowserManagementNotice() const {
+ return extracted_.browser_management_notice;
+ }
+#endif
+
+ base::string16 GetExtensionReportingTitle() const {
+ return extracted_.extension_reporting_title;
+ }
+
+ base::string16 GetPageSubtitle() const { return extracted_.subtitle; }
+
protected:
TestManagementUIHandler handler_;
content::BrowserTaskEnvironment task_environment_;
policy::MockPolicyService policy_service_;
policy::PolicyMap empty_policy_map_;
base::string16 device_domain_;
+ ContextualManagementSourceUpdate extracted_;
+ std::unique_ptr<TestingProfile> profile_;
};
+void ExpectMessagesToBeEQ(base::Value::ConstListView infolist,
+ const std::set<std::string>& expected_messages) {
+ ASSERT_EQ(infolist.size(), expected_messages.size());
+ std::set<std::string> tmp_expected(expected_messages);
+ for (const base::Value& info : infolist) {
+ const std::string* message_id = info.FindStringKey("messageId");
+ if (message_id) {
+ EXPECT_EQ(1u, tmp_expected.erase(*message_id));
+ }
+ }
+ EXPECT_TRUE(tmp_expected.empty());
+}
+
#if !defined(OS_CHROMEOS)
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateUnmanagedNoDomain) {
- auto profile = TestingProfile::Builder().Build();
+ PrepareProfileAndHandler(
+ /* profile_name= */ "",
+ /* override_policy_connector_is_managed= */ false,
+ /* use_account= */ false,
+ /* use_device= */ false);
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 browser_management_notice;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &browser_management_notice,
- &managed};
-
- handler_.SetAccountManagedForTesting(false);
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(data.DictSize(), 4u);
- EXPECT_EQ(extension_reporting_title,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED));
- EXPECT_EQ(browser_management_notice,
+ EXPECT_EQ(GetBrowserManagementNotice(),
l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_NOT_MANAGED_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
- EXPECT_EQ(subtitle,
+ EXPECT_EQ(GetPageSubtitle(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
}
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateManagedNoDomain) {
- auto profile = TestingProfile::Builder().Build();
+ PrepareProfileAndHandler();
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 browser_management_notice;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &browser_management_notice,
- &managed};
-
- handler_.SetAccountManagedForTesting(true);
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(data.DictSize(), 4u);
- EXPECT_EQ(extension_reporting_title,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED));
- EXPECT_EQ(browser_management_notice,
+ EXPECT_EQ(GetBrowserManagementNotice(),
l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_BROWSER_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
- EXPECT_EQ(subtitle, l10n_util::GetStringUTF16(IDS_MANAGEMENT_SUBTITLE));
- EXPECT_TRUE(managed);
+ EXPECT_EQ(GetPageSubtitle(),
+ l10n_util::GetStringUTF16(IDS_MANAGEMENT_SUBTITLE));
+ EXPECT_TRUE(GetManaged());
}
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateManagedConsumerDomain) {
- TestingProfile::Builder builder;
- builder.SetProfileName("managed@gmail.com");
- builder.OverridePolicyConnectorIsManagedForTesting(true);
- auto profile = builder.Build();
+ PrepareProfileAndHandler(
+ /* profile_name= */ "managed@gmail.com",
+ /* override_policy_connector_is_managed= */ true,
+ /* use_account= */ true, /* use_device= */ false);
- base::string16 extensions_installed;
- base::string16 subtitle;
- base::string16 browser_management_notice;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extensions_installed,
- &subtitle,
- &browser_management_notice,
- &managed};
-
- handler_.SetAccountManagedForTesting(true);
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(data.DictSize(), 4u);
- EXPECT_EQ(extensions_installed,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED));
- EXPECT_EQ(browser_management_notice,
+ EXPECT_EQ(GetBrowserManagementNotice(),
l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_BROWSER_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
- EXPECT_EQ(subtitle, l10n_util::GetStringUTF16(IDS_MANAGEMENT_SUBTITLE));
- EXPECT_TRUE(managed);
+ EXPECT_EQ(GetPageSubtitle(),
+ l10n_util::GetStringUTF16(IDS_MANAGEMENT_SUBTITLE));
+ EXPECT_TRUE(GetManaged());
}
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateUnmanagedKnownDomain) {
- TestingProfile::Builder builder;
- builder.SetProfileName("managed@manager.com");
- builder.OverridePolicyConnectorIsManagedForTesting(true);
- auto profile = builder.Build();
-
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 browser_management_notice;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &browser_management_notice,
- &managed};
-
- handler_.SetAccountManagedForTesting(false);
+ const std::string domain = "manager.com";
+ PrepareProfileAndHandler(
+ /* profile_name= */ "managed@" + domain,
+ /* override_policy_connector_is_managed= */ true,
+ /* use_account= */ false, /* use_device= */ false);
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(data.DictSize(), 4u);
- EXPECT_EQ(extension_reporting_title,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
- base::UTF8ToUTF16("manager.com")));
- EXPECT_EQ(browser_management_notice,
+ base::UTF8ToUTF16(domain)));
+ EXPECT_EQ(GetBrowserManagementNotice(),
l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_NOT_MANAGED_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
- EXPECT_EQ(subtitle,
+ EXPECT_EQ(GetPageSubtitle(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
- EXPECT_FALSE(managed);
+ EXPECT_FALSE(GetManaged());
}
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateUnmanagedCustomerDomain) {
- TestingProfile::Builder builder;
- builder.SetProfileName("managed@googlemail.com");
- auto profile = builder.Build();
-
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 browser_management_notice;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &browser_management_notice,
- &managed};
-
- handler_.SetAccountManagedForTesting(false);
-
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(data.DictSize(), 4u);
- EXPECT_EQ(extension_reporting_title,
+ PrepareProfileAndHandler(
+ /* profile_name= */ "managed@googlemail.com",
+ /* override_policy_connector_is_managed= */ false,
+ /* use_account= */ false, /* use_device= */ false);
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED));
- EXPECT_EQ(browser_management_notice,
+ EXPECT_EQ(GetBrowserManagementNotice(),
l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_NOT_MANAGED_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
- EXPECT_EQ(subtitle,
+ EXPECT_EQ(GetPageSubtitle(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE));
- EXPECT_FALSE(managed);
+ EXPECT_FALSE(GetManaged());
}
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateManagedKnownDomain) {
- TestingProfile::Builder builder;
- builder.SetProfileName("managed@gmail.com.manager.com.gmail.com");
- builder.OverridePolicyConnectorIsManagedForTesting(true);
- auto profile = builder.Build();
+ const std::string domain = "gmail.com.manager.com.gmail.com";
+ PrepareProfileAndHandler(
+ /* profile_name= */ "managed@" + domain,
+ /* override_policy_connector_is_managed= */ true,
+ /* use_account_for_testing= */ true, /* use_device= */ false);
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 browser_management_notice;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &browser_management_notice,
- &managed};
-
- handler_.SetAccountManagedForTesting(true);
- handler_.SetDeviceManagedForTesting(false);
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(data.DictSize(), 4u);
- EXPECT_EQ(extension_reporting_title,
- l10n_util::GetStringFUTF16(
- IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
- base::UTF8ToUTF16("gmail.com.manager.com.gmail.com")));
- EXPECT_EQ(browser_management_notice,
+ EXPECT_EQ(GetExtensionReportingTitle(),
+ l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
+ base::UTF8ToUTF16(domain)));
+ EXPECT_EQ(GetBrowserManagementNotice(),
l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_BROWSER_NOTICE,
base::UTF8ToUTF16(chrome::kManagedUiLearnMoreUrl)));
- EXPECT_EQ(subtitle,
- l10n_util::GetStringFUTF16(
- IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
- base::UTF8ToUTF16("gmail.com.manager.com.gmail.com")));
- EXPECT_TRUE(managed);
+ EXPECT_EQ(GetPageSubtitle(),
+ l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
+ base::UTF8ToUTF16(domain)));
+ EXPECT_TRUE(GetManaged());
}
#endif // !defined(OS_CHROMEOS)
@@ -346,203 +333,124 @@ TEST_F(ManagementUIHandlerTests,
#if defined(OS_CHROMEOS)
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateManagedAccountKnownDomain) {
- TestingProfile::Builder builder;
- builder.SetProfileName("managed@manager.com");
- builder.OverridePolicyConnectorIsManagedForTesting(true);
- auto profile = builder.Build();
+ const std::string domain = "manager.com";
+ PrepareProfileAndHandler(
+ /* profile_name= */ "managed@" + domain,
+ /* override_policy_connector_is_managed= */ true,
+ /* use_account= */ true, /* use_device= */ false,
+ /* device_name= */ "");
const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 management_overview;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &management_overview,
- &managed};
-
- handler_.SetAccountManagedForTesting(true);
- handler_.SetDeviceManagedForTesting(false);
- handler_.SetDeviceDomain("");
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(extension_reporting_title,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
- base::UTF8ToUTF16("manager.com")));
- EXPECT_EQ(subtitle,
+ base::UTF8ToUTF16(domain)));
+ EXPECT_EQ(GetPageSubtitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
l10n_util::GetStringUTF16(device_type),
- base::UTF8ToUTF16("manager.com")));
- EXPECT_EQ(management_overview,
+ base::UTF8ToUTF16(domain)));
+ EXPECT_EQ(GetManagementOverview(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_ACCOUNT_MANAGED_BY,
- base::UTF8ToUTF16("manager.com")));
- EXPECT_TRUE(managed);
+ base::UTF8ToUTF16(domain)));
+ EXPECT_TRUE(GetManaged());
}
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateManagedAccountUnknownDomain) {
- TestingProfile::Builder builder;
- auto profile = builder.Build();
+ PrepareProfileAndHandler(
+ /* profile_name= */ "",
+ /* override_policy_connector_is_managed= */ false,
+ /* use_account= */ true, /* use_device= */ false,
+ /* device_name= */ "");
const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 management_overview;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &management_overview,
- &managed};
-
- handler_.SetAccountManagedForTesting(true);
- handler_.SetDeviceManagedForTesting(false);
- handler_.SetDeviceDomain("");
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(extension_reporting_title,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED));
- EXPECT_EQ(subtitle,
+ EXPECT_EQ(GetPageSubtitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED,
l10n_util::GetStringUTF16(device_type)));
- EXPECT_EQ(management_overview, base::string16());
- EXPECT_TRUE(managed);
+ EXPECT_EQ(GetManagementOverview(), base::string16());
+ EXPECT_TRUE(GetManaged());
}
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateManagedDevice) {
- TestingProfile::Builder builder;
- builder.SetProfileName("managed@manager.com");
- auto profile = builder.Build();
+ PrepareProfileAndHandler(
+ /* profile_name= */ "managed@manager.com",
+ /* override_policy_connector_is_managed= */ false,
+ /* use_account= */ false, /* use_device= */ true);
const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 management_overview;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &management_overview,
- &managed};
-
- handler_.SetAccountManagedForTesting(false);
- handler_.SetDeviceManagedForTesting(true);
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(subtitle,
+ EXPECT_EQ(GetPageSubtitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
l10n_util::GetStringUTF16(device_type),
device_domain()));
- EXPECT_EQ(extension_reporting_title,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
device_domain()));
- EXPECT_EQ(management_overview, base::string16());
- EXPECT_TRUE(managed);
+ EXPECT_EQ(GetManagementOverview(), base::string16());
+ EXPECT_TRUE(GetManaged());
}
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateManagedDeviceAndAccount) {
- TestingProfile::Builder builder;
- builder.SetProfileName("managed@devicedomain.com");
- auto profile = builder.Build();
+ PrepareProfileAndHandler(
+ /* profile_name= */ "managed@devicedomain.com",
+ /* override_policy_connector_is_managed= */ false,
+ /* use_account= */ true, /* use_device= */ true);
const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 management_overview;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &management_overview,
- &managed};
-
- handler_.SetAccountManagedForTesting(true);
- handler_.SetDeviceManagedForTesting(true);
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(subtitle,
+ EXPECT_EQ(GetPageSubtitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
l10n_util::GetStringUTF16(device_type),
device_domain()));
- EXPECT_EQ(extension_reporting_title,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
device_domain()));
- EXPECT_EQ(management_overview,
+ EXPECT_EQ(GetManagementOverview(),
l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_DEVICE_AND_ACCOUNT_MANAGED_BY, device_domain()));
- EXPECT_TRUE(managed);
+ EXPECT_TRUE(GetManaged());
}
TEST_F(ManagementUIHandlerTests,
ManagementContextualSourceUpdateManagedDeviceAndAccountMultipleDomains) {
- TestingProfile::Builder builder;
- builder.SetProfileName("managed@manager.com");
- builder.OverridePolicyConnectorIsManagedForTesting(true);
- auto profile = builder.Build();
+ const std::string domain = "manager.com";
+ PrepareProfileAndHandler(
+ /* profile_name= */ "managed@" + domain,
+ /* override_policy_connector_is_managed= */ true,
+ /* use_account= */ true, /* use_device= */ true);
const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 management_overview;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &management_overview,
- &managed};
-
- handler_.SetAccountManagedForTesting(true);
- handler_.SetDeviceManagedForTesting(true);
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
-
- EXPECT_EQ(subtitle,
+ EXPECT_EQ(GetPageSubtitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_SUBTITLE_MANAGED_BY,
l10n_util::GetStringUTF16(device_type),
device_domain()));
- EXPECT_EQ(extension_reporting_title,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED_BY,
device_domain()));
- EXPECT_EQ(management_overview,
+ EXPECT_EQ(GetManagementOverview(),
l10n_util::GetStringFUTF16(
IDS_MANAGEMENT_DEVICE_MANAGED_BY_ACCOUNT_MANAGED_BY,
- device_domain(), base::UTF8ToUTF16("manager.com")));
- EXPECT_TRUE(managed);
+ device_domain(), base::UTF8ToUTF16(domain)));
+ EXPECT_TRUE(GetManaged());
}
TEST_F(ManagementUIHandlerTests, ManagementContextualSourceUpdateUnmanaged) {
- auto profile = TestingProfile::Builder().Build();
+ PrepareProfileAndHandler(
+ /* profile_name= */ "",
+ /* override_policy_connector_is_managed= */ false,
+ /* use_account= */ false, /* use_device= */ false,
+ /* device_domain= */ "");
const auto device_type = ui::GetChromeOSDeviceTypeResourceId();
- base::string16 extension_reporting_title;
- base::string16 subtitle;
- base::string16 management_overview;
- bool managed;
- ContextualManagementSourceUpdate extracted{
- &extension_reporting_title,
- &subtitle,
- &management_overview,
- &managed};
-
- handler_.SetAccountManagedForTesting(false);
- handler_.SetDeviceDomain("");
- auto data = handler_.GetContextualManagedDataForTesting(profile.get());
- ExtractContextualSourceUpdate(data, extracted);
- EXPECT_EQ(subtitle,
+ EXPECT_EQ(GetPageSubtitle(),
l10n_util::GetStringFUTF16(IDS_MANAGEMENT_NOT_MANAGED_SUBTITLE,
l10n_util::GetStringUTF16(device_type)));
- EXPECT_EQ(extension_reporting_title,
+ EXPECT_EQ(GetExtensionReportingTitle(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_EXTENSIONS_INSTALLED));
- EXPECT_EQ(management_overview,
+ EXPECT_EQ(GetManagementOverview(),
l10n_util::GetStringUTF16(IDS_MANAGEMENT_DEVICE_NOT_MANAGED));
- EXPECT_FALSE(managed);
+ EXPECT_FALSE(GetManaged());
}
#endif
@@ -556,20 +464,14 @@ TEST_F(ManagementUIHandlerTests,
ExtensionReportingInfoCloudExtensionAddsDefaultPolicies) {
handler_.EnableCloudReportingExtension(true);
- std::set<std::string> expected_messages = {
+ const std::set<std::string> expected_messages = {
kManagementExtensionReportMachineName, kManagementExtensionReportUsername,
kManagementExtensionReportVersion,
kManagementExtensionReportExtensionsPlugin,
kManagementExtensionReportSafeBrowsingWarnings};
- auto reporting_info = handler_.GetExtensionReportingInfo();
- const auto& reporting_info_list = reporting_info.GetList();
-
- for (const base::Value& info : reporting_info_list) {
- const std::string* messageId = info.FindStringKey("messageId");
- EXPECT_TRUE(expected_messages.find(*messageId) != expected_messages.end());
- }
- EXPECT_EQ(reporting_info.GetList().size(), expected_messages.size());
+ ExpectMessagesToBeEQ(handler_.GetExtensionReportingInfo().GetList(),
+ expected_messages);
}
TEST_F(ManagementUIHandlerTests, CloudReportingPolicy) {
@@ -587,14 +489,8 @@ TEST_F(ManagementUIHandlerTests, CloudReportingPolicy) {
kManagementExtensionReportVersion,
kManagementExtensionReportExtensionsPlugin};
- auto reporting_info = handler_.GetExtensionReportingInfo();
- const auto& reporting_info_list = reporting_info.GetList();
-
- for (const base::Value& info : reporting_info_list) {
- const std::string* messageId = info.FindStringKey("messageId");
- EXPECT_TRUE(expected_messages.find(*messageId) != expected_messages.end());
- }
- EXPECT_EQ(reporting_info.GetList().size(), expected_messages.size());
+ ExpectMessagesToBeEQ(handler_.GetExtensionReportingInfo().GetList(),
+ expected_messages);
}
TEST_F(ManagementUIHandlerTests, ExtensionReportingInfoPoliciesMerge) {
@@ -652,15 +548,8 @@ TEST_F(ManagementUIHandlerTests, ExtensionReportingInfoPoliciesMerge) {
kManagementExtensionReportUserBrowsingData,
kManagementExtensionReportPerfCrash};
- auto reporting_info = handler_.GetExtensionReportingInfo();
- const auto& reporting_info_list = reporting_info.GetList();
-
- for (const base::Value& info : reporting_info_list) {
- const std::string* message_id = info.FindStringKey("messageId");
- ASSERT_TRUE(message_id != nullptr);
- EXPECT_TRUE(expected_messages.find(*message_id) != expected_messages.end());
- }
- EXPECT_EQ(reporting_info.GetList().size(), expected_messages.size());
+ ExpectMessagesToBeEQ(handler_.GetExtensionReportingInfo().GetList(),
+ expected_messages);
}
TEST_F(ManagementUIHandlerTests, ThreatReportingInfo) {
diff --git a/chromium/chrome/browser/ui/webui/media/media_engagement_ui.cc b/chromium/chrome/browser/ui/webui/media/media_engagement_ui.cc
index 66a07e5567e..a4b0040ce31 100644
--- a/chromium/chrome/browser/ui/webui/media/media_engagement_ui.cc
+++ b/chromium/chrome/browser/ui/webui/media/media_engagement_ui.cc
@@ -18,7 +18,7 @@
#include "chrome/browser/media/media_engagement_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "components/component_updater/component_updater_service.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
@@ -151,14 +151,13 @@ MediaEngagementUI::MediaEngagementUI(content::WebUI* web_ui)
IDR_MEDIA_ENGAGEMENT_SCORE_DETAILS_MOJOM_LITE_JS);
source->SetDefaultResource(IDR_MEDIA_ENGAGEMENT_HTML);
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source.release());
- AddHandlerToRegistry(base::BindRepeating(
- &MediaEngagementUI::BindMediaEngagementScoreDetailsProvider,
- base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(MediaEngagementUI)
+
MediaEngagementUI::~MediaEngagementUI() = default;
-void MediaEngagementUI::BindMediaEngagementScoreDetailsProvider(
+void MediaEngagementUI::BindInterface(
mojo::PendingReceiver<media::mojom::MediaEngagementScoreDetailsProvider>
receiver) {
ui_handler_ = std::make_unique<MediaEngagementScoreDetailsProviderImpl>(
diff --git a/chromium/chrome/browser/ui/webui/media/media_engagement_ui.h b/chromium/chrome/browser/ui/webui/media/media_engagement_ui.h
index 51d367b598b..f7824a6ffa2 100644
--- a/chromium/chrome/browser/ui/webui/media/media_engagement_ui.h
+++ b/chromium/chrome/browser/ui/webui/media/media_engagement_ui.h
@@ -8,7 +8,7 @@
#include <memory>
#include "base/macros.h"
-#include "chrome/browser/media/media_engagement_score_details.mojom.h"
+#include "chrome/browser/media/media_engagement_score_details.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -18,14 +18,18 @@ class MediaEngagementUI : public ui::MojoWebUIController {
explicit MediaEngagementUI(content::WebUI* web_ui);
~MediaEngagementUI() override;
- private:
- void BindMediaEngagementScoreDetailsProvider(
+ // Instantiates the implementor of the MediaEngagementScoreDetailsProvider
+ // mojo interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<media::mojom::MediaEngagementScoreDetailsProvider>
receiver);
+ private:
std::unique_ptr<media::mojom::MediaEngagementScoreDetailsProvider>
ui_handler_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(MediaEngagementUI);
};
diff --git a/chromium/chrome/browser/ui/webui/media/media_feeds_ui.cc b/chromium/chrome/browser/ui/webui/media/media_feeds_ui.cc
new file mode 100644
index 00000000000..c71607dc988
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/media/media_feeds_ui.cc
@@ -0,0 +1,70 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/media/media_feeds_ui.h"
+
+#include "base/bind.h"
+
+#include "base/macros.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/media/history/media_history_keyed_service.h"
+#include "chrome/browser/media/history/media_history_keyed_service_factory.h"
+#include "chrome/browser/media/history/media_history_store.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+MediaFeedsUI::MediaFeedsUI(content::WebUI* web_ui)
+ : ui::MojoWebUIController(web_ui) {
+ // Setup the data source behind chrome://media-feeds.
+ std::unique_ptr<content::WebUIDataSource> source(
+ content::WebUIDataSource::Create(chrome::kChromeUIMediaFeedsHost));
+ source->AddResourcePath("media-data-table.js", IDR_MEDIA_DATA_TABLE_JS);
+ source->AddResourcePath("media-feeds.js", IDR_MEDIA_FEEDS_JS);
+ source->AddResourcePath(
+ "services/media_session/public/mojom/media_session.mojom-lite.js",
+ IDR_MEDIA_SESSION_MOJOM_LITE_JS);
+ source->AddResourcePath("ui/gfx/geometry/mojom/geometry.mojom-lite.js",
+ IDR_UI_GEOMETRY_MOJOM_LITE_JS);
+ source->AddResourcePath(
+ "chrome/browser/media/feeds/media_feeds_store.mojom-lite.js",
+ IDR_MEDIA_FEEDS_STORE_MOJOM_LITE_JS);
+ source->SetDefaultResource(IDR_MEDIA_FEEDS_HTML);
+ content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source.release());
+}
+
+WEB_UI_CONTROLLER_TYPE_IMPL(MediaFeedsUI)
+
+MediaFeedsUI::~MediaFeedsUI() = default;
+
+void MediaFeedsUI::BindInterface(
+ mojo::PendingReceiver<media_feeds::mojom::MediaFeedsStore> pending) {
+ receiver_.Add(this, std::move(pending));
+}
+
+void MediaFeedsUI::GetMediaFeeds(GetMediaFeedsCallback callback) {
+ GetMediaHistoryService()->GetMediaFeedsForDebug(std::move(callback));
+}
+
+void MediaFeedsUI::GetItemsForMediaFeed(int64_t feed_id,
+ GetItemsForMediaFeedCallback callback) {
+ GetMediaHistoryService()->GetItemsForMediaFeedForDebug(feed_id,
+ std::move(callback));
+}
+
+media_history::MediaHistoryKeyedService*
+MediaFeedsUI::GetMediaHistoryService() {
+ Profile* profile = Profile::FromWebUI(web_ui());
+ DCHECK(profile);
+
+ media_history::MediaHistoryKeyedService* service =
+ media_history::MediaHistoryKeyedServiceFactory::GetForProfile(profile);
+ DCHECK(service);
+ return service;
+}
diff --git a/chromium/chrome/browser/ui/webui/media/media_feeds_ui.h b/chromium/chrome/browser/ui/webui/media/media_feeds_ui.h
new file mode 100644
index 00000000000..bd8e647ffa2
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/media/media_feeds_ui.h
@@ -0,0 +1,44 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_MEDIA_MEDIA_FEEDS_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_MEDIA_MEDIA_FEEDS_UI_H_
+
+#include "chrome/browser/media/feeds/media_feeds_store.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "ui/webui/mojo_web_ui_controller.h"
+
+namespace media_history {
+class MediaHistoryKeyedService;
+} // namespace media_history
+
+// The UI for chrome://media-feeds.
+class MediaFeedsUI : public ui::MojoWebUIController,
+ public media_feeds::mojom::MediaFeedsStore {
+ public:
+ explicit MediaFeedsUI(content::WebUI* web_ui);
+ MediaFeedsUI(const MediaFeedsUI&) = delete;
+ MediaFeedsUI& operator=(const MediaFeedsUI&) = delete;
+ ~MediaFeedsUI() override;
+
+ // Instantiates the implementor of the MediaFeedsStore mojo interface passing
+ // the pending receiver that will be internally bound.
+ void BindInterface(
+ mojo::PendingReceiver<media_feeds::mojom::MediaFeedsStore> pending);
+
+ // media_history::mojom::MediaHistoryStore:
+ void GetMediaFeeds(GetMediaFeedsCallback callback) override;
+ void GetItemsForMediaFeed(int64_t feed_id,
+ GetItemsForMediaFeedCallback callback) override;
+
+ private:
+ media_history::MediaHistoryKeyedService* GetMediaHistoryService();
+
+ mojo::ReceiverSet<media_feeds::mojom::MediaFeedsStore> receiver_;
+
+ WEB_UI_CONTROLLER_TYPE_DECL();
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_MEDIA_MEDIA_FEEDS_UI_H_
diff --git a/chromium/chrome/browser/ui/webui/media/media_history_ui.cc b/chromium/chrome/browser/ui/webui/media/media_history_ui.cc
new file mode 100644
index 00000000000..6f432397756
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/media/media_history_ui.cc
@@ -0,0 +1,82 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/media/media_history_ui.h"
+
+#include "base/bind.h"
+
+#include "base/macros.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/media/history/media_history_keyed_service.h"
+#include "chrome/browser/media/history/media_history_keyed_service_factory.h"
+#include "chrome/browser/media/history/media_history_store.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+MediaHistoryUI::MediaHistoryUI(content::WebUI* web_ui)
+ : ui::MojoWebUIController(web_ui) {
+ // Setup the data source behind chrome://media-history.
+ std::unique_ptr<content::WebUIDataSource> source(
+ content::WebUIDataSource::Create(chrome::kChromeUIMediaHistoryHost));
+ source->AddResourcePath("media-data-table.js", IDR_MEDIA_DATA_TABLE_JS);
+ source->AddResourcePath("media-history.js", IDR_MEDIA_HISTORY_JS);
+ source->AddResourcePath(
+ "services/media_session/public/mojom/media_session.mojom-lite.js",
+ IDR_MEDIA_SESSION_MOJOM_LITE_JS);
+ source->AddResourcePath("ui/gfx/geometry/mojom/geometry.mojom-lite.js",
+ IDR_UI_GEOMETRY_MOJOM_LITE_JS);
+ source->AddResourcePath(
+ "chrome/browser/media/history/media_history_store.mojom-lite.js",
+ IDR_MEDIA_HISTORY_STORE_MOJOM_LITE_JS);
+ source->SetDefaultResource(IDR_MEDIA_HISTORY_HTML);
+ content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source.release());
+}
+
+WEB_UI_CONTROLLER_TYPE_IMPL(MediaHistoryUI)
+
+MediaHistoryUI::~MediaHistoryUI() = default;
+
+void MediaHistoryUI::BindInterface(
+ mojo::PendingReceiver<media_history::mojom::MediaHistoryStore> pending) {
+ receivers_.Add(this, std::move(pending));
+}
+
+void MediaHistoryUI::GetMediaHistoryStats(
+ GetMediaHistoryStatsCallback callback) {
+ return GetMediaHistoryService()->GetMediaHistoryStats(std::move(callback));
+}
+
+void MediaHistoryUI::GetMediaHistoryOriginRows(
+ GetMediaHistoryOriginRowsCallback callback) {
+ return GetMediaHistoryService()->GetOriginRowsForDebug(std::move(callback));
+}
+
+void MediaHistoryUI::GetMediaHistoryPlaybackRows(
+ GetMediaHistoryPlaybackRowsCallback callback) {
+ return GetMediaHistoryService()->GetMediaHistoryPlaybackRowsForDebug(
+ std::move(callback));
+}
+
+void MediaHistoryUI::GetMediaHistoryPlaybackSessionRows(
+ GetMediaHistoryPlaybackSessionRowsCallback callback) {
+ return GetMediaHistoryService()->GetPlaybackSessions(
+ base::nullopt, base::nullopt, std::move(callback));
+}
+
+media_history::MediaHistoryKeyedService*
+MediaHistoryUI::GetMediaHistoryService() {
+ Profile* profile = Profile::FromWebUI(web_ui());
+ DCHECK(profile);
+
+ media_history::MediaHistoryKeyedService* service =
+ media_history::MediaHistoryKeyedServiceFactory::GetForProfile(profile);
+ DCHECK(service);
+ return service;
+}
diff --git a/chromium/chrome/browser/ui/webui/media/media_history_ui.h b/chromium/chrome/browser/ui/webui/media/media_history_ui.h
new file mode 100644
index 00000000000..18a14b17a9c
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/media/media_history_ui.h
@@ -0,0 +1,48 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_MEDIA_MEDIA_HISTORY_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_MEDIA_MEDIA_HISTORY_UI_H_
+
+#include "chrome/browser/media/history/media_history_store.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "ui/webui/mojo_web_ui_controller.h"
+
+namespace media_history {
+class MediaHistoryKeyedService;
+} // namespace media_history
+
+// The UI for chrome://media-history.
+class MediaHistoryUI : public ui::MojoWebUIController,
+ public media_history::mojom::MediaHistoryStore {
+ public:
+ explicit MediaHistoryUI(content::WebUI* web_ui);
+ MediaHistoryUI(const MediaHistoryUI&) = delete;
+ MediaHistoryUI& operator=(const MediaHistoryUI&) = delete;
+ ~MediaHistoryUI() override;
+
+ // Instantiates the implementor of the MediaEngagementScoreDetailsProvider
+ // mojo interface passing the pending receiver that will be internally bound.
+ void BindInterface(
+ mojo::PendingReceiver<media_history::mojom::MediaHistoryStore> pending);
+
+ // media::mojom::MediaHistoryStore:
+ void GetMediaHistoryStats(GetMediaHistoryStatsCallback callback) override;
+ void GetMediaHistoryOriginRows(
+ GetMediaHistoryOriginRowsCallback callback) override;
+ void GetMediaHistoryPlaybackRows(
+ GetMediaHistoryPlaybackRowsCallback callback) override;
+ void GetMediaHistoryPlaybackSessionRows(
+ GetMediaHistoryPlaybackSessionRowsCallback callback) override;
+
+ private:
+ media_history::MediaHistoryKeyedService* GetMediaHistoryService();
+
+ mojo::ReceiverSet<media_history::mojom::MediaHistoryStore> receivers_;
+
+ WEB_UI_CONTROLLER_TYPE_DECL();
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_MEDIA_MEDIA_HISTORY_UI_H_
diff --git a/chromium/chrome/browser/ui/webui/media/webrtc_logs_ui.cc b/chromium/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
index a38cb8031a3..bfb7af3a448 100644
--- a/chromium/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
+++ b/chromium/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
@@ -35,6 +35,7 @@
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
+#include "ui/base/webui/web_ui_util.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/settings/cros_settings.h"
diff --git a/chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.cc b/chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.cc
index f3390a9b16f..20a5dab48ae 100644
--- a/chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.cc
+++ b/chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.cc
@@ -5,30 +5,84 @@
#include "chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.h"
#include "base/bind.h"
-#include "base/values.h"
#include "chrome/browser/media/router/media_router.h"
namespace media_router {
+namespace {
+
+base::Value CastProviderStateToValue(const mojom::CastProviderState& state) {
+ base::Value result(base::Value::Type::LIST);
+ for (const mojom::CastSessionStatePtr& session : state.session_state) {
+ base::Value session_value(base::Value::Type::DICTIONARY);
+ session_value.SetStringKey("sink_id", session->sink_id);
+ session_value.SetStringKey("app_id", session->app_id);
+ session_value.SetStringKey("session_id", session->session_id);
+ session_value.SetStringKey("route_description", session->route_description);
+ result.Append(std::move(session_value));
+ }
+ return result;
+}
+
+} // namespace
+
MediaRouterInternalsWebUIMessageHandler::
MediaRouterInternalsWebUIMessageHandler(const MediaRouter* router)
: router_(router) {
DCHECK(router_);
}
+MediaRouterInternalsWebUIMessageHandler::
+ ~MediaRouterInternalsWebUIMessageHandler() = default;
+
void MediaRouterInternalsWebUIMessageHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
- "getStatus",
+ "getState", base::BindRepeating(
+ &MediaRouterInternalsWebUIMessageHandler::HandleGetState,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "getProviderState",
base::BindRepeating(
- &MediaRouterInternalsWebUIMessageHandler::HandleGetStatus,
+ &MediaRouterInternalsWebUIMessageHandler::HandleGetProviderState,
base::Unretained(this)));
}
-void MediaRouterInternalsWebUIMessageHandler::HandleGetStatus(
+void MediaRouterInternalsWebUIMessageHandler::HandleGetState(
const base::ListValue* args) {
AllowJavascript();
const base::Value& callback_id = args->GetList()[0];
ResolveJavascriptCallback(callback_id, router_->GetState());
}
+void MediaRouterInternalsWebUIMessageHandler::HandleGetProviderState(
+ const base::ListValue* args) {
+ AllowJavascript();
+ base::Value callback_id = args->GetList()[0].Clone();
+ if (args->GetList().size() != 2 || !args->GetList()[1].is_string()) {
+ RejectJavascriptCallback(callback_id, base::Value("Invalid arguments"));
+ }
+
+ MediaRouteProviderId provider_id =
+ ProviderIdFromString(args->GetList()[1].GetString());
+ if (provider_id == MediaRouteProviderId::UNKNOWN) {
+ RejectJavascriptCallback(callback_id,
+ base::Value("Unknown MediaRouteProviderId"));
+ }
+ router_->GetProviderState(
+ provider_id,
+ base::BindOnce(&MediaRouterInternalsWebUIMessageHandler::OnProviderState,
+ weak_factory_.GetWeakPtr(), std::move(callback_id)));
+}
+
+void MediaRouterInternalsWebUIMessageHandler::OnProviderState(
+ base::Value callback_id,
+ mojom::ProviderStatePtr state) {
+ base::Value result;
+ if (state && state->is_cast_provider_state() &&
+ state->get_cast_provider_state()) {
+ result = CastProviderStateToValue(*(state->get_cast_provider_state()));
+ }
+ ResolveJavascriptCallback(callback_id, result);
+}
+
} // namespace media_router
diff --git a/chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.h b/chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.h
index b893c1e370b..bd40bce8957 100644
--- a/chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.h
+++ b/chromium/chrome/browser/ui/webui/media_router/media_router_internals_webui_message_handler.h
@@ -7,6 +7,9 @@
#include <string>
+#include "base/memory/weak_ptr.h"
+#include "base/values.h"
+#include "chrome/common/media_router/mojom/media_router.mojom.h"
#include "content/public/browser/web_ui_message_handler.h"
namespace media_router {
@@ -19,16 +22,23 @@ class MediaRouterInternalsWebUIMessageHandler
: public content::WebUIMessageHandler {
public:
explicit MediaRouterInternalsWebUIMessageHandler(const MediaRouter* router);
+ ~MediaRouterInternalsWebUIMessageHandler() override;
private:
// WebUIMessageHandler implementation.
void RegisterMessages() override;
// Handlers for JavaScript messages.
- void HandleGetStatus(const base::ListValue* args);
+ void HandleGetState(const base::ListValue* args);
+ void HandleGetProviderState(const base::ListValue* args);
+
+ void OnProviderState(base::Value callback_id, mojom::ProviderStatePtr state);
// Pointer to the MediaRouter.
- const MediaRouter* router_;
+ const MediaRouter* const router_;
+
+ base::WeakPtrFactory<MediaRouterInternalsWebUIMessageHandler> weak_factory_{
+ this};
};
} // namespace media_router
diff --git a/chromium/chrome/browser/ui/webui/memory_internals_ui.cc b/chromium/chrome/browser/ui/webui/memory_internals_ui.cc
index fb012d59508..ab68e4f3788 100644
--- a/chromium/chrome/browser/ui/webui/memory_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/memory_internals_ui.cc
@@ -25,7 +25,7 @@
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "components/heap_profiling/supervisor.h"
#include "components/services/heap_profiling/public/cpp/settings.h"
#include "content/public/browser/browser_child_process_host_iterator.h"
diff --git a/chromium/chrome/browser/ui/webui/nacl_ui.cc b/chromium/chrome/browser/ui/webui/nacl_ui.cc
index dc610e2104a..c911931ff2b 100644
--- a/chromium/chrome/browser/ui/webui/nacl_ui.cc
+++ b/chromium/chrome/browser/ui/webui/nacl_ui.cc
@@ -24,6 +24,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/plugins/plugin_prefs.h"
@@ -371,13 +372,12 @@ void NaClDomHandler::MaybeRespondToPage() {
if (!pnacl_path_validated_) {
std::string* version_string = new std::string;
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
- base::Bind(&CheckPathAndVersion, version_string),
- base::Bind(&NaClDomHandler::DidCheckPathAndVersion,
- weak_ptr_factory_.GetWeakPtr(),
- base::Owned(version_string)));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&CheckPathAndVersion, version_string),
+ base::BindOnce(&NaClDomHandler::DidCheckPathAndVersion,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Owned(version_string)));
return;
}
diff --git a/chromium/chrome/browser/ui/webui/net_export_ui.cc b/chromium/chrome/browser/ui/webui/net_export_ui.cc
index 0924a6d7306..93bfc84f49a 100644
--- a/chromium/chrome/browser/ui/webui/net_export_ui.cc
+++ b/chromium/chrome/browser/ui/webui/net_export_ui.cc
@@ -8,6 +8,7 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -29,7 +30,7 @@
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/url_constants.h"
-#include "components/grit/components_resources.h"
+#include "components/grit/dev_ui_components_resources.h"
#include "components/net_log/net_export_file_writer.h"
#include "components/net_log/net_export_ui_constants.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index 3d53fdef64c..540abb1bce3 100644
--- a/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -15,15 +15,18 @@
#include "base/files/file_util.h"
#include "base/memory/weak_ptr.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/net/net_export_helper.h"
+#include "chrome/browser/policy/chrome_policy_conversions_client.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/net_internals_resources.h"
#include "components/onc/onc_constants.h"
+#include "components/policy/core/browser/policy_conversions.h"
#include "components/prefs/pref_member.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -42,13 +45,13 @@
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/chromeos/system_logs/debug_log_writer.h"
#include "chrome/browser/net/nss_context.h"
-#include "chrome/browser/policy/policy_conversions.h"
#include "chrome/common/logging_chrome.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
#include "chromeos/network/onc/onc_certificate_importer_impl.h"
#include "chromeos/network/onc/onc_parsed_certificates.h"
#include "chromeos/network/onc/onc_utils.h"
+#include "components/policy/core/browser/policy_conversions.h"
#endif
using content::BrowserThread;
@@ -436,13 +439,13 @@ void NetInternalsMessageHandler::OnStoreDebugLogs(bool combined,
if (file_manager::util::IsUnderNonNativeLocalPath(profile, path))
path = prefs->GetDefaultDownloadDirectoryForProfile();
base::FilePath policies_path = path.Append("policies.json");
+ auto client = std::make_unique<policy::ChromePolicyConversionsClient>(
+ web_ui()->GetWebContents()->GetBrowserContext());
std::string json_policies =
- policy::DictionaryPolicyConversions()
- .WithBrowserContext(web_ui()->GetWebContents()->GetBrowserContext())
- .ToJSON();
- base::PostTaskAndReply(
+ policy::DictionaryPolicyConversions(std::move(client)).ToJSON();
+ base::ThreadPool::PostTaskAndReply(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(DumpPolicyLogs, policies_path, json_policies),
base::BindOnce(&NetInternalsMessageHandler::OnDumpPolicyLogsCompleted,
diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/BUILD.gn b/chromium/chrome/browser/ui/webui/new_tab_page/BUILD.gn
index 4e8cb7ff269..e618c3e004d 100644
--- a/chromium/chrome/browser/ui/webui/new_tab_page/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/new_tab_page/BUILD.gn
@@ -5,7 +5,11 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "new_tab_page.mojom",
+ sources = [ "new_tab_page.mojom" ]
+
+ public_deps = [
+ "//mojo/public/mojom/base",
+ "//skia/public/mojom",
+ "//url/mojom:url_mojom_gurl",
]
}
diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/OWNERS b/chromium/chrome/browser/ui/webui/new_tab_page/OWNERS
index f05f418158c..13fc0b307a0 100644
--- a/chromium/chrome/browser/ui/webui/new_tab_page/OWNERS
+++ b/chromium/chrome/browser/ui/webui/new_tab_page/OWNERS
@@ -1,5 +1,4 @@
aee@chromium.org
-dbeam@chromium.org
mahmadi@chromium.org
tiborg@chromium.org
diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
index 97b132c36ad..41bd71a8a6b 100644
--- a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
+++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
@@ -4,6 +4,120 @@
module new_tab_page.mojom;
+import "skia/public/mojom/skcolor.mojom";
+import "url/mojom/url.mojom";
+import "mojo/public/mojom/base/text_direction.mojom";
+
+struct MostVisitedTile {
+ string title;
+ mojo_base.mojom.TextDirection title_direction;
+ url.mojom.Url url;
+};
+
+struct MostVisitedInfo {
+ bool custom_links_enabled;
+ bool visible;
+ array<MostVisitedTile> tiles;
+};
+
+struct ThemeColors {
+ // The theme's frame color.
+ skia.mojom.SkColor frame;
+ // The theme's active tab color.
+ skia.mojom.SkColor active_tab;
+};
+
+// A collection of background images.
+struct BackgroundCollection {
+ // Collection identifier.
+ string id;
+ // Localized string of the collection name.
+ string label;
+ // URL to a preview image for the collection. Can point to untrusted content.
+ url.mojom.Url preview_image_url;
+};
+
+// A background image in a collection.
+struct BackgroundImage {
+ // Localized string of extra image info.
+ string label;
+ // URL to a preview of the image. Can point to untrusted content.
+ url.mojom.Url preview_image_url;
+};
+
+// A predefined theme provided by Chrome. Created from data embedded in the
+// Chrome binary.
+struct ChromeTheme {
+ // Theme identifier.
+ int32 id;
+ // Localized string of the theme name.
+ string label;
+ ThemeColors colors;
+};
+
+enum ThemeType {
+ DEFAULT,
+ AUTOGENERATED,
+ CHROME,
+ THIRD_PARTY,
+};
+
+// Additional info for third-party themes.
+struct ThirdPartyThemeInfo {
+ // ID in the Chrome Web Store.
+ string id;
+ // Human-readable theme name.
+ string name;
+};
+
+union ThemeInfo {
+ // Set if the theme is a Chrome theme.
+ int32 chrome_theme_id;
+ // Set if the theme is autogenerated.
+ ThemeColors autogenerated_theme_colors;
+ // Set if the theme is a third-party theme.
+ ThirdPartyThemeInfo third_party_theme_info;
+};
+
+// A generic theme.
+struct Theme {
+ // The theme's type (e.g. default or third-party).
+ ThemeType type;
+ skia.mojom.SkColor background_color;
+ skia.mojom.SkColor shortcut_background_color;
+ skia.mojom.SkColor shortcut_text_color;
+ // True if the theme is dark (e.g. NTP background color is dark).
+ bool is_dark;
+ // Color of Google logo. If not set show the logo multi-colored.
+ skia.mojom.SkColor? logo_color;
+ // URL to the background image. Can point to untrusted content.
+ url.mojom.Url? background_image_url;
+ // Human readable attributions of the background image.
+ string? background_image_attribution_1;
+ string? background_image_attribution_2;
+ // URL associated with the background image. Used for href.
+ url.mojom.Url? background_image_attribution_url;
+
+ // TODO(crbug.com/1040682): Additional info about the theme depending on the
+ // type. That should be optional since only some themes require it. However,
+ // making this field optional crashes JS.
+ ThemeInfo info;
+};
+
+// The contents of a doodle.
+union DoodleContent {
+ // Doodle image encoded as data URL. Set for static and animated doodles.
+ string image;
+ // URL pointing to doodle page. Set for interactive doodles.
+ url.mojom.Url url;
+};
+
+// A doodle. Retrieved from the Google doodle server.
+struct Doodle {
+ // The doodle content.
+ DoodleContent content;
+};
+
// Used by the WebUI page to bootstrap bidirectional communication.
interface PageHandlerFactory {
// The WebUI page's |BrowserProxy| singleton calls this method when the page
@@ -14,8 +128,58 @@ interface PageHandlerFactory {
// Browser-side handler for requests from WebUI page.
interface PageHandler {
+ // Adds tile.
+ AddMostVisitedTile(url.mojom.Url url, string title) => (bool success);
+ // Deletes tile by |url|.
+ DeleteMostVisitedTile(url.mojom.Url url);
+ // Moves tile identified by url to a new position at index |new_pos|.
+ ReorderMostVisitedTile(url.mojom.Url url, uint8 new_pos);
+ // Replaces the custom and most-visited tiles with the default tile set.
+ RestoreMostVisitedDefaults();
+ // Set the visibility and whether custom links are enabled.
+ SetMostVisitedSettings(bool customLinksEnabled, bool visible);
+ // Undoes the last action done to the tiles (add, delete, reorder, restore or
+ // update). Note that only the last action can be undone.
+ UndoMostVisitedTileAction();
+ // Called to update the tiles.
+ UpdateMostVisitedInfo();
+ // Updates a tile by url.
+ UpdateMostVisitedTile(url.mojom.Url url, url.mojom.Url new_url,
+ string new_title)
+ => (bool success);
+ // Returns the pre-defined Chrome themes.
+ GetChromeThemes() => (array<ChromeTheme> chromeThemes);
+ // Applies the default theme.
+ ApplyDefaultTheme();
+ // Applies autogenerated theme for the given color.
+ ApplyAutogeneratedTheme(skia.mojom.SkColor frame_color);
+ // Applies the predefined Chrome theme with the given ID.
+ ApplyChromeTheme(int32 id);
+ // Confirms changes made to the theme.
+ ConfirmThemeChanges();
+ // Reverts changes made to the theme.
+ RevertThemeChanges();
+ // Returns the collections of background images.
+ GetBackgroundCollections() => (array<BackgroundCollection> collections);
+ // Returns the images of a collection identified by |collection_id|.
+ GetBackgroundImages(string collection_id) => (array<BackgroundImage> images);
+ // Invisibly focuses the omnibox.
+ FocusOmnibox();
+ // Pastes |text| into the omnibox.
+ PasteIntoOmnibox(string text);
+ // Gets current doodle if there is one.
+ GetDoodle() => (Doodle? doodle);
};
// WebUI-side handler for requests from the browser.
interface Page {
+ // Updates the page with most-visited info which includes whether the
+ // tiles should be shown, if links can be customized and the tiles.
+ SetMostVisitedInfo(MostVisitedInfo info);
+ // Sets the current theme.
+ SetTheme(Theme theme);
+ // If |focused| fakes focus on the fakebox.
+ SetFakeboxFocused(bool focused);
+ // If |visible| shows the fakebox.
+ SetFakeboxVisible(bool visible);
};
diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
index 2a8fa8c784a..a34ea8cc0c2 100644
--- a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
+++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
@@ -4,11 +4,408 @@
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h"
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/i18n/rtl.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/background/ntp_background_service.h"
+#include "chrome/browser/search/background/ntp_background_service_factory.h"
+#include "chrome/browser/search/chrome_colors/chrome_colors_factory.h"
+#include "chrome/browser/search/chrome_colors/chrome_colors_service.h"
+#include "chrome/browser/search/instant_service.h"
+#include "chrome/browser/search/instant_service_factory.h"
+#include "chrome/browser/search_provider_logos/logo_service_factory.h"
+#include "chrome/browser/ui/search/omnibox_utils.h"
+#include "chrome/common/search/generated_colors_info.h"
+#include "chrome/common/search/instant_types.h"
+#include "chrome/common/themes/autogenerated_theme_util.h"
+#include "components/search_provider_logos/logo_service.h"
+#include "components/search_provider_logos/switches.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/color_utils.h"
+
+namespace {
+
+new_tab_page::mojom::ThemePtr MakeTheme(const NtpTheme& ntp_theme) {
+ auto theme = new_tab_page::mojom::Theme::New();
+ if (ntp_theme.using_default_theme) {
+ theme->type = new_tab_page::mojom::ThemeType::DEFAULT;
+ // TODO(crbug.com/1040682): This info has no meaning for the default theme
+ // and shouldn't be used. We set it here to prevent a crash where mojo is
+ // complaing about an unset info. However, we cannot make the field optional
+ // as that is crashing JS. Once the JS crash is solved remove this line.
+ theme->info = new_tab_page::mojom::ThemeInfo::NewChromeThemeId(-1);
+ } else if (ntp_theme.color_id == -1) {
+ theme->type = new_tab_page::mojom::ThemeType::THIRD_PARTY;
+ auto info = new_tab_page::mojom::ThirdPartyThemeInfo::New();
+ info->id = ntp_theme.theme_id;
+ info->name = ntp_theme.theme_name;
+ theme->info =
+ new_tab_page::mojom::ThemeInfo::NewThirdPartyThemeInfo(std::move(info));
+ } else if (ntp_theme.color_id == 0) {
+ theme->type = new_tab_page::mojom::ThemeType::AUTOGENERATED;
+ auto theme_colors = new_tab_page::mojom::ThemeColors::New();
+ theme_colors->frame = ntp_theme.color_dark;
+ theme_colors->active_tab = ntp_theme.color_light;
+ theme->info = new_tab_page::mojom::ThemeInfo::NewAutogeneratedThemeColors(
+ std::move(theme_colors));
+ } else {
+ theme->type = new_tab_page::mojom::ThemeType::CHROME;
+ theme->info =
+ new_tab_page::mojom::ThemeInfo::NewChromeThemeId(ntp_theme.color_id);
+ }
+ theme->background_color = ntp_theme.background_color;
+ theme->shortcut_background_color = ntp_theme.shortcut_color;
+ theme->shortcut_text_color = ntp_theme.text_color;
+ theme->is_dark = !color_utils::IsDark(ntp_theme.text_color);
+ if (ntp_theme.logo_alternate) {
+ theme->logo_color = ntp_theme.logo_color;
+ }
+ if (!ntp_theme.custom_background_url.is_empty()) {
+ theme->background_image_url = ntp_theme.custom_background_url;
+ }
+ if (!ntp_theme.custom_background_attribution_line_1.empty()) {
+ theme->background_image_attribution_1 =
+ ntp_theme.custom_background_attribution_line_1;
+ }
+ if (!ntp_theme.custom_background_attribution_line_2.empty()) {
+ theme->background_image_attribution_2 =
+ ntp_theme.custom_background_attribution_line_2;
+ }
+ if (!ntp_theme.custom_background_attribution_action_url.is_empty()) {
+ theme->background_image_attribution_url =
+ ntp_theme.custom_background_attribution_action_url;
+ }
+ return theme;
+}
+
+} // namespace
+
NewTabPageHandler::NewTabPageHandler(
mojo::PendingReceiver<new_tab_page::mojom::PageHandler>
pending_page_handler,
- mojo::PendingRemote<new_tab_page::mojom::Page> pending_page)
- : page_{std::move(pending_page)},
- receiver_{this, std::move(pending_page_handler)} {}
+ mojo::PendingRemote<new_tab_page::mojom::Page> pending_page,
+ Profile* profile,
+ content::WebContents* web_contents)
+ : chrome_colors_service_(
+ chrome_colors::ChromeColorsFactory::GetForProfile(profile)),
+ instant_service_(InstantServiceFactory::GetForProfile(profile)),
+ ntp_background_service_(
+ NtpBackgroundServiceFactory::GetForProfile(profile)),
+ logo_service_(LogoServiceFactory::GetForProfile(profile)),
+ page_{std::move(pending_page)},
+ receiver_{this, std::move(pending_page_handler)},
+ web_contents_(web_contents) {
+ CHECK(instant_service_);
+ CHECK(ntp_background_service_);
+ CHECK(logo_service_);
+ CHECK(web_contents_);
+ instant_service_->AddObserver(this);
+ ntp_background_service_->AddObserver(this);
+ instant_service_->UpdateNtpTheme();
+ OmniboxTabHelper::CreateForWebContents(web_contents);
+ OmniboxTabHelper::FromWebContents(web_contents_)->AddObserver(this);
+}
+
+NewTabPageHandler::~NewTabPageHandler() {
+ instant_service_->RemoveObserver(this);
+ ntp_background_service_->RemoveObserver(this);
+ if (auto* helper = OmniboxTabHelper::FromWebContents(web_contents_)) {
+ helper->RemoveObserver(this);
+ }
+}
+
+void NewTabPageHandler::AddMostVisitedTile(
+ const GURL& url,
+ const std::string& title,
+ AddMostVisitedTileCallback callback) {
+ bool success = instant_service_->AddCustomLink(url, title);
+ std::move(callback).Run(success);
+}
+
+void NewTabPageHandler::DeleteMostVisitedTile(const GURL& url) {
+ if (instant_service_->IsCustomLinksEnabled()) {
+ instant_service_->DeleteCustomLink(url);
+ } else {
+ instant_service_->DeleteMostVisitedItem(url);
+ last_blacklisted_ = url;
+ }
+}
+
+void NewTabPageHandler::RestoreMostVisitedDefaults() {
+ if (instant_service_->IsCustomLinksEnabled()) {
+ instant_service_->ResetCustomLinks();
+ } else {
+ instant_service_->UndoAllMostVisitedDeletions();
+ }
+}
+
+void NewTabPageHandler::ReorderMostVisitedTile(const GURL& url,
+ uint8_t new_pos) {
+ instant_service_->ReorderCustomLink(url, new_pos);
+}
+
+void NewTabPageHandler::SetMostVisitedSettings(bool custom_links_enabled,
+ bool visible) {
+ auto pair = instant_service_->GetCurrentShortcutSettings();
+ // The first of the pair is true if most-visited tiles are being used.
+ bool old_custom_links_enabled = !pair.first;
+ bool old_visible = pair.second;
+ // |ToggleMostVisitedOrCustomLinks()| always notifies observers. Since we only
+ // want to notify once, we need to call |ToggleShortcutsVisibility()| with
+ // false if we are also going to call |ToggleMostVisitedOrCustomLinks()|.
+ bool toggleCustomLinksEnabled =
+ old_custom_links_enabled != custom_links_enabled;
+ if (old_visible != visible) {
+ instant_service_->ToggleShortcutsVisibility(
+ /* do_notify= */ !toggleCustomLinksEnabled);
+ }
+ if (toggleCustomLinksEnabled) {
+ instant_service_->ToggleMostVisitedOrCustomLinks();
+ }
+}
+
+void NewTabPageHandler::UndoMostVisitedTileAction() {
+ if (instant_service_->IsCustomLinksEnabled()) {
+ instant_service_->UndoCustomLinkAction();
+ } else if (last_blacklisted_.is_valid()) {
+ instant_service_->UndoMostVisitedDeletion(last_blacklisted_);
+ last_blacklisted_ = GURL();
+ }
+}
+
+void NewTabPageHandler::GetChromeThemes(GetChromeThemesCallback callback) {
+ std::vector<new_tab_page::mojom::ChromeThemePtr> themes;
+ for (const auto& color_info : chrome_colors::kGeneratedColorsInfo) {
+ auto theme_colors = GetAutogeneratedThemeColors(color_info.color);
+ auto theme = new_tab_page::mojom::ChromeTheme::New();
+ theme->id = color_info.id;
+ theme->label = l10n_util::GetStringUTF8(color_info.label_id);
+ auto colors = new_tab_page::mojom::ThemeColors::New();
+ colors->frame = theme_colors.frame_color;
+ colors->active_tab = theme_colors.active_tab_color;
+ theme->colors = std::move(colors);
+ themes.push_back(std::move(theme));
+ }
+ std::move(callback).Run(std::move(themes));
+}
+
+void NewTabPageHandler::ApplyDefaultTheme() {
+ chrome_colors_service_->ApplyDefaultTheme(web_contents_);
+}
+
+void NewTabPageHandler::ApplyAutogeneratedTheme(const SkColor& frame_color) {
+ chrome_colors_service_->ApplyAutogeneratedTheme(frame_color, web_contents_);
+}
+
+void NewTabPageHandler::ApplyChromeTheme(int32_t id) {
+ auto* begin = std::begin(chrome_colors::kGeneratedColorsInfo);
+ auto* end = std::end(chrome_colors::kGeneratedColorsInfo);
+ auto* result = std::find_if(begin, end,
+ [id](const chrome_colors::ColorInfo& color_info) {
+ return color_info.id == id;
+ });
+ if (result == end) {
+ return;
+ }
+ chrome_colors_service_->ApplyAutogeneratedTheme(result->color, web_contents_);
+}
+
+void NewTabPageHandler::ConfirmThemeChanges() {
+ chrome_colors_service_->ConfirmThemeChanges();
+}
+
+void NewTabPageHandler::RevertThemeChanges() {
+ chrome_colors_service_->RevertThemeChanges();
+}
+
+void NewTabPageHandler::UpdateMostVisitedInfo() {
+ instant_service_->UpdateMostVisitedInfo();
+}
+
+void NewTabPageHandler::UpdateMostVisitedTile(
+ const GURL& url,
+ const GURL& new_url,
+ const std::string& new_title,
+ UpdateMostVisitedTileCallback callback) {
+ bool success = instant_service_->UpdateCustomLink(
+ url, new_url != url ? new_url : GURL(), new_title);
+ std::move(callback).Run(success);
+}
+
+void NewTabPageHandler::GetBackgroundCollections(
+ GetBackgroundCollectionsCallback callback) {
+ if (!ntp_background_service_ || background_collections_callback_) {
+ std::move(callback).Run(
+ std::vector<new_tab_page::mojom::BackgroundCollectionPtr>());
+ return;
+ }
+ background_collections_callback_ = std::move(callback);
+ ntp_background_service_->FetchCollectionInfo();
+}
+
+void NewTabPageHandler::GetBackgroundImages(
+ const std::string& collection_id,
+ GetBackgroundImagesCallback callback) {
+ if (background_images_callback_) {
+ std::move(background_images_callback_)
+ .Run(std::vector<new_tab_page::mojom::BackgroundImagePtr>());
+ }
+ if (!ntp_background_service_) {
+ std::move(callback).Run(
+ std::vector<new_tab_page::mojom::BackgroundImagePtr>());
+ return;
+ }
+ images_request_collection_id_ = collection_id;
+ background_images_callback_ = std::move(callback);
+ ntp_background_service_->FetchCollectionImageInfo(collection_id);
+}
+
+void NewTabPageHandler::FocusOmnibox() {
+ search::FocusOmnibox(true, web_contents_);
+}
+
+void NewTabPageHandler::PasteIntoOmnibox(const std::string& text) {
+ search::PasteIntoOmnibox(base::UTF8ToUTF16(text), web_contents_);
+}
+
+void NewTabPageHandler::GetDoodle(GetDoodleCallback callback) {
+ search_provider_logos::LogoCallbacks callbacks;
+ std::string fresh_doodle_param;
+ if (net::GetValueForKeyInQuery(web_contents_->GetLastCommittedURL(),
+ "fresh-doodle", &fresh_doodle_param) &&
+ fresh_doodle_param == "1") {
+ // In fresh-doodle mode, wait for the desired doodle to be downloaded.
+ callbacks.on_fresh_encoded_logo_available =
+ base::BindOnce(&NewTabPageHandler::OnLogoAvailable,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback));
+ } else {
+ // In regular mode, return cached doodle as it is available faster.
+ callbacks.on_cached_encoded_logo_available =
+ base::BindOnce(&NewTabPageHandler::OnLogoAvailable,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback));
+ }
+ // This will trigger re-downloading the doodle and caching it. This means that
+ // in regular mode a new doodle will be returned on subsequent NTP loads.
+ logo_service_->GetLogo(std::move(callbacks), /*for_webui_ntp=*/true);
+}
+
+void NewTabPageHandler::NtpThemeChanged(const NtpTheme& ntp_theme) {
+ page_->SetTheme(MakeTheme(ntp_theme));
+}
+
+void NewTabPageHandler::MostVisitedInfoChanged(
+ const InstantMostVisitedInfo& info) {
+ std::vector<new_tab_page::mojom::MostVisitedTilePtr> list;
+ auto result = new_tab_page::mojom::MostVisitedInfo::New();
+ for (auto& tile : info.items) {
+ auto value = new_tab_page::mojom::MostVisitedTile::New();
+ if (tile.title.empty()) {
+ value->title = tile.url.spec();
+ value->title_direction = base::i18n::LEFT_TO_RIGHT;
+ } else {
+ value->title = base::UTF16ToUTF8(tile.title);
+ value->title_direction =
+ base::i18n::GetFirstStrongCharacterDirection(tile.title);
+ }
+ value->url = tile.url;
+ list.push_back(std::move(value));
+ }
+ result->custom_links_enabled = !info.use_most_visited;
+ result->tiles = std::move(list);
+ result->visible = info.is_visible;
+ page_->SetMostVisitedInfo(std::move(result));
+}
+
+void NewTabPageHandler::OnCollectionInfoAvailable() {
+ if (!background_collections_callback_) {
+ return;
+ }
+
+ std::vector<new_tab_page::mojom::BackgroundCollectionPtr> collections;
+ for (const auto& info : ntp_background_service_->collection_info()) {
+ auto collection = new_tab_page::mojom::BackgroundCollection::New();
+ collection->id = info.collection_id;
+ collection->label = info.collection_name;
+ collection->preview_image_url = GURL(info.preview_image_url);
+ collections.push_back(std::move(collection));
+ }
+ std::move(background_collections_callback_).Run(std::move(collections));
+}
+
+void NewTabPageHandler::OnCollectionImagesAvailable() {
+ if (!background_images_callback_) {
+ return;
+ }
+ std::vector<new_tab_page::mojom::BackgroundImagePtr> images;
+ if (ntp_background_service_->collection_images().empty()) {
+ std::move(background_images_callback_).Run(std::move(images));
+ }
+ auto collection_id =
+ ntp_background_service_->collection_images()[0].collection_id;
+ for (const auto& info : ntp_background_service_->collection_images()) {
+ DCHECK(info.collection_id == collection_id);
+ auto image = new_tab_page::mojom::BackgroundImage::New();
+ image->preview_image_url = GURL(info.thumbnail_image_url);
+ image->label = !info.attribution.empty() ? info.attribution[0] : "";
+ images.push_back(std::move(image));
+ }
+ std::move(background_images_callback_).Run(std::move(images));
+}
+
+void NewTabPageHandler::OnNextCollectionImageAvailable() {}
+
+void NewTabPageHandler::OnNtpBackgroundServiceShuttingDown() {
+ ntp_background_service_->RemoveObserver(this);
+ ntp_background_service_ = nullptr;
+}
+
+void NewTabPageHandler::OnOmniboxInputStateChanged() {
+ // This handler was added for the local NTP to show the fakebox when pressing
+ // escape while the omnibox has focus. The WebUI NTP only shows the fakebox
+ // when blurring the omnibox. Thus, we do nothing here.
+}
+
+void NewTabPageHandler::OnOmniboxFocusChanged(OmniboxFocusState state,
+ OmniboxFocusChangeReason reason) {
+ page_->SetFakeboxFocused(state == OMNIBOX_FOCUS_INVISIBLE);
+ // Don't make fakebox re-appear for a short moment before navigating away.
+ if (web_contents_->GetController().GetPendingEntry() == nullptr) {
+ page_->SetFakeboxVisible(reason != OMNIBOX_FOCUS_CHANGE_TYPING);
+ }
+}
-NewTabPageHandler::~NewTabPageHandler() = default;
+void NewTabPageHandler::OnLogoAvailable(
+ GetDoodleCallback callback,
+ search_provider_logos::LogoCallbackReason type,
+ const base::Optional<search_provider_logos::EncodedLogo>& logo) {
+ if (!logo) {
+ std::move(callback).Run(nullptr);
+ return;
+ }
+ auto doodle = new_tab_page::mojom::Doodle::New();
+ switch (logo->metadata.type) {
+ case search_provider_logos::LogoType::SIMPLE:
+ case search_provider_logos::LogoType::ANIMATED: {
+ if (!logo->encoded_image) {
+ std::move(callback).Run(nullptr);
+ return;
+ }
+ std::string base64;
+ base::Base64Encode(logo->encoded_image->data(), &base64);
+ auto data_url =
+ base::StringPrintf("data:%s;base64,%s",
+ logo->metadata.mime_type.c_str(), base64.c_str());
+ doodle->content = new_tab_page::mojom::DoodleContent::NewImage(data_url);
+ } break;
+ case search_provider_logos::LogoType::INTERACTIVE:
+ doodle->content = new_tab_page::mojom::DoodleContent::NewUrl(
+ logo->metadata.full_page_url);
+ break;
+ default:
+ std::move(callback).Run(nullptr);
+ return;
+ }
+ std::move(callback).Run(std::move(doodle));
+}
diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h
index ec681d9d4e3..38fccc1c1c7 100644
--- a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h
+++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h
@@ -6,26 +6,109 @@
#define CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_NEW_TAB_PAGE_HANDLER_H_
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/search/background/ntp_background_service_observer.h"
+#include "chrome/browser/search/instant_service_observer.h"
+#include "chrome/browser/ui/omnibox/omnibox_tab_helper.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h"
+#include "chrome/common/search/instant_types.h"
+#include "components/search_provider_logos/logo_common.h"
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
-class NewTabPageHandler : public content::WebContentsObserver,
- public new_tab_page::mojom::PageHandler {
+class GURL;
+class InstantService;
+class NtpBackgroundService;
+class Profile;
+
+namespace chrome_colors {
+class ChromeColorsService;
+} // namespace chrome_colors
+
+namespace content {
+class WebContents;
+} // namespace content
+
+namespace search_provider_logos {
+class LogoService;
+} // namespace search_provider_logos
+
+class NewTabPageHandler : public new_tab_page::mojom::PageHandler,
+ public InstantServiceObserver,
+ public NtpBackgroundServiceObserver,
+ public OmniboxTabHelper::Observer {
public:
- NewTabPageHandler(
- mojo::PendingReceiver<new_tab_page::mojom::PageHandler>
- pending_page_handler,
- mojo::PendingRemote<new_tab_page::mojom::Page> pending_page);
+ NewTabPageHandler(mojo::PendingReceiver<new_tab_page::mojom::PageHandler>
+ pending_page_handler,
+ mojo::PendingRemote<new_tab_page::mojom::Page> pending_page,
+ Profile* profile,
+ content::WebContents* web_contents);
~NewTabPageHandler() override;
+ // new_tab_page::mojom::PageHandler:
+ void AddMostVisitedTile(const GURL& url,
+ const std::string& title,
+ AddMostVisitedTileCallback callback) override;
+ void DeleteMostVisitedTile(const GURL& url) override;
+ void RestoreMostVisitedDefaults() override;
+ void ReorderMostVisitedTile(const GURL& url, uint8_t new_pos) override;
+ void SetMostVisitedSettings(bool custom_links_enabled, bool visible) override;
+ void UndoMostVisitedTileAction() override;
+ void UpdateMostVisitedInfo() override;
+ void UpdateMostVisitedTile(const GURL& url,
+ const GURL& new_url,
+ const std::string& new_title,
+ UpdateMostVisitedTileCallback callback) override;
+ void ApplyDefaultTheme() override;
+ void ApplyAutogeneratedTheme(const SkColor& frame_color) override;
+ void ApplyChromeTheme(int32_t id) override;
+ void ConfirmThemeChanges() override;
+ void GetChromeThemes(GetChromeThemesCallback callback) override;
+ void RevertThemeChanges() override;
+ void GetBackgroundCollections(
+ GetBackgroundCollectionsCallback callback) override;
+ void GetBackgroundImages(const std::string& collection_id,
+ GetBackgroundImagesCallback callback) override;
+ void FocusOmnibox() override;
+ void PasteIntoOmnibox(const std::string& text) override;
+ void GetDoodle(GetDoodleCallback callback) override;
+
private:
- mojo::Remote<new_tab_page::mojom::Page> page_;
+ // InstantServiceObserver:
+ void NtpThemeChanged(const NtpTheme& theme) override;
+ void MostVisitedInfoChanged(const InstantMostVisitedInfo& info) override;
+
+ // NtpBackgroundServiceObserver:
+ void OnCollectionInfoAvailable() override;
+ void OnCollectionImagesAvailable() override;
+ void OnNextCollectionImageAvailable() override;
+ void OnNtpBackgroundServiceShuttingDown() override;
+
+ // OmniboxTabHelper::Observer:
+ void OnOmniboxInputStateChanged() override;
+ void OnOmniboxFocusChanged(OmniboxFocusState state,
+ OmniboxFocusChangeReason reason) override;
+ void OnLogoAvailable(
+ GetDoodleCallback callback,
+ search_provider_logos::LogoCallbackReason type,
+ const base::Optional<search_provider_logos::EncodedLogo>& logo);
+
+ chrome_colors::ChromeColorsService* chrome_colors_service_;
+ InstantService* instant_service_;
+ NtpBackgroundService* ntp_background_service_;
+ search_provider_logos::LogoService* logo_service_;
+ GURL last_blacklisted_;
+ GetBackgroundCollectionsCallback background_collections_callback_;
+ std::string images_request_collection_id_;
+ GetBackgroundImagesCallback background_images_callback_;
+ mojo::Remote<new_tab_page::mojom::Page> page_;
mojo::Receiver<new_tab_page::mojom::PageHandler> receiver_;
+ content::WebContents* web_contents_;
+ base::WeakPtrFactory<NewTabPageHandler> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(NewTabPageHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
index d5dc19f7995..6007740cd12 100644
--- a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
+++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -4,46 +4,124 @@
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h"
+#include <memory>
+#include <utility>
+
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/managed_ui_handler.h"
+#include "chrome/browser/search/instant_service.h"
+#include "chrome/browser/search/instant_service_factory.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/webui/favicon_source.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h"
+#include "chrome/browser/ui/webui/new_tab_page/untrusted_source.h"
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/common/url_constants.h"
+#include "chrome/grit/generated_resources.h"
#include "chrome/grit/new_tab_page_resources.h"
#include "chrome/grit/new_tab_page_resources_map.h"
+#include "components/favicon_base/favicon_url_parser.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
using content::BrowserContext;
using content::WebContents;
namespace {
-content::WebUIDataSource* CreateNewTabPageUiHtmlSource() {
+constexpr char kGeneratedPath[] =
+ "@out_folder@/gen/chrome/browser/resources/new_tab_page/";
+
+content::WebUIDataSource* CreateNewTabPageUiHtmlSource(Profile* profile) {
content::WebUIDataSource* source =
content::WebUIDataSource::Create(chrome::kChromeUINewTabPageHost);
+ source->OverrideContentSecurityPolicyChildSrc(base::StringPrintf(
+ "frame-src %s;", chrome::kChromeUIUntrustedNewTabPageUrl));
+
+ ui::Accelerator undo_accelerator(ui::VKEY_Z, ui::EF_PLATFORM_ACCELERATOR);
+ source->AddString("undoDescription", l10n_util::GetStringFUTF16(
+ IDS_UNDO_DESCRIPTION,
+ undo_accelerator.GetShortcutText()));
+ source->AddString("googleBaseUrl",
+ GURL(TemplateURLServiceFactory::GetForProfile(profile)
+ ->search_terms_data()
+ .GoogleBaseURLValue())
+ .spec());
static constexpr webui::LocalizedString kStrings[] = {
{"title", IDS_NEW_TAB_TITLE},
+ {"undo", IDS_NEW_TAB_UNDO_THUMBNAIL_REMOVE},
+
+ // Custom Links
+ {"addLinkTitle", IDS_NTP_CUSTOM_LINKS_ADD_SHORTCUT_TITLE},
+ {"editLinkTitle", IDS_NTP_CUSTOM_LINKS_EDIT_SHORTCUT},
+ {"invalidUrl", IDS_NTP_CUSTOM_LINKS_INVALID_URL},
+ {"linkAddedMsg", IDS_NTP_CONFIRM_MSG_SHORTCUT_ADDED},
+ {"linkCancel", IDS_NTP_CUSTOM_LINKS_CANCEL},
+ {"linkCantCreate", IDS_NTP_CUSTOM_LINKS_CANT_CREATE},
+ {"linkCantEdit", IDS_NTP_CUSTOM_LINKS_CANT_EDIT},
+ {"linkDone", IDS_NTP_CUSTOM_LINKS_DONE},
+ {"linkEditedMsg", IDS_NTP_CONFIRM_MSG_SHORTCUT_EDITED},
+ {"linkRemove", IDS_NTP_CUSTOM_LINKS_REMOVE},
+ {"linkRemovedMsg", IDS_NTP_CONFIRM_MSG_SHORTCUT_REMOVED},
+ {"nameField", IDS_NTP_CUSTOM_LINKS_NAME},
+ {"restoreDefaultLinks", IDS_NTP_CONFIRM_MSG_RESTORE_DEFAULTS},
+ {"restoreThumbnailsShort", IDS_NEW_TAB_RESTORE_THUMBNAILS_SHORT_LINK},
+ {"urlField", IDS_NTP_CUSTOM_LINKS_URL},
+
+ // Customize button and dialog.
+ {"backButton", IDS_ACCNAME_BACK},
+ {"backgroundsMenuItem", IDS_NTP_CUSTOMIZE_MENU_BACKGROUND_LABEL},
+ {"cancelButton", IDS_CANCEL},
+ {"colorPickerLabel", IDS_NTP_CUSTOMIZE_COLOR_PICKER_LABEL},
+ {"customizeButton", IDS_NTP_CUSTOMIZE_BUTTON_LABEL},
+ {"customizeThisPage", IDS_NTP_CUSTOM_BG_CUSTOMIZE_NTP_LABEL},
+ {"defaultThemeLabel", IDS_NTP_CUSTOMIZE_DEFAULT_LABEL},
+ {"doneButton", IDS_DONE},
+ {"hideShortcuts", IDS_NTP_CUSTOMIZE_HIDE_SHORTCUTS_LABEL},
+ {"hideShortcutsDesc", IDS_NTP_CUSTOMIZE_HIDE_SHORTCUTS_DESC},
+ {"mostVisited", IDS_NTP_CUSTOMIZE_MOST_VISITED_LABEL},
+ {"myShortcuts", IDS_NTP_CUSTOMIZE_MY_SHORTCUTS_LABEL},
+ {"shortcutsCurated", IDS_NTP_CUSTOMIZE_MY_SHORTCUTS_DESC},
+ {"shortcutsMenuItem", IDS_NTP_CUSTOMIZE_MENU_SHORTCUTS_LABEL},
+ {"shortcutsOption", IDS_NTP_CUSTOMIZE_MENU_SHORTCUTS_LABEL},
+ {"shortcutsSuggested", IDS_NTP_CUSTOMIZE_MOST_VISITED_DESC},
+ {"themesMenuItem", IDS_NTP_CUSTOMIZE_MENU_COLOR_LABEL},
+ {"thirdPartyThemeDescription", IDS_NTP_CUSTOMIZE_3PT_THEME_DESC},
+ {"uninstallThirdPartyThemeButton", IDS_NTP_CUSTOMIZE_3PT_THEME_UNINSTALL},
+
+ // Voice search.
+ {"audioError", IDS_NEW_TAB_VOICE_AUDIO_ERROR},
+ {"close", IDS_NEW_TAB_VOICE_CLOSE_TOOLTIP},
+ {"details", IDS_NEW_TAB_VOICE_DETAILS},
+ {"languageError", IDS_NEW_TAB_VOICE_LANGUAGE_ERROR},
+ {"learnMore", IDS_LEARN_MORE},
+ {"listening", IDS_NEW_TAB_VOICE_LISTENING},
+ {"networkError", IDS_NEW_TAB_VOICE_NETWORK_ERROR},
+ {"noTranslation", IDS_NEW_TAB_VOICE_NO_TRANSLATION},
+ {"noVoice", IDS_NEW_TAB_VOICE_NO_VOICE},
+ {"otherError", IDS_NEW_TAB_VOICE_OTHER_ERROR},
+ {"permissionError", IDS_NEW_TAB_VOICE_PERMISSION_ERROR},
+ {"speak", IDS_NEW_TAB_VOICE_READY},
+ {"tryAgain", IDS_NEW_TAB_VOICE_TRY_AGAIN},
+ {"voiceSearchButtonLabel", IDS_TOOLTIP_MIC_SEARCH},
+ {"waiting", IDS_NEW_TAB_VOICE_WAITING},
+
+ // Search box.
+ {"searchBoxHint", IDS_GOOGLE_SEARCH_BOX_EMPTY_HINT_MD},
};
AddLocalizedStringsBulk(source, kStrings);
+ source->AddResourcePath("skcolor.mojom-lite.js",
+ IDR_NEW_TAB_PAGE_SKCOLOR_MOJO_LITE_JS);
source->AddResourcePath("new_tab_page.mojom-lite.js",
IDR_NEW_TAB_PAGE_MOJO_LITE_JS);
-
- std::string generated_path =
- "@out_folder@/gen/chrome/browser/resources/new_tab_page/";
- for (size_t i = 0; i < kNewTabPageResourcesSize; ++i) {
- base::StringPiece path = kNewTabPageResources[i].name;
- if (path.rfind(generated_path, 0) == 0) {
- path = path.substr(generated_path.length());
- }
- source->AddResourcePath(path, kNewTabPageResources[i].value);
- }
-
- source->SetDefaultResource(IDR_NEW_TAB_PAGE_NEW_TAB_PAGE_HTML);
- source->UseStringsJs();
+ webui::SetupWebUIDataSource(
+ source, base::make_span(kNewTabPageResources, kNewTabPageResourcesSize),
+ kGeneratedPath, IDR_NEW_TAB_PAGE_NEW_TAB_PAGE_HTML);
return source;
}
@@ -51,20 +129,38 @@ content::WebUIDataSource* CreateNewTabPageUiHtmlSource() {
} // namespace
NewTabPageUI::NewTabPageUI(content::WebUI* web_ui)
- : ui::MojoWebUIController(web_ui, true), page_factory_receiver_(this) {
- Profile* profile = Profile::FromWebUI(web_ui);
+ : ui::MojoWebUIController(web_ui, true),
+ page_factory_receiver_(this),
+ profile_(Profile::FromWebUI(web_ui)),
+ instant_service_(InstantServiceFactory::GetForProfile(profile_)),
+ web_contents_(web_ui->GetWebContents()) {
+ content::WebUIDataSource::Add(profile_,
+ CreateNewTabPageUiHtmlSource(profile_));
+
+ content::URLDataSource::Add(
+ profile_, std::make_unique<FaviconSource>(
+ profile_, chrome::FaviconUrlFormat::kFavicon2));
+ content::URLDataSource::Add(profile_,
+ std::make_unique<UntrustedSource>(profile_));
+
+ web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
+
+ UpdateBackgroundColor(*instant_service_->GetInitializedNtpTheme());
+ instant_service_->AddObserver(this);
+}
- content::WebUIDataSource* source = CreateNewTabPageUiHtmlSource();
- ManagedUIHandler::Initialize(web_ui, source);
- content::WebUIDataSource::Add(profile, source);
+WEB_UI_CONTROLLER_TYPE_IMPL(NewTabPageUI)
- AddHandlerToRegistry(base::BindRepeating(
- &NewTabPageUI::BindPageHandlerFactory, base::Unretained(this)));
+NewTabPageUI::~NewTabPageUI() {
+ instant_service_->RemoveObserver(this);
}
-NewTabPageUI::~NewTabPageUI() = default;
+// static
+bool NewTabPageUI::IsNewTabPageOrigin(const GURL& url) {
+ return url.GetOrigin() == GURL(chrome::kChromeUINewTabPageURL).GetOrigin();
+}
-void NewTabPageUI::BindPageHandlerFactory(
+void NewTabPageUI::BindInterface(
mojo::PendingReceiver<new_tab_page::mojom::PageHandlerFactory>
pending_receiver) {
if (page_factory_receiver_.is_bound()) {
@@ -80,10 +176,26 @@ void NewTabPageUI::CreatePageHandler(
pending_page_handler) {
DCHECK(pending_page.is_valid());
page_handler_ = std::make_unique<NewTabPageHandler>(
- std::move(pending_page_handler), std::move(pending_page));
+ std::move(pending_page_handler), std::move(pending_page), profile_,
+ web_contents_);
}
-// static
-bool NewTabPageUI::IsNewTabPageOrigin(const GURL& url) {
- return url.GetOrigin() == GURL(chrome::kChromeUINewTabPageURL).GetOrigin();
+void NewTabPageUI::NtpThemeChanged(const NtpTheme& theme) {
+ // Load time data is cached across page reloads. Update the background color
+ // here to prevent a white flicker on page reload.
+ UpdateBackgroundColor(theme);
+}
+
+void NewTabPageUI::MostVisitedInfoChanged(const InstantMostVisitedInfo& info) {}
+
+void NewTabPageUI::UpdateBackgroundColor(const NtpTheme& theme) {
+ std::unique_ptr<base::DictionaryValue> update(new base::DictionaryValue);
+ auto background_color = theme.background_color;
+ update->SetString(
+ "backgroundColor",
+ base::StringPrintf("#%02X%02X%02X", SkColorGetR(background_color),
+ SkColorGetG(background_color),
+ SkColorGetB(background_color)));
+ content::WebUIDataSource::Update(profile_, chrome::kChromeUINewTabPageHost,
+ std::move(update));
}
diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h
index b97c6cb6006..89080f2524e 100644
--- a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h
+++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_NEW_TAB_PAGE_UI_H_
#include "base/macros.h"
+#include "chrome/browser/search/instant_service_observer.h"
#include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -13,34 +14,53 @@
#include "ui/webui/mojo_web_ui_controller.h"
namespace content {
+class WebContents;
class WebUI;
}
class GURL;
+class InstantService;
class NewTabPageHandler;
+class Profile;
class NewTabPageUI : public ui::MojoWebUIController,
- public new_tab_page::mojom::PageHandlerFactory {
+ public new_tab_page::mojom::PageHandlerFactory,
+ public InstantServiceObserver {
public:
explicit NewTabPageUI(content::WebUI* web_ui);
~NewTabPageUI() override;
static bool IsNewTabPageOrigin(const GURL& url);
- private:
- void BindPageHandlerFactory(
+ // Instantiates the implementor of the mojom::PageHandlerFactory mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<new_tab_page::mojom::PageHandlerFactory>
pending_receiver);
+ private:
// new_tab_page::mojom::PageHandlerFactory:
void CreatePageHandler(
mojo::PendingRemote<new_tab_page::mojom::Page> pending_page,
mojo::PendingReceiver<new_tab_page::mojom::PageHandler>
pending_page_handler) override;
- std::unique_ptr<NewTabPageHandler> page_handler_;
+ // InstantServiceObserver:
+ void NtpThemeChanged(const NtpTheme& theme) override;
+ void MostVisitedInfoChanged(const InstantMostVisitedInfo& info) override;
+ // Updates the load time data with the current theme's background color. That
+ // way the background color is available as soon as the page loads and we
+ // prevent a potential white flicker.
+ void UpdateBackgroundColor(const NtpTheme& theme);
+
+ std::unique_ptr<NewTabPageHandler> page_handler_;
mojo::Receiver<new_tab_page::mojom::PageHandlerFactory>
page_factory_receiver_;
+ Profile* profile_;
+ InstantService* instant_service_;
+ content::WebContents* web_contents_;
+
+ WEB_UI_CONTROLLER_TYPE_DECL();
DISALLOW_COPY_AND_ASSIGN(NewTabPageUI);
};
diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc b/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc
new file mode 100644
index 00000000000..af00210d178
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc
@@ -0,0 +1,198 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/new_tab_page/untrusted_source.h"
+
+#include <string>
+#include <utility>
+
+#include "base/memory/ref_counted_memory.h"
+#include "base/optional.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search/one_google_bar/one_google_bar_data.h"
+#include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h"
+#include "chrome/browser/search/promos/promo_data.h"
+#include "chrome/browser/search/promos/promo_service_factory.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/new_tab_page_resources.h"
+#include "content/public/common/url_constants.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/template_expressions.h"
+
+namespace {
+
+std::string FormatTemplate(int resource_id,
+ const ui::TemplateReplacements& replacements) {
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ base::RefCountedMemory* bytes = bundle.LoadDataResourceBytes(resource_id);
+ base::StringPiece string_piece(reinterpret_cast<const char*>(bytes->front()),
+ bytes->size());
+ return ui::ReplaceTemplateExpressions(string_piece, replacements);
+}
+
+} // namespace
+
+UntrustedSource::UntrustedSource(Profile* profile)
+ : one_google_bar_service_(
+ OneGoogleBarServiceFactory::GetForProfile(profile)),
+ promo_service_(PromoServiceFactory::GetForProfile(profile)) {
+ // |promo_service_| is null in incognito, or when the feature is
+ // disabled.
+ if (promo_service_) {
+ promo_service_observer_.Add(promo_service_);
+ }
+
+ // |one_google_bar_service_| is null in incognito, or when the feature is
+ // disabled.
+ if (one_google_bar_service_) {
+ one_google_bar_service_observer_.Add(one_google_bar_service_);
+ }
+}
+
+UntrustedSource::~UntrustedSource() = default;
+
+std::string UntrustedSource::GetContentSecurityPolicyScriptSrc() {
+ return "script-src 'self' 'unsafe-inline' https:;";
+}
+
+std::string UntrustedSource::GetContentSecurityPolicyChildSrc() {
+ return "child-src https:;";
+}
+
+std::string UntrustedSource::GetSource() {
+ return chrome::kChromeUIUntrustedNewTabPageUrl;
+}
+
+void UntrustedSource::StartDataRequest(
+ const GURL& url,
+ const content::WebContents::Getter& wc_getter,
+ content::URLDataSource::GotDataCallback callback) {
+ const std::string path = url.has_path() ? url.path().substr(1) : "";
+ GURL url_param = GURL(url.query());
+ if (path == "one-google-bar" && one_google_bar_service_) {
+ one_google_bar_callbacks_.push_back(std::move(callback));
+ if (one_google_bar_callbacks_.size() == 1) {
+ one_google_bar_service_->Refresh();
+ }
+ return;
+ }
+ if (path == "one_google_bar.js") {
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ std::move(callback).Run(bundle.LoadDataResourceBytes(
+ IDR_NEW_TAB_PAGE_UNTRUSTED_ONE_GOOGLE_BAR_JS));
+ return;
+ }
+ if (path == "promo" && promo_service_) {
+ promo_callbacks_.push_back(std::move(callback));
+ if (promo_callbacks_.size() == 1) {
+ promo_service_->Refresh();
+ }
+ return;
+ }
+ if (path == "promo.js") {
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ std::move(callback).Run(
+ bundle.LoadDataResourceBytes(IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_JS));
+ return;
+ }
+ if (path == "image" && url_param.is_valid() &&
+ url_param.SchemeIs(url::kHttpsScheme)) {
+ ui::TemplateReplacements replacements;
+ replacements["url"] = url_param.spec();
+ std::string html =
+ FormatTemplate(IDR_NEW_TAB_PAGE_UNTRUSTED_IMAGE_HTML, replacements);
+ std::move(callback).Run(base::RefCountedString::TakeString(&html));
+ return;
+ }
+ if (path == "iframe" && url_param.is_valid() &&
+ url_param.SchemeIs(url::kHttpsScheme)) {
+ ui::TemplateReplacements replacements;
+ replacements["url"] = url_param.spec();
+ std::string html =
+ FormatTemplate(IDR_NEW_TAB_PAGE_UNTRUSTED_IFRAME_HTML, replacements);
+ std::move(callback).Run(base::RefCountedString::TakeString(&html));
+ return;
+ }
+ std::move(callback).Run(base::MakeRefCounted<base::RefCountedString>());
+}
+
+std::string UntrustedSource::GetMimeType(const std::string& path) {
+ if (base::EndsWith(path, ".js", base::CompareCase::INSENSITIVE_ASCII))
+ return "application/javascript";
+
+ return "text/html";
+}
+
+bool UntrustedSource::AllowCaching() {
+ return false;
+}
+
+std::string UntrustedSource::GetContentSecurityPolicyFrameAncestors() {
+ return base::StringPrintf("frame-ancestors %s",
+ chrome::kChromeUINewTabPageURL);
+}
+
+bool UntrustedSource::ShouldReplaceExistingSource() {
+ return false;
+}
+
+bool UntrustedSource::ShouldServiceRequest(
+ const GURL& url,
+ content::ResourceContext* resource_context,
+ int render_process_id) {
+ if (!url.SchemeIs(content::kChromeUIUntrustedScheme) || !url.has_path()) {
+ return false;
+ }
+ const std::string path = url.path().substr(1);
+ return path == "one-google-bar" || path == "one_google_bar.js" ||
+ path == "promo" || path == "promo.js" || path == "image" ||
+ path == "iframe";
+}
+
+void UntrustedSource::OnOneGoogleBarDataUpdated() {
+ base::Optional<OneGoogleBarData> data =
+ one_google_bar_service_->one_google_bar_data();
+ std::string html;
+ if (data.has_value()) {
+ ui::TemplateReplacements replacements;
+ replacements["barHtml"] = data->bar_html;
+ replacements["inHeadScript"] = data->in_head_script;
+ replacements["inHeadStyle"] = data->in_head_style;
+ replacements["afterBarScript"] = data->after_bar_script;
+ replacements["endOfBodyHtml"] = data->end_of_body_html;
+ replacements["endOfBodyScript"] = data->end_of_body_script;
+ html = FormatTemplate(IDR_NEW_TAB_PAGE_UNTRUSTED_ONE_GOOGLE_BAR_HTML,
+ replacements);
+ }
+ for (auto& callback : one_google_bar_callbacks_) {
+ std::move(callback).Run(base::RefCountedString::TakeString(&html));
+ }
+ one_google_bar_callbacks_.clear();
+}
+
+void UntrustedSource::OnOneGoogleBarServiceShuttingDown() {
+ one_google_bar_service_observer_.RemoveAll();
+ one_google_bar_service_ = nullptr;
+}
+
+void UntrustedSource::OnPromoDataUpdated() {
+ const auto& data = promo_service_->promo_data();
+ std::string html;
+ if (data.has_value() && !data->promo_html.empty()) {
+ ui::TemplateReplacements replacements;
+ replacements["data"] = data->promo_html;
+ html = FormatTemplate(IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_HTML, replacements);
+ }
+ for (auto& callback : promo_callbacks_) {
+ std::move(callback).Run(base::RefCountedString::TakeString(&html));
+ }
+ promo_callbacks_.clear();
+}
+
+void UntrustedSource::OnPromoServiceShuttingDown() {
+ promo_service_observer_.RemoveAll();
+ promo_service_ = nullptr;
+}
diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.h b/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.h
new file mode 100644
index 00000000000..29edb345439
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.h
@@ -0,0 +1,69 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_UNTRUSTED_SOURCE_H_
+#define CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_UNTRUSTED_SOURCE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/scoped_observer.h"
+#include "chrome/browser/search/one_google_bar/one_google_bar_service.h"
+#include "chrome/browser/search/one_google_bar/one_google_bar_service_observer.h"
+#include "chrome/browser/search/promos/promo_service.h"
+#include "chrome/browser/search/promos/promo_service_observer.h"
+#include "content/public/browser/url_data_source.h"
+
+class Profile;
+
+// Serves chrome-untrusted://new-tab-page/* sources which can return content
+// from outside the chromium codebase. The chrome-untrusted://new-tab-page/*
+// sources can only be embedded in the chrome://new-tab-page by using an
+// <iframe>.
+class UntrustedSource : public content::URLDataSource,
+ public OneGoogleBarServiceObserver,
+ public PromoServiceObserver {
+ public:
+ explicit UntrustedSource(Profile* profile);
+ ~UntrustedSource() override;
+ UntrustedSource(const UntrustedSource&) = delete;
+ UntrustedSource& operator=(const UntrustedSource&) = delete;
+
+ // content::URLDataSource:
+ std::string GetContentSecurityPolicyScriptSrc() override;
+ std::string GetContentSecurityPolicyChildSrc() override;
+ std::string GetSource() override;
+ void StartDataRequest(
+ const GURL& url,
+ const content::WebContents::Getter& wc_getter,
+ content::URLDataSource::GotDataCallback callback) override;
+ std::string GetMimeType(const std::string& path) override;
+ bool AllowCaching() override;
+ std::string GetContentSecurityPolicyFrameAncestors() override;
+ bool ShouldReplaceExistingSource() override;
+ bool ShouldServiceRequest(const GURL& url,
+ content::ResourceContext* resource_context,
+ int render_process_id) override;
+
+ private:
+ // OneGoogleBarServiceObserver:
+ void OnOneGoogleBarDataUpdated() override;
+ void OnOneGoogleBarServiceShuttingDown() override;
+
+ // PromoServiceObserver:
+ void OnPromoDataUpdated() override;
+ void OnPromoServiceShuttingDown() override;
+
+ std::vector<content::URLDataSource::GotDataCallback>
+ one_google_bar_callbacks_;
+ OneGoogleBarService* one_google_bar_service_;
+ ScopedObserver<OneGoogleBarService, OneGoogleBarServiceObserver>
+ one_google_bar_service_observer_{this};
+ std::vector<content::URLDataSource::GotDataCallback> promo_callbacks_;
+ PromoService* promo_service_;
+ ScopedObserver<PromoService, PromoServiceObserver> promo_service_observer_{
+ this};
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_NEW_TAB_PAGE_UNTRUSTED_SOURCE_H_
diff --git a/chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.cc b/chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.cc
index 596be278024..9ecead6534a 100644
--- a/chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.cc
@@ -9,7 +9,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
diff --git a/chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.cc b/chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.cc
index a9753fabdf2..a5b683d6728 100644
--- a/chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.cc
+++ b/chromium/chrome/browser/ui/webui/notifications_internals/notifications_internals_ui_message_handler.cc
@@ -15,12 +15,13 @@
#include "chrome/browser/notifications/scheduler/public/notification_params.h"
#include "chrome/browser/notifications/scheduler/public/notification_schedule_service.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_key.h"
#include "content/public/browser/web_ui.h"
NotificationsInternalsUIMessageHandler::NotificationsInternalsUIMessageHandler(
Profile* profile)
- : schedule_service_(
- NotificationScheduleServiceFactory::GetForBrowserContext(profile)) {}
+ : schedule_service_(NotificationScheduleServiceFactory::GetForKey(
+ profile->GetProfileKey())) {}
NotificationsInternalsUIMessageHandler::
~NotificationsInternalsUIMessageHandler() = default;
diff --git a/chromium/chrome/browser/ui/webui/ntp/OWNERS b/chromium/chrome/browser/ui/webui/ntp/OWNERS
index 733c1f71bc6..32b85cb193d 100644
--- a/chromium/chrome/browser/ui/webui/ntp/OWNERS
+++ b/chromium/chrome/browser/ui/webui/ntp/OWNERS
@@ -1,4 +1,3 @@
-dbeam@chromium.org
estade@chromium.org
# TEAM: ntp-dev@chromium.org
diff --git a/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 9c789a61ad4..93cb95d1973 100644
--- a/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -42,6 +42,8 @@
#include "chrome/browser/ui/webui/extensions/extension_basic_info.h"
#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
+#include "chrome/browser/web_applications/components/file_handler_manager.h"
+#include "chrome/browser/web_applications/components/web_app_provider_base.h"
#include "chrome/browser/web_applications/extensions/bookmark_app_finalizer_utils.h"
#include "chrome/browser/web_applications/extensions/bookmark_app_util.h"
#include "chrome/common/buildflags.h"
@@ -59,7 +61,6 @@
#include "components/prefs/scoped_user_pref_update.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_ui.h"
-#include "content/public/common/favicon_url.h"
#include "extensions/browser/app_sorting.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
@@ -149,9 +150,10 @@ void AppLauncherHandler::CreateAppInfo(const Extension* extension,
.GetByID(extension->id());
extensions::GetExtensionBasicInfo(extension, enabled, value);
- value->SetBoolean("mayDisable", extensions::ExtensionSystem::Get(
- service->profile())->management_policy()->UserMayModifySettings(
- extension, NULL));
+ value->SetBoolean("mayDisable",
+ extensions::ExtensionSystem::Get(service->profile())
+ ->management_policy()
+ ->UserMayModifySettings(extension, nullptr));
bool is_locally_installed =
!extension->is_hosted_app() ||
@@ -316,7 +318,7 @@ void AppLauncherHandler::Observe(int type,
&app_info);
web_ui()->CallJavascriptFunctionUnsafe("ntp.appMoved", app_info);
} else {
- HandleGetApps(NULL);
+ HandleGetApps(nullptr);
}
break;
}
@@ -467,9 +469,8 @@ void AppLauncherHandler::HandleGetApps(const base::ListValue* args) {
registrar_.Add(this, chrome::NOTIFICATION_APP_LAUNCHER_REORDERED,
content::Source<AppSorting>(
ExtensionSystem::Get(profile)->app_sorting()));
- registrar_.Add(this,
- extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
- content::Source<CrxInstaller>(NULL));
+ registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_INSTALL_ERROR,
+ content::Source<CrxInstaller>(nullptr));
registrar_.Add(this,
extensions::NOTIFICATION_EXTENSION_LOAD_ERROR,
content::Source<Profile>(profile));
@@ -540,7 +541,7 @@ void AppLauncherHandler::HandleLaunchApp(const base::ListValue* args) {
// it automatically.
Browser* browser = chrome::FindBrowserWithWebContents(
web_ui()->GetWebContents());
- WebContents* old_contents = NULL;
+ WebContents* old_contents = nullptr;
if (browser)
old_contents = browser->tab_strip_model()->GetActiveWebContents();
@@ -594,8 +595,9 @@ void AppLauncherHandler::HandleUninstallApp(const base::ListValue* args) {
if (!extension)
return;
- if (!extensions::ExtensionSystem::Get(extension_service_->profile())->
- management_policy()->UserMayModifySettings(extension, NULL)) {
+ if (!extensions::ExtensionSystem::Get(extension_service_->profile())
+ ->management_policy()
+ ->UserMayModifySettings(extension, nullptr)) {
LOG(ERROR) << "Attempt to uninstall an extension that is non-usermanagable "
<< "was made. Extension id : " << extension->id();
return;
@@ -658,7 +660,10 @@ void AppLauncherHandler::HandleInstallAppLocally(const base::ListValue* args) {
SetBookmarkAppIsLocallyInstalled(profile, extension, true);
if (extensions::CanBookmarkAppCreateOsShortcuts()) {
extensions::BookmarkAppCreateOsShortcuts(
- profile, extension, true /* add_to_desktop */, base::DoNothing());
+ profile, extension, true /* add_to_desktop */,
+ base::BindOnce(&AppLauncherHandler::
+ OnExtensionShortcutsCreatedRegisterFileHandlers,
+ weak_ptr_factory_.GetWeakPtr(), extension_id));
}
// Use the appAdded to update the app icon's color to no longer be greyscale.
@@ -852,6 +857,15 @@ void AppLauncherHandler::PromptToEnableApp(const std::string& extension_id) {
extension_enable_flow_->StartForWebContents(web_ui()->GetWebContents());
}
+void AppLauncherHandler::OnExtensionShortcutsCreatedRegisterFileHandlers(
+ const extensions::ExtensionId& extension_id,
+ bool /*shortcuts_created*/) {
+ auto* provider = web_app::WebAppProviderBase::GetProviderBase(
+ extension_service_->profile());
+ provider->file_handler_manager().EnableAndRegisterOsFileHandlers(
+ extension_id);
+}
+
void AppLauncherHandler::OnExtensionUninstallDialogClosed(
bool did_start_uninstall,
const base::string16& error) {
diff --git a/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.h b/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.h
index c2a7659aeb9..00cf254bf45 100644
--- a/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.h
+++ b/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.h
@@ -154,6 +154,12 @@ class AppLauncherHandler
// Prompts the user to re-enable the app for |extension_id|.
void PromptToEnableApp(const std::string& extension_id);
+ // Registers file handlers for |extension_id|, after shortcuts have been
+ // created.
+ void OnExtensionShortcutsCreatedRegisterFileHandlers(
+ const extensions::ExtensionId& extension_id,
+ bool shortcuts_created);
+
// ExtensionUninstallDialog::Delegate:
void OnExtensionUninstallDialogClosed(bool did_start_uninstall,
const base::string16& error) override;
@@ -228,6 +234,9 @@ class AppLauncherHandler
// Used for favicon loading tasks.
base::CancelableTaskTracker cancelable_task_tracker_;
+ // Used to register file handlers after shortcuts have been created.
+ base::WeakPtrFactory<AppLauncherHandler> weak_ptr_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(AppLauncherHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc b/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc
index 7b661301ba4..8a7336be70b 100644
--- a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc
+++ b/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc
@@ -8,41 +8,24 @@
#include "base/bind.h"
#include "base/feature_list.h"
-#include "base/metrics/user_metrics.h"
-#include "base/metrics/user_metrics_action.h"
#include "base/values.h"
-#include "chrome/browser/content_settings/cookie_settings_factory.h"
-#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
-#include "components/content_settings/core/browser/cookie_settings.h"
-#include "components/content_settings/core/common/features.h"
-#include "components/content_settings/core/common/pref_names.h"
-#include "components/policy/core/common/policy_service.h"
-#include "components/policy/policy_constants.h"
-#include "components/prefs/pref_service.h"
+#include "chrome/browser/ui/cookie_controls/cookie_controls_service.h"
+#include "chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h"
+#include "chrome/common/chrome_features.h"
namespace {
-static const char* kSettingsIcon = "cr:settings_icon";
static const char* kPolicyIcon = "cr20:domain";
-
-enum class CookieControlsEnforcement {
- kNoEnforcement,
- kEnforcedByPolicy,
- kEnforcedByCookieSetting
-};
-
-CookieControlsEnforcement GetCookieControlsEnforcement(const Profile* profile) {
- if (profile->GetPrefs()->IsManagedPreference(prefs::kBlockThirdPartyCookies))
- return CookieControlsEnforcement::kEnforcedByPolicy;
- if (profile->GetPrefs()->GetBoolean(prefs::kBlockThirdPartyCookies))
- return CookieControlsEnforcement::kEnforcedByCookieSetting;
- return CookieControlsEnforcement::kNoEnforcement;
-}
+static const char* kExtensionIcon = "cr:extension";
+static const char* kSettingsIcon = "cr:settings_icon";
} // namespace
-CookieControlsHandler::CookieControlsHandler() {}
+CookieControlsHandler::CookieControlsHandler(Profile* profile)
+ : service_(CookieControlsServiceFactory::GetForProfile(profile)) {}
-CookieControlsHandler::~CookieControlsHandler() {}
+CookieControlsHandler::~CookieControlsHandler() {
+ service_->RemoveObserver(this);
+}
void CookieControlsHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
@@ -58,44 +41,18 @@ void CookieControlsHandler::RegisterMessages() {
}
void CookieControlsHandler::OnJavascriptAllowed() {
- Profile* profile = Profile::FromWebUI(web_ui());
- pref_change_registrar_.Init(profile->GetPrefs());
- pref_change_registrar_.Add(
- prefs::kCookieControlsMode,
- base::Bind(&CookieControlsHandler::SendCookieControlsUIChanges,
- base::Unretained(this)));
- pref_change_registrar_.Add(
- prefs::kBlockThirdPartyCookies,
- base::Bind(&CookieControlsHandler::SendCookieControlsUIChanges,
- base::Unretained(this)));
- policy_registrar_ = std::make_unique<policy::PolicyChangeRegistrar>(
- profile->GetProfilePolicyConnector()->policy_service(),
- policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()));
- policy_registrar_->Observe(
- policy::key::kBlockThirdPartyCookies,
- base::BindRepeating(
- &CookieControlsHandler::OnThirdPartyCookieBlockingPolicyChanged,
- base::Unretained(this)));
+ service_->AddObserver(this);
}
void CookieControlsHandler::OnJavascriptDisallowed() {
- pref_change_registrar_.RemoveAll();
- policy_registrar_.reset();
+ service_->RemoveObserver(this);
}
void CookieControlsHandler::HandleCookieControlsToggleChanged(
const base::ListValue* args) {
bool checked;
CHECK(args->GetBoolean(0, &checked));
- Profile* profile = Profile::FromWebUI(web_ui());
- profile->GetPrefs()->SetInteger(
- prefs::kCookieControlsMode,
- static_cast<int>(
- checked ? content_settings::CookieControlsMode::kIncognitoOnly
- : content_settings::CookieControlsMode::kOff));
- base::RecordAction(
- checked ? base::UserMetricsAction("CookieControls.NTP.Enabled")
- : base::UserMetricsAction("CookieControls.NTP.Disabled"));
+ service_->HandleCookieControlsToggleChanged(checked);
}
void CookieControlsHandler::HandleObserveCookieControlsSettingsChanges(
@@ -104,44 +61,39 @@ void CookieControlsHandler::HandleObserveCookieControlsSettingsChanges(
SendCookieControlsUIChanges();
}
-bool CookieControlsHandler::GetToggleCheckedValue(const Profile* profile) {
- return CookieSettingsFactory::GetForProfile(const_cast<Profile*>(profile))
- ->ShouldBlockThirdPartyCookies();
-}
-
-void CookieControlsHandler::SendCookieControlsUIChanges() {
- Profile* profile = Profile::FromWebUI(web_ui());
- base::DictionaryValue dict;
- dict.SetBoolKey("enforced", ShouldEnforceCookieControls(profile));
- dict.SetBoolKey("checked", GetToggleCheckedValue(profile));
- dict.SetStringKey("icon", GetEnforcementIcon(profile));
- FireWebUIListener("cookie-controls-changed", dict);
-}
-
-void CookieControlsHandler::OnThirdPartyCookieBlockingPolicyChanged(
- const base::Value* previous,
- const base::Value* current) {
- SendCookieControlsUIChanges();
-}
-
-bool CookieControlsHandler::ShouldHideCookieControlsUI(const Profile* profile) {
- return !base::FeatureList::IsEnabled(
- content_settings::kImprovedCookieControls);
-}
-
-bool CookieControlsHandler::ShouldEnforceCookieControls(
- const Profile* profile) {
- return GetCookieControlsEnforcement(profile) !=
- CookieControlsEnforcement::kNoEnforcement;
-}
-
-const char* CookieControlsHandler::GetEnforcementIcon(const Profile* profile) {
- switch (GetCookieControlsEnforcement(profile)) {
+const char* CookieControlsHandler::GetEnforcementIcon(Profile* profile) {
+ CookieControlsService* service =
+ CookieControlsServiceFactory::GetForProfile(profile);
+ switch (service->GetCookieControlsEnforcement()) {
case CookieControlsEnforcement::kEnforcedByPolicy:
return kPolicyIcon;
+ case CookieControlsEnforcement::kEnforcedByExtension:
+ return kExtensionIcon;
case CookieControlsEnforcement::kEnforcedByCookieSetting:
return kSettingsIcon;
case CookieControlsEnforcement::kNoEnforcement:
return "";
}
}
+
+void CookieControlsHandler::OnThirdPartyCookieBlockingPrefChanged() {
+ SendCookieControlsUIChanges();
+}
+
+void CookieControlsHandler::OnThirdPartyCookieBlockingPolicyChanged() {
+ SendCookieControlsUIChanges();
+}
+
+void CookieControlsHandler::SendCookieControlsUIChanges() {
+ Profile* profile = Profile::FromWebUI(web_ui());
+ base::DictionaryValue dict;
+ dict.SetBoolKey("enforced", service_->ShouldEnforceCookieControls());
+ dict.SetBoolKey("checked", service_->GetToggleCheckedValue());
+ dict.SetStringKey("icon", CookieControlsHandler::GetEnforcementIcon(profile));
+ bool use_new_cookie_page =
+ base::FeatureList::IsEnabled(features::kPrivacySettingsRedesign);
+ dict.SetString("cookieSettingsUrl",
+ use_new_cookie_page ? "chrome://settings/cookies"
+ : "chrome://settings/content/cookies");
+ FireWebUIListener("cookie-controls-changed", dict);
+}
diff --git a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.h b/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.h
index a56a2461a7a..c23870ee741 100644
--- a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.h
+++ b/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.h
@@ -7,25 +7,19 @@
#include <memory>
-#include "components/prefs/pref_change_registrar.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/cookie_controls/cookie_controls_service.h"
#include "content/public/browser/web_ui_message_handler.h"
-class CookieControlsHandlerTest;
-class Profile;
-
namespace base {
class ListValue;
-class Value;
} // namespace base
-namespace policy {
-class PolicyChangeRegistrar;
-}
-
// Handles requests for prefs::kCookieControlsMode retrival/update.
-class CookieControlsHandler : public content::WebUIMessageHandler {
+class CookieControlsHandler : public content::WebUIMessageHandler,
+ public CookieControlsService::Observer {
public:
- CookieControlsHandler();
+ explicit CookieControlsHandler(Profile* profile);
~CookieControlsHandler() override;
// WebUIMessageHandler
@@ -34,32 +28,19 @@ class CookieControlsHandler : public content::WebUIMessageHandler {
void OnJavascriptDisallowed() override;
void HandleCookieControlsToggleChanged(const base::ListValue* args);
-
void HandleObserveCookieControlsSettingsChanges(const base::ListValue* args);
+ static const char* GetEnforcementIcon(Profile* profile);
- // Whether cookie controls UI should be hidden in incognito ntp.
- static bool ShouldHideCookieControlsUI(const Profile* profile);
-
- // Whether cookie controls should appear enforced.
- static bool ShouldEnforceCookieControls(const Profile* profile);
-
- static const char* GetEnforcementIcon(const Profile* profile);
-
- static bool GetToggleCheckedValue(const Profile* profile);
+ // CookieControlsService::Observer
+ void OnThirdPartyCookieBlockingPrefChanged() override;
+ void OnThirdPartyCookieBlockingPolicyChanged() override;
private:
- friend class CookieControlsHandlerTest;
-
// Updates cookie controls UI when third-party cookie blocking setting has
// changed.
void SendCookieControlsUIChanges();
- void OnThirdPartyCookieBlockingPolicyChanged(const base::Value* previous,
- const base::Value* current);
-
- PrefChangeRegistrar pref_change_registrar_;
-
- std::unique_ptr<policy::PolicyChangeRegistrar> policy_registrar_;
+ CookieControlsService* service_;
DISALLOW_COPY_AND_ASSIGN(CookieControlsHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler_unittest.cc b/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler_unittest.cc
deleted file mode 100644
index e269fef1122..00000000000
--- a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler_unittest.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/ntp/cookie_controls_handler.h"
-
-#include "base/values.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
-#include "components/content_settings/core/browser/cookie_settings.h"
-#include "components/content_settings/core/common/pref_names.h"
-#include "components/prefs/pref_service.h"
-#include "content/public/test/test_web_ui.h"
-
-class CookieControlsHandlerTest : public ChromeRenderViewHostTestHarness {
- public:
- void SetUp() override {
- ChromeRenderViewHostTestHarness::SetUp();
- web_ui_.set_web_contents(web_contents());
- handler_ = std::make_unique<CookieControlsHandler>();
- handler_->set_web_ui(&web_ui_);
- }
-
- void TearDown() override {
- handler_->set_web_ui(nullptr);
- ChromeRenderViewHostTestHarness::TearDown();
- }
-
- protected:
- content::TestWebUI web_ui_;
- std::unique_ptr<CookieControlsHandler> handler_;
-};
-
-TEST_F(CookieControlsHandlerTest, HandleCookieControlsToggleChanged) {
- EXPECT_EQ(
- static_cast<int>(content_settings::CookieControlsMode::kIncognitoOnly),
- Profile::FromWebUI(&web_ui_)->GetPrefs()->GetInteger(
- prefs::kCookieControlsMode));
- base::ListValue args_false;
- args_false.AppendBoolean(false);
- handler_->HandleCookieControlsToggleChanged(&args_false);
- EXPECT_EQ(static_cast<int>(content_settings::CookieControlsMode::kOff),
- Profile::FromWebUI(&web_ui_)->GetPrefs()->GetInteger(
- prefs::kCookieControlsMode));
- base::ListValue args_true;
- args_true.AppendBoolean(true);
- handler_->HandleCookieControlsToggleChanged(&args_true);
- EXPECT_EQ(
- static_cast<int>(content_settings::CookieControlsMode::kIncognitoOnly),
- Profile::FromWebUI(&web_ui_)->GetPrefs()->GetInteger(
- prefs::kCookieControlsMode));
-}
diff --git a/chromium/chrome/browser/ui/webui/ntp/core_app_launcher_handler.h b/chromium/chrome/browser/ui/webui/ntp/core_app_launcher_handler.h
index 44a4f7e27c5..bc6c7790db4 100644
--- a/chromium/chrome/browser/ui/webui/ntp/core_app_launcher_handler.h
+++ b/chromium/chrome/browser/ui/webui/ntp/core_app_launcher_handler.h
@@ -12,7 +12,6 @@
#include "base/values.h"
#include "chrome/common/extensions/extension_constants.h"
#include "content/public/browser/web_ui_message_handler.h"
-#include "extensions/common/extension.h"
namespace user_prefs {
class PrefRegistrySyncable;
diff --git a/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.cc b/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.cc
index 620f7eed511..6d549a735e1 100644
--- a/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.cc
+++ b/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.cc
@@ -59,7 +59,7 @@ NewTabUI::NewTabUI(content::WebUI* web_ui) : content::WebUIController(web_ui) {
if (!profile->IsGuestSession()) {
web_ui->AddMessageHandler(std::make_unique<ThemeHandler>());
- web_ui->AddMessageHandler(std::make_unique<CookieControlsHandler>());
+ web_ui->AddMessageHandler(std::make_unique<CookieControlsHandler>(profile));
}
// content::URLDataSource assumes the ownership of the html source.
diff --git a/chromium/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chromium/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
index 95e3357a227..84c088a6617 100644
--- a/chromium/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
+++ b/chromium/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -26,6 +26,8 @@
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/apps/app_info_dialog.h"
+#include "chrome/browser/ui/cookie_controls/cookie_controls_service.h"
+#include "chrome/browser/ui/cookie_controls/cookie_controls_service_factory.h"
#include "chrome/browser/ui/layout_constants.h"
#include "chrome/browser/ui/webui/app_launcher_login_handler.h"
#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
@@ -50,7 +52,6 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_process_host.h"
-#include "extensions/common/extension.h"
#include "extensions/common/extension_urls.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
@@ -95,8 +96,11 @@ SkColor GetThemeColor(const ui::ThemeProvider& tp, int id) {
SkColor color = tp.GetColor(id);
// If web contents are being inverted because the system is in high-contrast
// mode, any system theme colors we use must be inverted too to cancel out.
- return color_utils::IsInvertedColorScheme() ?
- color_utils::InvertColor(color) : color;
+ return ui::NativeTheme::GetInstanceForNativeUi()
+ ->GetHighContrastColorScheme() ==
+ ui::NativeTheme::HighContrastColorScheme::kDark
+ ? color_utils::InvertColor(color)
+ : color;
}
// Get the CSS string for the background position on the new tab page for the
@@ -303,28 +307,31 @@ void NTPResourceCache::CreateNewTabIncognitoHTML() {
replacements["learnMoreLink"] = kLearnMoreIncognitoUrl;
replacements["title"] = l10n_util::GetStringUTF8(IDS_NEW_TAB_TITLE);
replacements["hideCookieControls"] =
- CookieControlsHandler::ShouldHideCookieControlsUI(profile_) ? "hidden"
- : "";
+ CookieControlsServiceFactory::GetForProfile(profile_)
+ ->ShouldHideCookieControlsUI()
+ ? "hidden"
+ : "";
replacements["cookieControlsTitle"] =
- l10n_util::GetStringUTF8(IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE);
- replacements["cookieControlsDescription"] = l10n_util::GetStringUTF8(
- IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_SUBLABEL);
+ l10n_util::GetStringUTF8(IDS_NEW_TAB_OTR_THIRD_PARTY_COOKIE);
+ replacements["cookieControlsDescription"] =
+ l10n_util::GetStringUTF8(IDS_NEW_TAB_OTR_THIRD_PARTY_COOKIE_SUBLABEL);
// Ensure passing off-the-record profile; |profile_| might not be incognito.
DCHECK(profile_->HasOffTheRecordProfile());
replacements["cookieControlsToggleChecked"] =
- CookieControlsHandler::GetToggleCheckedValue(
+ CookieControlsServiceFactory::GetForProfile(
profile_->GetOffTheRecordProfile())
+ ->GetToggleCheckedValue()
? "checked"
: "";
replacements["hideTooltipIcon"] =
- CookieControlsHandler::ShouldEnforceCookieControls(profile_) ? ""
- : "hidden";
+ CookieControlsServiceFactory::GetForProfile(profile_)
+ ->ShouldEnforceCookieControls()
+ ? ""
+ : "hidden";
replacements["cookieControlsToolTipIcon"] =
CookieControlsHandler::GetEnforcementIcon(profile_);
- replacements["cookieControlsTooltipText"] = l10n_util::GetStringFUTF8(
- IDS_NEW_TAB_OTR_COOKIE_CONTROLS_CONTROLLED_TOOLTIP_TEXT,
- l10n_util::GetStringUTF16(IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE),
- l10n_util::GetStringUTF16(IDS_SETTINGS_SITE_SETTINGS_COOKIES));
+ replacements["cookieControlsTooltipText"] = l10n_util::GetStringUTF8(
+ IDS_NEW_TAB_OTR_COOKIE_CONTROLS_CONTROLLED_TOOLTIP_TEXT);
const ui::ThemeProvider& tp =
ThemeService::GetThemeProviderForProfile(profile_);
@@ -338,6 +345,7 @@ void NTPResourceCache::CreateNewTabIncognitoHTML() {
incognito_tab_html(
ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
IDR_INCOGNITO_TAB_HTML));
+ CHECK(*incognito_tab_html);
std::string full_html =
ReplaceTemplateExpressions(*incognito_tab_html, replacements);
@@ -404,6 +412,7 @@ void NTPResourceCache::CreateNewTabGuestHTML() {
guest_tab_html(
ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
guest_tab_idr));
+ CHECK(*guest_tab_html);
ui::TemplateReplacements replacements;
ui::TemplateReplacementsFromDictionaryValue(localized_strings, &replacements);
std::string full_html =
@@ -520,6 +529,7 @@ void NTPResourceCache::CreateNewTabHTML() {
new_tab_html(
ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
IDR_NEW_TAB_4_HTML));
+ CHECK(*new_tab_html);
std::string full_html = webui::GetI18nTemplateHtml(
base::StringPiece(reinterpret_cast<const char*>((*new_tab_html)->front()),
(*new_tab_html)->size()),
@@ -549,7 +559,8 @@ void NTPResourceCache::CreateNewTabIncognitoCSS() {
static const base::NoDestructor<scoped_refptr<base::RefCountedMemory>>
new_tab_theme_css(
ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
- IDR_NEW_INCOGNITO_TAB_THEME_CSS));
+ IDR_INCOGNITO_TAB_THEME_CSS));
+ CHECK(*new_tab_theme_css);
// Create the string from our template and the replacements.
std::string full_css =
@@ -629,6 +640,7 @@ void NTPResourceCache::CreateNewTabCSS() {
new_tab_theme_css(
ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
IDR_NEW_TAB_4_THEME_CSS));
+ CHECK(*new_tab_theme_css);
// Create the string from our template and the replacements.
std::string css_string =
diff --git a/chromium/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc b/chromium/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
index 8f72bc23a7b..c2a62bd570c 100644
--- a/chromium/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
@@ -5,6 +5,8 @@
#include "chrome/browser/ui/webui/ntp_tiles_internals_ui.h"
#include <memory>
+#include <string>
+#include <vector>
#include "base/bind.h"
#include "build/build_config.h"
@@ -15,7 +17,7 @@
#include "chrome/browser/search/suggestions/suggestions_service_factory.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/common/url_constants.h"
-#include "components/grit/components_resources.h"
+#include "components/grit/dev_ui_components_resources.h"
#include "components/history/core/browser/top_sites.h"
#include "components/image_fetcher/core/image_fetcher_impl.h"
#include "components/ntp_tiles/features.h"
diff --git a/chromium/chrome/browser/ui/webui/omnibox/BUILD.gn b/chromium/chrome/browser/ui/webui/omnibox/BUILD.gn
index bf547a06b42..b58f3e4bc9c 100644
--- a/chromium/chrome/browser/ui/webui/omnibox/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/omnibox/BUILD.gn
@@ -5,7 +5,5 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "omnibox.mojom",
- ]
+ sources = [ "omnibox.mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc b/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc
index c8dc602ed4d..c6e3c553d56 100644
--- a/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc
+++ b/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc
@@ -29,45 +29,19 @@
#include "components/history/core/browser/history_service.h"
#include "components/history/core/browser/url_database.h"
#include "components/omnibox/browser/autocomplete_classifier.h"
-#include "components/omnibox/browser/autocomplete_controller.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/autocomplete_provider.h"
#include "components/omnibox/browser/omnibox_controller_emitter.h"
#include "components/search_engines/template_url.h"
#include "content/public/browser/web_ui.h"
#include "third_party/metrics_proto/omnibox_event.pb.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image.h"
using bookmarks::BookmarkModel;
-using OmniboxPageImageCallback =
- base::RepeatingCallback<void(const SkBitmap& bitmap)>;
namespace {
-using ImageReciever = std::function<void(std::string)>;
-
-class OmniboxPageImageObserver : public BitmapFetcherService::Observer {
- public:
- explicit OmniboxPageImageObserver(ImageReciever image_reciever)
- : image_reciever_(image_reciever) {}
-
- void OnImageChanged(BitmapFetcherService::RequestId request_id,
- const SkBitmap& bitmap) override {
- auto data = gfx::Image::CreateFrom1xBitmap(bitmap).As1xPNGBytes();
- std::string base_64;
- base::Base64Encode(base::StringPiece(data->front_as<char>(), data->size()),
- &base_64);
- const char kDataUrlPrefix[] = "data:image/png;base64,";
- std::string data_url = GURL(kDataUrlPrefix + base_64).spec();
- image_reciever_(data_url);
- }
-
- private:
- const ImageReciever image_reciever_;
-
- DISALLOW_COPY_AND_ASSIGN(OmniboxPageImageObserver);
-};
-
std::string SuggestionAnswerTypeToString(int answer_type) {
switch (answer_type) {
case SuggestionAnswer::ANSWER_TYPE_INVALID:
@@ -223,28 +197,25 @@ struct TypeConverter<mojom::AutocompleteResultsForProviderPtr,
OmniboxPageHandler::OmniboxPageHandler(
Profile* profile,
mojo::PendingReceiver<mojom::OmniboxPageHandler> receiver)
- : profile_(profile), receiver_(this, std::move(receiver)), observer_(this) {
+ : profile_(profile),
+ receiver_(this, std::move(receiver)),
+ observer_(this) {
observer_.Add(OmniboxControllerEmitter::GetForBrowserContext(profile_));
ResetController();
}
-OmniboxPageHandler::~OmniboxPageHandler() {}
+OmniboxPageHandler::~OmniboxPageHandler() = default;
-void OmniboxPageHandler::OnResultChanged(bool default_match_changed) {
- OnOmniboxResultChanged(default_match_changed, controller_.get());
-}
-
-void OmniboxPageHandler::OnOmniboxQuery(AutocompleteController* controller,
- const AutocompleteInput& input) {
+void OmniboxPageHandler::OnStart(AutocompleteController* controller,
+ const AutocompleteInput& input) {
time_omnibox_started_ = base::Time::Now();
input_ = input;
page_->HandleNewAutocompleteQuery(controller == controller_.get(),
base::UTF16ToUTF8(input.text()));
}
-void OmniboxPageHandler::OnOmniboxResultChanged(
- bool default_match_changed,
- AutocompleteController* controller) {
+void OmniboxPageHandler::OnResultChanged(AutocompleteController* controller,
+ bool default_match_changed) {
mojom::OmniboxResponsePtr response(mojom::OmniboxResponse::New());
response->cursor_position = input_.cursor_position();
response->time_since_omnibox_started_ms =
@@ -304,62 +275,30 @@ void OmniboxPageHandler::OnOmniboxResultChanged(
controller == controller_.get());
// Fill in image data
- BitmapFetcherService* image_service =
+ BitmapFetcherService* bitmap_fetcher_service =
BitmapFetcherServiceFactory::GetForBrowserContext(profile_);
- if (!image_service)
- return;
+
for (std::string image_url : image_urls) {
- const ImageReciever handleAnswerImageData = [this,
- image_url](std::string data) {
- page_->HandleAnswerImageData(image_url, data);
- };
- if (!image_url.empty()) {
- // TODO(jdonnelly, rhalavati, manukh): Create a helper function with
- // Callback to create annotation and pass it to image_service, merging
- // the annotations in omnibox_page_handler.cc, chrome_omnibox_client.cc,
- // and chrome_autocomplete_provider_client.cc.
- auto traffic_annotation = net::DefineNetworkTrafficAnnotation(
- "omnibox_debug_results_change", R"(
- semantics {
- sender: "Omnibox"
- description:
- "Chromium provides answers in the suggestion list for "
- "certain queries that user types in the omnibox. This request "
- "retrieves a small image (for example, an icon illustrating "
- "the current weather conditions) when this can add information "
- "to an answer."
- trigger:
- "Change of results for the query typed by the user in the "
- "omnibox."
- data:
- "The only data sent is the path to an image. No user data is "
- "included, although some might be inferrable (e.g. whether the "
- "weather is sunny or rainy in the user's current location) "
- "from the name of the image in the path."
- destination: WEBSITE
- }
- policy {
- cookies_allowed: YES
- cookies_store: "user"
- setting:
- "You can enable or disable this feature via 'Use a prediction "
- "service to help complete searches and URLs typed in the "
- "address bar.' in Chromium's settings under Advanced. The "
- "feature is enabled by default."
- chrome_policy {
- SearchSuggestEnabled {
- policy_options {mode: MANDATORY}
- SearchSuggestEnabled: false
- }
- }
- })");
- image_service->RequestImage(
- GURL(image_url), new OmniboxPageImageObserver(handleAnswerImageData),
- traffic_annotation);
+ if (image_url.empty()) {
+ continue;
}
+ bitmap_fetcher_service->RequestImage(
+ GURL(image_url), base::BindOnce(&OmniboxPageHandler::OnBitmapFetched,
+ weak_factory_.GetWeakPtr(), image_url));
}
}
+void OmniboxPageHandler::OnBitmapFetched(const std::string& image_url,
+ const SkBitmap& bitmap) {
+ auto data = gfx::Image::CreateFrom1xBitmap(bitmap).As1xPNGBytes();
+ std::string base_64;
+ base::Base64Encode(base::StringPiece(data->front_as<char>(), data->size()),
+ &base_64);
+ const char kDataUrlPrefix[] = "data:image/png;base64,";
+ std::string data_url = GURL(kDataUrlPrefix + base_64).spec();
+ page_->HandleAnswerImageData(image_url, data_url);
+}
+
bool OmniboxPageHandler::LookupIsTypedHost(const base::string16& host,
bool* is_typed_host) const {
history::HistoryService* const history_service =
@@ -410,12 +349,14 @@ void OmniboxPageHandler::StartOmniboxQuery(const std::string& input_string,
input.set_keyword_mode_entry_method(metrics::OmniboxEventProto::TAB);
input.set_from_omnibox_focus(zero_suggest);
- OnOmniboxQuery(controller_.get(), input);
- controller_->Start(input_);
+ controller_->Start(input);
}
void OmniboxPageHandler::ResetController() {
controller_ = std::make_unique<AutocompleteController>(
- std::make_unique<ChromeAutocompleteProviderClient>(profile_), this,
+ std::make_unique<ChromeAutocompleteProviderClient>(profile_),
AutocompleteClassifier::DefaultOmniboxProviders());
+ // We will observe our internal AutocompleteController directly, so there's
+ // no reason to hook it up to the profile-keyed OmniboxControllerEmitter.
+ controller_->AddObserver(this);
}
diff --git a/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.h b/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.h
index c960ff022e6..2922746b243 100644
--- a/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.h
+++ b/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.h
@@ -11,9 +11,10 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/ui/webui/omnibox/omnibox.mojom.h"
-#include "components/omnibox/browser/autocomplete_controller_delegate.h"
+#include "components/omnibox/browser/autocomplete_controller.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/omnibox_controller_emitter.h"
@@ -29,23 +30,19 @@ class Profile;
// private AutocompleteController. It also listens for updates from the
// AutocompleteController to OnResultChanged() and passes those results to
// the OmniboxPage.
-class OmniboxPageHandler : public AutocompleteControllerDelegate,
- public mojom::OmniboxPageHandler,
- public OmniboxControllerEmitter::Observer {
+class OmniboxPageHandler : public AutocompleteController::Observer,
+ public mojom::OmniboxPageHandler {
public:
// OmniboxPageHandler is deleted when the supplied pipe is destroyed.
OmniboxPageHandler(Profile* profile,
mojo::PendingReceiver<mojom::OmniboxPageHandler> receiver);
~OmniboxPageHandler() override;
- // AutocompleteControllerDelegate overrides:
- void OnResultChanged(bool default_match_changed) override;
-
- // OmniboxControllerEmitter::Observer overrides:
- void OnOmniboxQuery(AutocompleteController* controller,
- const AutocompleteInput& input) override;
- void OnOmniboxResultChanged(bool default_match_changed,
- AutocompleteController* controller) override;
+ // AutocompleteController::Observer overrides:
+ void OnStart(AutocompleteController* controller,
+ const AutocompleteInput& input) override;
+ void OnResultChanged(AutocompleteController* controller,
+ bool default_match_changed) override;
// mojom::OmniboxPageHandler overrides:
void SetClientPage(mojo::PendingRemote<mojom::OmniboxPage> page) override;
@@ -61,6 +58,8 @@ class OmniboxPageHandler : public AutocompleteControllerDelegate,
int32_t page_classification) override;
private:
+ void OnBitmapFetched(const std::string& image_url, const SkBitmap& bitmap);
+
// Looks up whether the hostname is a typed host (i.e., has received
// typed visits). Return true if the lookup succeeded; if so, the
// value of |is_typed_host| is set appropriately.
@@ -90,9 +89,11 @@ class OmniboxPageHandler : public AutocompleteControllerDelegate,
mojo::Receiver<mojom::OmniboxPageHandler> receiver_;
- ScopedObserver<OmniboxControllerEmitter, OmniboxControllerEmitter::Observer>
+ ScopedObserver<OmniboxControllerEmitter, AutocompleteController::Observer>
observer_;
+ base::WeakPtrFactory<OmniboxPageHandler> weak_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(OmniboxPageHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/omnibox/omnibox_popup_handler.cc b/chromium/chrome/browser/ui/webui/omnibox/omnibox_popup_handler.cc
new file mode 100644
index 00000000000..993b22ab01d
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/omnibox/omnibox_popup_handler.cc
@@ -0,0 +1,7 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/omnibox/omnibox_popup_handler.h"
+
+OmniboxPopupHandler::OmniboxPopupHandler() = default;
diff --git a/chromium/chrome/browser/ui/webui/omnibox/omnibox_popup_handler.h b/chromium/chrome/browser/ui/webui/omnibox/omnibox_popup_handler.h
new file mode 100644
index 00000000000..ef7fdde0129
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/omnibox/omnibox_popup_handler.h
@@ -0,0 +1,26 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_OMNIBOX_OMNIBOX_POPUP_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_OMNIBOX_OMNIBOX_POPUP_HANDLER_H_
+
+#include "base/macros.h"
+#include "components/omnibox/browser/omnibox_popup_model.h"
+
+// The WebUI handler for the experimental WebUI omnibox popup.
+class OmniboxPopupHandler {
+ public:
+ OmniboxPopupHandler();
+
+ // These are roughly speaking analogues of the OmniboxPopupView API.
+ // TODO(tommycli): Update the OmniboxPopupView API to better suit WebUI,
+ // then this class could potentially be an implementor of OmniboxPopupView.
+ void InvalidateLine(size_t line) {}
+ void OnSelectedLineChanged(size_t old_selected_line,
+ size_t new_selected_line) {}
+
+ DISALLOW_COPY_AND_ASSIGN(OmniboxPopupHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_OMNIBOX_OMNIBOX_POPUP_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.cc b/chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.cc
index 0b5b49cde52..a93133375f3 100644
--- a/chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.cc
+++ b/chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.cc
@@ -7,16 +7,22 @@
#include <utility>
#include "base/bind.h"
+#include "base/feature_list.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/omnibox/omnibox_page_handler.h"
#include "chrome/browser/ui/webui/version_handler.h"
#include "chrome/browser/ui/webui/version_ui.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/omnibox_resources.h"
+#include "components/omnibox/common/omnibox_features.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
+#if !defined(OS_ANDROID)
+#include "chrome/browser/ui/webui/omnibox/omnibox_popup_handler.h"
+#endif
+
OmniboxUI::OmniboxUI(content::WebUI* web_ui)
: ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true) {
// Set up the chrome://omnibox/ source.
@@ -42,15 +48,24 @@ OmniboxUI::OmniboxUI(content::WebUI* web_ui)
IDR_OMNIBOX_MOJO_JS);
source->SetDefaultResource(IDR_OMNIBOX_HTML);
+#if !defined(OS_ANDROID)
+ if (base::FeatureList::IsEnabled(omnibox::kWebUIOmniboxPopup)) {
+ source->AddResourcePath("omnibox_popup.js", IDR_OMNIBOX_POPUP_JS);
+ source->AddResourcePath("omnibox_popup.html", IDR_OMNIBOX_POPUP_HTML);
+
+ popup_handler_ = std::make_unique<OmniboxPopupHandler>();
+ }
+#endif
+
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
- AddHandlerToRegistry(base::BindRepeating(&OmniboxUI::BindOmniboxPageHandler,
- base::Unretained(this)));
web_ui->AddMessageHandler(std::make_unique<VersionHandler>());
}
+WEB_UI_CONTROLLER_TYPE_IMPL(OmniboxUI)
+
OmniboxUI::~OmniboxUI() {}
-void OmniboxUI::BindOmniboxPageHandler(
+void OmniboxUI::BindInterface(
mojo::PendingReceiver<mojom::OmniboxPageHandler> receiver) {
omnibox_handler_ = std::make_unique<OmniboxPageHandler>(
Profile::FromWebUI(web_ui()), std::move(receiver));
diff --git a/chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.h b/chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.h
index 81f3ad0e054..bab7f36ff36 100644
--- a/chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.h
+++ b/chromium/chrome/browser/ui/webui/omnibox/omnibox_ui.h
@@ -6,24 +6,41 @@
#define CHROME_BROWSER_UI_WEBUI_OMNIBOX_OMNIBOX_UI_H_
#include "base/macros.h"
-#include "chrome/browser/ui/webui/omnibox/omnibox.mojom.h"
+#include "build/build_config.h"
+#include "chrome/browser/ui/webui/omnibox/omnibox.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
class OmniboxPageHandler;
+#if !defined(OS_ANDROID)
+class OmniboxPopupHandler;
+#endif
+
// The UI for chrome://omnibox/
class OmniboxUI : public ui::MojoWebUIController {
public:
explicit OmniboxUI(content::WebUI* contents);
~OmniboxUI() override;
- private:
- void BindOmniboxPageHandler(
- mojo::PendingReceiver<mojom::OmniboxPageHandler> receiver);
+ // Instantiates the implementor of the mojom::OmniboxPageHandler mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(mojo::PendingReceiver<mojom::OmniboxPageHandler> receiver);
+
+#if !defined(OS_ANDROID)
+ // This is needed for the Views native UI to call into the WebUI code.
+ OmniboxPopupHandler* popup_handler() { return popup_handler_.get(); }
+#endif
+ private:
std::unique_ptr<OmniboxPageHandler> omnibox_handler_;
+#if !defined(OS_ANDROID)
+ std::unique_ptr<OmniboxPopupHandler> popup_handler_;
+#endif
+
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(OmniboxUI);
};
diff --git a/chromium/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc
index 9b435b73e8b..1d3271b586f 100644
--- a/chromium/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc
+++ b/chromium/chrome/browser/ui/webui/policy_indicator_localized_strings_provider.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/webui/web_ui_util.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
diff --git a/chromium/chrome/browser/ui/webui/policy_ui.cc b/chromium/chrome/browser/ui/webui/policy_ui.cc
index fcc27d5d6c3..7695bbf055d 100644
--- a/chromium/chrome/browser/ui/webui/policy_ui.cc
+++ b/chromium/chrome/browser/ui/webui/policy_ui.cc
@@ -11,9 +11,10 @@
#include "chrome/browser/ui/webui/policy_ui_handler.h"
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/common/url_constants.h"
-#include "components/grit/components_resources.h"
+#include "components/grit/dev_ui_components_resources.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/web_ui.h"
+#include "ui/base/webui/web_ui_util.h"
namespace {
diff --git a/chromium/chrome/browser/ui/webui/policy_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/policy_ui_browsertest.cc
index e224936dc94..af6412c0f1b 100644
--- a/chromium/chrome/browser/ui/webui/policy_ui_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/policy_ui_browsertest.cc
@@ -449,18 +449,6 @@ IN_PROC_BROWSER_TEST_F(PolicyUITest, WritePoliciesToJSONFile) {
std::string(policy::key::kDefaultImagesSetting),
nullptr);
-#if !defined(OS_CHROMEOS)
- // This also checks that we bypass the policy that blocks file selection
- // dialogs. This is a desktop only policy.
- values.Set(policy::key::kAllowFileSelectionDialogs,
- policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
- policy::POLICY_SOURCE_PLATFORM,
- std::make_unique<base::Value>(false), nullptr);
- SetExpectedPolicy(&expected_values, policy::key::kAllowFileSelectionDialogs,
- "mandatory", "machine", "platform", std::string(),
- std::string(), false, base::Value(false));
-#endif
-
popups_blocked_for_urls.AppendString("ddd");
values.Set(policy::key::kPopupsBlockedForUrls, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM,
@@ -474,6 +462,24 @@ IN_PROC_BROWSER_TEST_F(PolicyUITest, WritePoliciesToJSONFile) {
// Check writing changed policies to the same file (should overwrite the
// contents).
VerifyExportingPolicies(expected_values);
+
+#if !defined(OS_CHROMEOS)
+ // This also checks that we do not bypass the policy that blocks file
+ // selection dialogs. This is a desktop only policy.
+ values.Set(policy::key::kAllowFileSelectionDialogs,
+ policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE,
+ policy::POLICY_SOURCE_PLATFORM,
+ std::make_unique<base::Value>(false), nullptr);
+ popups_blocked_for_urls.AppendString("eeeeee");
+ values.Set(policy::key::kPopupsBlockedForUrls, policy::POLICY_LEVEL_MANDATORY,
+ policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM,
+ popups_blocked_for_urls.CreateDeepCopy(), nullptr);
+ provider_.UpdateChromePolicy(values);
+
+ // Check writing changed policies did not overwrite the exported policies
+ // because the file selection dialog is not allowed.
+ VerifyExportingPolicies(expected_values);
+#endif
}
IN_PROC_BROWSER_TEST_F(PolicyUITest, SendPolicyNames) {
diff --git a/chromium/chrome/browser/ui/webui/policy_ui_handler.cc b/chromium/chrome/browser/ui/webui/policy_ui_handler.cc
index cee8afd1c4d..d117f23c2de 100644
--- a/chromium/chrome/browser/ui/webui/policy_ui_handler.cc
+++ b/chromium/chrome/browser/ui/webui/policy_ui_handler.cc
@@ -22,6 +22,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -29,16 +30,18 @@
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/policy/browser_dm_token_storage.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
-#include "chrome/browser/policy/policy_conversions.h"
+#include "chrome/browser/policy/chrome_policy_conversions_client.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/policy/schema_registry_service.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/common/channel_info.h"
#include "chrome/grit/chromium_strings.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/browser/cloud/message_util.h"
#include "components/policy/core/browser/configuration_policy_handler_list.h"
+#include "components/policy/core/browser/policy_conversions.h"
#include "components/policy/core/common/cloud/cloud_policy_client.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "components/policy/core/common/cloud/cloud_policy_core.h"
@@ -50,6 +53,7 @@
#include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h"
#include "components/policy/core/common/cloud/machine_level_user_cloud_policy_store.h"
#include "components/policy/core/common/policy_details.h"
+#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_namespace.h"
#include "components/policy/core/common/policy_scheduler.h"
#include "components/policy/core/common/policy_types.h"
@@ -65,7 +69,7 @@
#include "google_apis/gaia/gaia_auth_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/time_format.h"
-#include "ui/shell_dialogs/select_file_policy.h"
+#include "ui/base/webui/web_ui_util.h"
#if defined(OS_ANDROID)
#include "chrome/browser/ui/android/android_about_app_info.h"
@@ -101,6 +105,12 @@
#include "extensions/common/manifest_constants.h"
#endif
+#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#include "chrome/browser/google/google_update_policy_fetcher_win.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+
namespace em = enterprise_management;
namespace {
@@ -143,6 +153,17 @@ base::string16 GetPolicyStatusFromStore(
return status;
}
+base::string16 GetTimeSinceLastRefreshString(base::Time last_refresh_time) {
+ if (last_refresh_time.is_null())
+ return l10n_util::GetStringUTF16(IDS_POLICY_NEVER_FETCHED);
+ base::Time now = base::Time::NowFromSystemTime();
+ base::TimeDelta elapsed_time;
+ if (now > last_refresh_time)
+ elapsed_time = now - last_refresh_time;
+ return ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED,
+ ui::TimeFormat::LENGTH_SHORT, elapsed_time);
+}
+
void GetStatusFromCore(const policy::CloudPolicyCore* core,
base::DictionaryValue* dict) {
const policy::CloudPolicyStore* store = core->store();
@@ -185,13 +206,8 @@ void GetStatusFromCore(const policy::CloudPolicyCore* core,
"refreshInterval",
ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
ui::TimeFormat::LENGTH_SHORT, refresh_interval));
- dict->SetString(
- "timeSinceLastRefresh",
- last_refresh_time.is_null()
- ? l10n_util::GetStringUTF16(IDS_POLICY_NEVER_FETCHED)
- : ui::TimeFormat::Simple(
- ui::TimeFormat::FORMAT_ELAPSED, ui::TimeFormat::LENGTH_SHORT,
- base::Time::NowFromSystemTime() - last_refresh_time));
+ dict->SetString("timeSinceLastRefresh",
+ GetTimeSinceLastRefreshString(last_refresh_time));
}
#if defined(OS_CHROMEOS)
@@ -512,6 +528,8 @@ void MachineLevelUserCloudPolicyStatusProvider::GetStatus(
base::DictionaryValue* dict) {
policy::CloudPolicyStore* store = core_->store();
policy::CloudPolicyClient* client = core_->client();
+ policy::CloudPolicyRefreshScheduler* refresh_scheduler =
+ core_->refresh_scheduler();
policy::BrowserDMTokenStorage* dmTokenStorage =
policy::BrowserDMTokenStorage::Get();
@@ -521,7 +539,9 @@ void MachineLevelUserCloudPolicyStatusProvider::GetStatus(
ui::TimeFormat::Simple(
ui::TimeFormat::FORMAT_DURATION, ui::TimeFormat::LENGTH_SHORT,
base::TimeDelta::FromMilliseconds(
- policy::CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs)));
+ refresh_scheduler ? refresh_scheduler->GetActualRefreshDelay()
+ : policy::CloudPolicyRefreshScheduler::
+ kDefaultRefreshDelayMs)));
if (dmTokenStorage) {
dict->SetString("enrollmentToken",
@@ -535,12 +555,10 @@ void MachineLevelUserCloudPolicyStatusProvider::GetStatus(
dict->SetString("status", status);
const em::PolicyData* policy = store->policy();
if (policy) {
- dict->SetString(
- "timeSinceLastRefresh",
- ui::TimeFormat::Simple(
- ui::TimeFormat::FORMAT_ELAPSED, ui::TimeFormat::LENGTH_SHORT,
- base::Time::NowFromSystemTime() -
- base::Time::FromJavaTime(policy->timestamp())));
+ dict->SetString("timeSinceLastRefresh",
+ GetTimeSinceLastRefreshString(
+ refresh_scheduler ? refresh_scheduler->last_refresh()
+ : base::Time()));
std::string username = policy->username();
dict->SetString("domain", gaia::ExtractDomainName(username));
}
@@ -658,13 +676,8 @@ void UserActiveDirectoryPolicyStatusProvider::GetStatus(
ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION,
ui::TimeFormat::LENGTH_SHORT, refresh_interval));
- dict->SetString(
- "timeSinceLastRefresh",
- last_refresh_time.is_null()
- ? l10n_util::GetStringUTF16(IDS_POLICY_NEVER_FETCHED)
- : ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED,
- ui::TimeFormat::LENGTH_SHORT,
- base::Time::Now() - last_refresh_time));
+ dict->SetString("timeSinceLastRefresh",
+ GetTimeSinceLastRefreshString(last_refresh_time));
GetUserAffiliationStatus(dict, profile_);
}
@@ -729,6 +742,7 @@ void PolicyUIHandler::AddCommonLocalizedStringsToSource(
{"levelMandatory", IDS_POLICY_LEVEL_MANDATORY},
{"levelRecommended", IDS_POLICY_LEVEL_RECOMMENDED},
{"error", IDS_POLICY_LABEL_ERROR},
+ {"deprecated", IDS_POLICY_LABEL_DEPRECATED},
{"ignored", IDS_POLICY_LABEL_IGNORED},
{"notSpecified", IDS_POLICY_NOT_SPECIFIED},
{"ok", IDS_POLICY_OK},
@@ -806,6 +820,17 @@ void PolicyUIHandler::RegisterMessages() {
#endif // !defined(OS_ANDROID)
#endif // defined(OS_CHROMEOS)
+#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ base::PostTaskAndReplyWithResult(
+ base::ThreadPool::CreateCOMSTATaskRunner(
+ {base::TaskPriority::USER_BLOCKING,
+ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, base::MayBlock()})
+ .get(),
+ FROM_HERE, base::BindOnce(&GetGoogleUpdatePolicies),
+ base::BindOnce(&PolicyUIHandler::SetUpdaterPolicies,
+ weak_factory_.GetWeakPtr()));
+#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+
if (!user_status_provider_.get())
user_status_provider_ = std::make_unique<PolicyStatusProvider>();
if (!device_status_provider_.get())
@@ -874,7 +899,7 @@ void PolicyUIHandler::OnPolicyUpdated(const policy::PolicyNamespace& ns,
}
base::Value PolicyUIHandler::GetPolicyNames() const {
- base::DictionaryValue names;
+ base::Value names(base::Value::Type::DICTIONARY);
Profile* profile = Profile::FromWebUI(web_ui());
policy::SchemaRegistry* registry = profile->GetOriginalProfile()
->GetPolicySchemaRegistryService()
@@ -882,17 +907,26 @@ base::Value PolicyUIHandler::GetPolicyNames() const {
scoped_refptr<policy::SchemaMap> schema_map = registry->schema_map();
// Add Chrome policy names.
- auto chrome_policy_names = std::make_unique<base::ListValue>();
+ base::Value chrome_policy_names(base::Value::Type::LIST);
policy::PolicyNamespace chrome_ns(policy::POLICY_DOMAIN_CHROME, "");
const policy::Schema* chrome_schema = schema_map->GetSchema(chrome_ns);
for (auto it = chrome_schema->GetPropertiesIterator(); !it.IsAtEnd();
it.Advance()) {
- chrome_policy_names->Append(base::Value(it.key()));
+ chrome_policy_names.Append(base::Value(it.key()));
}
- auto chrome_values = std::make_unique<base::DictionaryValue>();
- chrome_values->SetString("name", "Chrome Policies");
- chrome_values->SetList("policyNames", std::move(chrome_policy_names));
- names.Set("chrome", std::move(chrome_values));
+ base::Value chrome_values(base::Value::Type::DICTIONARY);
+ chrome_values.SetStringKey("name", "Chrome Policies");
+ chrome_values.SetKey("policyNames", std::move(chrome_policy_names));
+ names.SetKey("chrome", std::move(chrome_values));
+
+#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ if (updater_policies_) {
+ base::Value updater_policies(base::Value::Type::DICTIONARY);
+ updater_policies.SetStringKey("name", "Google Update Policies");
+ updater_policies.SetKey("policyNames", GetGoogleUpdatePolicyNames());
+ names.SetKey("updater", std::move(updater_policies));
+ }
+#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
#if BUILDFLAG(ENABLE_EXTENSIONS)
// Add extension policy names.
@@ -904,19 +938,32 @@ base::Value PolicyUIHandler::GetPolicyNames() const {
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
- return std::move(names);
+ return names;
}
base::Value PolicyUIHandler::GetPolicyValues() const {
- return policy::ArrayPolicyConversions()
- .WithBrowserContext(web_ui()->GetWebContents()->GetBrowserContext())
+ auto client = std::make_unique<policy::ChromePolicyConversionsClient>(
+ web_ui()->GetWebContents()->GetBrowserContext());
+
+#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ if (updater_policies_) {
+ return policy::ArrayPolicyConversions(std::move(client))
+ .EnableConvertValues(true)
+ .WithUpdaterPolicies(updater_policies_->DeepCopy())
+ .WithUpdaterPolicySchemas(GetGoogleUpdatePolicySchemas())
+ .ToValue();
+ }
+#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+
+ return policy::ArrayPolicyConversions(std::move(client))
.EnableConvertValues(true)
.ToValue();
}
void PolicyUIHandler::AddExtensionPolicyNames(
- base::DictionaryValue* names,
+ base::Value* names,
policy::PolicyDomain policy_domain) const {
+ DCHECK(names->is_dict());
#if BUILDFLAG(ENABLE_EXTENSIONS)
#if defined(OS_CHROMEOS)
@@ -946,21 +993,21 @@ void PolicyUIHandler::AddExtensionPolicyNames(
extensions::manifest_keys::kStorageManagedSchema)) {
continue;
}
- auto extension_value = std::make_unique<base::DictionaryValue>();
- extension_value->SetString("name", extension->name());
+ base::Value extension_value(base::Value::Type::DICTIONARY);
+ extension_value.SetStringKey("name", extension->name());
const policy::Schema* schema = schema_map->GetSchema(
policy::PolicyNamespace(policy_domain, extension->id()));
- auto policy_names = std::make_unique<base::ListValue>();
+ base::Value policy_names(base::Value::Type::LIST);
if (schema && schema->valid()) {
// Get policy names from the extension's policy schema.
// Store in a map, not an array, for faster lookup on JS side.
for (auto prop = schema->GetPropertiesIterator(); !prop.IsAtEnd();
prop.Advance()) {
- policy_names->Append(base::Value(prop.key()));
+ policy_names.Append(base::Value(prop.key()));
}
}
- extension_value->Set("policyNames", std::move(policy_names));
- names->Set(extension->id(), std::move(extension_value));
+ extension_value.SetKey("policyNames", std::move(policy_names));
+ names->SetKey(extension->id(), std::move(extension_value));
}
#endif // BUILDFLAG(ENABLE_EXTENSIONS)
}
@@ -1011,13 +1058,9 @@ void PolicyUIHandler::HandleExportPoliciesJson(const base::ListValue* args) {
base::FilePath initial_path =
initial_dir.Append(FILE_PATH_LITERAL("policies.json"));
- // Here we overwrite the actual value of SelectFileDialog policy by passing a
- // nullptr to ui::SelectFileDialog::Create instead of the actual policy value.
- // This is done for the following reason: the admin might want to set this
- // policy for the user to forbid the select file dialogs, but this shouldn't
- // block the possibility to export the policies.
export_policies_select_file_dialog_ = ui::SelectFileDialog::Create(
- this, std::unique_ptr<ui::SelectFilePolicy>());
+ this,
+ std::make_unique<ChromeSelectFilePolicy>(web_ui()->GetWebContents()));
ui::SelectFileDialog::FileTypeInfo file_type_info;
file_type_info.extensions = {{FILE_PATH_LITERAL("json")}};
gfx::NativeWindow owning_window = webcontents->GetTopLevelNativeWindow();
@@ -1065,10 +1108,10 @@ void DoWritePoliciesToJSONFile(const base::FilePath& path,
void PolicyUIHandler::WritePoliciesToJSONFile(
const base::FilePath& path) const {
+ auto client = std::make_unique<policy::ChromePolicyConversionsClient>(
+ web_ui()->GetWebContents()->GetBrowserContext());
base::Value dict =
- policy::DictionaryPolicyConversions()
- .WithBrowserContext(web_ui()->GetWebContents()->GetBrowserContext())
- .ToValue();
+ policy::DictionaryPolicyConversions(std::move(client)).ToValue();
base::Value chrome_metadata(base::Value::Type::DICTIONARY);
@@ -1121,9 +1164,9 @@ void PolicyUIHandler::WritePoliciesToJSONFile(
base::JSONWriter::WriteWithOptions(
dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_policies);
- base::PostTask(
+ base::ThreadPool::PostTask(
FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
base::BindOnce(&DoWritePoliciesToJSONFile, path, json_policies));
}
@@ -1148,6 +1191,15 @@ void PolicyUIHandler::SendPolicies() {
FireWebUIListener("policies-updated", GetPolicyNames(), GetPolicyValues());
}
+#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+void PolicyUIHandler::SetUpdaterPolicies(
+ std::unique_ptr<policy::PolicyMap> updater_policies) {
+ updater_policies_ = std::move(updater_policies);
+ if (updater_policies_)
+ SendPolicies();
+}
+#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+
void PolicyUIHandler::OnRefreshPoliciesDone() {
SendPolicies();
SendStatus();
diff --git a/chromium/chrome/browser/ui/webui/policy_ui_handler.h b/chromium/chrome/browser/ui/webui/policy_ui_handler.h
index d803adef1e4..dcba4d6d7cb 100644
--- a/chromium/chrome/browser/ui/webui/policy_ui_handler.h
+++ b/chromium/chrome/browser/ui/webui/policy_ui_handler.h
@@ -14,6 +14,8 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/values.h"
+#include "build/branding_buildflags.h"
+#include "build/build_config.h"
#include "components/policy/core/browser/policy_error_map.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_namespace.h"
@@ -31,6 +33,10 @@
class PolicyStatusProvider;
+namespace policy {
+class PolicyMap;
+}
+
// The JavaScript message handler for the chrome://policy page.
class PolicyUIHandler : public content::WebUIMessageHandler,
#if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -77,7 +83,7 @@ class PolicyUIHandler : public content::WebUIMessageHandler,
base::Value GetPolicyNames() const;
base::Value GetPolicyValues() const;
- void AddExtensionPolicyNames(base::DictionaryValue* names,
+ void AddExtensionPolicyNames(base::Value* names,
policy::PolicyDomain policy_domain) const;
void HandleExportPoliciesJson(const base::ListValue* args);
@@ -89,6 +95,12 @@ class PolicyUIHandler : public content::WebUIMessageHandler,
// metadata is sent.
void SendPolicies();
+#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ // Sets |updater_policies_| in this instance and refreshes the UI via
+ // SendPolicies.
+ void SetUpdaterPolicies(std::unique_ptr<policy::PolicyMap> updater_policies);
+#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+
// Send the status of cloud policy to the UI. For each scope that has cloud
// policy enabled (device and/or user), a dictionary containing status
// information is sent.
@@ -111,6 +123,10 @@ class PolicyUIHandler : public content::WebUIMessageHandler,
std::unique_ptr<PolicyStatusProvider> device_status_provider_;
std::unique_ptr<PolicyStatusProvider> machine_status_provider_;
+#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ std::unique_ptr<policy::PolicyMap> updater_policies_;
+#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+
base::WeakPtrFactory<PolicyUIHandler> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PolicyUIHandler);
diff --git a/chromium/chrome/browser/ui/webui/predictors/predictors_handler.cc b/chromium/chrome/browser/ui/webui/predictors/predictors_handler.cc
index 50387cd2635..366c9e40cb3 100644
--- a/chromium/chrome/browser/ui/webui/predictors/predictors_handler.cc
+++ b/chromium/chrome/browser/ui/webui/predictors/predictors_handler.cc
@@ -17,7 +17,6 @@
#include "chrome/browser/predictors/resource_prefetch_predictor_tables.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/web_ui.h"
-#include "content/public/common/resource_type.h"
using predictors::AutocompleteActionPredictor;
using predictors::ResourcePrefetchPredictor;
@@ -91,7 +90,7 @@ void PredictorsHandler::RequestResourcePrefetchPredictorDb(
// Origin table cache.
auto db = std::make_unique<base::ListValue>();
AddOriginDataMapToListValue(
- *resource_prefetch_predictor->origin_data_->data_cache_, db.get());
+ resource_prefetch_predictor->origin_data_->GetAllCached(), db.get());
dict.Set("origin_db", std::move(db));
}
}
diff --git a/chromium/chrome/browser/ui/webui/predictors/predictors_ui.cc b/chromium/chrome/browser/ui/webui/predictors/predictors_ui.cc
index 5decbb83c29..ba374623271 100644
--- a/chromium/chrome/browser/ui/webui/predictors/predictors_ui.cc
+++ b/chromium/chrome/browser/ui/webui/predictors/predictors_ui.cc
@@ -9,7 +9,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/predictors/predictors_handler.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
diff --git a/chromium/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
index f1efaf51d10..1eef8757773 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -594,12 +594,10 @@ TEST_F(ExtensionPrinterHandlerTest, GetUsbPrinters) {
fake_usb_manager_.CreateAndAddDevice(0, 1, "Google", "USB Printer", "");
base::RunLoop().RunUntilIdle();
- const Extension* extension_1 =
- env_.MakeExtension(*base::test::ParseJsonDeprecated(kExtension1),
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
- const Extension* extension_2 =
- env_.MakeExtension(*base::test::ParseJsonDeprecated(kExtension2),
- "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
+ const Extension* extension_1 = env_.MakeExtension(
+ base::test::ParseJson(kExtension1), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+ const Extension* extension_2 = env_.MakeExtension(
+ base::test::ParseJson(kExtension2), "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
extensions::DevicePermissionsManager* permissions_manager =
extensions::DevicePermissionsManager::Get(env_.profile());
diff --git a/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc b/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc
new file mode 100644
index 00000000000..5c9d71fd8e0
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc
@@ -0,0 +1,50 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/print_preview/fake_print_render_frame.h"
+
+#include <utility>
+
+#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
+
+namespace printing {
+
+FakePrintRenderFrame::FakePrintRenderFrame(
+ blink::AssociatedInterfaceProvider* provider) {
+ provider->OverrideBinderForTesting(
+ mojom::PrintRenderFrame::Name_,
+ base::BindRepeating(&FakePrintRenderFrame::BindPrintRenderFrameReceiver,
+ base::Unretained(this)));
+}
+
+FakePrintRenderFrame::~FakePrintRenderFrame() = default;
+
+void FakePrintRenderFrame::PrintRequestedPages() {}
+
+void FakePrintRenderFrame::PrintForSystemDialog() {}
+
+void FakePrintRenderFrame::InitiatePrintPreview(
+ mojo::PendingAssociatedRemote<mojom::PrintRenderer> print_renderer,
+ bool has_selection) {}
+
+void FakePrintRenderFrame::PrintPreview(base::Value settings) {}
+
+void FakePrintRenderFrame::OnPrintPreviewDialogClosed() {}
+
+void FakePrintRenderFrame::PrintFrameContent(
+ mojom::PrintFrameContentParamsPtr params) {}
+
+void FakePrintRenderFrame::PrintingDone(bool success) {}
+
+void FakePrintRenderFrame::SetPrintingEnabled(bool enabled) {}
+
+void FakePrintRenderFrame::PrintNodeUnderContextMenu() {}
+
+void FakePrintRenderFrame::BindPrintRenderFrameReceiver(
+ mojo::ScopedInterfaceEndpointHandle handle) {
+ receiver_.Bind(mojo::PendingAssociatedReceiver<mojom::PrintRenderFrame>(
+ std::move(handle)));
+}
+
+} // namespace printing
diff --git a/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h b/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h
new file mode 100644
index 00000000000..fb66df20dd6
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h
@@ -0,0 +1,46 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_FAKE_PRINT_RENDER_FRAME_H_
+#define CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_FAKE_PRINT_RENDER_FRAME_H_
+
+#include "base/values.h"
+#include "components/printing/common/print.mojom.h"
+#include "mojo/public/cpp/bindings/associated_receiver.h"
+#include "mojo/public/cpp/bindings/pending_associated_remote.h"
+#include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+
+namespace printing {
+
+// This class implements a PrintRenderFrame that can be attached to an
+// AssociatedInterfaceProvider to intercept requests from the browser for unit
+// tests.
+class FakePrintRenderFrame : public mojom::PrintRenderFrame {
+ public:
+ explicit FakePrintRenderFrame(blink::AssociatedInterfaceProvider* provider);
+ ~FakePrintRenderFrame() override;
+
+ private:
+ // printing::mojom::PrintRenderFrame:
+ void PrintRequestedPages() override;
+ void PrintForSystemDialog() override;
+ void InitiatePrintPreview(
+ mojo::PendingAssociatedRemote<mojom::PrintRenderer> print_renderer,
+ bool has_selection) override;
+ void PrintPreview(base::Value settings) override;
+ void OnPrintPreviewDialogClosed() override;
+ void PrintFrameContent(mojom::PrintFrameContentParamsPtr params) override;
+ void PrintingDone(bool success) override;
+ void SetPrintingEnabled(bool enabled) override;
+ void PrintNodeUnderContextMenu() override;
+
+ void BindPrintRenderFrameReceiver(mojo::ScopedInterfaceEndpointHandle handle);
+
+ mojo::AssociatedReceiver<mojom::PrintRenderFrame> receiver_{this};
+};
+
+} // namespace printing
+
+#endif // CHROME_BROWSER_UI_WEBUI_PRINT_PREVIEW_FAKE_PRINT_RENDER_FRAME_H_
diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
index 1fc3dec3ee6..7fa87252fc3 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -12,8 +12,9 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/printing/cups_print_job_manager.h"
@@ -26,7 +27,6 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_utils.h"
#include "chrome/common/pref_names.h"
-#include "chrome/common/webui_url_constants.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
#include "chromeos/printing/printer_configuration.h"
@@ -56,8 +56,6 @@ PrinterBasicInfo ToBasicInfo(const chromeos::Printer& printer) {
basic_info.options[kCUPSEnterprisePrinter] =
(printer.source() == chromeos::Printer::SRC_POLICY) ? kValueTrue
: kValueFalse;
- // TODO(1023589): Get the printer's EULA url from the printer object.
- basic_info.options[kPrinterEulaURL] = "";
basic_info.printer_name = printer.id();
basic_info.display_name = printer.display_name();
basic_info.printer_description = printer.description();
@@ -73,9 +71,9 @@ void AddPrintersToList(const std::vector<chromeos::Printer>& printers,
base::Value FetchCapabilitiesAsync(const std::string& device_name,
const PrinterBasicInfo& basic_info,
- bool has_secure_protocol) {
- auto print_backend = PrintBackend::CreateInstance(
- nullptr, g_browser_process->GetApplicationLocale());
+ bool has_secure_protocol,
+ const std::string& locale) {
+ auto print_backend = PrintBackend::CreateInstance(nullptr, locale);
return GetSettingsOnBlockingTaskRunner(
device_name, basic_info, PrinterSemanticCapsAndDefaults::Papers(),
has_secure_protocol, print_backend);
@@ -94,15 +92,13 @@ void FetchCapabilities(const chromeos::Printer& printer,
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
PrinterBasicInfo basic_info = ToBasicInfo(printer);
- bool has_secure_protocol = !printer.HasNetworkProtocol() ||
- printer.GetProtocol() == chromeos::Printer::kIpps;
// USER_VISIBLE because the result is displayed in the print preview dialog.
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&FetchCapabilitiesAsync, printer.id(), basic_info,
- has_secure_protocol),
+ printer.HasSecureProtocol(),
+ g_browser_process->GetApplicationLocale()),
base::BindOnce(&CapabilitiesFetched, std::move(policies), std::move(cb)));
}
@@ -206,9 +202,9 @@ void LocalPrinterHandlerChromeos::StartGetCapability(
}
// Log printer configuration for selected printer.
- UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.ProtocolUsed",
- printer->GetProtocol(),
- chromeos::Printer::kProtocolMax);
+ base::UmaHistogramEnumeration("Printing.CUPS.ProtocolUsed",
+ printer->GetProtocol(),
+ chromeos::Printer::kProtocolMax);
if (printers_manager_->IsPrinterInstalled(*printer)) {
// Skip setup if the printer does not need to be installed.
@@ -268,7 +264,7 @@ void LocalPrinterHandlerChromeos::OnResolvedEulaUrl(
return;
}
- GURL eula_url(chrome::kChromeUIOSCreditsURL + license);
+ GURL eula_url = chromeos::PrinterConfigurer::GeneratePrinterEulaUrl(license);
std::move(cb).Run(eula_url.spec());
}
@@ -330,7 +326,7 @@ void LocalPrinterHandlerChromeos::StartPrint(
scoped_refptr<base::RefCountedMemory> print_data,
PrintCallback callback) {
size_t size_in_kb = print_data->size() / 1024;
- UMA_HISTOGRAM_MEMORY_KB("Printing.CUPS.PrintDocumentSize", size_in_kb);
+ base::UmaHistogramMemoryKB("Printing.CUPS.PrintDocumentSize", size_in_kb);
if (profile_->GetPrefs()->GetBoolean(
prefs::kPrintingSendUsernameAndFilenameEnabled)) {
std::string username = chromeos::ProfileHelper::Get()
diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc
index b31f4f35078..7ee3667f587 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos_unittest.cc
@@ -200,8 +200,7 @@ TEST_F(LocalPrinterHandlerChromeosTest, GetPrinters) {
"printerDescription": "description1",
"printerName": "saved",
"printerOptions": {
- "cupsEnterprisePrinter": "false",
- "printerEulaUrl": ""
+ "cupsEnterprisePrinter": "false"
}
},
{
@@ -210,8 +209,7 @@ TEST_F(LocalPrinterHandlerChromeosTest, GetPrinters) {
"printerDescription": "description2",
"printerName": "enterprise",
"printerOptions": {
- "cupsEnterprisePrinter": "true",
- "printerEulaUrl": ""
+ "cupsEnterprisePrinter": "true"
}
},
{
@@ -220,8 +218,7 @@ TEST_F(LocalPrinterHandlerChromeosTest, GetPrinters) {
"printerDescription": "description3",
"printerName": "automatic",
"printerOptions": {
- "cupsEnterprisePrinter": "false",
- "printerEulaUrl": ""
+ "cupsEnterprisePrinter": "false"
}
}
]
@@ -346,7 +343,7 @@ TEST_F(LocalPrinterHandlerChromeosTest, StartFetchValidEulaUrl) {
task_environment_.RunUntilIdle();
- EXPECT_EQ(fetched_eula_url, "chrome://os-credits/expected_make_model");
+ EXPECT_EQ(fetched_eula_url, "chrome://os-credits/#expected_make_model");
}
// Test that a printer with no PPD license will return an empty string.
diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
index f6b6ad0e54d..876b308dfd0 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc
@@ -11,7 +11,8 @@
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
@@ -32,42 +33,43 @@ namespace {
scoped_refptr<base::TaskRunner> CreatePrinterHandlerTaskRunner() {
// USER_VISIBLE because the result is displayed in the print preview dialog.
static constexpr base::TaskTraits kTraits = {
- base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE};
+ base::MayBlock(), base::TaskPriority::USER_VISIBLE};
#if defined(USE_CUPS)
// CUPS is thread safe.
- return base::CreateTaskRunner(kTraits);
+ return base::ThreadPool::CreateTaskRunner(kTraits);
#elif defined(OS_WIN)
// Windows drivers are likely not thread-safe.
- return base::CreateSingleThreadTaskRunner(kTraits);
+ return base::ThreadPool::CreateSingleThreadTaskRunner(kTraits);
#else
// Be conservative on unsupported platforms.
- return base::CreateSingleThreadTaskRunner(kTraits);
+ return base::ThreadPool::CreateSingleThreadTaskRunner(kTraits);
#endif
}
-PrinterList EnumeratePrintersAsync() {
+PrinterList EnumeratePrintersAsync(const std::string& locale) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
- scoped_refptr<PrintBackend> print_backend(PrintBackend::CreateInstance(
- nullptr, g_browser_process->GetApplicationLocale()));
+ scoped_refptr<PrintBackend> print_backend(
+ PrintBackend::CreateInstance(nullptr, locale));
PrinterList printer_list;
print_backend->EnumeratePrinters(&printer_list);
return printer_list;
}
-base::Value FetchCapabilitiesAsync(const std::string& device_name) {
- PrinterSemanticCapsAndDefaults::Papers additional_papers;
+base::Value FetchCapabilitiesAsync(const std::string& device_name,
+ const std::string& locale) {
+ PrinterSemanticCapsAndDefaults::Papers user_defined_papers;
#if defined(OS_MACOSX)
if (base::FeatureList::IsEnabled(features::kEnableCustomMacPaperSizes))
- additional_papers = GetMacCustomPaperSizes();
+ user_defined_papers = GetMacCustomPaperSizes();
#endif
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
- scoped_refptr<PrintBackend> print_backend(PrintBackend::CreateInstance(
- nullptr, g_browser_process->GetApplicationLocale()));
+ scoped_refptr<PrintBackend> print_backend(
+ PrintBackend::CreateInstance(nullptr, locale));
VLOG(1) << "Get printer capabilities start for " << device_name;
@@ -78,15 +80,15 @@ base::Value FetchCapabilitiesAsync(const std::string& device_name) {
}
return GetSettingsOnBlockingTaskRunner(
- device_name, basic_info, additional_papers,
- /* has_secure_protocol */ false, print_backend);
+ device_name, basic_info, std::move(user_defined_papers),
+ /*has_secure_protocol=*/false, print_backend);
}
-std::string GetDefaultPrinterAsync() {
+std::string GetDefaultPrinterAsync(const std::string& locale) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
- scoped_refptr<PrintBackend> print_backend(PrintBackend::CreateInstance(
- nullptr, g_browser_process->GetApplicationLocale()));
+ scoped_refptr<PrintBackend> print_backend(
+ PrintBackend::CreateInstance(nullptr, locale));
std::string default_printer = print_backend->GetDefaultPrinterName();
VLOG(1) << "Default Printer: " << default_printer;
@@ -107,9 +109,11 @@ void LocalPrinterHandlerDefault::Reset() {}
void LocalPrinterHandlerDefault::GetDefaultPrinter(DefaultPrinterCallback cb) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- base::PostTaskAndReplyWithResult(task_runner_.get(), FROM_HERE,
- base::BindOnce(&GetDefaultPrinterAsync),
- std::move(cb));
+ base::PostTaskAndReplyWithResult(
+ task_runner_.get(), FROM_HERE,
+ base::BindOnce(&GetDefaultPrinterAsync,
+ g_browser_process->GetApplicationLocale()),
+ std::move(cb));
}
void LocalPrinterHandlerDefault::StartGetPrinters(
@@ -119,7 +123,9 @@ void LocalPrinterHandlerDefault::StartGetPrinters(
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
base::PostTaskAndReplyWithResult(
- task_runner_.get(), FROM_HERE, base::BindOnce(&EnumeratePrintersAsync),
+ task_runner_.get(), FROM_HERE,
+ base::BindOnce(&EnumeratePrintersAsync,
+ g_browser_process->GetApplicationLocale()),
base::BindOnce(&ConvertPrinterListForCallback, std::move(callback),
std::move(done_callback)));
}
@@ -131,7 +137,9 @@ void LocalPrinterHandlerDefault::StartGetCapability(
base::PostTaskAndReplyWithResult(
task_runner_.get(), FROM_HERE,
- base::BindOnce(&FetchCapabilitiesAsync, device_name), std::move(cb));
+ base::BindOnce(&FetchCapabilitiesAsync, device_name,
+ g_browser_process->GetApplicationLocale()),
+ std::move(cb));
}
void LocalPrinterHandlerDefault::StartPrint(
diff --git a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
index c87e8694d1f..394ce8f6601 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/pdf_printer_handler.cc
@@ -17,6 +17,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/app_mode/app_mode_utils.h"
@@ -199,10 +200,8 @@ void PdfPrinterHandler::StartGetCapability(const std::string& destination_id,
if (base::FeatureList::IsEnabled(features::kEnableCustomMacPaperSizes)) {
// Read the Mac custom paper sizes on a separate thread.
// USER_VISIBLE because the result is displayed in the print preview dialog.
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(),
- base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&GetMacCustomPaperSizes),
base::BindOnce(&ConstructCapabilitiesAndCompleteCallback,
destination_id, std::move(callback)));
@@ -360,9 +359,8 @@ void PdfPrinterHandler::SelectFile(const base::FilePath& default_filename,
// Handle the no prompting case. Like the dialog prompt, this function
// returns and eventually FileSelected() gets called.
if (!prompt_user) {
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&base::GetUniquePath, path.Append(default_filename)),
base::BindOnce(&PdfPrinterHandler::OnGotUniqueFileName,
weak_ptr_factory_.GetWeakPtr()));
@@ -379,18 +377,16 @@ void PdfPrinterHandler::SelectFile(const base::FilePath& default_filename,
// Get default download directory. This will be used as a fallback if the
// save directory does not exist.
base::FilePath default_path = download_prefs->DownloadPath();
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&SelectSaveDirectory, path, default_path),
base::BindOnce(&PdfPrinterHandler::OnDirectorySelected,
weak_ptr_factory_.GetWeakPtr(), default_filename));
}
void PdfPrinterHandler::PostPrintToPdfTask() {
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&PrintToPdfCallback, print_data_, print_to_pdf_path_,
std::move(pdf_file_saved_closure_)));
print_to_pdf_path_.clear();
diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 9d9c689a4b9..113d34201f9 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -16,12 +16,14 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
+#include "base/containers/flat_set.h"
#include "base/feature_list.h"
#include "base/i18n/number_formatting.h"
#include "base/json/json_reader.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -60,7 +62,6 @@
#include "components/prefs/pref_service.h"
#include "components/printing/browser/printer_capabilities.h"
#include "components/printing/common/cloud_print_cdd_conversion.h"
-#include "components/printing/common/print_messages.h"
#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h"
#include "components/url_formatter/url_formatter.h"
@@ -75,16 +76,17 @@
#include "printing/backend/print_backend_consts.h"
#include "printing/buildflags/buildflags.h"
#include "printing/print_settings.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/icu/source/i18n/unicode/ulocdata.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/account_manager/account_manager_util.h"
-#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
-#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
+#include "chrome/browser/device_identity/device_oauth2_token_service.h"
+#include "chrome/browser/device_identity/device_oauth2_token_service_factory.h"
#include "chrome/browser/ui/settings_window_manager_chromeos.h"
#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h"
#include "chromeos/printing/printer_configuration.h"
-#include "services/identity/public/cpp/scope_set.h"
+#include "components/signin/public/identity_manager/scope_set.h"
#endif
using content::RenderFrameHost;
@@ -170,16 +172,16 @@ void ReportPrintSettingHistogram(PrintSettingsBuckets setting) {
void ReportPrintDocumentTypeAndSizeHistograms(PrintDocumentTypeBuckets doctype,
size_t average_page_size_in_kb) {
- UMA_HISTOGRAM_ENUMERATION("PrintPreview.PrintDocumentType", doctype,
- PRINT_DOCUMENT_TYPE_BUCKET_BOUNDARY);
+ base::UmaHistogramEnumeration("PrintPreview.PrintDocumentType", doctype,
+ PRINT_DOCUMENT_TYPE_BUCKET_BOUNDARY);
switch (doctype) {
case HTML_DOCUMENT:
- UMA_HISTOGRAM_MEMORY_KB("PrintPreview.PrintDocumentSize.HTML",
- average_page_size_in_kb);
+ base::UmaHistogramMemoryKB("PrintPreview.PrintDocumentSize.HTML",
+ average_page_size_in_kb);
break;
case PDF_DOCUMENT:
- UMA_HISTOGRAM_MEMORY_KB("PrintPreview.PrintDocumentSize.PDF",
- average_page_size_in_kb);
+ base::UmaHistogramMemoryKB("PrintPreview.PrintDocumentSize.PDF",
+ average_page_size_in_kb);
break;
default:
NOTREACHED();
@@ -339,9 +341,24 @@ void ReportPrintSettingsStats(const base::Value& print_settings,
ReportPrintSettingHistogram(duplex_mode_opt.value() ? DUPLEX : SIMPLEX);
base::Optional<int> color_mode_opt = print_settings.FindIntKey(kSettingColor);
- if (color_mode_opt) {
- ReportPrintSettingHistogram(
- IsColorModelSelected(color_mode_opt.value()) ? COLOR : BLACK_AND_WHITE);
+ if (color_mode_opt.has_value()) {
+ bool unknown_color_model = color_mode_opt.value() == UNKNOWN_COLOR_MODEL;
+ if (!unknown_color_model) {
+ base::Optional<bool> is_color =
+ IsColorModelSelected(color_mode_opt.value());
+ ReportPrintSettingHistogram(is_color.value() ? COLOR : BLACK_AND_WHITE);
+ }
+
+ // Record whether the printing backend does not understand the printer's
+ // color capabilities. Do this only once per device.
+ static base::NoDestructor<base::flat_set<std::string>> seen_devices;
+ auto result =
+ seen_devices->insert(*print_settings.FindStringKey(kSettingDeviceName));
+ bool is_new_device = result.second;
+ if (is_new_device) {
+ base::UmaHistogramBoolean("Printing.CUPS.UnknownPpdColorModel",
+ unknown_color_model);
+ }
}
if (preview_settings.FindIntKey(kSettingMarginsType).value_or(0) != 0)
@@ -470,15 +487,12 @@ class PrintPreviewHandler::AccessTokenService
void RequestToken(base::OnceCallback<void(const std::string&)> callback) {
// There can only be one pending request at a time. See
// cloud_print_interface_js.js.
- const identity::ScopeSet scopes{cloud_devices::kCloudPrintAuthScope};
+ const signin::ScopeSet scopes{cloud_devices::kCloudPrintAuthScope};
DCHECK(!device_request_callback_);
- chromeos::DeviceOAuth2TokenService* token_service =
- chromeos::DeviceOAuth2TokenServiceFactory::Get();
- CoreAccountId account_id = token_service->GetRobotAccountId();
-
- device_request_ =
- token_service->StartAccessTokenRequest(account_id, scopes, this);
+ DeviceOAuth2TokenService* token_service =
+ DeviceOAuth2TokenServiceFactory::Get();
+ device_request_ = token_service->StartAccessTokenRequest(scopes, this);
device_request_callback_ = std::move(callback);
}
@@ -518,8 +532,8 @@ PrintPreviewHandler::PrintPreviewHandler()
}
PrintPreviewHandler::~PrintPreviewHandler() {
- UMA_HISTOGRAM_COUNTS_1M("PrintPreview.ManagePrinters",
- manage_printers_dialog_request_count_);
+ base::UmaHistogramCounts1M("PrintPreview.ManagePrinters",
+ manage_printers_dialog_request_count_);
UnregisterForGaiaCookieChanges();
}
@@ -821,16 +835,19 @@ void PrintPreviewHandler::HandleGetPreview(const base::ListValue* args) {
VLOG(1) << "Print preview request start";
- rfh->Send(new PrintMsg_PrintPreview(
- rfh->GetRoutingID(), static_cast<base::DictionaryValue&>(settings)));
+ if (!print_render_frame_.is_bound())
+ rfh->GetRemoteAssociatedInterfaces()->GetInterface(&print_render_frame_);
+
+ print_render_frame_->PrintPreview(settings.Clone());
last_preview_settings_ = std::move(settings);
}
void PrintPreviewHandler::HandlePrint(const base::ListValue* args) {
// Record the number of times the user requests to regenerate preview data
// before printing.
- UMA_HISTOGRAM_COUNTS_1M("PrintPreview.RegeneratePreviewRequest.BeforePrint",
- regenerate_preview_request_count_);
+ base::UmaHistogramCounts1M(
+ "PrintPreview.RegeneratePreviewRequest.BeforePrint",
+ regenerate_preview_request_count_);
std::string callback_id;
CHECK(args->GetString(0, &callback_id));
CHECK(!callback_id.empty());
@@ -1010,8 +1027,9 @@ void PrintPreviewHandler::HandleClosePreviewDialog(
// Record the number of times the user requests to regenerate preview data
// before cancelling.
- UMA_HISTOGRAM_COUNTS_1M("PrintPreview.RegeneratePreviewRequest.BeforeCancel",
- regenerate_preview_request_count_);
+ base::UmaHistogramCounts1M(
+ "PrintPreview.RegeneratePreviewRequest.BeforeCancel",
+ regenerate_preview_request_count_);
}
#if defined(OS_CHROMEOS)
@@ -1257,7 +1275,7 @@ void PrintPreviewHandler::OnAccountsInCookieUpdated(
base::Value account_list(base::Value::Type::LIST);
const std::vector<gaia::ListedAccount>& accounts =
accounts_in_cookie_jar_info.signed_in_accounts;
- for (const auto account : accounts) {
+ for (const auto& account : accounts) {
account_list.Append(account.email);
}
FireWebUIListener("user-accounts-updated", std::move(account_list));
diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h
index 4c5948ae70a..ab2dcacf9f9 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h
+++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -18,8 +18,10 @@
#include "base/timer/timer.h"
#include "chrome/common/buildflags.h"
#include "components/prefs/pref_service.h"
+#include "components/printing/common/print.mojom.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "content/public/browser/web_ui_message_handler.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
#include "printing/backend/print_backend.h"
#include "printing/buildflags/buildflags.h"
#include "printing/print_job_constants.h"
@@ -367,6 +369,9 @@ class PrintPreviewHandler : public content::WebUIMessageHandler,
// Set of printer types on the deny list.
base::flat_set<PrinterType> printer_type_deny_list_;
+ // Used to transmit mojo interface method calls to the associated receiver.
+ mojo::AssociatedRemote<mojom::PrintRenderFrame> print_render_frame_;
+
base::WeakPtrFactory<PrintPreviewHandler> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(PrintPreviewHandler);
diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
index 4e58527fc57..286ec9b139c 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
@@ -15,6 +15,7 @@
#include "base/json/json_writer.h"
#include "base/memory/ref_counted_memory.h"
#include "base/optional.h"
+#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
@@ -22,6 +23,7 @@
#include "base/values.h"
#include "chrome/browser/printing/print_test_utils.h"
#include "chrome/browser/printing/print_view_manager.h"
+#include "chrome/browser/ui/webui/print_preview/fake_print_render_frame.h"
#include "chrome/browser/ui/webui/print_preview/policy_settings.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#include "chrome/browser/ui/webui/print_preview/printer_handler.h"
@@ -29,16 +31,13 @@
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/prefs/pref_service.h"
-#include "components/printing/common/print_messages.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/test_web_ui.h"
-#include "ipc/ipc_test_sink.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace printing {
@@ -208,6 +207,31 @@ class FakePrintPreviewUI : public PrintPreviewUI {
DISALLOW_COPY_AND_ASSIGN(FakePrintPreviewUI);
};
+class TestPrintPreviewPrintRenderFrame : public FakePrintRenderFrame {
+ public:
+ explicit TestPrintPreviewPrintRenderFrame(
+ blink::AssociatedInterfaceProvider* provider)
+ : FakePrintRenderFrame(provider) {}
+
+ ~TestPrintPreviewPrintRenderFrame() final = default;
+
+ const base::Value& GetSettings() { return settings_; }
+
+ void SetCompletionClosure(base::OnceClosure closure) {
+ closure_ = std::move(closure);
+ }
+
+ private:
+ // FakePrintRenderFrame:
+ void PrintPreview(base::Value settings) final {
+ settings_ = std::move(settings);
+ std::move(closure_).Run();
+ }
+
+ base::OnceClosure closure_;
+ base::Value settings_;
+};
+
class TestPrintPreviewHandler : public PrintPreviewHandler {
public:
TestPrintPreviewHandler(std::unique_ptr<PrinterHandler> printer_handler,
@@ -314,12 +338,12 @@ class PrintPreviewHandlerTest : public testing::Test {
// locale code sync up correctly.
browser_process->SetApplicationLocale(locale);
base::test::ScopedRestoreICUDefaultLocale scoped_locale(locale);
- base::testing::ResetFormatters();
+ base::ResetFormattersForTesting();
handler()->HandleGetInitialSettings(list_args.get());
}
// Reset again now that |scoped_locale| has been destroyed.
browser_process->SetApplicationLocale(original_locale);
- base::testing::ResetFormatters();
+ base::ResetFormattersForTesting();
// In response to get initial settings, the initial settings are sent back.
ASSERT_EQ(1u, web_ui()->call_data().size());
@@ -502,28 +526,10 @@ class PrintPreviewHandlerTest : public testing::Test {
}
}
- IPC::TestSink& initiator_sink() {
- content::RenderFrameHost* rfh = initiator_web_contents_->GetMainFrame();
- auto* rph = static_cast<content::MockRenderProcessHost*>(rfh->GetProcess());
- return rph->sink();
- }
-
- IPC::TestSink& preview_sink() {
- content::RenderFrameHost* rfh = preview_web_contents_->GetMainFrame();
- auto* rph = static_cast<content::MockRenderProcessHost*>(rfh->GetProcess());
- return rph->sink();
- }
-
- base::DictionaryValue VerifyPreviewMessage() {
- // Verify that the preview was requested from the renderer
- EXPECT_TRUE(
- initiator_sink().GetUniqueMessageMatching(PrintMsg_PrintPreview::ID));
- const IPC::Message* msg =
- initiator_sink().GetFirstMessageMatching(PrintMsg_PrintPreview::ID);
- EXPECT_TRUE(msg);
- PrintMsg_PrintPreview::Param param;
- PrintMsg_PrintPreview::Read(msg, &param);
- return std::move(std::get<0>(param));
+ blink::AssociatedInterfaceProvider*
+ GetInitiatorAssociatedInterfaceProvider() {
+ return initiator_web_contents_->GetMainFrame()
+ ->GetRemoteAssociatedInterfaces();
}
const Profile* profile() { return profile_.get(); }
@@ -837,14 +843,20 @@ TEST_F(PrintPreviewHandlerTest, Print) {
TEST_F(PrintPreviewHandlerTest, GetPreview) {
Initialize();
+ base::RunLoop run_loop;
+ TestPrintPreviewPrintRenderFrame print_render_frame(
+ GetInitiatorAssociatedInterfaceProvider());
+ print_render_frame.SetCompletionClosure(run_loop.QuitClosure());
+
base::Value print_ticket = GetPrintPreviewTicket();
std::unique_ptr<base::ListValue> list_args =
ConstructPreviewArgs("test-callback-id-1", print_ticket);
handler()->HandleGetPreview(list_args.get());
+ run_loop.Run();
// Verify that the preview was requested from the renderer with the
// appropriate settings.
- base::DictionaryValue preview_params = VerifyPreviewMessage();
+ const base::Value& preview_params = print_render_frame.GetSettings();
bool preview_id_found = false;
for (const auto& it : preview_params.DictItems()) {
if (it.first == kPreviewUIID) { // This is added by the handler.
@@ -861,12 +873,18 @@ TEST_F(PrintPreviewHandlerTest, GetPreview) {
TEST_F(PrintPreviewHandlerTest, SendPreviewUpdates) {
Initialize();
+ base::RunLoop run_loop;
+ TestPrintPreviewPrintRenderFrame print_render_frame(
+ GetInitiatorAssociatedInterfaceProvider());
+ print_render_frame.SetCompletionClosure(run_loop.QuitClosure());
+
const char callback_id_in[] = "test-callback-id-1";
base::Value print_ticket = GetPrintPreviewTicket();
std::unique_ptr<base::ListValue> list_args =
ConstructPreviewArgs(callback_id_in, print_ticket);
handler()->HandleGetPreview(list_args.get());
- base::DictionaryValue preview_params = VerifyPreviewMessage();
+ run_loop.Run();
+ const base::Value& preview_params = print_render_frame.GetSettings();
// Read the preview UI ID and request ID
base::Optional<int> request_value =
diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index 19dba387e24..cf3c71f478d 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -15,7 +15,7 @@
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
-#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_functions.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -44,7 +44,6 @@
#include "chrome/grit/print_preview_resources.h"
#include "chrome/grit/print_preview_resources_map.h"
#include "components/prefs/pref_service.h"
-#include "components/printing/browser/print_manager_utils.h"
#include "components/printing/common/print_messages.h"
#include "components/strings/grit/components_strings.h"
#include "components/user_manager/user_manager.h"
@@ -56,6 +55,7 @@
#include "printing/print_job_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_features.h"
+#include "ui/base/webui/web_ui_util.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/web_dialogs/web_dialog_delegate.h"
#include "ui/web_dialogs/web_dialog_ui.h"
@@ -254,8 +254,6 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) {
{"printPagesLabel", IDS_PRINT_PREVIEW_PRINT_PAGES_LABEL},
{"printPreviewPageLabelPlural", IDS_PRINT_PREVIEW_PAGE_LABEL_PLURAL},
{"printPreviewPageLabelSingular", IDS_PRINT_PREVIEW_PAGE_LABEL_SINGULAR},
- {"printPreviewNewSummaryFormatShort",
- IDS_PRINT_PREVIEW_NEW_SUMMARY_FORMAT_SHORT},
{"printPreviewSheetsLabelPlural", IDS_PRINT_PREVIEW_SHEETS_LABEL_PLURAL},
{"printPreviewSheetsLabelSingular",
IDS_PRINT_PREVIEW_SHEETS_LABEL_SINGULAR},
@@ -280,6 +278,8 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) {
{"scalingInstruction", IDS_PRINT_PREVIEW_SCALING_INSTRUCTION},
{"scalingLabel", IDS_PRINT_PREVIEW_SCALING_LABEL},
{"searchBoxPlaceholder", IDS_PRINT_PREVIEW_SEARCH_BOX_PLACEHOLDER},
+ {"searchResultBubbleText", IDS_SEARCH_RESULT_BUBBLE_TEXT},
+ {"searchResultsBubbleText", IDS_SEARCH_RESULTS_BUBBLE_TEXT},
{"selectButton", IDS_PRINT_PREVIEW_BUTTON_SELECT},
{"seeMore", IDS_PRINT_PREVIEW_SEE_MORE},
{"seeMoreDestinationsLabel", IDS_PRINT_PREVIEW_SEE_MORE_DESTINATIONS_LABEL},
@@ -343,6 +343,7 @@ void SetupPrintPreviewPlugin(content::WebUIDataSource* source) {
int id;
} kPdfResources[] = {
{"pdf/browser_api.js", IDR_PDF_BROWSER_API_JS},
+ {"pdf/constants.js", IDR_PDF_CONSTANTS_JS},
{"pdf/controller.js", IDR_PDF_CONTROLLER_JS},
{"pdf/elements/icons.js", IDR_PDF_ICONS_JS},
{"pdf/elements/shared-vars.js", IDR_PDF_SHARED_VARS_JS},
@@ -371,7 +372,6 @@ void SetupPrintPreviewPlugin(content::WebUIDataSource* source) {
{"pdf/metrics.js", IDR_PDF_METRICS_JS},
{"pdf/navigator.js", IDR_PDF_NAVIGATOR_JS},
{"pdf/open_pdf_params_parser.js", IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS},
- {"pdf/pdf_fitting_type.js", IDR_PDF_PDF_FITTING_TYPE_JS},
{"pdf/pdf_scripting_api.js", IDR_PDF_PDF_SCRIPTING_API_JS},
{"pdf/pdf_viewer.js", IDR_PDF_PDF_VIEWER_JS},
{"pdf/toolbar_manager.js", IDR_PDF_TOOLBAR_MANAGER_JS},
@@ -508,10 +508,6 @@ void PrintPreviewUI::SetInitiatorTitle(
initiator_title_ = job_title;
}
-bool PrintPreviewUI::ShouldCompositeDocumentUsingIndividualPages() const {
- return printing::IsOopifEnabled() && source_is_modifiable_;
-}
-
bool PrintPreviewUI::LastPageComposited(int page_number) const {
if (pages_to_render_.empty())
return false;
@@ -596,8 +592,9 @@ void PrintPreviewUI::OnPrintPreviewCancelled(int request_id) {
void PrintPreviewUI::OnPrintPreviewRequest(int request_id) {
if (!initial_preview_start_time_.is_null()) {
- UMA_HISTOGRAM_TIMES("PrintPreview.InitializationTime",
- base::TimeTicks::Now() - initial_preview_start_time_);
+ base::UmaHistogramTimes(
+ "PrintPreview.InitializationTime",
+ base::TimeTicks::Now() - initial_preview_start_time_);
}
g_print_preview_request_id_map.Get().Set(*id_, request_id);
}
@@ -672,16 +669,13 @@ void PrintPreviewUI::OnDidPreviewPage(
}
void PrintPreviewUI::OnPreviewDataIsAvailable(
- int expected_pages_count,
scoped_refptr<base::RefCountedMemory> data,
int preview_request_id) {
- VLOG(1) << "Print preview request finished with "
- << expected_pages_count << " pages";
-
if (!initial_preview_start_time_.is_null()) {
- UMA_HISTOGRAM_TIMES("PrintPreview.InitialDisplayTime",
- base::TimeTicks::Now() - initial_preview_start_time_);
- UMA_HISTOGRAM_COUNTS_1M(
+ base::UmaHistogramTimes(
+ "PrintPreview.InitialDisplayTime",
+ base::TimeTicks::Now() - initial_preview_start_time_);
+ base::UmaHistogramCounts1M(
"PrintPreview.RegeneratePreviewRequest.BeforeFirstData",
handler_->regenerate_preview_request_count());
initial_preview_start_time_ = base::TimeTicks();
diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h
index 144f6d5db5a..7aca7015dfa 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h
+++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h
@@ -75,13 +75,6 @@ class PrintPreviewUI : public ConstrainedWebDialogUI {
const gfx::Size& page_size() const { return page_size_; }
- // Determines if the PDF compositor is being used to generate full document
- // from individual pages, which can avoid the need for an extra composite
- // request containing all of the pages together.
- // TODO(awscreen): Can remove this method once all modifiable content is
- // handled with MSKP document type.
- bool ShouldCompositeDocumentUsingIndividualPages() const;
-
// Returns true if |page_number| is the last page in |pages_to_render_|.
// |page_number| is a 0-based number.
bool LastPageComposited(int page_number) const;
@@ -156,10 +149,8 @@ class PrintPreviewUI : public ConstrainedWebDialogUI {
int preview_request_id);
// Notifies the Web UI renderer that preview data is available.
- // |expected_pages_count| specifies the total number of pages.
// |preview_request_id| indicates which request resulted in this response.
- void OnPreviewDataIsAvailable(int expected_pages_count,
- scoped_refptr<base::RefCountedMemory> data,
+ void OnPreviewDataIsAvailable(scoped_refptr<base::RefCountedMemory> data,
int preview_request_id);
// Notifies the Web UI that the print preview failed to render for the request
diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_browsertest.cc
index aeb5a260f12..25eb97f2dd1 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_browsertest.cc
@@ -135,7 +135,7 @@ IN_PROC_BROWSER_TEST_F(PrintPreviewBrowserTest,
ui_test_utils::NavigateToURLWithDisposition(
browser(), GURL("about:blank"), WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP);
browser()->tab_strip_model()->ActivateTabAt(
0, {TabStripModel::GestureType::kOther});
diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
index 3af226798f7..d09c6609e5c 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui_unittest.cc
@@ -22,6 +22,7 @@
#include "content/public/browser/plugin_service.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
#include "printing/print_job_constants.h"
using content::WebContents;
diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_utils.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
index 99331f9dad2..c0bed875af9 100644
--- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
+++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_utils.cc
@@ -53,7 +53,7 @@ void PrintersToValues(const PrinterList& printer_list,
printer.printer_description);
auto options = std::make_unique<base::DictionaryValue>();
- for (const auto opt_it : printer.options)
+ for (const auto& opt_it : printer.options)
options->SetString(opt_it.first, opt_it.second);
#if defined(OS_CHROMEOS)
@@ -61,10 +61,6 @@ void PrintersToValues(const PrinterList& printer_list,
kCUPSEnterprisePrinter,
base::Contains(printer.options, kCUPSEnterprisePrinter) &&
printer.options.at(kCUPSEnterprisePrinter) == kValueTrue);
-
- auto it = printer.options.find(kPrinterEulaURL);
- options->SetString(kPrinterEulaURL,
- it != printer.options.end() ? it->second : "");
#endif // defined(OS_CHROMEOS)
printer_info->Set(kSettingPrinterOptions, std::move(options));
diff --git a/chromium/chrome/browser/ui/webui/profile_helper.cc b/chromium/chrome/browser/ui/webui/profile_helper.cc
index 48a822cd594..b1f7bdf09a1 100644
--- a/chromium/chrome/browser/ui/webui/profile_helper.cc
+++ b/chromium/chrome/browser/ui/webui/profile_helper.cc
@@ -21,8 +21,6 @@
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
-#include "extensions/browser/app_window/app_window.h"
-#include "extensions/browser/app_window/app_window_registry.h"
namespace webui {
namespace {
diff --git a/chromium/chrome/browser/ui/webui/profile_helper_browsertest.cc b/chromium/chrome/browser/ui/webui/profile_helper_browsertest.cc
index c6f2e95b4a0..9441a583722 100644
--- a/chromium/chrome/browser/ui/webui/profile_helper_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/profile_helper_browsertest.cc
@@ -139,7 +139,13 @@ IN_PROC_BROWSER_TEST_F(ProfileHelperTest, OpenNewWindowForProfile) {
#endif
}
-IN_PROC_BROWSER_TEST_F(ProfileHelperTest, DeleteSoleProfile) {
+// TODO(https://crbug.com/1073451) flaky on windows bots
+#if defined(OS_WIN)
+#define MAYBE_DeleteSoleProfile DISABLED_DeleteSoleProfile
+#else
+#define MAYBE_DeleteSoleProfile DeleteSoleProfile
+#endif
+IN_PROC_BROWSER_TEST_F(ProfileHelperTest, MAYBE_DeleteSoleProfile) {
content::TestWebUI web_ui;
Browser* original_browser = browser();
ProfileAttributesStorage& storage =
@@ -163,7 +169,13 @@ IN_PROC_BROWSER_TEST_F(ProfileHelperTest, DeleteSoleProfile) {
EXPECT_EQ(1u, storage.GetNumberOfProfiles());
}
-IN_PROC_BROWSER_TEST_F(ProfileHelperTest, DeleteActiveProfile) {
+// TODO(https://crbug.com/1073451) flaky on windows bots
+#if defined(OS_WIN)
+#define MAYBE_DeleteActiveProfile DISABLED_DeleteActiveProfile
+#else
+#define MAYBE_DeleteActiveProfile DeleteActiveProfile
+#endif
+IN_PROC_BROWSER_TEST_F(ProfileHelperTest, MAYBE_DeleteActiveProfile) {
content::TestWebUI web_ui;
Browser* original_browser = browser();
ProfileAttributesStorage& storage =
diff --git a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc
index 6d2752f9c00..22ea3e49882 100644
--- a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc
+++ b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc
@@ -30,6 +30,10 @@ void QuotaInternalsHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"requestInfo", base::BindRepeating(&QuotaInternalsHandler::OnRequestInfo,
base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "triggerStoragePressure",
+ base::BindRepeating(&QuotaInternalsHandler::OnTriggerStoragePressure,
+ base::Unretained(this)));
}
void QuotaInternalsHandler::ReportAvailableSpace(int64_t available_space) {
@@ -85,4 +89,19 @@ void QuotaInternalsHandler::OnRequestInfo(const base::ListValue*) {
Profile::FromWebUI(web_ui()))->GetQuotaManager());
}
+void QuotaInternalsHandler::OnTriggerStoragePressure(
+ const base::ListValue* args) {
+ CHECK_EQ(1U, args->GetSize());
+ std::string origin_string;
+ CHECK(args->GetString(0, &origin_string));
+ GURL url(origin_string);
+
+ if (!proxy_.get())
+ proxy_ = new QuotaInternalsProxy(this);
+ proxy_->TriggerStoragePressure(
+ url::Origin::Create(url),
+ BrowserContext::GetDefaultStoragePartition(Profile::FromWebUI(web_ui()))
+ ->GetQuotaManager());
+}
+
} // namespace quota_internals
diff --git a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h
index 515002f0c32..9e74b93ce4d 100644
--- a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h
+++ b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h
@@ -45,6 +45,7 @@ class QuotaInternalsHandler : public content::WebUIMessageHandler {
private:
void OnRequestInfo(const base::ListValue*);
+ void OnTriggerStoragePressure(const base::ListValue*);
void SendMessage(const std::string& message, const base::Value& value);
scoped_refptr<QuotaInternalsProxy> proxy_;
diff --git a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
index daefcc3f6ca..100c0a069a6 100644
--- a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
+++ b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc
@@ -67,7 +67,20 @@ void QuotaInternalsProxy::RequestInfo(
ReportStatistics(stats);
}
-QuotaInternalsProxy::~QuotaInternalsProxy() {}
+void QuotaInternalsProxy::TriggerStoragePressure(
+ url::Origin origin,
+ scoped_refptr<storage::QuotaManager> quota_manager) {
+ DCHECK(quota_manager.get());
+ if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+ base::PostTask(FROM_HERE, {BrowserThread::IO},
+ base::BindOnce(&QuotaInternalsProxy::TriggerStoragePressure,
+ this, origin, quota_manager));
+ return;
+ }
+ quota_manager->SimulateStoragePressure(origin);
+}
+
+QuotaInternalsProxy::~QuotaInternalsProxy() = default;
#define RELAY_TO_HANDLER(func, arg_t) \
void QuotaInternalsProxy::func(arg_t arg) { \
@@ -119,9 +132,9 @@ void QuotaInternalsProxy::DidDumpQuotaTable(const QuotaTableEntries& entries) {
std::vector<PerHostStorageInfo> host_info;
host_info.reserve(entries.size());
- for (auto itr(entries.begin()); itr != entries.end(); ++itr) {
- PerHostStorageInfo info(itr->host, itr->type);
- info.set_quota(itr->quota);
+ for (const auto& entry : entries) {
+ PerHostStorageInfo info(entry.host, entry.type);
+ info.set_quota(entry.quota);
host_info.push_back(info);
}
@@ -169,8 +182,7 @@ void QuotaInternalsProxy::DidGetHostUsage(const std::string& host,
void QuotaInternalsProxy::RequestPerOriginInfo(StorageType type) {
DCHECK(quota_manager_.get());
- std::set<url::Origin> origins;
- quota_manager_->GetCachedOrigins(type, &origins);
+ std::set<url::Origin> origins = quota_manager_->GetCachedOrigins(type);
std::vector<PerOriginStorageInfo> origin_info;
origin_info.reserve(origins.size());
diff --git a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h
index 0f562f5d428..893f2dd39ab 100644
--- a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h
+++ b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h
@@ -18,7 +18,7 @@
#include "base/sequenced_task_runner_helpers.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/quota/quota_manager.h"
-#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
+#include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h"
namespace quota_internals {
@@ -39,6 +39,9 @@ class QuotaInternalsProxy
explicit QuotaInternalsProxy(QuotaInternalsHandler* handler);
void RequestInfo(scoped_refptr<storage::QuotaManager> quota_manager);
+ void TriggerStoragePressure(
+ url::Origin origin,
+ scoped_refptr<storage::QuotaManager> quota_manager);
private:
friend class base::DeleteHelper<QuotaInternalsProxy>;
diff --git a/chromium/chrome/browser/ui/webui/recent_site_settings_helper.cc b/chromium/chrome/browser/ui/webui/recent_site_settings_helper.cc
new file mode 100644
index 00000000000..00a93c28ebd
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/recent_site_settings_helper.cc
@@ -0,0 +1,249 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/recent_site_settings_helper.h"
+
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/site_settings_helper.h"
+#include "components/content_settings/core/common/content_settings_utils.h"
+#include "components/permissions/permission_decision_auto_blocker.h"
+
+namespace site_settings {
+
+namespace {
+
+// The priority for surfacing a permission to the user.
+constexpr int GetPriorityForType(ContentSettingsType type) {
+ switch (type) {
+ case ContentSettingsType::GEOLOCATION:
+ return 0;
+ case ContentSettingsType::MEDIASTREAM_CAMERA:
+ return 1;
+ case ContentSettingsType::MEDIASTREAM_MIC:
+ return 2;
+ case ContentSettingsType::NOTIFICATIONS:
+ return 3;
+ case ContentSettingsType::BACKGROUND_SYNC:
+ return 4;
+ default:
+ // Every other |content_type| is considered of lower but equal priority
+ return 5;
+ }
+}
+
+// Return the most recent timestamp from the settings contained in a
+// RecentSitePermissions struct. Returns base::Time() if no settings exist.
+base::Time GetMostRecentTimestamp(const RecentSitePermissions& x) {
+ auto most_recent = base::Time();
+ for (const auto& setting : x.settings) {
+ if (setting.timestamp > most_recent)
+ most_recent = setting.timestamp;
+ }
+ return most_recent;
+}
+
+// Return a map keyed on URLs of all TimestampedSettings which currently apply
+// to the provided profile for the provided content types.
+std::map<GURL, std::vector<TimestampedSetting>> GetAllSettingsForProfile(
+ Profile* profile,
+ std::vector<ContentSettingsType> content_types) {
+ auto* auto_blocker =
+ PermissionDecisionAutoBlockerFactory::GetForProfile(profile);
+ HostContentSettingsMap* content_settings_map =
+ HostContentSettingsMapFactory::GetForProfile(profile);
+ std::map<GURL, std::vector<TimestampedSetting>> results;
+ for (auto content_type : content_types) {
+ auto exceptions_for_type = site_settings::GetSiteExceptionsForContentType(
+ content_settings_map, content_type);
+ for (const auto& e : exceptions_for_type) {
+ auto last_modified = content_settings_map->GetSettingLastModifiedDate(
+ e.primary_pattern, e.secondary_pattern, content_type);
+ if (last_modified.is_null()) {
+ continue;
+ }
+ GURL origin = GURL(e.primary_pattern.ToString()).GetOrigin();
+ results[origin].emplace_back(
+ last_modified, content_type,
+ content_settings::ValueToContentSetting(&e.setting_value),
+ site_settings::SiteSettingSource::kPreference);
+ }
+
+ // Get sites under embargo.
+ auto embargoed_sites = auto_blocker->GetEmbargoedOrigins(content_type);
+ for (auto& url : embargoed_sites) {
+ auto last_modified =
+ PermissionDecisionAutoBlockerFactory::GetForProfile(profile)
+ ->GetEmbargoStartTime(url, content_type);
+ results[url.GetOrigin()].emplace_back(
+ last_modified, content_type, ContentSetting::CONTENT_SETTING_BLOCK,
+ site_settings::SiteSettingSource::kEmbargo);
+ }
+ }
+
+ // Keep only the first entry for any content type. This will be the enforced
+ // user set permission appropriate for the profile.
+ for (auto& source_settings : results) {
+ std::stable_sort(
+ source_settings.second.begin(), source_settings.second.end(),
+ [](const TimestampedSetting& x, const TimestampedSetting& y) {
+ return x.content_type < y.content_type;
+ });
+ source_settings.second.erase(
+ std::unique(
+ source_settings.second.begin(), source_settings.second.end(),
+ [](const TimestampedSetting& x, const TimestampedSetting& y) {
+ return x.content_type == y.content_type;
+ }),
+ source_settings.second.end());
+ }
+ return results;
+}
+
+} // namespace
+
+TimestampedSetting::TimestampedSetting()
+ : timestamp(base::Time()),
+ content_type(ContentSettingsType::DEFAULT),
+ content_setting(ContentSetting::CONTENT_SETTING_DEFAULT),
+ setting_source(site_settings::SiteSettingSource::kDefault) {}
+TimestampedSetting::TimestampedSetting(const TimestampedSetting& other) =
+ default;
+TimestampedSetting::TimestampedSetting(
+ base::Time timestamp,
+ ContentSettingsType content_type,
+ ContentSetting content_setting,
+ site_settings::SiteSettingSource setting_source)
+ : timestamp(timestamp),
+ content_type(content_type),
+ content_setting(content_setting),
+ setting_source(setting_source) {}
+TimestampedSetting::~TimestampedSetting() = default;
+
+RecentSitePermissions::RecentSitePermissions()
+ : origin(GURL()),
+ incognito(false),
+ settings(std::vector<TimestampedSetting>()) {}
+RecentSitePermissions::RecentSitePermissions(
+ const RecentSitePermissions& other) = default;
+RecentSitePermissions::RecentSitePermissions(RecentSitePermissions&& other) =
+ default;
+RecentSitePermissions::RecentSitePermissions(
+ GURL origin,
+ bool incognito,
+ std::vector<TimestampedSetting> settings)
+ : origin(origin), incognito(incognito), settings(settings) {}
+RecentSitePermissions::~RecentSitePermissions() = default;
+
+std::vector<RecentSitePermissions> GetRecentSitePermissions(
+ Profile* profile,
+ std::vector<ContentSettingsType> content_types,
+ size_t max_sources) {
+ std::map<GURL, std::vector<TimestampedSetting>> regular_settings =
+ GetAllSettingsForProfile(profile, content_types);
+ std::map<GURL, std::vector<TimestampedSetting>> incognito_settings;
+
+ if (profile->HasOffTheRecordProfile()) {
+ incognito_settings = GetAllSettingsForProfile(
+ profile->GetOffTheRecordProfile(), content_types);
+
+ // Remove all permission entries in the incognito map which also have
+ // an entry in the regular settings. This may result in an empty setting
+ // vector, in which case we remove the map entry.
+ // TODO(https://crbug.com/1049531): Make determining actual source of
+ // active permission simpler.
+ for (auto incognito_iter = incognito_settings.begin();
+ incognito_iter != incognito_settings.end();) {
+ auto regular_iter = regular_settings.find(incognito_iter->first);
+ if (regular_iter == regular_settings.end()) {
+ ++incognito_iter;
+ continue;
+ }
+
+ // Define an arbitrary ordering on TimestampedSetting's so we can sort
+ // and make use of set difference
+ auto arbitrary_strict_weak_ordering = [](const TimestampedSetting& x,
+ const TimestampedSetting& y) {
+ return std::tie(x.timestamp, x.content_type, x.content_setting,
+ x.setting_source) <
+ std::tie(y.timestamp, y.content_type, y.content_setting,
+ y.setting_source);
+ };
+
+ std::vector<TimestampedSetting> incognito_only_settings;
+ std::sort(regular_iter->second.begin(), regular_iter->second.end(),
+ arbitrary_strict_weak_ordering);
+ std::sort(incognito_iter->second.begin(), incognito_iter->second.end(),
+ arbitrary_strict_weak_ordering);
+ std::set_difference(
+ incognito_iter->second.begin(), incognito_iter->second.end(),
+ regular_iter->second.begin(), regular_iter->second.end(),
+ std::back_inserter(incognito_only_settings),
+ arbitrary_strict_weak_ordering);
+
+ if (incognito_only_settings.empty()) {
+ incognito_iter = incognito_settings.erase(incognito_iter);
+ } else {
+ incognito_iter->second = incognito_only_settings;
+ ++incognito_iter;
+ }
+ }
+ }
+
+ // Combine incognito and regular permissions and sort based on the most
+ // recent setting for each source.
+ std::vector<RecentSitePermissions> all_site_permissions;
+ for (auto& url_settings_pair : regular_settings) {
+ all_site_permissions.push_back({url_settings_pair.first,
+ false /*incognito*/,
+ std::move(url_settings_pair.second)});
+ }
+ for (auto& url_settings_pair : incognito_settings) {
+ all_site_permissions.push_back({url_settings_pair.first, true /*incognito*/,
+ std::move(url_settings_pair.second)});
+ }
+ std::sort(all_site_permissions.begin(), all_site_permissions.end(),
+ [](const RecentSitePermissions& x, const RecentSitePermissions& y) {
+ return GetMostRecentTimestamp(x) > GetMostRecentTimestamp(y);
+ });
+
+ // Sort source permissions based on their priority for surfacing to the user
+ for (auto& site_permissions : all_site_permissions) {
+ std::sort(site_permissions.settings.begin(),
+ site_permissions.settings.end(),
+ [](const TimestampedSetting& x, const TimestampedSetting& y) {
+ if (GetPriorityForType(x.content_type) !=
+ GetPriorityForType(y.content_type)) {
+ return GetPriorityForType(x.content_type) <
+ GetPriorityForType(y.content_type);
+ }
+ return x.timestamp > y.timestamp;
+ });
+ }
+
+ if (all_site_permissions.size() <= max_sources) {
+ return all_site_permissions;
+ }
+
+ // We only want to surface the recent permissions for sites. Explicitly no
+ // settings older than the newest setting for the (max_sources + 1)th source.
+ auto min_timestamp =
+ GetMostRecentTimestamp(all_site_permissions[max_sources]);
+ all_site_permissions.erase(all_site_permissions.begin() + max_sources,
+ all_site_permissions.end());
+
+ for (auto& site_permissions : all_site_permissions) {
+ site_permissions.settings.erase(
+ std::remove_if(site_permissions.settings.begin(),
+ site_permissions.settings.end(),
+ [min_timestamp](const TimestampedSetting& x) {
+ return x.timestamp < min_timestamp;
+ }),
+ site_permissions.settings.end());
+ }
+ return all_site_permissions;
+}
+
+} // namespace site_settings
diff --git a/chromium/chrome/browser/ui/webui/recent_site_settings_helper.h b/chromium/chrome/browser/ui/webui/recent_site_settings_helper.h
new file mode 100644
index 00000000000..92b680ba0e6
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/recent_site_settings_helper.h
@@ -0,0 +1,65 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_RECENT_SITE_SETTINGS_HELPER_H_
+#define CHROME_BROWSER_UI_WEBUI_RECENT_SITE_SETTINGS_HELPER_H_
+
+#include <vector>
+
+#include "base/time/time.h"
+#include "chrome/browser/ui/webui/site_settings_helper.h"
+#include "components/content_settings/core/common/content_settings.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "url/gurl.h"
+
+class Profile;
+
+namespace site_settings {
+
+struct TimestampedSetting {
+ base::Time timestamp;
+ ContentSettingsType content_type;
+ ContentSetting content_setting;
+ site_settings::SiteSettingSource setting_source;
+
+ TimestampedSetting();
+ TimestampedSetting(const TimestampedSetting& other);
+ TimestampedSetting& operator=(const TimestampedSetting& other) = default;
+ TimestampedSetting(TimestampedSetting&& other) = default;
+ TimestampedSetting(base::Time timestamp,
+ ContentSettingsType content_type,
+ ContentSetting content_setting,
+ site_settings::SiteSettingSource setting_source);
+ ~TimestampedSetting();
+};
+
+struct RecentSitePermissions {
+ GURL origin;
+ bool incognito;
+ std::vector<TimestampedSetting> settings;
+
+ RecentSitePermissions();
+ RecentSitePermissions(const RecentSitePermissions& other);
+ RecentSitePermissions& operator=(const RecentSitePermissions& other) =
+ default;
+ RecentSitePermissions(RecentSitePermissions&& other);
+ RecentSitePermissions(GURL origin,
+ bool incognito,
+ std::vector<TimestampedSetting> settings);
+ ~RecentSitePermissions();
+};
+
+// Returns a list containing the most recent permission changes for the
+// provided content types grouped by origin/profile (incognito, regular)
+// combinations. Limited to |max_sources| origin/profile pairings and ordered
+// from most recently adjusted site to least recently. Includes permissions
+// changed by embargo, but not those changed by enterprise policy.
+std::vector<RecentSitePermissions> GetRecentSitePermissions(
+ Profile* profile,
+ std::vector<ContentSettingsType> content_types,
+ size_t max_sources);
+
+} // namespace site_settings
+
+#endif // CHROME_BROWSER_UI_WEBUI_RECENT_SITE_SETTINGS_HELPER_H_
diff --git a/chromium/chrome/browser/ui/webui/recent_site_settings_helper_unittest.cc b/chromium/chrome/browser/ui/webui/recent_site_settings_helper_unittest.cc
new file mode 100644
index 00000000000..870ef2d0012
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/recent_site_settings_helper_unittest.cc
@@ -0,0 +1,349 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/recent_site_settings_helper.h"
+
+#include "base/test/simple_test_clock.h"
+#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/permissions/permission_decision_auto_blocker.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace site_settings {
+
+namespace {
+
+ContentSetting kBlocked = ContentSetting::CONTENT_SETTING_BLOCK;
+ContentSetting kAllowed = ContentSetting::CONTENT_SETTING_ALLOW;
+ContentSetting kDefault = ContentSetting::CONTENT_SETTING_DEFAULT;
+site_settings::SiteSettingSource kEmbargo =
+ site_settings::SiteSettingSource::kEmbargo;
+site_settings::SiteSettingSource kPreference =
+ site_settings::SiteSettingSource::kPreference;
+ContentSettingsType kNotifications = ContentSettingsType::NOTIFICATIONS;
+ContentSettingsType kPlugins = ContentSettingsType::PLUGINS;
+ContentSettingsType kPopups = ContentSettingsType::POPUPS;
+ContentSettingsType kLocation = ContentSettingsType::GEOLOCATION;
+
+} // namespace
+
+class RecentSiteSettingsHelperTest : public testing::Test {
+ protected:
+ TestingProfile* profile() { return &profile_; }
+ TestingProfile* incognito_profile() { return incognito_profile_; }
+
+ base::SimpleTestClock* clock() { return &clock_; }
+
+ void CreateIncognitoProfile() {
+ incognito_profile_ = TestingProfile::Builder().BuildIncognito(profile());
+ }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ base::SimpleTestClock clock_;
+ TestingProfile profile_;
+ TestingProfile* incognito_profile_;
+};
+
+TEST_F(RecentSiteSettingsHelperTest, IncognitoPermissionTimestamps) {
+ // Confirm our expectation that content settings prefs copied to the incognito
+ // profile have a timestamp of base::Time().
+ HostContentSettingsMap* map =
+ HostContentSettingsMapFactory::GetForProfile(profile());
+ const GURL url("http://example.com");
+ const ContentSettingsPattern primary_pattern =
+ ContentSettingsPattern::FromURLNoWildcard(url);
+ const ContentSettingsPattern wildcard_pattern =
+ ContentSettingsPattern::Wildcard();
+ map->SetContentSettingDefaultScope(url, url, kNotifications, std::string(),
+ kBlocked);
+
+ CreateIncognitoProfile();
+ HostContentSettingsMap* incognito_map =
+ HostContentSettingsMapFactory::GetForProfile(incognito_profile());
+ EXPECT_NE(base::Time(),
+ map->GetSettingLastModifiedDate(primary_pattern, wildcard_pattern,
+ kNotifications));
+ EXPECT_EQ(base::Time(),
+ incognito_map->GetSettingLastModifiedDate(
+ primary_pattern, wildcard_pattern, kNotifications));
+}
+
+TEST_F(RecentSiteSettingsHelperTest, CheckRecentSitePermissions) {
+ const GURL url1("https://example.com");
+ const GURL url2("http://example.com");
+ std::vector<ContentSettingsType> content_types = {kNotifications, kPlugins,
+ kPopups, kLocation};
+ clock()->SetNow(base::Time::Now());
+
+ HostContentSettingsMap* map =
+ HostContentSettingsMapFactory::GetForProfile(profile());
+ map->SetClockForTesting(clock());
+
+ auto* auto_blocker =
+ PermissionDecisionAutoBlockerFactory::GetForProfile(profile());
+ auto_blocker->SetClockForTesting(clock());
+
+ // Check that with default permissions nothing is returned.
+ auto recent_permissions =
+ GetRecentSitePermissions(profile(), content_types, 10);
+ EXPECT_EQ(0UL, recent_permissions.size());
+
+ // Add two permissions for different urls via different mechanisms and
+ // confirm they're returned correctly. Ensure that simply creating an
+ // ingocnito profile does not change recent permissions.
+ for (int i = 0; i < 3; ++i) {
+ auto_blocker->RecordDismissAndEmbargo(url1, kNotifications, false);
+ }
+
+ clock()->Advance(base::TimeDelta::FromHours(2));
+ map->SetContentSettingDefaultScope(url2, url2, kPlugins, std::string(),
+ kAllowed);
+ CreateIncognitoProfile();
+
+ recent_permissions = GetRecentSitePermissions(profile(), content_types, 10);
+ {
+ EXPECT_EQ(2UL, recent_permissions.size());
+ EXPECT_EQ(1UL, recent_permissions[0].settings.size());
+ EXPECT_EQ(1UL, recent_permissions[1].settings.size());
+
+ EXPECT_EQ(url1.spec(), recent_permissions[1].origin);
+ EXPECT_EQ(url2.spec(), recent_permissions[0].origin);
+
+ auto url1_permissions = recent_permissions[1].settings;
+ auto url2_permissions = recent_permissions[0].settings;
+
+ EXPECT_EQ(kNotifications, url1_permissions[0].content_type);
+ EXPECT_EQ(kBlocked, url1_permissions[0].content_setting);
+ EXPECT_EQ(kEmbargo, url1_permissions[0].setting_source);
+
+ EXPECT_EQ(kPlugins, url2_permissions[0].content_type);
+ EXPECT_EQ(kAllowed, url2_permissions[0].content_setting);
+ EXPECT_EQ(kPreference, url2_permissions[0].setting_source);
+ }
+
+ // Ensure incognito generated permissions are separated correctly.
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ HostContentSettingsMap* incognito_map =
+ HostContentSettingsMapFactory::GetForProfile(incognito_profile());
+ incognito_map->SetClockForTesting(clock());
+ incognito_map->SetContentSettingDefaultScope(url1, url1, kPlugins,
+ std::string(), kAllowed);
+
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ permissions::PermissionDecisionAutoBlocker* incognito_auto_blocker =
+ PermissionDecisionAutoBlockerFactory::GetForProfile(incognito_profile());
+ incognito_auto_blocker->SetClockForTesting(clock());
+ for (int i = 0; i < 3; ++i) {
+ incognito_auto_blocker->RecordDismissAndEmbargo(url1, kNotifications,
+ false);
+ }
+
+ recent_permissions = GetRecentSitePermissions(profile(), content_types, 10);
+ {
+ EXPECT_EQ(3UL, recent_permissions.size());
+ EXPECT_EQ(2UL, recent_permissions[0].settings.size());
+ EXPECT_EQ(1UL, recent_permissions[1].settings.size());
+ EXPECT_EQ(1UL, recent_permissions[2].settings.size());
+
+ EXPECT_EQ(url1.spec(), recent_permissions[2].origin);
+ EXPECT_EQ(url2.spec(), recent_permissions[1].origin);
+ EXPECT_EQ(url1.spec(), recent_permissions[0].origin);
+
+ EXPECT_TRUE(recent_permissions[0].incognito);
+ EXPECT_FALSE(recent_permissions[1].incognito);
+ EXPECT_FALSE(recent_permissions[2].incognito);
+
+ auto incognito_url1_permissions = recent_permissions[0].settings;
+
+ EXPECT_EQ(kNotifications, incognito_url1_permissions[0].content_type);
+ EXPECT_EQ(kBlocked, incognito_url1_permissions[0].content_setting);
+ EXPECT_EQ(kEmbargo, incognito_url1_permissions[0].setting_source);
+
+ EXPECT_EQ(kPlugins, incognito_url1_permissions[1].content_type);
+ EXPECT_EQ(kAllowed, incognito_url1_permissions[1].content_setting);
+ EXPECT_EQ(kPreference, incognito_url1_permissions[1].setting_source);
+ }
+
+ // Test additional permissions are correctly compacted down to the provided
+ // maximum number of sources and that order of origins is based on the
+ // most recent permission for that source.
+ const GURL url3("https://example.com:8443");
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ map->SetContentSettingDefaultScope(url1, url1, kPlugins, std::string(),
+ kBlocked);
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ for (int i = 0; i < 4; ++i) {
+ auto_blocker->RecordIgnoreAndEmbargo(url3, kNotifications, false);
+ }
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ map->SetContentSettingDefaultScope(url2, url2, kPopups, std::string(),
+ kAllowed);
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ map->SetContentSettingDefaultScope(url3, url3, kPopups, std::string(),
+ kBlocked);
+
+ recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
+ {
+ EXPECT_EQ(3UL, recent_permissions.size());
+ EXPECT_EQ(2UL, recent_permissions[0].settings.size());
+ EXPECT_EQ(1UL, recent_permissions[1].settings.size());
+ EXPECT_EQ(1UL, recent_permissions[2].settings.size());
+
+ EXPECT_EQ(url3.spec(), recent_permissions[0].origin);
+ EXPECT_EQ(url2.spec(), recent_permissions[1].origin);
+ EXPECT_EQ(url1.spec(), recent_permissions[2].origin);
+
+ // The oldest record will those for the inconito URL1, they should have
+ // been removed.
+ EXPECT_FALSE(recent_permissions[2].incognito);
+ auto url1_permissions = recent_permissions[2].settings;
+ auto url2_permissions = recent_permissions[1].settings;
+ auto url3_permissions = recent_permissions[0].settings;
+
+ EXPECT_EQ(kPlugins, url1_permissions[0].content_type);
+ EXPECT_EQ(kBlocked, url1_permissions[0].content_setting);
+ EXPECT_EQ(kPreference, url1_permissions[0].setting_source);
+
+ EXPECT_EQ(kPopups, url2_permissions[0].content_type);
+ EXPECT_EQ(kAllowed, url2_permissions[0].content_setting);
+ EXPECT_EQ(kPreference, url2_permissions[0].setting_source);
+
+ EXPECT_EQ(kNotifications, url3_permissions[0].content_type);
+ EXPECT_EQ(kBlocked, url3_permissions[0].content_setting);
+ EXPECT_EQ(kEmbargo, url3_permissions[0].setting_source);
+
+ EXPECT_EQ(kPopups, url3_permissions[1].content_type);
+ EXPECT_EQ(kBlocked, url3_permissions[1].content_setting);
+ EXPECT_EQ(kPreference, url3_permissions[1].setting_source);
+ }
+
+ // Assign a new permission to a previously recorded site whose other
+ // permissions are too old and ensure only the recent permission is returned.
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ incognito_map->SetContentSettingDefaultScope(url1, url1, kPopups,
+ std::string(), kBlocked);
+ recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
+ {
+ EXPECT_EQ(3UL, recent_permissions.size());
+ EXPECT_EQ(1UL, recent_permissions[0].settings.size());
+ EXPECT_EQ(url1.spec(), recent_permissions[0].origin);
+ EXPECT_TRUE(recent_permissions[0].incognito);
+
+ EXPECT_EQ(kPopups, recent_permissions[0].settings[0].content_type);
+ EXPECT_EQ(kBlocked, recent_permissions[0].settings[0].content_setting);
+ EXPECT_EQ(kPreference, recent_permissions[0].settings[0].setting_source);
+ }
+
+ // Reset a changed permission to default and confirm it does not appear as a
+ // recent permission change.
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ map->SetContentSettingDefaultScope(url3, url3, kPopups, std::string(),
+ kDefault);
+ recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
+ {
+ EXPECT_EQ(3UL, recent_permissions.size());
+ EXPECT_EQ(1UL, recent_permissions[0].settings.size());
+ EXPECT_NE(url3.spec(), recent_permissions[0].origin);
+ }
+
+ // Expire all existing embargoes, then re-embargo a site with a single
+ // dismissal and confirm this is recorded as a new permission change. Also
+ // confirm that sources with no permission changes associated are not
+ // considered. I.e. url3 now has an expired embargo and a default setting. It
+ // should not be considered and should allow the plugins setting for url1 to
+ // be included as a recent change.
+ clock()->Advance(base::TimeDelta::FromDays(7));
+ auto_blocker->RecordDismissAndEmbargo(url1, kNotifications, false);
+ recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
+ {
+ EXPECT_EQ(3UL, recent_permissions.size());
+ EXPECT_EQ(2UL, recent_permissions[0].settings.size());
+ EXPECT_EQ(2UL, recent_permissions[1].settings.size());
+ EXPECT_EQ(2UL, recent_permissions[2].settings.size());
+
+ EXPECT_EQ(url1.spec(), recent_permissions[0].origin);
+ EXPECT_FALSE(recent_permissions[0].incognito);
+ auto url1_permissions = recent_permissions[0].settings;
+
+ EXPECT_EQ(kNotifications, url1_permissions[0].content_type);
+ EXPECT_EQ(kBlocked, url1_permissions[0].content_setting);
+ EXPECT_EQ(kEmbargo, url1_permissions[0].setting_source);
+
+ EXPECT_EQ(kPlugins, url1_permissions[1].content_type);
+ EXPECT_EQ(kBlocked, url1_permissions[1].content_setting);
+ EXPECT_EQ(kPreference, url1_permissions[1].setting_source);
+ }
+
+ // Confirm that powerful permissions are listed first, and that other
+ // permissions remain sorted by time.
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ map->SetContentSettingDefaultScope(url1, url1, kPopups, std::string(),
+ kBlocked);
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ map->SetContentSettingDefaultScope(url1, url1, kLocation, std::string(),
+ kAllowed);
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ map->SetContentSettingDefaultScope(url1, url1, kPlugins, std::string(),
+ kAllowed);
+
+ recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
+ {
+ EXPECT_EQ(3UL, recent_permissions.size());
+
+ auto url1_permissions = recent_permissions[0].settings;
+ EXPECT_EQ(4UL, url1_permissions.size());
+
+ EXPECT_EQ(kLocation, url1_permissions[0].content_type);
+ EXPECT_EQ(kNotifications, url1_permissions[1].content_type);
+ EXPECT_EQ(kPlugins, url1_permissions[2].content_type);
+ EXPECT_EQ(kPopups, url1_permissions[3].content_type);
+ }
+
+ // Check that adding a conflicting permission to the regular profile after
+ // the incognito profile has been created returns correctly for each profile.
+ const GURL url4("http://example.com:8443");
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ incognito_map->SetContentSettingDefaultScope(url4, url4, kLocation,
+ std::string(), kAllowed);
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ map->SetContentSettingDefaultScope(url4, url4, kLocation, std::string(),
+ kBlocked);
+
+ recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
+ {
+ EXPECT_EQ(3UL, recent_permissions.size());
+ EXPECT_EQ(url4.spec(), recent_permissions[0].origin);
+ EXPECT_EQ(url4.spec(), recent_permissions[1].origin);
+ EXPECT_EQ(1UL, recent_permissions[0].settings.size());
+ EXPECT_EQ(1UL, recent_permissions[1].settings.size());
+ EXPECT_FALSE(recent_permissions[0].incognito);
+ EXPECT_TRUE(recent_permissions[1].incognito);
+ EXPECT_EQ(kLocation, recent_permissions[0].settings[0].content_type);
+ EXPECT_EQ(kLocation, recent_permissions[1].settings[0].content_type);
+ EXPECT_EQ(kBlocked, recent_permissions[0].settings[0].content_setting);
+ EXPECT_EQ(kAllowed, recent_permissions[1].settings[0].content_setting);
+ }
+
+ // Check that resetting the permission to default in the regular profile
+ // does not affect the permission in the incognito profile.
+ clock()->Advance(base::TimeDelta::FromHours(1));
+ map->SetContentSettingDefaultScope(url4, url4, kLocation, std::string(),
+ kDefault);
+
+ recent_permissions = GetRecentSitePermissions(profile(), content_types, 3);
+ {
+ EXPECT_EQ(3UL, recent_permissions.size());
+ EXPECT_EQ(url4.spec(), recent_permissions[0].origin);
+ EXPECT_EQ(1UL, recent_permissions[0].settings.size());
+ EXPECT_TRUE(recent_permissions[0].incognito);
+ EXPECT_EQ(kLocation, recent_permissions[0].settings[0].content_type);
+ EXPECT_EQ(kAllowed, recent_permissions[0].settings[0].content_setting);
+ }
+}
+
+} // namespace site_settings
diff --git a/chromium/chrome/browser/ui/webui/reset_password/BUILD.gn b/chromium/chrome/browser/ui/webui/reset_password/BUILD.gn
index 46529aa8ccb..bd425a30ea7 100644
--- a/chromium/chrome/browser/ui/webui/reset_password/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/reset_password/BUILD.gn
@@ -5,7 +5,5 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "reset_password.mojom",
- ]
+ sources = [ "reset_password.mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.cc b/chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
index e6293d9e973..abb08f07c5a 100644
--- a/chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
+++ b/chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
@@ -14,10 +14,10 @@
#include "chrome/browser/ui/webui/reset_password/reset_password.mojom.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/browser_resources.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
-#include "components/safe_browsing/password_protection/metrics_util.h"
-#include "components/safe_browsing/password_protection/password_protection_service.h"
-#include "components/safe_browsing/proto/csd.pb.h"
+#include "components/safe_browsing/content/password_protection/metrics_util.h"
+#include "components/safe_browsing/content/password_protection/password_protection_service.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/proto/csd.pb.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/url_formatter.h"
#include "components/user_prefs/user_prefs.h"
@@ -121,14 +121,13 @@ ResetPasswordUI::ResetPasswordUI(content::WebUI* web_ui)
content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
html_source.release());
-
- AddHandlerToRegistry(base::BindRepeating(
- &ResetPasswordUI::BindResetPasswordHandler, base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(ResetPasswordUI)
+
ResetPasswordUI::~ResetPasswordUI() {}
-void ResetPasswordUI::BindResetPasswordHandler(
+void ResetPasswordUI::BindInterface(
mojo::PendingReceiver<mojom::ResetPasswordHandler> receiver) {
ui_handler_ = std::make_unique<ResetPasswordHandlerImpl>(
web_ui()->GetWebContents(), std::move(receiver));
diff --git a/chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.h b/chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.h
index 3bd39465b30..901a026badf 100644
--- a/chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.h
+++ b/chromium/chrome/browser/ui/webui/reset_password/reset_password_ui.h
@@ -24,15 +24,19 @@ class ResetPasswordUI : public ui::MojoWebUIController {
explicit ResetPasswordUI(content::WebUI* web_ui);
~ResetPasswordUI() override;
- private:
- void BindResetPasswordHandler(
+ // Instantiates the implementor of the mojom::ResetPasswordHandler mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<mojom::ResetPasswordHandler> receiver);
+ private:
base::DictionaryValue PopulateStrings() const;
std::unique_ptr<mojom::ResetPasswordHandler> ui_handler_;
const PasswordType password_type_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(ResetPasswordUI);
};
diff --git a/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc b/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc
index a4f1c53905c..1e11b2d01ec 100644
--- a/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc
+++ b/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc
@@ -15,6 +15,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/sandbox_type.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/process_type.h"
#include "services/service_manager/sandbox/win/sandbox_win.h"
@@ -25,6 +26,45 @@ using content::RenderProcessHost;
namespace sandbox_handler {
namespace {
+
+// This only includes OS_WIN included SandboxType values.
+std::string GetSandboxTypeInEnglish(content::SandboxType sandbox_type) {
+ switch (sandbox_type) {
+ case content::SandboxType::kInvalid:
+ return "Invalid";
+ case content::SandboxType::kNoSandbox:
+ return "Unsandboxed";
+ case content::SandboxType::kNoSandboxAndElevatedPrivileges:
+ return "Unsandboxed (Elevated)";
+ case content::SandboxType::kXrCompositing:
+ return "XR Compositing";
+ case content::SandboxType::kRenderer:
+ return "Renderer";
+ case content::SandboxType::kUtility:
+ return "Utility";
+ case content::SandboxType::kGpu:
+ return "GPU";
+ case content::SandboxType::kPpapi:
+ return "PPAPI";
+ case content::SandboxType::kNetwork:
+ return "Network";
+ case content::SandboxType::kCdm:
+ return "CDM";
+ case content::SandboxType::kPrintCompositor:
+ return "Print Compositor";
+ case content::SandboxType::kAudio:
+ return "Audio";
+ case content::SandboxType::kSoda:
+ return "SODA";
+ case content::SandboxType::kProxyResolver:
+ return "Proxy Resolver";
+ case content::SandboxType::kPdfConversion:
+ return "PDF Conversion";
+ case content::SandboxType::kSharingService:
+ return "Sharing";
+ }
+}
+
base::Value FetchBrowserChildProcesses() {
// The |BrowserChildProcessHostIterator| must only be used on the IO thread.
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
@@ -43,7 +83,10 @@ base::Value FetchBrowserChildProcesses() {
process_data.process_type)));
proc.SetPath("name", base::Value(process_data.name));
proc.SetPath("metricsName", base::Value(process_data.metrics_name));
- browser_processes.GetList().push_back(std::move(proc));
+ proc.SetPath(
+ "sandboxType",
+ base::Value(GetSandboxTypeInEnglish(process_data.sandbox_type)));
+ browser_processes.Append(std::move(proc));
}
return browser_processes;
@@ -64,7 +107,7 @@ base::Value FetchRenderHostProcesses() {
proc.SetPath(
"processId",
base::Value(base::strict_cast<double>(host->GetProcess().Pid())));
- renderer_processes.GetList().push_back(std::move(proc));
+ renderer_processes.Append(std::move(proc));
}
return renderer_processes;
@@ -95,9 +138,9 @@ void SandboxHandler::HandleRequestSandboxDiagnostics(
base::PostTaskAndReplyWithResult(
FROM_HERE, {content::BrowserThread::IO},
- base::Bind(&FetchBrowserChildProcesses),
- base::Bind(&SandboxHandler::FetchBrowserChildProcessesCompleted,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&FetchBrowserChildProcesses),
+ base::BindOnce(&SandboxHandler::FetchBrowserChildProcessesCompleted,
+ weak_ptr_factory_.GetWeakPtr()));
}
void SandboxHandler::FetchBrowserChildProcessesCompleted(
diff --git a/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc b/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc
index 9c3783b3791..40567210a5a 100644
--- a/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc
@@ -9,7 +9,7 @@
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
diff --git a/chromium/chrome/browser/ui/webui/settings/OWNERS b/chromium/chrome/browser/ui/webui/settings/OWNERS
index 93f7d799e7d..b19cbb7cc52 100644
--- a/chromium/chrome/browser/ui/webui/settings/OWNERS
+++ b/chromium/chrome/browser/ui/webui/settings/OWNERS
@@ -2,4 +2,9 @@ file://chrome/browser/resources/settings/OWNERS
per-file people_handler*=tangltom@chromium.org
+per-file safe_browsing_handler*=msramek@chromium.org
+per-file safe_browsing_handler*=sauski@google.com
+per-file site_settings_handler*=msramek@chromium.org
+per-file site_settings_handler*=sauski@google.com
+
# COMPONENT: UI>Settings
diff --git a/chromium/chrome/browser/ui/webui/settings/about_handler.cc b/chromium/chrome/browser/ui/webui/settings/about_handler.cc
index 21c3de52e0d..bcc0134af2f 100644
--- a/chromium/chrome/browser/ui/webui/settings/about_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/about_handler.cc
@@ -22,7 +22,9 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/system/sys_info.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/branding_buildflags.h"
@@ -56,6 +58,7 @@
#if defined(OS_CHROMEOS)
#include "base/i18n/time_formatting.h"
+#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
@@ -71,6 +74,7 @@
#include "chromeos/constants/chromeos_switches.h"
#include "chromeos/dbus/power/power_manager_client.h"
#include "chromeos/dbus/update_engine_client.h"
+#include "chromeos/dbus/util/version_loader.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/system/statistics_provider.h"
@@ -227,6 +231,19 @@ std::string ReadRegulatoryLabelText(const base::FilePath& label_dir_path) {
return std::string();
}
+std::unique_ptr<base::DictionaryValue> GetVersionInfo() {
+ std::unique_ptr<base::DictionaryValue> version_info(
+ new base::DictionaryValue);
+ version_info->SetString("osVersion",
+ chromeos::version_loader::GetVersion(
+ chromeos::version_loader::VERSION_FULL));
+ version_info->SetString("arcVersion",
+ chromeos::version_loader::GetARCVersion());
+ version_info->SetString("osFirmware",
+ chromeos::version_loader::GetFirmware());
+ return version_info;
+}
+
#endif // defined(OS_CHROMEOS)
std::string UpdateStatusToString(VersionUpdater::Status status) {
@@ -335,16 +352,21 @@ AboutHandler* AboutHandler::Create(content::WebUIDataSource* html_source,
base::string16 os_with_linux_license = l10n_util::GetStringFUTF16(
IDS_ABOUT_CROS_WITH_LINUX_VERSION_LICENSE,
base::ASCIIToUTF16(chrome::kChromeUIOSCreditsURL),
- base::ASCIIToUTF16(chrome::kChromeUILinuxCreditsURL));
+ base::ASCIIToUTF16(chrome::kChromeUICrostiniCreditsURL));
html_source->AddString("aboutProductOsWithLinuxLicense",
os_with_linux_license);
html_source->AddBoolean("aboutEnterpriseManaged", IsEnterpriseManaged());
-
- html_source->AddString("endOfLifeMessage", l10n_util::GetStringFUTF16(
- IDS_EOL_NOTIFICATION_EOL,
- ui::GetChromeOSDeviceName()));
- html_source->AddString("endOfLifeLearnMoreURL",
- base::ASCIIToUTF16(chrome::kEolNotificationURL));
+ html_source->AddBoolean("aboutIsArcEnabled",
+ arc::IsArcPlayStoreEnabledForProfile(profile));
+ html_source->AddBoolean("aboutIsDeveloperMode",
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ chromeos::switches::kSystemDevMode));
+
+ html_source->AddString("endOfLifeMessage",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_ABOUT_PAGE_LAST_UPDATE_MESSAGE,
+ ui::GetChromeOSDeviceName(),
+ base::ASCIIToUTF16(chrome::kEolNotificationURL)));
#endif
return new AboutHandler();
@@ -380,6 +402,9 @@ void AboutHandler::RegisterMessages() {
base::BindRepeating(&AboutHandler::HandleRequestUpdateOverCellular,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
+ "getVersionInfo", base::BindRepeating(&AboutHandler::HandleGetVersionInfo,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
"getRegulatoryInfo",
base::BindRepeating(&AboutHandler::HandleGetRegulatoryInfo,
base::Unretained(this)));
@@ -387,6 +412,10 @@ void AboutHandler::RegisterMessages() {
"getChannelInfo", base::BindRepeating(&AboutHandler::HandleGetChannelInfo,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
+ "canChangeChannel",
+ base::BindRepeating(&AboutHandler::HandleCanChangeChannel,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
"refreshTPMFirmwareUpdateStatus",
base::BindRepeating(&AboutHandler::HandleRefreshTPMFirmwareUpdateStatus,
base::Unretained(this)));
@@ -572,17 +601,33 @@ void AboutHandler::HandleSetChannel(const base::ListValue* args) {
}
}
+void AboutHandler::HandleGetVersionInfo(const base::ListValue* args) {
+ CHECK_EQ(1U, args->GetSize());
+ std::string callback_id;
+ CHECK(args->GetString(0, &callback_id));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(&GetVersionInfo),
+ base::BindOnce(&AboutHandler::OnGetVersionInfoReady,
+ weak_factory_.GetWeakPtr(), callback_id));
+}
+
+void AboutHandler::OnGetVersionInfoReady(
+ std::string callback_id,
+ std::unique_ptr<base::DictionaryValue> version_info) {
+ ResolveJavascriptCallback(base::Value(callback_id), *version_info);
+}
+
void AboutHandler::HandleGetRegulatoryInfo(const base::ListValue* args) {
CHECK_EQ(1U, args->GetSize());
std::string callback_id;
CHECK(args->GetString(0, &callback_id));
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
- base::Bind(&FindRegulatoryLabelDir),
- base::Bind(&AboutHandler::OnRegulatoryLabelDirFound,
- weak_factory_.GetWeakPtr(), callback_id));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(&FindRegulatoryLabelDir),
+ base::BindOnce(&AboutHandler::OnRegulatoryLabelDirFound,
+ weak_factory_.GetWeakPtr(), callback_id));
}
void AboutHandler::HandleGetChannelInfo(const base::ListValue* args) {
@@ -595,6 +640,15 @@ void AboutHandler::HandleGetChannelInfo(const base::ListValue* args) {
callback_id));
}
+void AboutHandler::HandleCanChangeChannel(const base::ListValue* args) {
+ CHECK_EQ(1U, args->GetSize());
+ std::string callback_id;
+ CHECK(args->GetString(0, &callback_id));
+ ResolveJavascriptCallback(
+ base::Value(callback_id),
+ base::Value(CanChangeChannel(Profile::FromWebUI(web_ui()))));
+}
+
void AboutHandler::OnGetCurrentChannel(std::string callback_id,
const std::string& current_channel) {
version_updater_->GetChannel(
@@ -610,8 +664,6 @@ void AboutHandler::OnGetTargetChannel(std::string callback_id,
new base::DictionaryValue);
channel_info->SetString("currentChannel", current_channel);
channel_info->SetString("targetChannel", target_channel);
- channel_info->SetBoolean("canChangeChannel",
- CanChangeChannel(Profile::FromWebUI(web_ui())));
ResolveJavascriptCallback(base::Value(callback_id), *channel_info);
}
@@ -672,10 +724,14 @@ void AboutHandler::OnGetEndOfLifeInfo(
base::Value response(base::Value::Type::DICTIONARY);
if (!eol_info.eol_date.is_null()) {
response.SetBoolKey("hasEndOfLife", eol_info.eol_date <= base::Time::Now());
- response.SetStringKey("aboutPageEndOfLifeMessage",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_ABOUT_PAGE_END_OF_LIFE_MESSAGE,
- base::TimeFormatMonthAndYear(eol_info.eol_date)));
+ int eol_string_id = eol_info.eol_date <= base::Time::Now()
+ ? IDS_SETTINGS_ABOUT_PAGE_END_OF_LIFE_MESSAGE_PAST
+ : IDS_SETTINGS_ABOUT_PAGE_END_OF_LIFE_MESSAGE_FUTURE;
+ response.SetStringKey(
+ "aboutPageEndOfLifeMessage",
+ l10n_util::GetStringFUTF16(
+ eol_string_id, base::TimeFormatMonthAndYear(eol_info.eol_date),
+ base::ASCIIToUTF16(chrome::kEolNotificationURL)));
} else {
response.SetBoolKey("hasEndOfLife", false);
response.SetStringKey("aboutPageEndOfLifeMessage", "");
@@ -765,12 +821,11 @@ void AboutHandler::OnRegulatoryLabelDirFound(
return;
}
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
- base::Bind(&ReadRegulatoryLabelText, label_dir_path),
- base::Bind(&AboutHandler::OnRegulatoryLabelTextRead,
- weak_factory_.GetWeakPtr(), callback_id, label_dir_path));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::BindOnce(&ReadRegulatoryLabelText, label_dir_path),
+ base::BindOnce(&AboutHandler::OnRegulatoryLabelTextRead,
+ weak_factory_.GetWeakPtr(), callback_id, label_dir_path));
}
void AboutHandler::OnRegulatoryLabelTextRead(
diff --git a/chromium/chrome/browser/ui/webui/settings/about_handler.h b/chromium/chrome/browser/ui/webui/settings/about_handler.h
index 679bad2fa37..e69de9f2d82 100644
--- a/chromium/chrome/browser/ui/webui/settings/about_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/about_handler.h
@@ -25,6 +25,7 @@
#endif // defined(OS_CHROMEOS)
namespace base {
+class DictionaryValue;
class FilePath;
class ListValue;
}
@@ -99,8 +100,18 @@ class AboutHandler : public settings::SettingsPageUIHandler,
// Sets the release track version.
void HandleSetChannel(const base::ListValue* args);
- // Retrieves combined channel info.
+ // Retrieves OS, ARC and firmware versions.
+ void HandleGetVersionInfo(const base::ListValue* args);
+ void OnGetVersionInfoReady(
+ std::string callback_id,
+ std::unique_ptr<base::DictionaryValue> version_info);
+
+ // Retrieves channel info.
void HandleGetChannelInfo(const base::ListValue* args);
+
+ // Checks whether we can change the current channel.
+ void HandleCanChangeChannel(const base::ListValue* args);
+
// Callbacks for version_updater_->GetChannel calls.
void OnGetCurrentChannel(std::string callback_id,
const std::string& current_channel);
diff --git a/chromium/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc b/chromium/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc
index 6c11c87a3f5..8a02491acd6 100644
--- a/chromium/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc
@@ -19,10 +19,6 @@
#include "components/user_manager/user_manager.h"
#endif // defined(OS_CHROMEOS)
-#if defined(OS_MACOSX)
-#include "chrome/browser/first_run/upgrade_util_mac.h"
-#endif
-
namespace settings {
namespace {
@@ -86,11 +82,6 @@ void BrowserLifetimeHandler::HandleRestart(
void BrowserLifetimeHandler::HandleRelaunch(
const base::ListValue* args) {
-#if defined(OS_MACOSX)
- if (!upgrade_util::ShouldContinueToRelaunchForUpgrade())
- return;
-#endif // OS_MACOSX
-
chrome::AttemptRelaunch();
}
diff --git a/chromium/chrome/browser/ui/webui/settings/change_password_handler.cc b/chromium/chrome/browser/ui/webui/settings/change_password_handler.cc
deleted file mode 100644
index b34815f9c76..00000000000
--- a/chromium/chrome/browser/ui/webui/settings/change_password_handler.cc
+++ /dev/null
@@ -1,81 +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 "chrome/browser/ui/webui/settings/change_password_handler.h"
-
-#include "base/bind.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
-#include "components/prefs/pref_service.h"
-#include "components/safe_browsing/password_protection/metrics_util.h"
-#include "components/safe_browsing/proto/csd.pb.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui.h"
-
-namespace settings {
-
-using password_manager::metrics_util::PasswordType;
-using safe_browsing::ChromePasswordProtectionService;
-using safe_browsing::LoginReputationClientResponse;
-using safe_browsing::RequestOutcome;
-
-ChangePasswordHandler::ChangePasswordHandler(
- Profile* profile,
- safe_browsing::ChromePasswordProtectionService* service)
- : profile_(profile), service_(service) {
- DCHECK(service_);
-}
-
-ChangePasswordHandler::~ChangePasswordHandler() {}
-
-void ChangePasswordHandler::RegisterMessages() {
- web_ui()->RegisterMessageCallback(
- "initializeChangePasswordHandler",
- base::BindRepeating(&ChangePasswordHandler::HandleInitialize,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "changePassword",
- base::BindRepeating(&ChangePasswordHandler::HandleChangePassword,
- base::Unretained(this)));
-}
-
-void ChangePasswordHandler::OnJavascriptAllowed() {
- pref_registrar_.Init(profile_->GetPrefs());
- pref_registrar_.Add(
- prefs::kSafeBrowsingUnhandledGaiaPasswordReuses,
- base::Bind(&ChangePasswordHandler::UpdateChangePasswordCardVisibility,
- base::Unretained(this)));
-}
-
-void ChangePasswordHandler::OnJavascriptDisallowed() {
- pref_registrar_.RemoveAll();
-}
-
-void ChangePasswordHandler::HandleInitialize(const base::ListValue* args) {
- AllowJavascript();
- UpdateChangePasswordCardVisibility();
-}
-
-void ChangePasswordHandler::HandleChangePassword(const base::ListValue* args) {
- service_->OnUserAction(
- web_ui()->GetWebContents(),
- service_->reused_password_account_type_for_last_shown_warning(),
- RequestOutcome::UNKNOWN,
- LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED, "unused_token",
- safe_browsing::WarningUIType::CHROME_SETTINGS,
- safe_browsing::WarningAction::CHANGE_PASSWORD);
-}
-
-void ChangePasswordHandler::UpdateChangePasswordCardVisibility() {
- FireWebUIListener(
- "change-password-visibility",
- base::Value(
- service_->IsWarningEnabled(
- service_
- ->reused_password_account_type_for_last_shown_warning()) &&
- safe_browsing::ChromePasswordProtectionService::
- ShouldShowChangePasswordSettingUI(profile_)));
-}
-
-} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/change_password_handler.h b/chromium/chrome/browser/ui/webui/settings/change_password_handler.h
deleted file mode 100644
index f1ea3806473..00000000000
--- a/chromium/chrome/browser/ui/webui/settings/change_password_handler.h
+++ /dev/null
@@ -1,51 +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 CHROME_BROWSER_UI_WEBUI_SETTINGS_CHANGE_PASSWORD_HANDLER_H_
-#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHANGE_PASSWORD_HANDLER_H_
-
-#include "base/macros.h"
-#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
-#include "components/prefs/pref_change_registrar.h"
-
-class Profile;
-
-namespace safe_browsing {
-class ChromePasswordProtectionService;
-}
-
-namespace settings {
-
-// Chrome "Change Password" settings page UI handler.
-class ChangePasswordHandler : public SettingsPageUIHandler {
- public:
- explicit ChangePasswordHandler(
- Profile* profile,
- safe_browsing::ChromePasswordProtectionService* service);
- ~ChangePasswordHandler() override;
-
- // settings::SettingsPageUIHandler:
- void RegisterMessages() override;
- void OnJavascriptAllowed() override;
- void OnJavascriptDisallowed() override;
-
- private:
- void HandleInitialize(const base::ListValue* args);
-
- void HandleChangePassword(const base::ListValue* args);
-
- void UpdateChangePasswordCardVisibility();
-
- Profile* profile_;
-
- PrefChangeRegistrar pref_registrar_;
-
- safe_browsing::ChromePasswordProtectionService* service_;
-
- DISALLOW_COPY_AND_ASSIGN(ChangePasswordHandler);
-};
-
-} // namespace settings
-
-#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHANGE_PASSWORD_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/DEPS b/chromium/chrome/browser/ui/webui/settings/chromeos/DEPS
new file mode 100644
index 00000000000..eb3c6b1fa0c
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+chrome/services/local_search_service",
+ "+device/udev_linux/fake_udev_loader.h", # For keyboard unit test.
+]
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/OWNERS b/chromium/chrome/browser/ui/webui/settings/chromeos/OWNERS
index f42990c5d35..ff0d48d0403 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/OWNERS
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/OWNERS
@@ -1,3 +1,5 @@
+file://chrome/browser/resources/settings/chromeos/OWNERS
+
per-file multidevice_handler*=file://chromeos/components/multidevice/OWNERS
-# COMPONENT: UI>Settings
+# COMPONENT: OS>Systems>Settings
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
index 34dbb5b6fac..e1d62743ff2 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
@@ -4,8 +4,10 @@
#include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h"
+#include "ash/public/cpp/tablet_mode.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/metrics/histogram_functions.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
@@ -18,11 +20,24 @@
namespace chromeos {
namespace settings {
-AccessibilityHandler::AccessibilityHandler(content::WebUI* webui)
- : profile_(Profile::FromWebUI(webui)) {
+namespace {
+
+void RecordShowShelfNavigationButtonsValueChange(bool enabled) {
+ base::UmaHistogramBoolean(
+ "Accessibility.CrosShelfNavigationButtonsInTabletModeChanged."
+ "OsSettings",
+ enabled);
}
-AccessibilityHandler::~AccessibilityHandler() {}
+} // namespace
+
+AccessibilityHandler::AccessibilityHandler(Profile* profile)
+ : profile_(profile) {}
+
+AccessibilityHandler::~AccessibilityHandler() {
+ if (a11y_nav_buttons_toggle_metrics_reporter_timer_.IsRunning())
+ a11y_nav_buttons_toggle_metrics_reporter_timer_.FireNow();
+}
void AccessibilityHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
@@ -35,13 +50,21 @@ void AccessibilityHandler::RegisterMessages() {
&AccessibilityHandler::HandleShowSelectToSpeakSettings,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
- "getStartupSoundEnabled",
- base::BindRepeating(&AccessibilityHandler::HandleGetStartupSoundEnabled,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
"setStartupSoundEnabled",
base::BindRepeating(&AccessibilityHandler::HandleSetStartupSoundEnabled,
base::Unretained(this)));
+
+ web_ui()->RegisterMessageCallback(
+ "recordSelectedShowShelfNavigationButtonValue",
+ base::BindRepeating(
+ &AccessibilityHandler::
+ HandleRecordSelectedShowShelfNavigationButtonsValue,
+ base::Unretained(this)));
+
+ web_ui()->RegisterMessageCallback(
+ "manageA11yPageReady",
+ base::BindRepeating(&AccessibilityHandler::HandleManageA11yPageReady,
+ base::Unretained(this)));
}
void AccessibilityHandler::HandleShowChromeVoxSettings(
@@ -54,20 +77,54 @@ void AccessibilityHandler::HandleShowSelectToSpeakSettings(
OpenExtensionOptionsPage(extension_misc::kSelectToSpeakExtensionId);
}
-void AccessibilityHandler::HandleGetStartupSoundEnabled(
+void AccessibilityHandler::HandleSetStartupSoundEnabled(
const base::ListValue* args) {
- AllowJavascript();
- FireWebUIListener(
- "startup-sound-enabled-updated",
- base::Value(AccessibilityManager::Get()->GetStartupSoundEnabled()));
+ DCHECK_EQ(1U, args->GetSize());
+ bool enabled;
+ args->GetBoolean(0, &enabled);
+ AccessibilityManager::Get()->SetStartupSoundEnabled(enabled);
}
-void AccessibilityHandler::HandleSetStartupSoundEnabled(
+void AccessibilityHandler::HandleRecordSelectedShowShelfNavigationButtonsValue(
const base::ListValue* args) {
DCHECK_EQ(1U, args->GetSize());
bool enabled;
args->GetBoolean(0, &enabled);
- AccessibilityManager::Get()->SetStartupSoundEnabled(enabled);
+
+ a11y_nav_buttons_toggle_metrics_reporter_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(10),
+ base::BindOnce(&RecordShowShelfNavigationButtonsValueChange, enabled));
+}
+
+void AccessibilityHandler::HandleManageA11yPageReady(
+ const base::ListValue* args) {
+ AllowJavascript();
+
+ // When tablet mode is active we can return early since tablet mode
+ // is supported.
+ if (ash::TabletMode::Get()->InTabletMode()) {
+ FireWebUIListener(
+ "initial-data-ready",
+ base::Value(AccessibilityManager::Get()->GetStartupSoundEnabled()),
+ base::Value(true /* tablet_mode_supported */));
+ return;
+ }
+
+ PowerManagerClient::Get()->GetSwitchStates(
+ base::BindOnce(&AccessibilityHandler::OnReceivedSwitchStates,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void AccessibilityHandler::OnReceivedSwitchStates(
+ base::Optional<PowerManagerClient::SwitchStates> switch_states) {
+ bool tablet_mode_supported =
+ switch_states.has_value() &&
+ switch_states->tablet_mode != PowerManagerClient::TabletMode::UNSUPPORTED;
+
+ FireWebUIListener(
+ "initial-data-ready",
+ base::Value(AccessibilityManager::Get()->GetStartupSoundEnabled()),
+ base::Value(tablet_mode_supported));
}
void AccessibilityHandler::OpenExtensionOptionsPage(const char extension_id[]) {
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
index 80d735832cb..54290f81dd8 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
@@ -6,16 +6,14 @@
#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ACCESSIBILITY_HANDLER_H_
#include "base/macros.h"
+#include "base/timer/timer.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "chromeos/dbus/power/power_manager_client.h"
namespace base {
class ListValue;
}
-namespace content {
-class WebUI;
-}
-
class Profile;
namespace chromeos {
@@ -23,7 +21,7 @@ namespace settings {
class AccessibilityHandler : public ::settings::SettingsPageUIHandler {
public:
- explicit AccessibilityHandler(content::WebUI* webui);
+ explicit AccessibilityHandler(Profile* profile);
~AccessibilityHandler() override;
// SettingsPageUIHandler implementation.
@@ -31,18 +29,36 @@ class AccessibilityHandler : public ::settings::SettingsPageUIHandler {
void OnJavascriptAllowed() override {}
void OnJavascriptDisallowed() override {}
+ // Callback which updates if startup sound is enabled and if tablet
+ // mode is supported. Visible for testing.
+ void HandleManageA11yPageReady(const base::ListValue* args);
+
private:
// Callback for the messages to show settings for ChromeVox or
// Select To Speak.
void HandleShowChromeVoxSettings(const base::ListValue* args);
void HandleShowSelectToSpeakSettings(const base::ListValue* args);
- void HandleGetStartupSoundEnabled(const base::ListValue* args);
void HandleSetStartupSoundEnabled(const base::ListValue* args);
+ void HandleRecordSelectedShowShelfNavigationButtonsValue(
+ const base::ListValue* args);
+
+ // Callback which updates visibility for the shelf navigation buttons
+ // accessibility setting, depending on whether tablet mode is supported.
+ void OnReceivedSwitchStates(
+ base::Optional<chromeos::PowerManagerClient::SwitchStates> switch_states);
void OpenExtensionOptionsPage(const char extension_id[]);
Profile* profile_; // Weak pointer.
+ // Timer to record user changed value for the accessibility setting to turn
+ // shelf navigation buttons on in tablet mode. The metric is recorded with 10
+ // second delay to avoid overreporting when the user keeps toggling the
+ // setting value in the screen UI.
+ base::OneShotTimer a11y_nav_buttons_toggle_metrics_reporter_timer_;
+
+ base::WeakPtrFactory<AccessibilityHandler> weak_ptr_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(AccessibilityHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_unittest.cc
new file mode 100644
index 00000000000..8ee78caacd8
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_unittest.cc
@@ -0,0 +1,103 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h"
+
+#include <memory>
+
+#include "ash/public/cpp/test/test_tablet_mode.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chromeos/dbus/power/fake_power_manager_client.h"
+#include "content/public/test/test_web_ui.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace settings {
+
+class TestingAccessibilityHandler : public AccessibilityHandler {
+ public:
+ explicit TestingAccessibilityHandler(content::WebUI* web_ui)
+ : AccessibilityHandler(/* profile */ nullptr) {
+ set_web_ui(web_ui);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestingAccessibilityHandler);
+};
+
+class AccessibilityHandlerTest : public ChromeRenderViewHostTestHarness {
+ public:
+ AccessibilityHandlerTest() = default;
+ AccessibilityHandlerTest(const AccessibilityHandlerTest&) = delete;
+ AccessibilityHandlerTest& operator=(const AccessibilityHandlerTest&) = delete;
+
+ void SetUp() override {
+ ChromeRenderViewHostTestHarness::SetUp();
+ PowerManagerClient::InitializeFake();
+ test_tablet_mode_ = std::make_unique<ash::TestTabletMode>();
+ handler_ = std::make_unique<TestingAccessibilityHandler>(&web_ui_);
+ }
+
+ void TearDown() override {
+ handler_.reset();
+ test_tablet_mode_.reset();
+ PowerManagerClient::Shutdown();
+ ChromeRenderViewHostTestHarness::TearDown();
+ }
+
+ content::TestWebUI web_ui_;
+ std::unique_ptr<ash::TestTabletMode> test_tablet_mode_;
+ std::unique_ptr<TestingAccessibilityHandler> handler_;
+};
+
+// Test that when tablet mode is supported, the correct data is returned by
+// HandleManageA11yPageReady().
+TEST_F(AccessibilityHandlerTest, ManageA11yPageReadyTabletModeSupported) {
+ // Set tablet mode as supported.
+ chromeos::FakePowerManagerClient::Get()->SetTabletMode(
+ chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks());
+
+ handler_->HandleManageA11yPageReady(/* args */ nullptr);
+
+ // Wait for the AccessibilityHandler to receive data from PowerManagerClient.
+ base::RunLoop().RunUntilIdle();
+
+ const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
+
+ // Ensure tablet mode is returned as supported.
+ EXPECT_TRUE(call_data.arg3()->GetBool());
+}
+
+// Test that when tablet mode is unsupported, the correct data is returned by
+// HandleManageA11yPageReady().
+TEST_F(AccessibilityHandlerTest, ManageA11yPageReadyTabletModeUnsupported) {
+ // Set tablet mode as unsupported.
+ chromeos::FakePowerManagerClient::Get()->SetTabletMode(
+ chromeos::PowerManagerClient::TabletMode::UNSUPPORTED, base::TimeTicks());
+ handler_->HandleManageA11yPageReady(/* args */ nullptr);
+
+ // Wait for the AccessibilityHandler to receive data from PowerManagerClient.
+ base::RunLoop().RunUntilIdle();
+
+ const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
+
+ // Ensure tablet mode is returned as unsupported.
+ EXPECT_FALSE(call_data.arg3()->GetBool());
+}
+
+// Test that when tablet mode is enabled, the correct data is returned by
+// HandleManageA11yPageReady().
+TEST_F(AccessibilityHandlerTest, ManageA11yPageReadyTabletModeEnabled) {
+ test_tablet_mode_->SetEnabledForTest(true);
+ handler_->HandleManageA11yPageReady(/* args */ nullptr);
+
+ const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
+
+ // Ensure tablet mode is returned as supported.
+ EXPECT_TRUE(call_data.arg3()->GetBool());
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
index a8b296703d0..e6d80c5a757 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
@@ -23,6 +23,7 @@
#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h"
#include "chrome/grit/generated_resources.h"
#include "chromeos/components/account_manager/account_manager_factory.h"
+#include "components/signin/public/identity_manager/consent_level.h"
#include "components/user_manager/user.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/google_service_auth_error.h"
@@ -273,12 +274,13 @@ void AccountManagerUIHandler::OnGetAccounts(
GetEnterpriseDomainFromUsername(user->GetDisplayEmail()));
} else if (profile_->GetProfilePolicyConnector()->IsManaged()) {
device_account.SetOrganization(GetEnterpriseDomainFromUsername(
- identity_manager_->GetPrimaryAccountInfo().email));
+ identity_manager_
+ ->GetPrimaryAccountInfo(signin::ConsentLevel::kNotRequired)
+ .email));
}
// Device account must show up at the top.
- accounts.GetList().insert(accounts.GetList().begin(),
- device_account.Build());
+ accounts.Insert(accounts.GetList().begin(), device_account.Build());
}
ResolveJavascriptCallback(callback_id, accounts);
@@ -418,17 +420,26 @@ void AccountManagerUIHandler::OnAccountRemoved(
RefreshUI();
}
-// |signin::IdentityManager::Observer| overrides. For newly added accounts,
-// |signin::IdentityManager| may take some time to fetch user's full name and
-// account image. Whenever that is completed, we may need to update the UI with
-// this new set of information. Note that we may be listening to
-// |signin::IdentityManager| but we still consider |AccountManager| to be the
-// source of truth for account list.
+// |signin::IdentityManager::Observer| overrides.
+//
+// For newly added accounts, |signin::IdentityManager| may take some time to
+// fetch user's full name and account image. Whenever that is completed, we may
+// need to update the UI with this new set of information. Note that we may be
+// listening to |signin::IdentityManager| but we still consider |AccountManager|
+// to be the source of truth for account list.
void AccountManagerUIHandler::OnExtendedAccountInfoUpdated(
const AccountInfo& info) {
RefreshUI();
}
+void AccountManagerUIHandler::OnErrorStateOfRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info,
+ const GoogleServiceAuthError& error) {
+ if (error.state() != GoogleServiceAuthError::NONE) {
+ RefreshUI();
+ }
+}
+
void AccountManagerUIHandler::RefreshUI() {
FireWebUIListener("accounts-changed");
}
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
index 39f24fbbbec..21e8adf1bc8 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
@@ -44,6 +44,9 @@ class AccountManagerUIHandler : public ::settings::SettingsPageUIHandler,
// |signin::IdentityManager::Observer| overrides.
void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
+ void OnErrorStateOfRefreshTokenUpdatedForAccount(
+ const CoreAccountInfo& account_info,
+ const GoogleServiceAuthError& error) override;
private:
friend class AccountManagerUIHandlerTest;
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc
new file mode 100644
index 00000000000..e3c7e6d7645
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc
@@ -0,0 +1,32 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h"
+
+#include "base/bind.h"
+#include "base/values.h"
+
+namespace chromeos {
+namespace settings {
+
+AmbientModeHandler::AmbientModeHandler() = default;
+
+AmbientModeHandler::~AmbientModeHandler() = default;
+
+void AmbientModeHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "onAmbientModePageReady",
+ base::BindRepeating(&AmbientModeHandler::HandleInitialized,
+ base::Unretained(this)));
+}
+
+void AmbientModeHandler::HandleInitialized(const base::ListValue* args) {
+ CHECK(args);
+ CHECK(args->empty());
+
+ AllowJavascript();
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h
new file mode 100644
index 00000000000..a52b109160a
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_AMBIENT_MODE_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_AMBIENT_MODE_HANDLER_H_
+
+#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+
+namespace base {
+class ListValue;
+} // namespace base
+
+namespace chromeos {
+namespace settings {
+
+// Chrome OS ambient mode settings page UI handler, to allow users to customize
+// photo frame and other related functionalities.
+class AmbientModeHandler : public ::settings::SettingsPageUIHandler {
+ public:
+ AmbientModeHandler();
+ AmbientModeHandler(const AmbientModeHandler&) = delete;
+ AmbientModeHandler& operator=(const AmbientModeHandler&) = delete;
+ ~AmbientModeHandler() override;
+
+ // settings::SettingsPageUIHandler:
+ void RegisterMessages() override;
+ void OnJavascriptAllowed() override {}
+ void OnJavascriptDisallowed() override {}
+
+ private:
+ // WebUI call to signal js side is ready.
+ void HandleInitialized(const base::ListValue* args);
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_AMBIENT_MODE_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc
new file mode 100644
index 00000000000..c9cfb838ce3
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc
@@ -0,0 +1,393 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h"
+
+#include <numeric>
+
+#include "base/system/sys_info.h"
+#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
+#include "base/values.h"
+#include "chrome/browser/browsing_data/browsing_data_appcache_helper.h"
+#include "chrome/browser/browsing_data/browsing_data_cache_storage_helper.h"
+#include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
+#include "chrome/browser/browsing_data/browsing_data_database_helper.h"
+#include "chrome/browser/browsing_data/browsing_data_file_system_helper.h"
+#include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h"
+#include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h"
+#include "chrome/browser/browsing_data/browsing_data_service_worker_helper.h"
+#include "chrome/browser/chromeos/crostini/crostini_features.h"
+#include "chrome/browser/chromeos/file_manager/path_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chromeos/cryptohome/cryptohome_util.h"
+#include "chromeos/dbus/cryptohome/cryptohome_client.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/session/arc_bridge_service.h"
+#include "components/arc/storage_manager/arc_storage_manager.h"
+#include "components/browsing_data/content/conditional_cache_counting_helper.h"
+#include "components/browsing_data/content/local_storage_helper.h"
+#include "components/user_manager/user_manager.h"
+#include "content/public/browser/storage_partition.h"
+
+namespace chromeos {
+namespace settings {
+namespace calculator {
+
+namespace {
+
+void GetSizeStatBlocking(const base::FilePath& mount_path,
+ int64_t* total_size,
+ int64_t* available_size) {
+ int64_t size = base::SysInfo::AmountOfTotalDiskSpace(mount_path);
+ if (size >= 0)
+ *total_size = size;
+ size = base::SysInfo::AmountOfFreeDiskSpace(mount_path);
+ if (size >= 0)
+ *available_size = size;
+}
+
+} // namespace
+
+SizeCalculator::SizeCalculator(const CalculationType& calculation_type)
+ : calculation_type_(calculation_type) {}
+
+SizeCalculator::~SizeCalculator() {}
+
+void SizeCalculator::StartCalculation() {
+ if (calculating_)
+ return;
+ calculating_ = true;
+ PerformCalculation();
+}
+
+void SizeCalculator::AddObserver(SizeCalculator::Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void SizeCalculator::RemoveObserver(SizeCalculator::Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void SizeCalculator::NotifySizeCalculated(
+ int64_t total_bytes,
+ const base::Optional<int64_t>& available_bytes) {
+ calculating_ = false;
+ for (SizeCalculator::Observer& observer : observers_) {
+ observer.OnSizeCalculated(calculation_type_, total_bytes, available_bytes);
+ }
+}
+
+SizeStatCalculator::SizeStatCalculator(Profile* profile)
+ : SizeCalculator(CalculationType::kInUse), profile_(profile) {}
+
+SizeStatCalculator::~SizeStatCalculator() = default;
+void SizeStatCalculator::PerformCalculation() {
+ const base::FilePath my_files_path =
+ file_manager::util::GetMyFilesFolderForProfile(profile_);
+
+ int64_t* total_size = new int64_t(0);
+ int64_t* available_size = new int64_t(0);
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::Bind(&GetSizeStatBlocking, my_files_path, total_size,
+ available_size),
+ base::Bind(&SizeStatCalculator::OnGetSizeStat,
+ weak_ptr_factory_.GetWeakPtr(), base::Owned(total_size),
+ base::Owned(available_size)));
+}
+
+void SizeStatCalculator::OnGetSizeStat(int64_t* total_bytes,
+ int64_t* available_bytes) {
+ NotifySizeCalculated(*total_bytes, *available_bytes);
+}
+
+MyFilesSizeCalculator::MyFilesSizeCalculator(Profile* profile)
+ : SizeCalculator(CalculationType::kMyFiles), profile_(profile) {}
+
+MyFilesSizeCalculator::~MyFilesSizeCalculator() = default;
+
+void MyFilesSizeCalculator::PerformCalculation() {
+ const base::FilePath my_files_path =
+ file_manager::util::GetMyFilesFolderForProfile(profile_);
+
+ const base::FilePath android_files_path =
+ base::FilePath(file_manager::util::GetAndroidFilesPath());
+
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&MyFilesSizeCalculator::ComputeLocalFilesSize,
+ base::Unretained(this), my_files_path, android_files_path),
+ base::BindOnce(&MyFilesSizeCalculator::OnGetMyFilesSize,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+int64_t MyFilesSizeCalculator::ComputeLocalFilesSize(
+ const base::FilePath& my_files_path,
+ const base::FilePath& android_files_path) {
+ int64_t size = 0;
+
+ // Compute directory size of My Files.
+ size += base::ComputeDirectorySize(my_files_path);
+
+ // Compute directory size of Play Files.
+ size += base::ComputeDirectorySize(android_files_path);
+
+ // Remove size of Download. If Android is enabled, the size of the Download
+ // folder is counted in both My Files and Play files. If Android is disabled,
+ // the Download folder doesn't exist and the returned size is 0.
+ const base::FilePath download_files_path =
+ android_files_path.AppendASCII("Download");
+ size -= base::ComputeDirectorySize(download_files_path);
+
+ return size;
+}
+
+void MyFilesSizeCalculator::OnGetMyFilesSize(int64_t total_bytes) {
+ NotifySizeCalculated(total_bytes);
+}
+
+BrowsingDataSizeCalculator::BrowsingDataSizeCalculator(Profile* profile)
+ : SizeCalculator(CalculationType::kBrowsingData), profile_(profile) {}
+
+BrowsingDataSizeCalculator::~BrowsingDataSizeCalculator() = default;
+
+void BrowsingDataSizeCalculator::PerformCalculation() {
+ has_browser_cache_size_ = false;
+ has_browser_site_data_size_ = false;
+
+ // Fetch the size of http cache in browsing data.
+ browsing_data::ConditionalCacheCountingHelper::Count(
+ content::BrowserContext::GetDefaultStoragePartition(profile_),
+ base::Time(), base::Time::Max(),
+ base::BindOnce(&BrowsingDataSizeCalculator::OnGetCacheSize,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ // Fetch the size of site data in browsing data.
+ if (!site_data_size_collector_.get()) {
+ content::StoragePartition* storage_partition =
+ content::BrowserContext::GetDefaultStoragePartition(profile_);
+ site_data_size_collector_ = std::make_unique<SiteDataSizeCollector>(
+ storage_partition->GetPath(),
+ new BrowsingDataCookieHelper(storage_partition),
+ new BrowsingDataDatabaseHelper(profile_),
+ new browsing_data::LocalStorageHelper(profile_),
+ new BrowsingDataAppCacheHelper(storage_partition->GetAppCacheService()),
+ new BrowsingDataIndexedDBHelper(storage_partition),
+ BrowsingDataFileSystemHelper::Create(
+ storage_partition->GetFileSystemContext()),
+ new BrowsingDataServiceWorkerHelper(
+ storage_partition->GetServiceWorkerContext()),
+ new BrowsingDataCacheStorageHelper(
+ storage_partition->GetCacheStorageContext()),
+ BrowsingDataFlashLSOHelper::Create(profile_));
+ }
+ site_data_size_collector_->Fetch(
+ base::Bind(&BrowsingDataSizeCalculator::OnGetBrowsingDataSize,
+ weak_ptr_factory_.GetWeakPtr(), /*is_site_data=*/true));
+}
+
+void BrowsingDataSizeCalculator::OnGetCacheSize(bool is_upper_limit,
+ int64_t size) {
+ DCHECK(!is_upper_limit);
+ OnGetBrowsingDataSize(/*is_site_data=*/false, size);
+}
+
+void BrowsingDataSizeCalculator::OnGetBrowsingDataSize(bool is_site_data,
+ int64_t size) {
+ if (is_site_data) {
+ has_browser_site_data_size_ = true;
+ browser_site_data_size_ = size;
+ } else {
+ has_browser_cache_size_ = true;
+ browser_cache_size_ = size;
+ }
+ if (has_browser_cache_size_ && has_browser_site_data_size_) {
+ int64_t browsing_data_size;
+ if (browser_cache_size_ >= 0 && browser_site_data_size_ >= 0) {
+ browsing_data_size = browser_site_data_size_ + browser_cache_size_;
+ } else {
+ browsing_data_size = -1;
+ }
+ calculating_ = false;
+ NotifySizeCalculated(browsing_data_size);
+ }
+}
+
+AppsSizeCalculator::AppsSizeCalculator(Profile* profile)
+ : SizeCalculator(CalculationType::kAppsExtensions), profile_(profile) {}
+
+AppsSizeCalculator::~AppsSizeCalculator() {
+ arc::ArcServiceManager::Get()
+ ->arc_bridge_service()
+ ->storage_manager()
+ ->RemoveObserver(this);
+}
+
+void AppsSizeCalculator::OnConnectionReady() {
+ is_android_running_ = true;
+ StartCalculation();
+}
+
+void AppsSizeCalculator::OnConnectionClosed() {
+ is_android_running_ = false;
+}
+
+void AppsSizeCalculator::AddObserver(SizeCalculator::Observer* observer) {
+ // Start observing arc mojo connection when the first observer is added, to
+ // allow the calculation of android apps.
+ if (!observers_.might_have_observers()) {
+ arc::ArcServiceManager::Get()
+ ->arc_bridge_service()
+ ->storage_manager()
+ ->AddObserver(this);
+ }
+ observers_.AddObserver(observer);
+}
+
+void AppsSizeCalculator::RemoveObserver(SizeCalculator::Observer* observer) {
+ observers_.RemoveObserver(observer);
+ // Stop observing arc connection if all observers have been removed.
+ if (!observers_.might_have_observers()) {
+ arc::ArcServiceManager::Get()
+ ->arc_bridge_service()
+ ->storage_manager()
+ ->RemoveObserver(this);
+ }
+}
+
+void AppsSizeCalculator::PerformCalculation() {
+ apps_extensions_size_ = 0;
+ has_apps_extensions_size_ = false;
+ android_apps_size_ = 0;
+ has_android_apps_size_ = false;
+
+ UpdateAppsSize();
+ UpdateAndroidAppsSize();
+}
+
+void AppsSizeCalculator::UpdateAppsSize() {
+ // Apps and extensions installed from the web store located in
+ // [user-hash]/Extensions.
+ const base::FilePath extensions_path =
+ profile_->GetPath().AppendASCII("Extensions");
+
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&base::ComputeDirectorySize, extensions_path),
+ base::BindOnce(&AppsSizeCalculator::OnGetAppsSize,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void AppsSizeCalculator::OnGetAppsSize(int64_t total_bytes) {
+ apps_extensions_size_ = total_bytes;
+ has_apps_extensions_size_ = true;
+ UpdateAppsAndExtensionsSize();
+}
+
+void AppsSizeCalculator::UpdateAndroidAppsSize() {
+ if (!is_android_running_) {
+ has_android_apps_size_ = true;
+ UpdateAppsAndExtensionsSize();
+ return;
+ }
+
+ bool success = false;
+ auto* arc_storage_manager =
+ arc::ArcStorageManager::GetForBrowserContext(profile_);
+ if (arc_storage_manager) {
+ success = arc_storage_manager->GetApplicationsSize(
+ base::BindOnce(&AppsSizeCalculator::OnGetAndroidAppsSize,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+ if (!success) {
+ has_android_apps_size_ = true;
+ UpdateAppsAndExtensionsSize();
+ }
+}
+
+void AppsSizeCalculator::OnGetAndroidAppsSize(
+ bool succeeded,
+ arc::mojom::ApplicationsSizePtr size) {
+ has_android_apps_size_ = true;
+ if (succeeded) {
+ android_apps_size_ = size->total_code_bytes + size->total_data_bytes +
+ size->total_cache_bytes;
+ }
+ UpdateAppsAndExtensionsSize();
+}
+
+void AppsSizeCalculator::UpdateAppsAndExtensionsSize() {
+ if (has_apps_extensions_size_ && has_android_apps_size_) {
+ calculating_ = false;
+ NotifySizeCalculated(apps_extensions_size_ + android_apps_size_);
+ }
+}
+
+CrostiniSizeCalculator::CrostiniSizeCalculator(Profile* profile)
+ : SizeCalculator(CalculationType::kCrostini), profile_(profile) {}
+
+CrostiniSizeCalculator::~CrostiniSizeCalculator() = default;
+
+void CrostiniSizeCalculator::PerformCalculation() {
+ if (!crostini::CrostiniFeatures::Get()->IsEnabled(profile_)) {
+ NotifySizeCalculated(0);
+ return;
+ }
+
+ crostini::CrostiniManager::GetForProfile(profile_)->ListVmDisks(
+ base::BindOnce(&CrostiniSizeCalculator::OnGetCrostiniSize,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CrostiniSizeCalculator::OnGetCrostiniSize(crostini::CrostiniResult result,
+ int64_t total_bytes) {
+ calculating_ = false;
+ NotifySizeCalculated(total_bytes);
+}
+
+OtherUsersSizeCalculator::OtherUsersSizeCalculator()
+ : SizeCalculator(CalculationType::kOtherUsers) {}
+
+OtherUsersSizeCalculator::~OtherUsersSizeCalculator() = default;
+
+void OtherUsersSizeCalculator::PerformCalculation() {
+ other_users_.clear();
+ user_sizes_.clear();
+ const user_manager::UserList& users =
+ user_manager::UserManager::Get()->GetUsers();
+ for (auto* user : users) {
+ if (user->is_active())
+ continue;
+ other_users_.push_back(user);
+ CryptohomeClient::Get()->GetAccountDiskUsage(
+ cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId()),
+ base::BindOnce(&OtherUsersSizeCalculator::OnGetOtherUserSize,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+ // We should show "0 B" if there is no other user.
+ if (other_users_.empty()) {
+ NotifySizeCalculated(0);
+ }
+}
+
+void OtherUsersSizeCalculator::OnGetOtherUserSize(
+ base::Optional<cryptohome::BaseReply> reply) {
+ user_sizes_.push_back(cryptohome::AccountDiskUsageReplyToUsageSize(reply));
+ if (user_sizes_.size() != other_users_.size())
+ return;
+ int64_t other_users_total_bytes;
+ // If all the requests succeed, shows the total bytes in the UI.
+ if (std::count(user_sizes_.begin(), user_sizes_.end(), -1) == 0) {
+ other_users_total_bytes =
+ std::accumulate(user_sizes_.begin(), user_sizes_.end(), 0LL);
+ } else {
+ other_users_total_bytes = -1;
+ }
+ NotifySizeCalculated(other_users_total_bytes);
+}
+
+} // namespace calculator
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h
new file mode 100644
index 00000000000..8f483f50b95
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h
@@ -0,0 +1,296 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CALCULATOR_SIZE_CALCULATOR_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CALCULATOR_SIZE_CALCULATOR_H_
+
+#include <array>
+#include <bitset>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/files/file_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list_types.h"
+#include "base/values.h"
+#include "chrome/browser/browsing_data/site_data_size_collector.h"
+#include "chrome/browser/chromeos/crostini/crostini_manager.h"
+#include "chromeos/dbus/cryptohome/rpc.pb.h"
+#include "components/arc/mojom/storage_manager.mojom.h"
+#include "components/arc/session/connection_observer.h"
+#include "components/arc/storage_manager/arc_storage_manager.h"
+#include "components/user_manager/user.h"
+
+class Profile;
+
+namespace chromeos {
+namespace settings {
+namespace calculator {
+
+// Base class for the calculation of a specific storage item. Instances of this
+// class rely on their observers calling StartCalculation, and are designed to
+// notify observers about the calculated sizes.
+class SizeCalculator {
+ public:
+ // Enumeration listing the items displayed on the storage page.
+ enum class CalculationType {
+ kInUse = 0,
+ kMyFiles,
+ kBrowsingData,
+ kAppsExtensions,
+ kCrostini,
+ kOtherUsers,
+ kLast = kOtherUsers,
+ kSystem,
+ };
+
+ // Implement this interface to be notified about item size callbacks.
+ class Observer : public base::CheckedObserver {
+ public:
+ virtual void OnSizeCalculated(
+ const CalculationType& item_id,
+ int64_t total_bytes,
+ const base::Optional<int64_t>& available_bytes) = 0;
+ };
+
+ // Total number of storage items.
+ static constexpr int kCalculationTypeCount =
+ static_cast<int>(CalculationType::kLast) + 1;
+
+ explicit SizeCalculator(const CalculationType& calculation_type);
+ virtual ~SizeCalculator();
+
+ // Starts the size calculation of a given storage item.
+ void StartCalculation();
+
+ // Adds an observer.
+ virtual void AddObserver(Observer* observer);
+
+ // Removes an observer.
+ virtual void RemoveObserver(Observer* observer);
+
+ protected:
+ // Performs the size calculation.
+ virtual void PerformCalculation() = 0;
+
+ // Notify the StorageHandler about the calculated storage item size
+ void NotifySizeCalculated(
+ int64_t total_bytes,
+ const base::Optional<int64_t>& available_bytes = base::nullopt);
+
+ // Item id.
+ const CalculationType calculation_type_;
+
+ // Flag indicating that fetch operations for storage size are ongoing.
+ bool calculating_ = false;
+ // Observers being notified about storage items size changes.
+ base::ObserverList<SizeCalculator::Observer> observers_;
+};
+
+// Class handling the interactions with the filesystem to get storage
+// statistics, using OnSizeStatCalculated to notify observers.
+class SizeStatCalculator : public SizeCalculator {
+ public:
+ explicit SizeStatCalculator(Profile* profile);
+ ~SizeStatCalculator() override;
+
+ SizeStatCalculator(const SizeStatCalculator&) = delete;
+ SizeStatCalculator& operator=(const SizeStatCalculator&) = delete;
+
+ private:
+ friend class SizeStatTestAPI;
+
+ void PerformCalculation() override;
+
+ // Updates disk space information.
+ void OnGetSizeStat(int64_t* total_bytes, int64_t* available_bytes);
+
+ Profile* profile_;
+ base::WeakPtrFactory<SizeStatCalculator> weak_ptr_factory_{this};
+};
+
+// Class handling the calculation of the size of the user's personal files: My
+// files + Android Play files.
+class MyFilesSizeCalculator : public SizeCalculator {
+ public:
+ explicit MyFilesSizeCalculator(Profile* profile);
+ ~MyFilesSizeCalculator() override;
+
+ MyFilesSizeCalculator(const MyFilesSizeCalculator&) = delete;
+ MyFilesSizeCalculator& operator=(const MyFilesSizeCalculator&) = delete;
+
+ private:
+ friend class MyFilesSizeTestAPI;
+
+ void PerformCalculation() override;
+
+ // Computes the size of My Files and Play files.
+ int64_t ComputeLocalFilesSize(const base::FilePath& my_files_path,
+ const base::FilePath& android_files_path);
+
+ // Updates the size of My Files and Play files.
+ void OnGetMyFilesSize(int64_t total_bytes);
+
+ Profile* profile_;
+ base::WeakPtrFactory<MyFilesSizeCalculator> weak_ptr_factory_{this};
+};
+
+// Class handling the calculation of browsing data and cache.
+class BrowsingDataSizeCalculator : public SizeCalculator {
+ public:
+ explicit BrowsingDataSizeCalculator(Profile* profile);
+ ~BrowsingDataSizeCalculator() override;
+
+ BrowsingDataSizeCalculator(const BrowsingDataSizeCalculator&) = delete;
+ BrowsingDataSizeCalculator& operator=(const BrowsingDataSizeCalculator&) =
+ delete;
+
+ private:
+ friend class BrowsingDataSizeTestAPI;
+
+ void PerformCalculation() override;
+
+ // Callback to receive the cache size.
+ void OnGetCacheSize(bool is_upper_limit, int64_t size);
+
+ // Callback to update the size of browsing data.
+ void OnGetBrowsingDataSize(bool is_site_data, int64_t size);
+
+ // Total size of cache data in browsing data.
+ int64_t browser_cache_size_ = -1;
+
+ // True if we have already received the size of http cache.
+ bool has_browser_cache_size_ = false;
+
+ // Total size of site data in browsing data.
+ int64_t browser_site_data_size_ = -1;
+
+ // True if we have already received the size of http cache.
+ bool has_browser_site_data_size_ = false;
+
+ // Helper to compute the total size of all types of site date.
+ std::unique_ptr<SiteDataSizeCollector> site_data_size_collector_;
+
+ Profile* profile_;
+ base::WeakPtrFactory<BrowsingDataSizeCalculator> weak_ptr_factory_{this};
+};
+
+// Class handling the calculation of the size of the user's apps and extensions.
+class AppsSizeCalculator
+ : public SizeCalculator,
+ public arc::ConnectionObserver<arc::mojom::StorageManagerInstance> {
+ public:
+ explicit AppsSizeCalculator(Profile* profile);
+ ~AppsSizeCalculator() override;
+
+ AppsSizeCalculator(const AppsSizeCalculator&) = delete;
+ AppsSizeCalculator& operator=(const AppsSizeCalculator&) = delete;
+
+ // arc::ConnectionObserver<arc::mojom::StorageManagerInstance>:
+ void OnConnectionReady() override;
+ void OnConnectionClosed() override;
+
+ // Adds an observer. When the first observer is added, start observing the arc
+ // mojo connection UpdateAndroidAppsSize relies on.
+ void AddObserver(Observer* observer) override;
+
+ // Removes an observer. When the last observer is removed, stop observing the
+ // arc mojo connection.
+ void RemoveObserver(Observer* observer) override;
+
+ private:
+ friend class AppsSizeTestAPI;
+
+ void PerformCalculation() override;
+
+ // Requests updating the size of web store apps and extensions.
+ void UpdateAppsSize();
+
+ // Callback to update web store apps and extensions size.
+ void OnGetAppsSize(int64_t total_bytes);
+
+ // Requests updating the size of android apps.
+ void UpdateAndroidAppsSize();
+
+ // Callback to update Android apps and cache.
+ void OnGetAndroidAppsSize(bool succeeded,
+ arc::mojom::ApplicationsSizePtr size);
+
+ // Updates apps and extensions size.
+ void UpdateAppsAndExtensionsSize();
+
+ // Total size of apps and extensions
+ int64_t apps_extensions_size_ = 0;
+
+ // True if we have already received the size of apps and extensions.
+ bool has_apps_extensions_size_ = false;
+
+ // Total size of android apps
+ int64_t android_apps_size_ = 0;
+
+ // True if we have already received the size of Android apps.
+ bool has_android_apps_size_ = false;
+
+ // A flag for keeping track of the mojo connection status to the ARC
+ // container.
+ bool is_android_running_ = false;
+
+ Profile* profile_;
+ base::WeakPtrFactory<AppsSizeCalculator> weak_ptr_factory_{this};
+};
+
+// Class handling the calculation of crostini VM size.
+class CrostiniSizeCalculator : public SizeCalculator {
+ public:
+ explicit CrostiniSizeCalculator(Profile* profile);
+ ~CrostiniSizeCalculator() override;
+
+ CrostiniSizeCalculator(const CrostiniSizeCalculator&) = delete;
+ CrostiniSizeCalculator& operator=(const CrostiniSizeCalculator&) = delete;
+
+ private:
+ friend class CrostiniSizeTestAPI;
+
+ void PerformCalculation() override;
+
+ // Callback to update the size of Crostini VMs.
+ void OnGetCrostiniSize(crostini::CrostiniResult result, int64_t size);
+
+ Profile* profile_;
+ base::WeakPtrFactory<CrostiniSizeCalculator> weak_ptr_factory_{this};
+};
+
+// Class handling the calculation of other users' cryptohomes.
+class OtherUsersSizeCalculator : public SizeCalculator {
+ public:
+ OtherUsersSizeCalculator();
+ ~OtherUsersSizeCalculator() override;
+
+ OtherUsersSizeCalculator(const OtherUsersSizeCalculator&) = delete;
+ OtherUsersSizeCalculator& operator=(const OtherUsersSizeCalculator&) = delete;
+
+ private:
+ friend class OtherUsersSizeTestAPI;
+
+ void PerformCalculation() override;
+
+ // Callback to update the sizes of the other users.
+ void OnGetOtherUserSize(base::Optional<cryptohome::BaseReply> reply);
+
+ // The list of other users whose directory sizes will be accumulated as the
+ // size of "Other users".
+ user_manager::UserList other_users_;
+
+ // Fetched sizes of user directories.
+ std::vector<int64_t> user_sizes_;
+
+ base::WeakPtrFactory<OtherUsersSizeCalculator> weak_ptr_factory_{this};
+};
+
+} // namespace calculator
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CALCULATOR_SIZE_CALCULATOR_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h
new file mode 100644
index 00000000000..2e0850df244
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h
@@ -0,0 +1,156 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CALCULATOR_SIZE_CALCULATOR_TEST_API_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CALCULATOR_SIZE_CALCULATOR_TEST_API_H_
+
+#include <utility>
+
+#include "chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h"
+
+namespace chromeos {
+namespace settings {
+namespace calculator {
+
+class SizeStatTestAPI {
+ public:
+ explicit SizeStatTestAPI(StorageHandler* handler,
+ SizeStatCalculator* size_stat_calculator) {
+ size_stat_calculator_ = size_stat_calculator;
+ size_stat_calculator_->AddObserver(handler);
+ }
+
+ void StartCalculation() { size_stat_calculator_->StartCalculation(); }
+
+ void SimulateOnGetSizeStat(int64_t* total_size, int64_t* available_size) {
+ size_stat_calculator_->OnGetSizeStat(total_size, available_size);
+ }
+
+ private:
+ SizeStatCalculator* size_stat_calculator_;
+};
+
+class MyFilesSizeTestAPI {
+ public:
+ explicit MyFilesSizeTestAPI(StorageHandler* handler,
+ MyFilesSizeCalculator* my_files_size_calculator) {
+ my_files_size_calculator_ = my_files_size_calculator;
+ my_files_size_calculator_->AddObserver(handler);
+ }
+
+ void StartCalculation() { my_files_size_calculator_->StartCalculation(); }
+
+ void SimulateOnGetTotalBytes(int64_t total_bytes) {
+ my_files_size_calculator_->NotifySizeCalculated(total_bytes);
+ }
+
+ private:
+ MyFilesSizeCalculator* my_files_size_calculator_;
+};
+
+class BrowsingDataSizeTestAPI {
+ public:
+ explicit BrowsingDataSizeTestAPI(
+ StorageHandler* handler,
+ BrowsingDataSizeCalculator* browsing_data_size_calculator) {
+ browsing_data_size_calculator_ = browsing_data_size_calculator;
+ browsing_data_size_calculator_->AddObserver(handler);
+ }
+
+ void StartCalculation() {
+ browsing_data_size_calculator_->StartCalculation();
+ }
+
+ void SimulateOnGetBrowsingDataSize(bool is_site_data, int64_t size) {
+ browsing_data_size_calculator_->OnGetBrowsingDataSize(is_site_data, size);
+ }
+
+ private:
+ BrowsingDataSizeCalculator* browsing_data_size_calculator_;
+};
+
+class AppsSizeTestAPI {
+ public:
+ explicit AppsSizeTestAPI(StorageHandler* handler,
+ AppsSizeCalculator* apps_size_calculator) {
+ apps_size_calculator_ = apps_size_calculator;
+ apps_size_calculator_->AddObserver(handler);
+ }
+
+ void StartCalculation() { apps_size_calculator_->StartCalculation(); }
+
+ void SimulateOnGetAppsSize(int64_t total_bytes) {
+ apps_size_calculator_->OnGetAppsSize(total_bytes);
+ }
+
+ void SimulateOnGetAndroidAppsSize(bool succeeded,
+ uint64_t total_code_bytes,
+ uint64_t total_data_bytes,
+ uint64_t total_cache_bytes) {
+ arc::mojom::ApplicationsSizePtr result(
+ ::arc::mojom::ApplicationsSize::New());
+ result->total_code_bytes = total_code_bytes;
+ result->total_data_bytes = total_data_bytes;
+ result->total_cache_bytes = total_cache_bytes;
+ apps_size_calculator_->OnGetAndroidAppsSize(succeeded, std::move(result));
+ }
+
+ private:
+ AppsSizeCalculator* apps_size_calculator_;
+};
+
+class CrostiniSizeTestAPI {
+ public:
+ explicit CrostiniSizeTestAPI(
+ StorageHandler* handler,
+ CrostiniSizeCalculator* crostini_size_calculator) {
+ crostini_size_calculator_ = crostini_size_calculator;
+ crostini_size_calculator_->AddObserver(handler);
+ }
+
+ void StartCalculation() { crostini_size_calculator_->StartCalculation(); }
+
+ void SimulateOnGetCrostiniSize(int64_t size) {
+ crostini_size_calculator_->OnGetCrostiniSize(
+ crostini::CrostiniResult::SUCCESS, size);
+ }
+
+ private:
+ CrostiniSizeCalculator* crostini_size_calculator_;
+};
+
+class OtherUsersSizeTestAPI {
+ public:
+ explicit OtherUsersSizeTestAPI(
+ StorageHandler* handler,
+ OtherUsersSizeCalculator* other_users_size_calculator) {
+ other_users_size_calculator_ = other_users_size_calculator;
+ other_users_size_calculator_->AddObserver(handler);
+ }
+
+ void StartCalculation() { other_users_size_calculator_->StartCalculation(); }
+
+ void InitializeOtherUserSize(int user_count) {
+ // When calling OnGetOtherUserSize, a callback is fired when
+ // user_sizes_.size() == other_users_.size(). We want to control the size of
+ // |other_users_|, rather than its content. This function initializes
+ // other_users_ as a list of |user_count| nullptrs.
+ other_users_size_calculator_->other_users_ =
+ user_manager::UserList(user_count);
+ }
+
+ void SimulateOnGetOtherUserSize(base::Optional<cryptohome::BaseReply> reply) {
+ other_users_size_calculator_->OnGetOtherUserSize(reply);
+ }
+
+ private:
+ OtherUsersSizeCalculator* other_users_size_calculator_;
+};
+
+} // namespace calculator
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_CALCULATOR_SIZE_CALCULATOR_TEST_API_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
index ed3cdc8465d..4bd641f16e6 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc
@@ -18,6 +18,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/values.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/camera_presence_notifier.h"
@@ -228,8 +229,8 @@ void ChangePictureHandler::SendSelectedImage() {
DCHECK(previous_image_.IsThreadSafe());
// Post a task because GetBitmapDataUrl does PNG encoding, which is
// slow for large images.
- base::PostTaskAndReplyWithResult(
- FROM_HERE, {base::ThreadPool(), base::TaskPriority::USER_BLOCKING},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::TaskPriority::USER_BLOCKING},
base::BindOnce(&webui::GetBitmapDataUrl, *previous_image_.bitmap()),
base::BindOnce(&ChangePictureHandler::SendOldImage,
weak_ptr_factory_.GetWeakPtr()));
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
index a3bb95d292e..1be240f6115 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h
@@ -9,7 +9,7 @@
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "chrome/browser/chromeos/camera_presence_notifier.h"
-#include "chrome/browser/image_decoder.h"
+#include "chrome/browser/image_decoder/image_decoder.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
#include "components/user_manager/user_manager.h"
#include "ui/gfx/image/image_skia.h"
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
index 1c966904f49..1351b63b654 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc
@@ -9,21 +9,27 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/callback_forward.h"
#include "base/metrics/histogram_functions.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/chromeos/crostini/crostini_disk.h"
+#include "chrome/browser/chromeos/crostini/crostini_features.h"
+#include "chrome/browser/chromeos/crostini/crostini_installer.h"
+#include "chrome/browser/chromeos/crostini/crostini_port_forwarder.h"
+#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
+#include "chrome/browser/chromeos/crostini/crostini_types.mojom.h"
#include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/chromeos/file_manager/path_util.h"
#include "chrome/browser/chromeos/guest_os/guest_os_share_path.h"
-#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/lifetime/application_lifetime.h"
-#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_thread.h"
+#include "ui/display/screen.h"
namespace chromeos {
namespace settings {
@@ -105,11 +111,42 @@ void CrostiniHandler::RegisterMessages() {
"disableArcAdbSideload",
base::BindRepeating(&CrostiniHandler::HandleDisableArcAdbRequest,
weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "requestCrostiniContainerUpgradeView",
+ base::BindRepeating(&CrostiniHandler::HandleRequestContainerUpgradeView,
+ weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "requestCrostiniUpgraderDialogStatus",
+ base::BindRepeating(
+ &CrostiniHandler::HandleCrostiniUpgraderDialogStatusRequest,
+ weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "requestCrostiniContainerUpgradeAvailable",
+ base::BindRepeating(
+ &CrostiniHandler::HandleCrostiniContainerUpgradeAvailableRequest,
+ weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "addCrostiniPortForward",
+ base::BindRepeating(&CrostiniHandler::HandleAddCrostiniPortForward,
+ weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "getCrostiniDiskInfo",
+ base::BindRepeating(&CrostiniHandler::HandleGetCrostiniDiskInfo,
+ weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "resizeCrostiniDisk",
+ base::BindRepeating(&CrostiniHandler::HandleResizeCrostiniDisk,
+ weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "checkCrostiniMicSharingStatus",
+ base::BindRepeating(&CrostiniHandler::HandleCheckCrostiniMicSharingStatus,
+ weak_ptr_factory_.GetWeakPtr()));
}
void CrostiniHandler::OnJavascriptAllowed() {
- crostini::CrostiniManager::GetForProfile(profile_)
- ->AddInstallerViewStatusObserver(this);
+ auto* crostini_manager = crostini::CrostiniManager::GetForProfile(profile_);
+ crostini_manager->AddCrostiniDialogStatusObserver(this);
+ crostini_manager->AddCrostiniContainerPropertiesObserver(this);
if (chromeos::CrosUsbDetector::Get()) {
chromeos::CrosUsbDetector::Get()->AddUsbDeviceObserver(this);
}
@@ -117,11 +154,9 @@ void CrostiniHandler::OnJavascriptAllowed() {
}
void CrostiniHandler::OnJavascriptDisallowed() {
- if (crostini::CrostiniManager::GetForProfile(profile_)
- ->HasInstallerViewStatusObserver(this)) {
- crostini::CrostiniManager::GetForProfile(profile_)
- ->RemoveInstallerViewStatusObserver(this);
- }
+ auto* crostini_manager = crostini::CrostiniManager::GetForProfile(profile_);
+ crostini_manager->RemoveCrostiniDialogStatusObserver(this);
+ crostini_manager->RemoveCrostiniContainerPropertiesObserver(this);
if (chromeos::CrosUsbDetector::Get()) {
chromeos::CrosUsbDetector::Get()->RemoveUsbDeviceObserver(this);
}
@@ -131,8 +166,8 @@ void CrostiniHandler::OnJavascriptDisallowed() {
void CrostiniHandler::HandleRequestCrostiniInstallerView(
const base::ListValue* args) {
AllowJavascript();
- ShowCrostiniInstallerView(Profile::FromWebUI(web_ui()),
- crostini::CrostiniUISurface::kSettings);
+ crostini::CrostiniInstaller::GetForProfile(Profile::FromWebUI(web_ui()))
+ ->ShowDialog(crostini::CrostiniUISurface::kSettings);
}
void CrostiniHandler::HandleRequestRemoveCrostini(const base::ListValue* args) {
@@ -144,40 +179,42 @@ void CrostiniHandler::HandleRequestRemoveCrostini(const base::ListValue* args) {
void CrostiniHandler::HandleGetCrostiniSharedPathsDisplayText(
const base::ListValue* args) {
AllowJavascript();
- CHECK_EQ(2U, args->GetSize());
- std::string callback_id;
- const base::ListValue* paths;
- CHECK(args->GetString(0, &callback_id));
- CHECK(args->GetList(1, &paths));
+ CHECK_EQ(2U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+ base::Value::ConstListView paths = args->GetList()[1].GetList();
base::ListValue texts;
- for (auto it = paths->begin(); it != paths->end(); ++it) {
+ for (size_t i = 0; i < paths.size(); ++i) {
texts.AppendString(file_manager::util::GetPathDisplayTextForSettings(
- profile_, it->GetString()));
+ profile_, paths[i].GetString()));
}
ResolveJavascriptCallback(base::Value(callback_id), texts);
}
void CrostiniHandler::HandleRemoveCrostiniSharedPath(
const base::ListValue* args) {
- CHECK_EQ(2U, args->GetSize());
- std::string vm_name;
- CHECK(args->GetString(0, &vm_name));
- std::string path;
- CHECK(args->GetString(1, &path));
+ AllowJavascript();
+ CHECK_EQ(3U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+ std::string vm_name = args->GetList()[1].GetString();
+ std::string path = args->GetList()[2].GetString();
guest_os::GuestOsSharePath::GetForProfile(profile_)->UnsharePath(
vm_name, base::FilePath(path),
/*unpersist=*/true,
- base::BindOnce(
- [](const std::string& path, bool result,
- const std::string& failure_reason) {
- if (!result) {
- LOG(ERROR) << "Error unsharing " << path << ": "
- << failure_reason;
- }
- },
- path));
+ base::BindOnce(&CrostiniHandler::OnCrostiniSharedPathRemoved,
+ weak_ptr_factory_.GetWeakPtr(), callback_id, path));
+}
+
+void CrostiniHandler::OnCrostiniSharedPathRemoved(
+ const std::string& callback_id,
+ const std::string& path,
+ bool result,
+ const std::string& failure_reason) {
+ if (!result) {
+ LOG(ERROR) << "Error unsharing " << path << ": " << failure_reason;
+ }
+ ResolveJavascriptCallback(base::Value(callback_id), base::Value(result));
}
namespace {
@@ -195,12 +232,35 @@ base::ListValue UsbDevicesToListValue(
}
return usb_devices_list;
}
+
+base::Value CrostiniDiskInfoToValue(
+ std::unique_ptr<crostini::CrostiniDiskInfo> disk_info) {
+ base::Value disk_value(base::Value::Type::DICTIONARY);
+ if (!disk_info) {
+ disk_value.SetBoolKey("succeeded", false);
+ return disk_value;
+ }
+ disk_value.SetBoolKey("succeeded", true);
+ disk_value.SetBoolKey("canResize", disk_info->can_resize);
+ disk_value.SetBoolKey("isUserChosenSize", disk_info->is_user_chosen_size);
+ disk_value.SetIntKey("defaultIndex", disk_info->default_index);
+ base::Value ticks(base::Value::Type::LIST);
+ for (const auto& tick : disk_info->ticks) {
+ base::Value t(base::Value::Type::DICTIONARY);
+ t.SetDoubleKey("value", static_cast<double>(tick->value));
+ t.SetStringKey("ariaValue", tick->aria_value);
+ t.SetStringKey("label", tick->label);
+ ticks.Append(std::move(t));
+ }
+ disk_value.SetKey("ticks", std::move(ticks));
+ return disk_value;
+}
} // namespace
void CrostiniHandler::HandleGetCrostiniSharedUsbDevices(
const base::ListValue* args) {
AllowJavascript();
- CHECK_EQ(1U, args->GetSize());
+ CHECK_EQ(1U, args->GetList().size());
std::string callback_id = args->GetList()[0].GetString();
@@ -217,7 +277,7 @@ void CrostiniHandler::HandleGetCrostiniSharedUsbDevices(
void CrostiniHandler::HandleSetCrostiniUsbDeviceShared(
const base::ListValue* args) {
- CHECK_EQ(2U, args->GetSize());
+ CHECK_EQ(2U, args->GetList().size());
const auto& args_list = args->GetList();
std::string guid = args_list[0].GetString();
bool shared = args_list[1].GetBool();
@@ -245,14 +305,14 @@ void CrostiniHandler::OnUsbDevicesChanged() {
void CrostiniHandler::HandleExportCrostiniContainer(
const base::ListValue* args) {
- CHECK_EQ(0U, args->GetSize());
+ CHECK_EQ(0U, args->GetList().size());
crostini::CrostiniExportImport::GetForProfile(profile_)->ExportContainer(
web_ui()->GetWebContents());
}
void CrostiniHandler::HandleImportCrostiniContainer(
const base::ListValue* args) {
- CHECK_EQ(0U, args->GetSize());
+ CHECK_EQ(0U, args->GetList().size());
crostini::CrostiniExportImport::GetForProfile(profile_)->ImportContainer(
web_ui()->GetWebContents());
}
@@ -260,45 +320,57 @@ void CrostiniHandler::HandleImportCrostiniContainer(
void CrostiniHandler::HandleCrostiniInstallerStatusRequest(
const base::ListValue* args) {
AllowJavascript();
- CHECK_EQ(0U, args->GetSize());
+ CHECK_EQ(0U, args->GetList().size());
bool status = crostini::CrostiniManager::GetForProfile(profile_)
- ->GetInstallerViewStatus();
- OnCrostiniInstallerViewStatusChanged(status);
+ ->GetCrostiniDialogStatus(crostini::DialogType::INSTALLER);
+ OnCrostiniDialogStatusChanged(crostini::DialogType::INSTALLER, status);
}
void CrostiniHandler::HandleCrostiniExportImportOperationStatusRequest(
const base::ListValue* args) {
AllowJavascript();
- CHECK_EQ(0U, args->GetSize());
+ CHECK_EQ(0U, args->GetList().size());
bool in_progress = crostini::CrostiniExportImport::GetForProfile(profile_)
->GetExportImportOperationStatus();
OnCrostiniExportImportOperationStatusChanged(in_progress);
}
-void CrostiniHandler::OnCrostiniInstallerViewStatusChanged(bool status) {
+void CrostiniHandler::OnCrostiniDialogStatusChanged(
+ crostini::DialogType dialog_type,
+ bool status) {
// It's technically possible for this to be called before Javascript is
// enabled, in which case we must not call FireWebUIListener
if (IsJavascriptAllowed()) {
// Other side listens with cr.addWebUIListener
- FireWebUIListener("crostini-installer-status-changed", base::Value(status));
+ switch (dialog_type) {
+ case crostini::DialogType::INSTALLER:
+ FireWebUIListener("crostini-installer-status-changed",
+ base::Value(status));
+ break;
+ case crostini::DialogType::UPGRADER:
+ FireWebUIListener("crostini-upgrader-status-changed",
+ base::Value(status));
+ break;
+ case crostini::DialogType::REMOVER:
+ FireWebUIListener("crostini-remover-status-changed",
+ base::Value(status));
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
}
}
-void CrostiniHandler::OnCrostiniExportImportOperationStatusChanged(
- bool in_progress) {
- // Other side listens with cr.addWebUIListener
- FireWebUIListener("crostini-export-import-operation-status-changed",
- base::Value(in_progress));
-}
-
-void CrostiniHandler::HandleQueryArcAdbRequest(const base::ListValue* args) {
- AllowJavascript();
- CHECK_EQ(0U, args->GetSize());
-
- chromeos::SessionManagerClient* client =
- chromeos::SessionManagerClient::Get();
- client->QueryAdbSideload(base::Bind(&CrostiniHandler::OnQueryAdbSideload,
- weak_ptr_factory_.GetWeakPtr()));
+void CrostiniHandler::OnContainerOsReleaseChanged(
+ const crostini::ContainerId& container_id,
+ bool can_upgrade) {
+ if (crostini::CrostiniFeatures::Get()->IsContainerUpgradeUIAllowed(
+ profile_) &&
+ container_id == crostini::DefaultContainerId()) {
+ FireWebUIListener("crostini-container-upgrade-available-changed",
+ base::Value(can_upgrade));
+ }
}
void CrostiniHandler::OnQueryAdbSideload(
@@ -317,7 +389,7 @@ void CrostiniHandler::OnQueryAdbSideload(
}
void CrostiniHandler::HandleEnableArcAdbRequest(const base::ListValue* args) {
- CHECK_EQ(0U, args->GetSize());
+ CHECK_EQ(0U, args->GetList().size());
if (!CheckEligibilityToChangeArcAdbSideloading())
return;
@@ -331,7 +403,7 @@ void CrostiniHandler::HandleEnableArcAdbRequest(const base::ListValue* args) {
}
void CrostiniHandler::HandleDisableArcAdbRequest(const base::ListValue* args) {
- CHECK_EQ(0U, args->GetSize());
+ CHECK_EQ(0U, args->GetList().size());
if (!CheckEligibilityToChangeArcAdbSideloading())
return;
@@ -346,28 +418,133 @@ void CrostiniHandler::HandleDisableArcAdbRequest(const base::ListValue* args) {
}
bool CrostiniHandler::CheckEligibilityToChangeArcAdbSideloading() const {
- if (!chromeos::ProfileHelper::IsOwnerProfile(profile_)) {
- DVLOG(1) << "Only the owner can change adb sideloading status";
- return false;
- }
+ return crostini::CrostiniFeatures::Get()->CanChangeAdbSideloading(profile_);
+}
- if (user_manager::UserManager::Get()->IsLoggedInAsChildUser()) {
- DVLOG(1) << "adb sideloading is currently unsupported for child account";
- return false;
- }
+void CrostiniHandler::LaunchTerminal() {
+ crostini::LaunchCrostiniApp(
+ profile_, crostini::GetTerminalId(),
+ display::Screen::GetScreen()->GetPrimaryDisplay().id());
+}
- if (profile_->GetProfilePolicyConnector()->IsManaged()) {
- DVLOG(1) << "adb sideloading is currently unsupported for managed user";
- return false;
- }
+void CrostiniHandler::HandleRequestContainerUpgradeView(
+ const base::ListValue* args) {
+ CHECK_EQ(0U, args->GetList().size());
+ chromeos::CrostiniUpgraderDialog::Show(
+ base::BindOnce(&CrostiniHandler::LaunchTerminal,
+ weak_ptr_factory_.GetWeakPtr()),
+ // If the user cancels the upgrade, we won't need to restart Crostini and
+ // we don't want to run the launch closure which would launch Terminal.
+ /*only_run_launch_closure_on_restart=*/true);
+}
- policy::BrowserPolicyConnectorChromeOS* connector =
- g_browser_process->platform_part()->browser_policy_connector_chromeos();
- if (connector->IsEnterpriseManaged()) {
- DVLOG(1) << "adb sideloading is currently unsupported on managed device";
- return false;
- }
- return true;
+void CrostiniHandler::OnCrostiniExportImportOperationStatusChanged(
+ bool in_progress) {
+ // Other side listens with cr.addWebUIListener
+ FireWebUIListener("crostini-export-import-operation-status-changed",
+ base::Value(in_progress));
+}
+
+void CrostiniHandler::HandleQueryArcAdbRequest(const base::ListValue* args) {
+ AllowJavascript();
+ CHECK_EQ(0U, args->GetList().size());
+
+ chromeos::SessionManagerClient* client =
+ chromeos::SessionManagerClient::Get();
+ client->QueryAdbSideload(base::Bind(&CrostiniHandler::OnQueryAdbSideload,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void CrostiniHandler::HandleCrostiniUpgraderDialogStatusRequest(
+ const base::ListValue* args) {
+ AllowJavascript();
+ CHECK_EQ(0U, args->GetList().size());
+ bool is_open = crostini::CrostiniManager::GetForProfile(profile_)
+ ->GetCrostiniDialogStatus(crostini::DialogType::UPGRADER);
+ OnCrostiniDialogStatusChanged(crostini::DialogType::UPGRADER, is_open);
+}
+
+void CrostiniHandler::HandleCrostiniContainerUpgradeAvailableRequest(
+ const base::ListValue* args) {
+ AllowJavascript();
+
+ bool can_upgrade = crostini::ShouldAllowContainerUpgrade(profile_);
+ OnContainerOsReleaseChanged(crostini::DefaultContainerId(), can_upgrade);
+}
+
+void CrostiniHandler::HandleAddCrostiniPortForward(
+ const base::ListValue* args) {
+ CHECK_EQ(6U, args->GetList().size());
+
+ std::string callback_id = args->GetList()[0].GetString();
+ std::string vm_name = args->GetList()[1].GetString();
+ std::string container_name = args->GetList()[2].GetString();
+ int port_number = args->GetList()[3].GetInt();
+ int protocol_type = args->GetList()[4].GetInt();
+ std::string label = args->GetList()[5].GetString();
+
+ crostini::CrostiniPortForwarder::GetForProfile(profile_)->AddPort(
+ crostini::ContainerId(std::move(vm_name), std::move(container_name)),
+ port_number,
+ static_cast<crostini::CrostiniPortForwarder::Protocol>(protocol_type),
+ std::move(label),
+ base::Bind(&CrostiniHandler::OnPortForwardComplete,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback_id)));
+}
+
+void CrostiniHandler::OnPortForwardComplete(std::string callback_id,
+ bool success) {
+ ResolveJavascriptCallback(base::Value(callback_id), base::Value(success));
+}
+
+void CrostiniHandler::ResolveGetCrostiniDiskInfoCallback(
+ const std::string& callback_id,
+ std::unique_ptr<crostini::CrostiniDiskInfo> disk_info) {
+ ResolveJavascriptCallback(base::Value(std::move(callback_id)),
+ CrostiniDiskInfoToValue(std::move(disk_info)));
+}
+
+void CrostiniHandler::HandleGetCrostiniDiskInfo(const base::ListValue* args) {
+ AllowJavascript();
+ CHECK_EQ(2U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+ std::string vm_name = args->GetList()[1].GetString();
+ crostini::disk::GetDiskInfo(
+ base::BindOnce(&CrostiniHandler::ResolveGetCrostiniDiskInfoCallback,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback_id)),
+ profile_, std::move(vm_name));
+}
+
+void CrostiniHandler::HandleResizeCrostiniDisk(const base::ListValue* args) {
+ CHECK_EQ(3U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+ std::string vm_name = args->GetList()[1].GetString();
+ double bytes = args->GetList()[2].GetDouble();
+ crostini::disk::ResizeCrostiniDisk(
+ profile_, std::move(vm_name), bytes,
+ base::BindOnce(&CrostiniHandler::ResolveResizeCrostiniDiskCallback,
+ weak_ptr_factory_.GetWeakPtr(), std::move(callback_id)));
+}
+
+void CrostiniHandler::ResolveResizeCrostiniDiskCallback(
+ const std::string& callback_id,
+ bool succeeded) {
+ ResolveJavascriptCallback(base::Value(std::move(callback_id)),
+ base::Value(succeeded));
+}
+
+void CrostiniHandler::HandleCheckCrostiniMicSharingStatus(
+ const base::ListValue* args) {
+ CHECK_EQ(2U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+ bool proposed_value = args->GetList()[1].GetBool();
+ bool requiresRestart =
+ crostini::IsCrostiniRunning(profile_) &&
+ profile_->GetPrefs()->GetBoolean(
+ crostini::prefs::kCrostiniMicSharingAtLastLaunch) != proposed_value;
+
+ ResolveJavascriptCallback(base::Value(std::move(callback_id)),
+ base::Value(requiresRestart));
}
} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h
index bab8509806a..f51fc69e1b7 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h
@@ -18,14 +18,16 @@ class Profile;
namespace crostini {
enum class CrostiniResult;
-}
+struct CrostiniDiskInfo;
+} // namespace crostini
namespace chromeos {
namespace settings {
class CrostiniHandler : public ::settings::SettingsPageUIHandler,
- public crostini::InstallerViewStatusObserver,
+ public crostini::CrostiniDialogStatusObserver,
public crostini::CrostiniExportImport::Observer,
+ public crostini::CrostiniContainerPropertiesObserver,
public chromeos::CrosUsbDeviceObserver {
public:
explicit CrostiniHandler(Profile* profile);
@@ -45,6 +47,10 @@ class CrostiniHandler : public ::settings::SettingsPageUIHandler,
void HandleGetCrostiniSharedPathsDisplayText(const base::ListValue* args);
// Remove a specified path from being shared.
void HandleRemoveCrostiniSharedPath(const base::ListValue* args);
+ void OnCrostiniSharedPathRemoved(const std::string& callback_id,
+ const std::string& path,
+ bool result,
+ const std::string& failure_reason);
// Returns a list of available USB devices.
void HandleGetCrostiniSharedUsbDevices(const base::ListValue* args);
// Set the share state of a USB device.
@@ -57,8 +63,12 @@ class CrostiniHandler : public ::settings::SettingsPageUIHandler,
void HandleImportCrostiniContainer(const base::ListValue* args);
// Handle a request for the CrostiniInstallerView status.
void HandleCrostiniInstallerStatusRequest(const base::ListValue* args);
- // Handle the CrostiniInstallerView opening/closing.
- void OnCrostiniInstallerViewStatusChanged(bool open) override;
+ // crostini::CrostiniDialogStatusObserver
+ void OnCrostiniDialogStatusChanged(crostini::DialogType dialog_type,
+ bool open) override;
+ // crostini::CrostiniContainerPropertiesObserver
+ void OnContainerOsReleaseChanged(const crostini::ContainerId& container_id,
+ bool can_upgrade) override;
// Handle a request for the CrostiniExportImport operation status.
void HandleCrostiniExportImportOperationStatusRequest(
const base::ListValue* args);
@@ -70,6 +80,10 @@ class CrostiniHandler : public ::settings::SettingsPageUIHandler,
void HandleEnableArcAdbRequest(const base::ListValue* args);
// Handle a request for disabling adb sideloading in ARC.
void HandleDisableArcAdbRequest(const base::ListValue* args);
+ // Launch the Crostini terminal.
+ void LaunchTerminal();
+ // Handle a request for showing the container upgrade view.
+ void HandleRequestContainerUpgradeView(const base::ListValue* args);
// Callback of HandleQueryArcAdbRequest.
void OnQueryAdbSideload(
SessionManagerClient::AdbSideloadResponseCode response_code,
@@ -77,6 +91,26 @@ class CrostiniHandler : public ::settings::SettingsPageUIHandler,
// Returns whether the current user can change adb sideloading configuration
// on current device.
bool CheckEligibilityToChangeArcAdbSideloading() const;
+ // Handle a request for the CrostiniUpgraderDialog status.
+ void HandleCrostiniUpgraderDialogStatusRequest(const base::ListValue* args);
+ // Handle a request for the availability of a container upgrade.
+ void HandleCrostiniContainerUpgradeAvailableRequest(
+ const base::ListValue* args);
+ // Handles a request for forwarding a new port.
+ void HandleAddCrostiniPortForward(const base::ListValue* args);
+ // Callback of port forwarding requests.
+ void OnPortForwardComplete(std::string callback_id, bool success);
+ // Fetches disk info for a VM, can be slow (seconds).
+ void HandleGetCrostiniDiskInfo(const base::ListValue* args);
+ void ResolveGetCrostiniDiskInfoCallback(
+ const std::string& callback_id,
+ std::unique_ptr<crostini::CrostiniDiskInfo> disk_info);
+ // Handles a request to resize a Crostini disk.
+ void HandleResizeCrostiniDisk(const base::ListValue* args);
+ void ResolveResizeCrostiniDiskCallback(const std::string& callback_id,
+ bool succeeded);
+ // Checks if a restart is required to update mic sharing settings.
+ void HandleCheckCrostiniMicSharingStatus(const base::ListValue* args);
Profile* profile_;
// weak_ptr_factory_ should always be last member.
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index 74f1ab84039..fd6f8acdd11 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -14,12 +14,14 @@
#include "base/files/file_util.h"
#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/optional.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
@@ -37,12 +39,11 @@
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
+#include "chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
-#include "chrome/common/webui_url_constants.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
-#include "chromeos/printing/ppd_cache.h"
#include "chromeos/printing/ppd_line_reader.h"
#include "chromeos/printing/printer_configuration.h"
#include "chromeos/printing/printer_translator.h"
@@ -58,6 +59,7 @@
#include "net/base/ip_endpoint.h"
#include "net/url_request/url_request_context_getter.h"
#include "printing/backend/print_backend.h"
+#include "printing/printer_status.h"
#include "url/gurl.h"
namespace chromeos {
@@ -113,8 +115,8 @@ void QueryAutoconf(const std::string& printer_uri,
// Behavior for querying a non-IPP uri is undefined and disallowed.
if (!IsIppUri(printer_uri) || !optional.has_value()) {
PRINTER_LOG(ERROR) << "Printer uri is invalid: " << printer_uri;
- std::move(callback).Run(PrinterQueryResult::UNKNOWN_FAILURE, "", "", "", {},
- false);
+ std::move(callback).Run(PrinterQueryResult::UNKNOWN_FAILURE,
+ printing::PrinterStatus(), "", "", "", {}, false);
return;
}
@@ -168,6 +170,7 @@ std::unique_ptr<chromeos::Printer> DictToPrinter(
std::string printer_make_and_model;
std::string printer_address;
std::string printer_protocol;
+ std::string print_server_uri;
if (!printer_dict.GetString("printerId", &printer_id) ||
!printer_dict.GetString("printerName", &printer_name) ||
@@ -176,7 +179,8 @@ std::unique_ptr<chromeos::Printer> DictToPrinter(
!printer_dict.GetString("printerModel", &printer_model) ||
!printer_dict.GetString("printerMakeAndModel", &printer_make_and_model) ||
!printer_dict.GetString("printerAddress", &printer_address) ||
- !printer_dict.GetString("printerProtocol", &printer_protocol)) {
+ !printer_dict.GetString("printerProtocol", &printer_protocol) ||
+ !printer_dict.GetString("printServerUri", &print_server_uri)) {
return nullptr;
}
@@ -195,6 +199,7 @@ std::unique_ptr<chromeos::Printer> DictToPrinter(
printer->set_model(printer_model);
printer->set_make_and_model(printer_make_and_model);
printer->set_uri(printer_uri);
+ printer->set_print_server_uri(print_server_uri);
return printer;
}
@@ -237,11 +242,6 @@ void SetPpdReference(const Printer::PpdReference& ppd_ref, base::Value* info) {
}
}
-bool IsFilledPpdReference(const Printer::PpdReference& ppd_ref) {
- return ppd_ref.autoconf || !ppd_ref.user_supplied_ppd_url.empty() ||
- !ppd_ref.effective_make_and_model.empty();
-}
-
Printer::PpdReference GetPpdReference(const base::Value* info) {
const char ppd_ref_pathname[] = "printerPpdReference";
auto* user_supplied_ppd_url =
@@ -267,40 +267,11 @@ Printer::PpdReference GetPpdReference(const base::Value* info) {
return ret;
}
-bool ConvertToGURL(const std::string& url, GURL* gurl) {
- *gurl = GURL(url);
- if (!gurl->is_valid()) {
- // URL is not valid.
- return false;
- }
- if (!gurl->SchemeIsHTTPOrHTTPS() && !gurl->SchemeIs("ipp") &&
- !gurl->SchemeIs("ipps")) {
- // URL has unsupported scheme; we support only: http, https, ipp, ipps.
- return false;
- }
- // Replaces ipp/ipps by http/https. IPP standard describes protocol built
- // on top of HTTP, so both types of addresses have the same meaning in the
- // context of IPP interface. Moreover, the URL must have http/https scheme
- // to pass IsStandard() test from GURL library (see "Validation of the URL
- // address" below).
- bool set_ipp_port = false;
- if (gurl->SchemeIs("ipp")) {
- set_ipp_port = (gurl->IntPort() == url::PORT_UNSPECIFIED);
- *gurl = GURL("http" + url.substr(url.find_first_of(':')));
- } else if (gurl->SchemeIs("ipps")) {
- *gurl = GURL("https" + url.substr(url.find_first_of(':')));
- }
- // The default port for ipp is 631. If the schema ipp is replaced by http
- // and the port is not explicitly defined in the url, we have to overwrite
- // the default http port with the default ipp port. For ipps we do nothing
- // because implementers use the same port for ipps and https.
- if (set_ipp_port) {
- GURL::Replacements replacement;
- replacement.SetPortStr("631");
- *gurl = gurl->ReplaceComponents(replacement);
- }
- // Validation of the URL address.
- return gurl->IsStandard();
+GURL GenerateHttpCupsServerUrl(const GURL& server_url) {
+ GURL::Replacements replacement;
+ replacement.SetSchemeStr("http");
+ replacement.SetPortStr("631");
+ return server_url.ReplaceComponents(replacement);
}
} // namespace
@@ -405,6 +376,10 @@ void CupsPrintersHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"getEulaUrl", base::BindRepeating(&CupsPrintersHandler::HandleGetEulaUrl,
base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "queryPrintServer",
+ base::BindRepeating(&CupsPrintersHandler::HandleQueryPrintServer,
+ base::Unretained(this)));
}
void CupsPrintersHandler::OnJavascriptAllowed() {
@@ -513,8 +488,8 @@ void CupsPrintersHandler::HandleGetPrinterInfo(const base::ListValue* args) {
if (printer_address.empty()) {
// Run the failure callback.
- OnAutoconfQueried(callback_id, PrinterQueryResult::UNKNOWN_FAILURE, "", "",
- "", {}, false);
+ OnAutoconfQueried(callback_id, PrinterQueryResult::UNKNOWN_FAILURE,
+ printing::PrinterStatus(), "", "", "", {}, false);
return;
}
@@ -541,6 +516,7 @@ void CupsPrintersHandler::OnAutoconfQueriedDiscovered(
const std::string& callback_id,
Printer printer,
PrinterQueryResult result,
+ const printing::PrinterStatus& printer_status,
const std::string& make,
const std::string& model,
const std::string& make_and_model,
@@ -587,6 +563,7 @@ void CupsPrintersHandler::OnAutoconfQueriedDiscovered(
void CupsPrintersHandler::OnAutoconfQueried(
const std::string& callback_id,
PrinterQueryResult result,
+ const printing::PrinterStatus& printer_status,
const std::string& make,
const std::string& model,
const std::string& make_and_model,
@@ -736,7 +713,7 @@ void CupsPrintersHandler::AddOrReconfigurePrinter(const base::ListValue* args,
// Check if the printer already has a valid ppd_reference.
Printer::PpdReference ppd_ref = GetPpdReference(printer_dict);
- if (IsFilledPpdReference(ppd_ref)) {
+ if (ppd_ref.IsFilled()) {
*printer->mutable_ppd_reference() = ppd_ref;
} else if (!printer_ppd_path.empty()) {
GURL tmp = net::FilePathToFileURL(base::FilePath(printer_ppd_path));
@@ -1003,9 +980,8 @@ void CupsPrintersHandler::FileSelected(const base::FilePath& path,
// VerifyPpdContents() in order to determine whether the file appears to be a
// PPD file. The task's priority is USER_BLOCKING because the this task
// updates the UI as a result of a direct user action.
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(&ReadFileToStringWithMaxSize, path, kPpdMaxLineLength),
base::BindOnce(&CupsPrintersHandler::VerifyPpdContents,
weak_factory_.GetWeakPtr(), path));
@@ -1239,7 +1215,7 @@ void CupsPrintersHandler::OnGetEulaUrl(const std::string& callback_id,
return;
}
- GURL eula_url(chrome::kChromeUIOSCreditsURL + license);
+ GURL eula_url = PrinterConfigurer::GeneratePrinterEulaUrl(license);
ResolveJavascriptCallback(
base::Value(callback_id),
eula_url.is_valid() ? base::Value(eula_url.spec()) : base::Value());
@@ -1283,27 +1259,45 @@ void CupsPrintersHandler::HandleQueryPrintServer(const base::ListValue* args) {
CHECK(args->GetString(0, &callback_id));
CHECK(args->GetString(1, &server_url));
- GURL server_gurl;
- if (!ConvertToGURL(server_url, &server_gurl)) {
+ base::Optional<GURL> converted_server_url =
+ GenerateServerPrinterUrlWithValidScheme(server_url);
+ if (!converted_server_url) {
RejectJavascriptCallback(
base::Value(callback_id),
base::Value(PrintServerQueryResult::kIncorrectUrl));
return;
}
+ // Use fallback only if HasValidServerPrinterScheme is false.
+ QueryPrintServer(callback_id, converted_server_url.value(),
+ !HasValidServerPrinterScheme(GURL(server_url)));
+}
+
+void CupsPrintersHandler::QueryPrintServer(const std::string& callback_id,
+ const GURL& server_url,
+ bool should_fallback) {
server_printers_fetcher_ = std::make_unique<ServerPrintersFetcher>(
- server_gurl, "(from user)",
+ server_url, "(from user)",
base::BindRepeating(&CupsPrintersHandler::OnQueryPrintServerCompleted,
- weak_factory_.GetWeakPtr(), callback_id));
+ weak_factory_.GetWeakPtr(), callback_id,
+ should_fallback));
}
void CupsPrintersHandler::OnQueryPrintServerCompleted(
const std::string& callback_id,
+ bool should_fallback,
const ServerPrintersFetcher* sender,
const GURL& server_url,
std::vector<PrinterDetector::DetectedPrinter>&& returned_printers) {
const PrintServerQueryResult result = sender->GetLastError();
if (result != PrintServerQueryResult::kNoErrors) {
+ if (should_fallback) {
+ // Apply the fallback query.
+ QueryPrintServer(callback_id, GenerateHttpCupsServerUrl(server_url),
+ /*should_fallback=*/false);
+ return;
+ }
+
RejectJavascriptCallback(base::Value(callback_id), base::Value(result));
return;
}
@@ -1313,9 +1307,10 @@ void CupsPrintersHandler::OnQueryPrintServerCompleted(
printers_manager_->GetPrinters(PrinterClass::kSaved);
std::set<GURL> known_printers;
for (const Printer& printer : saved_printers) {
- GURL gurl;
- if (ConvertToGURL(printer.uri(), &gurl))
- known_printers.insert(gurl);
+ base::Optional<GURL> gurl =
+ GenerateServerPrinterUrlWithValidScheme(printer.uri());
+ if (gurl)
+ known_printers.insert(gurl.value());
}
// Built final list of printers and a list of current names. If "current name"
@@ -1325,11 +1320,10 @@ void CupsPrintersHandler::OnQueryPrintServerCompleted(
printers.reserve(returned_printers.size());
for (PrinterDetector::DetectedPrinter& printer : returned_printers) {
printers.push_back(std::move(printer.printer));
- GURL printer_gurl;
- if (ConvertToGURL(printers.back().uri(), &printer_gurl)) {
- if (known_printers.count(printer_gurl))
- printers.pop_back();
- }
+ base::Optional<GURL> printer_gurl =
+ GenerateServerPrinterUrlWithValidScheme(printers.back().uri());
+ if (printer_gurl && known_printers.count(printer_gurl.value()))
+ printers.pop_back();
}
// Delete fetcher object.
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
index 6e80a910a18..82de71cf6cc 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -18,7 +18,7 @@
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
#include "chromeos/printing/ppd_provider.h"
#include "chromeos/printing/printer_configuration.h"
-#include "printing/printer_query_result_chromeos.h"
+#include "printing/printer_query_result.h"
#include "ui/shell_dialogs/select_file_dialog.h"
namespace base {
@@ -30,6 +30,10 @@ namespace local_discovery {
class EndpointResolver;
} // namespace local_discovery
+namespace printing {
+struct PrinterStatus;
+} // namespace printing
+
class GURL;
class Profile;
@@ -77,14 +81,17 @@ class CupsPrintersHandler : public ::settings::SettingsPageUIHandler,
void HandleGetPrinterInfo(const base::ListValue* args);
// Handles the callback for HandleGetPrinterInfo. |callback_id| is the
- // identifier to resolve the correct Promise. |success| indicates if the query
- // was successful. |make| is the detected printer manufacturer. |model| is the
+ // identifier to resolve the correct Promise. |result| indicates if the query
+ // was successful. |printer_status| contains the current status of the
+ // printer. |make| is the detected printer manufacturer. |model| is the
// detected model. |make_and_model| is the unparsed printer-make-and-model
// string. |ipp_everywhere| indicates if configuration using the CUPS IPP
- // Everywhere driver should be attempted. If |success| is false, the values of
- // |make|, |model|, |make_and_model|, and |ipp_everywhere| are not specified.
+ // Everywhere driver should be attempted. If |result| is not SUCCESS, the
+ // values of |printer_status|, |make|, |model|, |make_and_model|, and
+ // |ipp_everywhere| are not specified.
void OnAutoconfQueried(const std::string& callback_id,
printing::PrinterQueryResult result,
+ const printing::PrinterStatus& printer_status,
const std::string& make,
const std::string& model,
const std::string& make_and_model,
@@ -96,6 +103,7 @@ class CupsPrintersHandler : public ::settings::SettingsPageUIHandler,
const std::string& callback_id,
Printer printer,
printing::PrinterQueryResult result,
+ const printing::PrinterStatus& printer_status,
const std::string& make,
const std::string& model,
const std::string& make_and_model,
@@ -214,8 +222,14 @@ class CupsPrintersHandler : public ::settings::SettingsPageUIHandler,
const net::IPEndPoint& endpoint);
void HandleQueryPrintServer(const base::ListValue* args);
+
+ void QueryPrintServer(const std::string& callback_id,
+ const GURL& server_url,
+ bool should_fallback);
+
void OnQueryPrintServerCompleted(
const std::string& callback_id,
+ bool should_fallback,
const ServerPrintersFetcher* sender,
const GURL& server_url,
std::vector<PrinterDetector::DetectedPrinter>&& returned_printers);
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
index 59656e6e848..39ceb89c02a 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc
@@ -168,8 +168,8 @@ void DateTimeHandler::HandleShowParentAccessForTimeZone(
ash::LoginScreen::Get()->ShowParentAccessWidget(
user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(),
- base::BindRepeating(&DateTimeHandler::OnParentAccessValidation,
- weak_ptr_factory_.GetWeakPtr()),
+ base::BindOnce(&DateTimeHandler::OnParentAccessValidation,
+ weak_ptr_factory_.GetWeakPtr()),
ash::ParentAccessRequestReason::kChangeTimezone, false /* extra_dimmer */,
base::Time());
}
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
index ee16a539c7b..7195f59a799 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc
@@ -6,7 +6,6 @@
#include "ash/public/cpp/keyboard_shortcut_viewer.h"
#include "ash/public/cpp/tablet_mode.h"
-#include "ash/public/mojom/constants.mojom.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/values.h"
@@ -21,25 +20,33 @@ namespace {
struct KeyboardsStateResult {
bool has_internal_keyboard = false;
- bool has_external_non_apple_keyboard = false;
- bool has_apple_keyboard = false;
+ bool has_external_apple_keyboard = false;
+ bool has_external_chromeos_keyboard = false;
+ bool has_external_generic_keyboard = false;
};
KeyboardsStateResult GetKeyboardsState() {
KeyboardsStateResult result;
for (const ui::InputDevice& keyboard :
ui::DeviceDataManager::GetInstance()->GetKeyboardDevices()) {
- result.has_internal_keyboard |=
- (keyboard.type == ui::INPUT_DEVICE_INTERNAL);
-
- const ui::EventRewriterChromeOS::DeviceType type =
- ui::EventRewriterChromeOS::GetDeviceType(keyboard);
- if (type == ui::EventRewriterChromeOS::kDeviceAppleKeyboard) {
- result.has_apple_keyboard = true;
- } else if (type ==
- ui::EventRewriterChromeOS::kDeviceExternalNonAppleKeyboard ||
- type == ui::EventRewriterChromeOS::kDeviceExternalUnknown) {
- result.has_external_non_apple_keyboard = true;
+ switch (ui::EventRewriterChromeOS::GetDeviceType(keyboard)) {
+ case ui::EventRewriterChromeOS::kDeviceInternalKeyboard:
+ result.has_internal_keyboard = true;
+ break;
+ case ui::EventRewriterChromeOS::kDeviceExternalAppleKeyboard:
+ result.has_external_apple_keyboard = true;
+ break;
+ case ui::EventRewriterChromeOS::kDeviceExternalChromeOsKeyboard:
+ result.has_external_chromeos_keyboard = true;
+ break;
+ case ui::EventRewriterChromeOS::kDeviceExternalGenericKeyboard:
+ case ui::EventRewriterChromeOS::kDeviceExternalUnknown:
+ result.has_external_generic_keyboard = true;
+ break;
+ case ui::EventRewriterChromeOS::kDeviceHotrodRemote:
+ case ui::EventRewriterChromeOS::kDeviceVirtualCoreKeyboard:
+ case ui::EventRewriterChromeOS::kDeviceUnknown:
+ break;
}
}
@@ -131,8 +138,8 @@ void KeyboardHandler::UpdateShowKeys() {
// kHasChromeOSKeyboard will be unset on Chromebooks that have standalone Caps
// Lock keys.
const KeyboardsStateResult keyboards_state = GetKeyboardsState();
- const bool has_caps_lock = keyboards_state.has_apple_keyboard ||
- keyboards_state.has_external_non_apple_keyboard ||
+ const bool has_caps_lock = keyboards_state.has_external_apple_keyboard ||
+ keyboards_state.has_external_generic_keyboard ||
!base::CommandLine::ForCurrentProcess()->HasSwitch(
chromeos::switches::kHasChromeOSKeyboard);
@@ -140,9 +147,10 @@ void KeyboardHandler::UpdateShowKeys() {
keyboard_params.SetKey("showCapsLock", base::Value(has_caps_lock));
keyboard_params.SetKey(
"showExternalMetaKey",
- base::Value(keyboards_state.has_external_non_apple_keyboard));
- keyboard_params.SetKey("showAppleCommandKey",
- base::Value(keyboards_state.has_apple_keyboard));
+ base::Value(keyboards_state.has_external_generic_keyboard));
+ keyboard_params.SetKey(
+ "showAppleCommandKey",
+ base::Value(keyboards_state.has_external_apple_keyboard));
keyboard_params.SetKey("hasInternalKeyboard",
base::Value(keyboards_state.has_internal_keyboard));
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
index 8f4f6318a50..a558502222a 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc
@@ -15,6 +15,7 @@
#include "base/observer_list.h"
#include "chromeos/constants/chromeos_switches.h"
#include "content/public/test/test_web_ui.h"
+#include "device/udev_linux/fake_udev_loader.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/devices/device_data_manager_test_api.h"
#include "ui/events/devices/input_device.h"
@@ -192,11 +193,46 @@ TEST_F(KeyboardHandlerTest, NonChromeOSKeyboard) {
}
TEST_F(KeyboardHandlerTest, ExternalKeyboard) {
+ auto fake_udev = std::make_unique<testing::FakeUdevLoader>();
+
+ // Standard internal keyboard on x86 device.
+ const ui::InputDevice internal_kbd(
+ 1, ui::INPUT_DEVICE_INTERNAL, "AT Translated Set 2 keyboard", "",
+ base::FilePath("/devices/platform/i8042/serio0/input/input1"), 1, 1,
+ 0xab41);
+ fake_udev->AddFakeDevice(internal_kbd.name, internal_kbd.sys_path.value(), {},
+ {});
+ // Generic external USB keyboard.
+ const ui::InputDevice external_generic_kbd(
+ 2, ui::INPUT_DEVICE_USB, "Logitech USB Keyboard", "",
+ base::FilePath("/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/"
+ "0003:046D:C31C.0007/"
+ "input/input2"),
+ 0x046d, 0xc31c, 0x0111);
+ fake_udev->AddFakeDevice(external_generic_kbd.name,
+ external_generic_kbd.sys_path.value(), {}, {});
+ // Apple keyboard.
+ const ui::InputDevice external_apple_kbd(
+ 3, ui::INPUT_DEVICE_USB, "Apple Inc. Apple Keyboard", "",
+ base::FilePath("/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.1/"
+ "0003:05AC:026C.000A/input/input3"),
+ 0x05ac, 0x026c, 0x0111);
+ fake_udev->AddFakeDevice(external_apple_kbd.name,
+ external_apple_kbd.sys_path.value(), {}, {});
+ // Chrome OS external USB keyboard.
+ const ui::InputDevice external_chromeos_kbd(
+ 4, ui::INPUT_DEVICE_USB, "LG USB Keyboard", "",
+ base::FilePath("/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/"
+ "0003:04CA:0082.000B/input/input4"),
+ 0x04ca, 0x0082, 0x0111);
+ fake_udev->AddFakeDevice(external_chromeos_kbd.name,
+ external_chromeos_kbd.sys_path.value(), {},
+ {{"CROS_KEYBOARD_TOP_ROW_LAYOUT", "1"}});
+
// An internal keyboard shouldn't change the defaults.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
chromeos::switches::kHasChromeOSKeyboard);
- device_data_manager_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{
- {1, ui::INPUT_DEVICE_INTERNAL, "internal keyboard"}});
+ device_data_manager_test_api_.SetKeyboardDevices({internal_kbd});
handler_test_api_.Initialize();
EXPECT_TRUE(HasInternalSearchKey());
EXPECT_FALSE(HasCapsLock());
@@ -206,20 +242,28 @@ TEST_F(KeyboardHandlerTest, ExternalKeyboard) {
// Simulate an external keyboard being connected. We should assume there's a
// Caps Lock and Meta keys now.
- device_data_manager_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{
- {1, ui::INPUT_DEVICE_INTERNAL, "internal keyboard"},
- {2, ui::INPUT_DEVICE_USB, "external keyboard"}});
+ device_data_manager_test_api_.SetKeyboardDevices(
+ std::vector<ui::InputDevice>{internal_kbd, external_generic_kbd});
EXPECT_TRUE(HasInternalSearchKey());
EXPECT_TRUE(HasCapsLock());
EXPECT_TRUE(HasExternalMetaKey());
EXPECT_FALSE(HasAppleCommandKey());
EXPECT_FALSE(HasAssistantKey());
+ // However when connecting external ChromeOS-branded keyboard, we should not
+ // see neither CapsLock not meta keys.
+ device_data_manager_test_api_.SetKeyboardDevices(
+ std::vector<ui::InputDevice>{internal_kbd, external_chromeos_kbd});
+ EXPECT_TRUE(HasInternalSearchKey());
+ EXPECT_FALSE(HasCapsLock());
+ EXPECT_FALSE(HasExternalMetaKey());
+ EXPECT_FALSE(HasAppleCommandKey());
+ EXPECT_FALSE(HasAssistantKey());
+
// Simulate an external Apple keyboard being connected. Now users can remap
// the command key.
- device_data_manager_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{
- {1, ui::INPUT_DEVICE_INTERNAL, "internal keyboard"},
- {3, ui::INPUT_DEVICE_USB, "Apple Inc. Apple Keyboard"}});
+ device_data_manager_test_api_.SetKeyboardDevices(
+ std::vector<ui::InputDevice>{internal_kbd, external_apple_kbd});
EXPECT_TRUE(HasInternalSearchKey());
EXPECT_TRUE(HasCapsLock());
EXPECT_FALSE(HasExternalMetaKey());
@@ -228,9 +272,8 @@ TEST_F(KeyboardHandlerTest, ExternalKeyboard) {
// Simulate two external keyboards (Apple and non-Apple) are connected at the
// same time.
- device_data_manager_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{
- {2, ui::INPUT_DEVICE_USB, "external keyboard"},
- {3, ui::INPUT_DEVICE_USB, "Apple Inc. Apple Keyboard"}});
+ device_data_manager_test_api_.SetKeyboardDevices(
+ std::vector<ui::InputDevice>{external_generic_kbd, external_apple_kbd});
EXPECT_FALSE(HasInternalSearchKey());
EXPECT_TRUE(HasCapsLock());
EXPECT_TRUE(HasExternalMetaKey());
@@ -242,7 +285,8 @@ TEST_F(KeyboardHandlerTest, ExternalKeyboard) {
// should show the capslock and external meta remapping.
// https://crbug.com/834594.
device_data_manager_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{
- {4, ui::INPUT_DEVICE_USB, "Topre Corporation Realforce 87"}});
+ {5, ui::INPUT_DEVICE_USB, "Topre Corporation Realforce 87", "",
+ external_generic_kbd.sys_path, 0x046d, 0xc31c, 0x0111}});
EXPECT_FALSE(HasInternalSearchKey());
EXPECT_TRUE(HasCapsLock());
EXPECT_TRUE(HasExternalMetaKey());
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
index 1906a330cd5..a5c66d6f18f 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc
@@ -79,11 +79,34 @@ int PowerSourceToDisplayId(
} // namespace
+PowerHandler::IdleBehaviorInfo::IdleBehaviorInfo() = default;
+PowerHandler::IdleBehaviorInfo::~IdleBehaviorInfo() = default;
+
+PowerHandler::IdleBehaviorInfo::IdleBehaviorInfo(
+ const std::set<PowerHandler::IdleBehavior>& possible_behaviors,
+ const PowerHandler::IdleBehavior& current_behavior,
+ const bool is_managed)
+ : possible_behaviors(possible_behaviors),
+ current_behavior(current_behavior),
+ is_managed(is_managed) {}
+
+PowerHandler::IdleBehaviorInfo::IdleBehaviorInfo(const IdleBehaviorInfo& o) =
+ default;
+
const char PowerHandler::kPowerManagementSettingsChangedName[] =
"power-management-settings-changed";
-const char PowerHandler::kIdleBehaviorKey[] = "idleBehavior";
-const char PowerHandler::kIdleControlledKey[] = "idleControlled";
+
+const char PowerHandler::kPossibleAcIdleBehaviorsKey[] =
+ "possibleAcIdleBehaviors";
+const char PowerHandler::kPossibleBatteryIdleBehaviorsKey[] =
+ "possibleBatteryIdleBehaviors";
+const char PowerHandler::kCurrentAcIdleBehaviorKey[] = "currentAcIdleBehavior";
+const char PowerHandler::kCurrentBatteryIdleBehaviorKey[] =
+ "currentBatteryIdleBehavior";
const char PowerHandler::kLidClosedBehaviorKey[] = "lidClosedBehavior";
+const char PowerHandler::kAcIdleManagedKey[] = "acIdleManaged";
+const char PowerHandler::kBatteryIdleManagedKey[] = "batteryIdleManaged";
+
const char PowerHandler::kLidClosedControlledKey[] = "lidClosedControlled";
const char PowerHandler::kHasLidKey[] = "hasLid";
@@ -96,9 +119,11 @@ void PowerHandler::TestAPI::RequestPowerManagementSettings() {
handler_->HandleRequestPowerManagementSettings(&args);
}
-void PowerHandler::TestAPI::SetIdleBehavior(IdleBehavior behavior) {
+void PowerHandler::TestAPI::SetIdleBehavior(IdleBehavior behavior,
+ bool when_on_ac) {
base::ListValue args;
args.AppendInteger(static_cast<int>(behavior));
+ args.AppendBoolean(when_on_ac);
handler_->HandleSetIdleBehavior(&args);
}
@@ -205,49 +230,48 @@ void PowerHandler::HandleSetIdleBehavior(const base::ListValue* args) {
AllowJavascript();
int value = 0;
+ bool when_on_ac = true;
CHECK(args->GetInteger(0, &value));
+ CHECK(args->GetBoolean(1, &when_on_ac));
+
+ const char* idle_pref = when_on_ac ? ash::prefs::kPowerAcIdleAction
+ : ash::prefs::kPowerBatteryIdleAction;
+ const char* screen_dim_delay_pref =
+ when_on_ac ? ash::prefs::kPowerAcScreenDimDelayMs
+ : ash::prefs::kPowerBatteryScreenDimDelayMs;
+ const char* screen_off_delay_pref =
+ when_on_ac ? ash::prefs::kPowerAcScreenOffDelayMs
+ : ash::prefs::kPowerBatteryScreenOffDelayMs;
+ const char* screen_lock_delay_pref =
+ when_on_ac ? ash::prefs::kPowerAcScreenLockDelayMs
+ : ash::prefs::kPowerBatteryScreenLockDelayMs;
+
switch (static_cast<IdleBehavior>(value)) {
case IdleBehavior::DISPLAY_OFF_SLEEP:
- // The default behavior is to turn the display off and sleep. Clear the
- // prefs so we use the default delays.
- prefs_->ClearPref(ash::prefs::kPowerAcIdleAction);
- prefs_->ClearPref(ash::prefs::kPowerAcScreenDimDelayMs);
- prefs_->ClearPref(ash::prefs::kPowerAcScreenOffDelayMs);
- prefs_->ClearPref(ash::prefs::kPowerAcScreenLockDelayMs);
- prefs_->ClearPref(ash::prefs::kPowerBatteryIdleAction);
- prefs_->ClearPref(ash::prefs::kPowerBatteryScreenDimDelayMs);
- prefs_->ClearPref(ash::prefs::kPowerBatteryScreenOffDelayMs);
- prefs_->ClearPref(ash::prefs::kPowerBatteryScreenLockDelayMs);
+ // The default behavior is to turn the display off and sleep.
+ // Clear the prefs so we use the default delays.
+ prefs_->ClearPref(idle_pref);
+ prefs_->ClearPref(screen_dim_delay_pref);
+ prefs_->ClearPref(screen_off_delay_pref);
+ prefs_->ClearPref(screen_lock_delay_pref);
break;
case IdleBehavior::DISPLAY_OFF:
- // Override idle actions to keep the system awake, but use the default
- // screen delays.
- prefs_->SetInteger(ash::prefs::kPowerAcIdleAction,
- PowerPolicyController::ACTION_DO_NOTHING);
- prefs_->ClearPref(ash::prefs::kPowerAcScreenDimDelayMs);
- prefs_->ClearPref(ash::prefs::kPowerAcScreenOffDelayMs);
- prefs_->ClearPref(ash::prefs::kPowerAcScreenLockDelayMs);
- prefs_->SetInteger(ash::prefs::kPowerBatteryIdleAction,
- PowerPolicyController::ACTION_DO_NOTHING);
- prefs_->ClearPref(ash::prefs::kPowerBatteryScreenDimDelayMs);
- prefs_->ClearPref(ash::prefs::kPowerBatteryScreenOffDelayMs);
- prefs_->ClearPref(ash::prefs::kPowerBatteryScreenLockDelayMs);
+ // Override idle actions to keep the system awake, but use the
+ // default screen delays.
+ prefs_->SetInteger(idle_pref, PowerPolicyController::ACTION_DO_NOTHING);
+ prefs_->ClearPref(screen_dim_delay_pref);
+ prefs_->ClearPref(screen_off_delay_pref);
+ prefs_->ClearPref(screen_lock_delay_pref);
break;
case IdleBehavior::DISPLAY_ON:
- // Override idle actions and set screen delays to 0 in order to disable
- // them (i.e. keep the screen on).
- prefs_->SetInteger(ash::prefs::kPowerAcIdleAction,
- PowerPolicyController::ACTION_DO_NOTHING);
- prefs_->SetInteger(ash::prefs::kPowerAcScreenDimDelayMs, 0);
- prefs_->SetInteger(ash::prefs::kPowerAcScreenOffDelayMs, 0);
- prefs_->SetInteger(ash::prefs::kPowerAcScreenLockDelayMs, 0);
- prefs_->SetInteger(ash::prefs::kPowerBatteryIdleAction,
- PowerPolicyController::ACTION_DO_NOTHING);
- prefs_->SetInteger(ash::prefs::kPowerBatteryScreenDimDelayMs, 0);
- prefs_->SetInteger(ash::prefs::kPowerBatteryScreenOffDelayMs, 0);
- prefs_->SetInteger(ash::prefs::kPowerBatteryScreenLockDelayMs, 0);
+ // Override idle actions and set screen delays to 0 in order to
+ // disable them (i.e. keep the screen on).
+ prefs_->SetInteger(idle_pref, PowerPolicyController::ACTION_DO_NOTHING);
+ prefs_->SetInteger(screen_dim_delay_pref, 0);
+ prefs_->SetInteger(screen_off_delay_pref, 0);
+ prefs_->SetInteger(screen_lock_delay_pref, 0);
break;
- default:
+ case IdleBehavior::OTHER:
NOTREACHED() << "Invalid idle behavior " << value;
}
}
@@ -336,32 +360,10 @@ void PowerHandler::SendPowerSources() {
}
void PowerHandler::SendPowerManagementSettings(bool force) {
- // Infer the idle behavior based on the idle action (determining whether we'll
- // sleep eventually or not) and the AC screen-off delay. Policy can request
- // more-nuanced combinations of AC/battery actions and delays, but we wouldn't
- // be able to display something meaningful in the UI in those cases anyway.
- const PowerPolicyController::Action idle_action =
- static_cast<PowerPolicyController::Action>(
- prefs_->GetInteger(ash::prefs::kPowerAcIdleAction));
- IdleBehavior idle_behavior = IdleBehavior::OTHER;
- if (idle_action == PowerPolicyController::ACTION_SUSPEND) {
- idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
- } else if (idle_action == PowerPolicyController::ACTION_DO_NOTHING) {
- idle_behavior =
- (prefs_->GetInteger(ash::prefs::kPowerAcScreenOffDelayMs) > 0
- ? IdleBehavior::DISPLAY_OFF
- : IdleBehavior::DISPLAY_ON);
- }
-
- const bool idle_controlled =
- prefs_->IsManagedPreference(ash::prefs::kPowerAcIdleAction) ||
- prefs_->IsManagedPreference(ash::prefs::kPowerAcScreenDimDelayMs) ||
- prefs_->IsManagedPreference(ash::prefs::kPowerAcScreenOffDelayMs) ||
- prefs_->IsManagedPreference(ash::prefs::kPowerAcScreenLockDelayMs) ||
- prefs_->IsManagedPreference(ash::prefs::kPowerBatteryIdleAction) ||
- prefs_->IsManagedPreference(ash::prefs::kPowerBatteryScreenDimDelayMs) ||
- prefs_->IsManagedPreference(ash::prefs::kPowerBatteryScreenOffDelayMs) ||
- prefs_->IsManagedPreference(ash::prefs::kPowerBatteryScreenLockDelayMs);
+ const PowerHandler::IdleBehaviorInfo ac_idle_info =
+ GetAllowedIdleBehaviors(PowerSource::kAc);
+ const PowerHandler::IdleBehaviorInfo battery_idle_info =
+ GetAllowedIdleBehaviors(PowerSource::kBattery);
const PowerPolicyController::Action lid_closed_behavior =
static_cast<PowerPolicyController::Action>(
@@ -371,23 +373,37 @@ void PowerHandler::SendPowerManagementSettings(bool force) {
const bool has_lid = lid_state_ != PowerManagerClient::LidState::NOT_PRESENT;
// Don't notify the UI if nothing changed.
- if (!force && idle_behavior == last_idle_behavior_ &&
- idle_controlled == last_idle_controlled_ &&
+ if (!force && ac_idle_info == last_ac_idle_info_ &&
+ battery_idle_info == last_battery_idle_info_ &&
lid_closed_behavior == last_lid_closed_behavior_ &&
lid_closed_controlled == last_lid_closed_controlled_ &&
- has_lid == last_has_lid_)
+ has_lid == last_has_lid_) {
return;
+ }
base::DictionaryValue dict;
- dict.SetInteger(kIdleBehaviorKey, static_cast<int>(idle_behavior));
- dict.SetBoolean(kIdleControlledKey, idle_controlled);
+ base::Value* list = dict.SetKey(kPossibleAcIdleBehaviorsKey,
+ base::Value(base::Value::Type::LIST));
+ for (auto idle_behavior : ac_idle_info.possible_behaviors)
+ list->Append(static_cast<int>(idle_behavior));
+
+ list = dict.SetKey(kPossibleBatteryIdleBehaviorsKey,
+ base::Value(base::Value::Type::LIST));
+ for (auto idle_behavior : battery_idle_info.possible_behaviors)
+ list->Append(static_cast<int>(idle_behavior));
+ dict.SetInteger(kCurrentAcIdleBehaviorKey,
+ static_cast<int>(ac_idle_info.current_behavior));
+ dict.SetInteger(kCurrentBatteryIdleBehaviorKey,
+ static_cast<int>(battery_idle_info.current_behavior));
dict.SetInteger(kLidClosedBehaviorKey, lid_closed_behavior);
+ dict.SetBoolean(kAcIdleManagedKey, ac_idle_info.is_managed);
+ dict.SetBoolean(kBatteryIdleManagedKey, battery_idle_info.is_managed);
dict.SetBoolean(kLidClosedControlledKey, lid_closed_controlled);
dict.SetBoolean(kHasLidKey, has_lid);
FireWebUIListener(kPowerManagementSettingsChangedName, dict);
- last_idle_behavior_ = idle_behavior;
- last_idle_controlled_ = idle_controlled;
+ last_ac_idle_info_ = ac_idle_info;
+ last_battery_idle_info_ = battery_idle_info;
last_lid_closed_behavior_ = lid_closed_behavior;
last_lid_closed_controlled_ = lid_closed_controlled;
last_has_lid_ = has_lid;
@@ -401,5 +417,159 @@ void PowerHandler::OnGotSwitchStates(
SendPowerManagementSettings(false /* force */);
}
+PowerHandler::IdleBehaviorInfo PowerHandler::GetAllowedIdleBehaviors(
+ PowerSource power_source) {
+ const char* idle_pref = power_source == PowerSource::kAc
+ ? ash::prefs::kPowerAcIdleAction
+ : ash::prefs::kPowerBatteryIdleAction;
+ const char* screen_off_delay_pref =
+ power_source == PowerSource::kAc
+ ? ash::prefs::kPowerAcScreenOffDelayMs
+ : ash::prefs::kPowerBatteryScreenOffDelayMs;
+
+ std::set<IdleBehavior> possible_behaviors;
+ IdleBehavior current_idle_behavior;
+
+ // If idle action is managed and set to suspend, only possible idle
+ // behaviour is sleep with display off.
+ if (prefs_->IsManagedPreference(idle_pref) &&
+ prefs_->GetInteger(idle_pref) == PowerPolicyController::ACTION_SUSPEND) {
+ current_idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
+ possible_behaviors.insert(IdleBehavior::DISPLAY_OFF_SLEEP);
+ return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+ IsIdleManaged(power_source));
+ }
+
+ // If idle action is managed and set to SHUT_DOWN/STOP_SESSION, only
+ // possible idle behaviour is other.
+ if (prefs_->IsManagedPreference(idle_pref) &&
+ (prefs_->GetInteger(idle_pref) ==
+ PowerPolicyController::ACTION_STOP_SESSION ||
+ prefs_->GetInteger(idle_pref) ==
+ PowerPolicyController::ACTION_SHUT_DOWN)) {
+ current_idle_behavior = IdleBehavior::OTHER;
+ possible_behaviors.insert(IdleBehavior::OTHER);
+ return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+ IsIdleManaged(power_source));
+ }
+
+ // Note that after this point |idle_pref| should either be:
+ // 1. Not managed.
+ // 2. Or managed and set to
+ // PowerPolicyController::ACTION_DO_NOTHING.
+ DCHECK(!prefs_->IsManagedPreference(idle_pref) ||
+ (prefs_->GetInteger(idle_pref) ==
+ PowerPolicyController::ACTION_DO_NOTHING));
+
+ // If screen off delay is managed and set to a value greater than 0
+ // and
+ // 1. If idle action is managed and set to DO_NOTHING, only
+ // possible idle behavior is DISPLAY_OFF.
+ // 2. If idle action is not managed then possible idle options
+ // are DiSPLAY_OFF and DISPLAY_OFF_SLEEP
+ if (prefs_->IsManagedPreference(screen_off_delay_pref) &&
+ prefs_->GetInteger(screen_off_delay_pref) > 0) {
+ if (prefs_->IsManagedPreference(idle_pref) &&
+ prefs_->GetInteger(idle_pref) ==
+ PowerPolicyController::ACTION_DO_NOTHING) {
+ current_idle_behavior = IdleBehavior::DISPLAY_OFF;
+ possible_behaviors.insert(IdleBehavior::DISPLAY_OFF);
+ return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+ IsIdleManaged(power_source));
+ }
+
+ possible_behaviors.insert(IdleBehavior::DISPLAY_OFF);
+ possible_behaviors.insert(IdleBehavior::DISPLAY_OFF_SLEEP);
+ // Set the current default option based on the current idle action.
+ const PowerPolicyController::Action idle_action =
+ static_cast<PowerPolicyController::Action>(
+ prefs_->GetInteger(idle_pref));
+
+ if (idle_action == PowerPolicyController::ACTION_SUSPEND)
+ current_idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
+ else
+ current_idle_behavior = IdleBehavior::DISPLAY_OFF;
+ return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+ IsIdleManaged(power_source));
+ }
+
+ // If idle action is managed and set to DO_NOTHING, and
+ // 1. If screen off delay is also managed (and set to 0), only
+ // possible idle
+ // action is DISPLAY_ON.
+ // 2. If AC screen off delay is not managed, possible idle actions
+ // are DISPLAY_ON && DISPLAY_OFF.
+ if (prefs_->IsManagedPreference(idle_pref) &&
+ prefs_->GetInteger(idle_pref) ==
+ PowerPolicyController::ACTION_DO_NOTHING) {
+ if (prefs_->IsManagedPreference(screen_off_delay_pref)) {
+ // Note that we reach here only when screen off delays are
+ // set by enterprise policy to 0 to prevent display from turning
+ // off.
+ DCHECK(prefs_->GetInteger(screen_off_delay_pref) == 0);
+ current_idle_behavior = IdleBehavior::DISPLAY_ON;
+ possible_behaviors.insert(IdleBehavior::DISPLAY_ON);
+ return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+ IsIdleManaged(power_source));
+ }
+ possible_behaviors.insert(IdleBehavior::DISPLAY_ON);
+ possible_behaviors.insert(IdleBehavior::DISPLAY_OFF);
+ // Set the current default option based on the current screen off
+ // delay.
+ current_idle_behavior = prefs_->GetInteger(screen_off_delay_pref) > 0
+ ? IdleBehavior::DISPLAY_OFF
+ : IdleBehavior::DISPLAY_ON;
+ return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+ IsIdleManaged(power_source));
+ }
+
+ // Looks like we did not find enterprise policy restricitng the idle
+ // options. So add all three idle options to what user can select
+ // from.
+ possible_behaviors.insert(IdleBehavior::DISPLAY_ON);
+ possible_behaviors.insert(IdleBehavior::DISPLAY_OFF);
+ possible_behaviors.insert(IdleBehavior::DISPLAY_OFF_SLEEP);
+
+ // Infer the idle behavior based on the current idle action
+ // (determining whether we'll sleep eventually or not) and the AC
+ // screen-off delay.
+ const PowerPolicyController::Action idle_action =
+ static_cast<PowerPolicyController::Action>(prefs_->GetInteger(idle_pref));
+
+ if (idle_action == PowerPolicyController::ACTION_SUSPEND) {
+ current_idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
+ } else if (idle_action == PowerPolicyController::ACTION_DO_NOTHING) {
+ current_idle_behavior = (prefs_->GetInteger(screen_off_delay_pref) > 0
+ ? IdleBehavior::DISPLAY_OFF
+ : IdleBehavior::DISPLAY_ON);
+ } else {
+ current_idle_behavior = IdleBehavior::OTHER;
+ possible_behaviors.insert(IdleBehavior::OTHER);
+ }
+
+ return IdleBehaviorInfo(possible_behaviors, current_idle_behavior,
+ IsIdleManaged(power_source));
+}
+
+bool PowerHandler::IsIdleManaged(PowerSource power_source) {
+ switch (power_source) {
+ case PowerSource::kAc:
+ return prefs_->IsManagedPreference(ash::prefs::kPowerAcIdleAction) ||
+ prefs_->IsManagedPreference(
+ ash::prefs::kPowerAcScreenDimDelayMs) ||
+ prefs_->IsManagedPreference(
+ ash::prefs::kPowerAcScreenOffDelayMs) ||
+ prefs_->IsManagedPreference(ash::prefs::kPowerAcScreenLockDelayMs);
+ case PowerSource::kBattery:
+ return prefs_->IsManagedPreference(ash::prefs::kPowerBatteryIdleAction) ||
+ prefs_->IsManagedPreference(
+ ash::prefs::kPowerBatteryScreenDimDelayMs) ||
+ prefs_->IsManagedPreference(
+ ash::prefs::kPowerBatteryScreenOffDelayMs) ||
+ prefs_->IsManagedPreference(
+ ash::prefs::kPowerBatteryScreenLockDelayMs);
+ }
+}
+
} // namespace settings
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
index d55a3944bd5..1d125b0295a 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.h
@@ -6,6 +6,7 @@
#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_POWER_HANDLER_H_
#include <memory>
+#include <set>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -22,7 +23,7 @@ class PrefService;
namespace base {
class ListValue;
class TimeTicks;
-}
+} // namespace base
namespace chromeos {
namespace settings {
@@ -43,8 +44,12 @@ class PowerHandler : public ::settings::SettingsPageUIHandler,
// WebUI message name and dictionary keys. Shared with tests.
static const char kPowerManagementSettingsChangedName[];
- static const char kIdleBehaviorKey[];
- static const char kIdleControlledKey[];
+ static const char kPossibleAcIdleBehaviorsKey[];
+ static const char kPossibleBatteryIdleBehaviorsKey[];
+ static const char kAcIdleManagedKey[];
+ static const char kBatteryIdleManagedKey[];
+ static const char kCurrentAcIdleBehaviorKey[];
+ static const char kCurrentBatteryIdleBehaviorKey[];
static const char kLidClosedBehaviorKey[];
static const char kLidClosedControlledKey[];
static const char kHasLidKey[];
@@ -56,7 +61,9 @@ class PowerHandler : public ::settings::SettingsPageUIHandler,
~TestAPI();
void RequestPowerManagementSettings();
- void SetIdleBehavior(IdleBehavior behavior);
+ // Sets AC idle behavior to |behavior| if |when_on_ac| is true. Otherwise
+ // sets battery idle behavior to |behavior|.
+ void SetIdleBehavior(IdleBehavior behavior, bool when_on_ac);
void SetLidClosedBehavior(PowerPolicyController::Action behavior);
private:
@@ -80,6 +87,33 @@ class PowerHandler : public ::settings::SettingsPageUIHandler,
const base::TimeTicks& timestamp) override;
private:
+ enum class PowerSource { kAc, kBattery };
+
+ // Struct holding possible idle behaviors and the current behavior while
+ // charging/when on battery.
+ struct IdleBehaviorInfo {
+ IdleBehaviorInfo();
+ IdleBehaviorInfo(const std::set<IdleBehavior>& possible_behaviors,
+ const IdleBehavior& current_behavior,
+ const bool is_managed);
+
+ IdleBehaviorInfo(const IdleBehaviorInfo& o);
+ ~IdleBehaviorInfo();
+
+ bool operator==(const IdleBehaviorInfo& o) const {
+ return (possible_behaviors == o.possible_behaviors &&
+ current_behavior == o.current_behavior &&
+ is_managed == o.is_managed);
+ }
+
+ // All possible idle behaviors.
+ std::set<IdleBehavior> possible_behaviors;
+ // Current idle behavior.
+ IdleBehavior current_behavior = IdleBehavior::DISPLAY_OFF_SLEEP;
+ // Whether enterpise policy manages idle behavior.
+ bool is_managed = false;
+ };
+
// Handler to request updating the power status.
void HandleUpdatePowerStatus(const base::ListValue* args);
@@ -109,7 +143,16 @@ class PowerHandler : public ::settings::SettingsPageUIHandler,
void OnGotSwitchStates(
base::Optional<PowerManagerClient::SwitchStates> result);
- PrefService* prefs_; // Not owned.
+ // Returns all possible idle behaviors (that a user can choose from) and
+ // current idle behavior based on enterprise policy and other factors when on
+ // |power_source|.
+ IdleBehaviorInfo GetAllowedIdleBehaviors(PowerSource power_source);
+
+ // Returns true if the enterprise policy enforces any settings that can impact
+ // the idle behavior of the device when on |power_source|.
+ bool IsIdleManaged(PowerSource power_source);
+
+ PrefService* const prefs_;
// Used to watch power management prefs for changes so the UI can be notified.
std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
@@ -123,10 +166,10 @@ class PowerHandler : public ::settings::SettingsPageUIHandler,
// Last values sent by SendPowerManagementSettings(), cached here so
// SendPowerManagementSettings() can avoid spamming the UI after this class
// changes multiple prefs at once.
- IdleBehavior last_idle_behavior_ = IdleBehavior::DISPLAY_OFF_SLEEP;
+ IdleBehaviorInfo last_ac_idle_info_;
+ IdleBehaviorInfo last_battery_idle_info_;
PowerPolicyController::Action last_lid_closed_behavior_ =
PowerPolicyController::ACTION_SUSPEND;
- bool last_idle_controlled_ = false;
bool last_lid_closed_controlled_ = false;
bool last_has_lid_ = true;
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
index c27e55cb6d4..c928ccd2d75 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc
@@ -2,9 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
-
#include <memory>
+#include <set>
#include <utility>
#include "ash/public/cpp/ash_pref_names.h"
@@ -13,6 +12,7 @@
#include "base/run_loop.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/dbus/power/fake_power_manager_client.h"
#include "chromeos/dbus/power/power_policy_controller.h"
@@ -24,8 +24,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using testing::Return;
using testing::_;
+using testing::Return;
namespace chromeos {
namespace settings {
@@ -48,6 +48,34 @@ class TestPowerHandler : public PowerHandler {
class PowerHandlerTest : public InProcessBrowserTest {
protected:
+ struct DevicePowerSettings {
+ // Initialize with initial settings.
+ DevicePowerSettings() {
+ possible_ac_behaviors.insert(
+ PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
+ possible_ac_behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF);
+ possible_ac_behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_ON);
+ possible_battery_behaviors.insert(
+ PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
+ possible_battery_behaviors.insert(
+ PowerHandler::IdleBehavior::DISPLAY_OFF);
+ possible_battery_behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_ON);
+ }
+
+ std::set<PowerHandler::IdleBehavior> possible_ac_behaviors;
+ std::set<PowerHandler::IdleBehavior> possible_battery_behaviors;
+ PowerHandler::IdleBehavior current_ac_behavior =
+ PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP;
+ PowerHandler::IdleBehavior current_battery_behavior =
+ PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP;
+ bool ac_idle_managed = false;
+ bool battery_idle_managed = false;
+ PowerPolicyController::Action lid_closed_behavior =
+ PowerPolicyController::ACTION_SUSPEND;
+ bool lid_closed_controlled = false;
+ bool has_lid = true;
+ };
+
PowerHandlerTest() = default;
~PowerHandlerTest() override = default;
@@ -99,23 +127,32 @@ class PowerHandlerTest : public InProcessBrowserTest {
return std::string();
}
- // Returns a string for the given settings that can be compared against the
- // output of GetLastSettingsChangedMessage().
- std::string CreateSettingsChangedString(
- PowerHandler::IdleBehavior idle_behavior,
- bool idle_controlled,
- PowerPolicyController::Action lid_closed_behavior,
- bool lid_closed_controlled,
- bool has_lid) {
+ // Returns a string for the given |settings|. Used to verify expected
+ // settings are sent to the UI.
+ std::string ToString(const DevicePowerSettings& settings) {
base::DictionaryValue dict;
- dict.SetInteger(PowerHandler::kIdleBehaviorKey,
- static_cast<int>(idle_behavior));
- dict.SetBoolean(PowerHandler::kIdleControlledKey, idle_controlled);
- dict.SetInteger(PowerHandler::kLidClosedBehaviorKey, lid_closed_behavior);
+ base::Value* list = dict.SetKey(PowerHandler::kPossibleAcIdleBehaviorsKey,
+ base::Value(base::Value::Type::LIST));
+ for (auto idle_behavior : settings.possible_ac_behaviors)
+ list->Append(static_cast<int>(idle_behavior));
+
+ list = dict.SetKey(PowerHandler::kPossibleBatteryIdleBehaviorsKey,
+ base::Value(base::Value::Type::LIST));
+ for (auto idle_behavior : settings.possible_battery_behaviors)
+ list->Append(static_cast<int>(idle_behavior));
+
+ dict.SetInteger(PowerHandler::kCurrentAcIdleBehaviorKey,
+ static_cast<int>(settings.current_ac_behavior));
+ dict.SetInteger(PowerHandler::kCurrentBatteryIdleBehaviorKey,
+ static_cast<int>(settings.current_battery_behavior));
+ dict.SetBoolean(PowerHandler::kAcIdleManagedKey, settings.ac_idle_managed);
+ dict.SetBoolean(PowerHandler::kBatteryIdleManagedKey,
+ settings.battery_idle_managed);
+ dict.SetInteger(PowerHandler::kLidClosedBehaviorKey,
+ settings.lid_closed_behavior);
dict.SetBoolean(PowerHandler::kLidClosedControlledKey,
- lid_closed_controlled);
- dict.SetBoolean(PowerHandler::kHasLidKey, has_lid);
-
+ settings.lid_closed_controlled);
+ dict.SetBoolean(PowerHandler::kHasLidKey, settings.has_lid);
std::string out;
EXPECT_TRUE(base::JSONWriter::Write(dict, &out));
return out;
@@ -129,6 +166,12 @@ class PowerHandlerTest : public InProcessBrowserTest {
return GetPrefs()->GetInteger(name);
}
+ // Trigger power pref managed change.
+ void UpdateChromePolicy(policy::PolicyMap* policy_map) {
+ provider_.UpdateChromePolicy(*policy_map);
+ base::RunLoop().RunUntilIdle();
+ }
+
// Sets a policy update which will cause power pref managed change.
void SetPolicyForPolicyKey(policy::PolicyMap* policy_map,
const std::string& policy_key,
@@ -136,8 +179,7 @@ class PowerHandlerTest : public InProcessBrowserTest {
policy_map->Set(policy_key, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
std::move(value), nullptr);
- provider_.UpdateChromePolicy(*policy_map);
- base::RunLoop().RunUntilIdle();
+ UpdateChromePolicy(policy_map);
}
std::unique_ptr<TestPowerHandler> handler_;
@@ -154,155 +196,215 @@ class PowerHandlerTest : public InProcessBrowserTest {
// Verifies that settings are sent to WebUI when requested.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendInitialSettings) {
test_api_->RequestPowerManagementSettings();
- EXPECT_EQ(
- CreateSettingsChangedString(
- PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
- false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
- false /* lid_closed_controlled */, true /* has_lid */),
- GetLastSettingsChangedMessage());
+ // Initialized to initial settings.
+ DevicePowerSettings settings;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
}
// Verifies that WebUI receives updated settings when the lid state changes.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendSettingsForLidStateChanges) {
chromeos::FakePowerManagerClient::Get()->SetLidState(
PowerManagerClient::LidState::NOT_PRESENT, base::TimeTicks());
- EXPECT_EQ(
- CreateSettingsChangedString(
- PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
- false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
- false /* lid_closed_controlled */, false /* has_lid */),
- GetLastSettingsChangedMessage());
+
+ DevicePowerSettings settings;
+ settings.has_lid = false;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
chromeos::FakePowerManagerClient::Get()->SetLidState(
PowerManagerClient::LidState::OPEN, base::TimeTicks());
- EXPECT_EQ(
- CreateSettingsChangedString(
- PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
- false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
- false /* lid_closed_controlled */, true /* has_lid */),
- GetLastSettingsChangedMessage());
+ settings.has_lid = true;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
}
-// Verifies that when various prefs are controlled, the corresponding settings
-// are reported as controlled to WebUI.
+// Verifies that when various prefs are controlled, the corresponding
+// settings are reported as controlled/managed to WebUI.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendSettingsForControlledPrefs) {
policy::PolicyMap policy_map;
- // Making an arbitrary delay pref managed should result in the idle setting
- // being reported as controlled.
+ // Making an arbitrary AC delay pref managed should result in the AC idle
+ // setting being reported as managed.
SetPolicyForPolicyKey(&policy_map, policy::key::kScreenDimDelayAC,
std::make_unique<base::Value>(10000));
- EXPECT_EQ(
- CreateSettingsChangedString(
- PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
- true /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
- false /* lid_closed_controlled */, true /* has_lid */),
- GetLastSettingsChangedMessage());
+ DevicePowerSettings settings;
+ settings.ac_idle_managed = true;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+ // Ditto for battery delay pref managed.
+ SetPolicyForPolicyKey(&policy_map, policy::key::kScreenDimDelayBattery,
+ std::make_unique<base::Value>(10000));
+ settings.battery_idle_managed = true;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
// Ditto for making the lid action pref managed.
SetPolicyForPolicyKey(
&policy_map, policy::key::kLidCloseAction,
std::make_unique<base::Value>(PowerPolicyController::ACTION_SUSPEND));
- EXPECT_EQ(
- CreateSettingsChangedString(
- PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
- true /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
- true /* lid_closed_controlled */, true /* has_lid */),
- GetLastSettingsChangedMessage());
+ settings.lid_closed_controlled = true;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
}
-// Verifies that idle-related prefs are distilled into the proper WebUI
-// settings.
+// Verifies that idle-related prefs (when not managed by enterpise policy)
+// are distilled into the proper WebUI settings.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendIdleSettingForPrefChanges) {
- // Set a do-nothing idle action and a nonzero screen-off delay.
+ // Initial power settings.
+ DevicePowerSettings settings;
+ // Set a AC do-nothing idle action and a AC nonzero screen-off delay. User
+ // should see all three options (DISPLAY_ON, DISPLAY_OFF and
+ // DISPLAY_OFF_SLEEP) and the selected setting when on AC should be set to
+ // DISPLAY_OFF.
GetPrefs()->Set(ash::prefs::kPowerAcIdleAction,
base::Value(PowerPolicyController::ACTION_DO_NOTHING));
GetPrefs()->Set(ash::prefs::kPowerAcScreenOffDelayMs, base::Value(10000));
- EXPECT_EQ(CreateSettingsChangedString(PowerHandler::IdleBehavior::DISPLAY_OFF,
- false /* idle_controlled */,
- PowerPolicyController::ACTION_SUSPEND,
- false /* lid_closed_controlled */,
- true /* has_lid */),
- GetLastSettingsChangedMessage());
-
- // Now set the delay to zero and check that the setting goes to "display on".
- GetPrefs()->Set(ash::prefs::kPowerAcScreenOffDelayMs, base::Value(0));
- EXPECT_EQ(CreateSettingsChangedString(PowerHandler::IdleBehavior::DISPLAY_ON,
- false /* idle_controlled */,
- PowerPolicyController::ACTION_SUSPEND,
- false /* lid_closed_controlled */,
- true /* has_lid */),
- GetLastSettingsChangedMessage());
+
+ // Current AC idle behavior should be DISPLAY_OFF.
+ settings.current_ac_behavior = PowerHandler::IdleBehavior::DISPLAY_OFF;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+ // Now set the battery screen off delay to zero along with battery do-nothing
+ // idle action and check that the selected setting goes to "display on" when
+ // on battery.
+ GetPrefs()->Set(ash::prefs::kPowerBatteryIdleAction,
+ base::Value(PowerPolicyController::ACTION_DO_NOTHING));
+ GetPrefs()->Set(ash::prefs::kPowerBatteryScreenOffDelayMs, base::Value(0));
+
+ // Current battery idle behavior should be DISPLAY_ON.
+ settings.current_battery_behavior = PowerHandler::IdleBehavior::DISPLAY_ON;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
// Other idle actions should result in an "other" setting.
GetPrefs()->Set(ash::prefs::kPowerAcIdleAction,
base::Value(PowerPolicyController::ACTION_STOP_SESSION));
- EXPECT_EQ(CreateSettingsChangedString(
- PowerHandler::IdleBehavior::OTHER, false /* idle_controlled */,
- PowerPolicyController::ACTION_SUSPEND,
- false /* lid_closed_controlled */, true /* has_lid */),
- GetLastSettingsChangedMessage());
+ // Current AC idle behavior should be OTHER.
+ settings.current_ac_behavior = PowerHandler::IdleBehavior::OTHER;
+ // Possible AC idle behaviors should include OTHER too.
+ settings.possible_ac_behaviors.insert(PowerHandler::IdleBehavior::OTHER);
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+}
+
+// Verifies that idle-related prefs when managed by enterpise policy are
+// distilled into the proper WebUI settings.
+IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendManagedIdleSettingForPrefChanges) {
+ policy::PolicyMap policy_map;
+ // Set Enterpise policy that forces AC idle action to suspend. Only possible
+ // AC idle option visible to the user should be DISPLAY_OFF_SLEEP and the
+ // current should also be set to same.
+ SetPolicyForPolicyKey(&policy_map, policy::key::kIdleActionAC,
+ std::make_unique<base::Value>(
+ chromeos::PowerPolicyController::ACTION_SUSPEND));
+ DevicePowerSettings settings;
+ std::set<PowerHandler::IdleBehavior> behaviors;
+ behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
+ settings.possible_ac_behaviors = behaviors;
+ settings.ac_idle_managed = true;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+ // Set Enterpise policy that forces battery idle action to Shutdown. Only
+ // possible battery idle option visible to the user then should be OTHER and
+ // the default should also be set to same.
+ SetPolicyForPolicyKey(&policy_map, policy::key::kIdleActionBattery,
+ std::make_unique<base::Value>(
+ chromeos::PowerPolicyController::ACTION_SHUT_DOWN));
+ behaviors.clear();
+ behaviors.insert(PowerHandler::IdleBehavior::OTHER);
+ settings.possible_battery_behaviors = behaviors;
+ settings.current_battery_behavior = PowerHandler::IdleBehavior::OTHER;
+ settings.battery_idle_managed = true;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+ // Erase battery idle action.
+ policy_map.Erase(policy::key::kIdleActionBattery);
+
+ // Set battery idle action to DO_NOTHING in Enterpise policy. The user then
+ // should not see DISPLAY_OFF_SLEEP in available options.
+ SetPolicyForPolicyKey(
+ &policy_map, policy::key::kIdleActionBattery,
+ std::make_unique<base::Value>(
+ chromeos::PowerPolicyController::ACTION_DO_NOTHING));
+ behaviors.clear();
+ behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF);
+ behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_ON);
+ settings.possible_battery_behaviors = behaviors;
+ settings.current_battery_behavior = PowerHandler::IdleBehavior::DISPLAY_OFF;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+ // Set battery screen delay in Enterprise policy on top of DO_NOTHING idle
+ // action. The user should see only see DISPLAY_OFF as the possible battery
+ // idle action.
+ SetPolicyForPolicyKey(&policy_map, policy::key::kScreenOffDelayBattery,
+ std::make_unique<base::Value>(10000));
+ behaviors.clear();
+ behaviors.insert(PowerHandler::IdleBehavior::DISPLAY_OFF);
+ settings.possible_battery_behaviors = behaviors;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
+
+ // Now stop enforcing battery idle action (to DO_NOTHING) in enterprise
+ // policy. The user should see DISPLAY_OFF and DISPLAY_OFF_SLEEP as
+ // the possible battery idle actions.
+ policy_map.Erase(policy::key::kIdleActionBattery);
+ UpdateChromePolicy(&policy_map);
+ settings.possible_battery_behaviors.insert(
+ PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
+ settings.current_battery_behavior =
+ PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
}
// Verifies that the lid-closed pref's value is sent directly to WebUI.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendLidSettingForPrefChanges) {
GetPrefs()->Set(ash::prefs::kPowerLidClosedAction,
base::Value(PowerPolicyController::ACTION_SHUT_DOWN));
- EXPECT_EQ(
- CreateSettingsChangedString(
- PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
- false /* idle_controlled */, PowerPolicyController::ACTION_SHUT_DOWN,
- false /* lid_closed_controlled */, true /* has_lid */),
- GetLastSettingsChangedMessage());
+ DevicePowerSettings settings;
+ settings.lid_closed_behavior = PowerPolicyController::ACTION_SHUT_DOWN;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
GetPrefs()->Set(ash::prefs::kPowerLidClosedAction,
base::Value(PowerPolicyController::ACTION_STOP_SESSION));
- EXPECT_EQ(CreateSettingsChangedString(
- PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
- false /* idle_controlled */,
- PowerPolicyController::ACTION_STOP_SESSION,
- false /* lid_closed_controlled */, true /* has_lid */),
- GetLastSettingsChangedMessage());
+ settings.lid_closed_behavior = PowerPolicyController::ACTION_STOP_SESSION;
+ EXPECT_EQ(ToString(settings), GetLastSettingsChangedMessage());
}
// Verifies that requests from WebUI to update the idle behavior update prefs
// appropriately.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SetIdleBehavior) {
- // Request the "Keep display on" setting and check that prefs are set
+ // Request the "Keep display on" AC setting and check that prefs are set
// appropriately.
- test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON);
+ test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON,
+ true /* is_ac */);
EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
GetIntPref(ash::prefs::kPowerAcIdleAction));
EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
- EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
- GetIntPref(ash::prefs::kPowerBatteryIdleAction));
- EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
- EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
- EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerBatteryScreenLockDelayMs));
+ EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryIdleAction));
+ EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
+ EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
+ EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenLockDelayMs));
- // "Turn off display" should set the idle prefs but clear the screen
- // delays.
- test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF);
+ // "Turn off display" battery setting should set the battery idle pref but
+ // clear the battery screen delays.
+ test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF,
+ false /* is_battery */);
EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
GetIntPref(ash::prefs::kPowerAcIdleAction));
- EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
- EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
- EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
+ EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
+ EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
+ EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
GetIntPref(ash::prefs::kPowerBatteryIdleAction));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenLockDelayMs));
- // Now switch to the "Keep display on" setting (to set the prefs again) and
- // check that the "Turn off display and sleep" setting clears all the prefs.
- test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON);
- test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
- EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcIdleAction));
- EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
- EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
- EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
+ // Now switch to the "Keep display on" battery setting (to set the prefs
+ // again) and check that the "Turn off display and sleep" battery setting
+ // clears all the battery prefs.
+ test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON,
+ false /* is_battery */);
+ test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
+ false /* is_battery */);
+ EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
+ GetIntPref(ash::prefs::kPowerAcIdleAction));
+ EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
+ EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
+ EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryIdleAction));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
index 0eebb3c1814..128d85cb80b 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc
@@ -6,46 +6,16 @@
#include <algorithm>
#include <limits>
-#include <numeric>
+#include <memory>
#include <string>
+#include <utility>
-#include "base/bind.h"
-#include "base/feature_list.h"
-#include "base/files/file_util.h"
-#include "base/system/sys_info.h"
-#include "base/task/post_task.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/browsing_data/browsing_data_appcache_helper.h"
-#include "chrome/browser/browsing_data/browsing_data_cache_storage_helper.h"
-#include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
-#include "chrome/browser/browsing_data/browsing_data_database_helper.h"
-#include "chrome/browser/browsing_data/browsing_data_file_system_helper.h"
-#include "chrome/browser/browsing_data/browsing_data_flash_lso_helper.h"
-#include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h"
-#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
-#include "chrome/browser/browsing_data/browsing_data_service_worker_helper.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
-#include "chrome/browser/chromeos/crostini/crostini_features.h"
-#include "chrome/browser/chromeos/crostini/crostini_manager.h"
-#include "chrome/browser/chromeos/crostini/crostini_util.h"
-#include "chrome/browser/chromeos/drive/file_system_util.h"
#include "chrome/browser/chromeos/file_manager/path_util.h"
#include "chrome/browser/platform_util.h"
-#include "chrome/browser/profiles/profile.h"
#include "chrome/grit/generated_resources.h"
-#include "chromeos/cryptohome/cryptohome_util.h"
-#include "chromeos/dbus/cryptohome/cryptohome_client.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/disks/disk.h"
#include "components/arc/arc_features.h"
-#include "components/arc/arc_prefs.h"
-#include "components/arc/arc_service_manager.h"
-#include "components/arc/arc_util.h"
-#include "components/arc/session/arc_bridge_service.h"
-#include "components/browsing_data/content/conditional_cache_counting_helper.h"
-#include "components/user_manager/user_manager.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_ui_data_source.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/text/bytes_formatting.h"
@@ -55,41 +25,43 @@ using chromeos::disks::DiskMountManager;
namespace chromeos {
namespace settings {
-namespace {
-
-void GetSizeStatBlocking(const base::FilePath& mount_path,
- int64_t* total_size,
- int64_t* available_size) {
- int64_t size = base::SysInfo::AmountOfTotalDiskSpace(mount_path);
- if (size >= 0)
- *total_size = size;
- size = base::SysInfo::AmountOfFreeDiskSpace(mount_path);
- if (size >= 0)
- *available_size = size;
-}
-
-// Threshold to show a message indicating space is critically low (512 MB).
-const int64_t kSpaceCriticallyLowBytes = 512 * 1024 * 1024;
-// Threshold to show a message indicating space is low (1 GB).
-const int64_t kSpaceLowBytes = 1 * 1024 * 1024 * 1024;
+namespace {
constexpr char kAndroidEnabled[] = "androidEnabled";
+const char* CalculationTypeToEventName(
+ calculator::SizeCalculator::CalculationType x) {
+ switch (x) {
+ case calculator::SizeCalculator::CalculationType::kSystem:
+ return "storage-system-size-changed";
+ case calculator::SizeCalculator::CalculationType::kInUse:
+ return "storage-size-stat-changed";
+ case calculator::SizeCalculator::CalculationType::kMyFiles:
+ return "storage-my-files-size-changed";
+ case calculator::SizeCalculator::CalculationType::kBrowsingData:
+ return "storage-browsing-data-size-changed";
+ case calculator::SizeCalculator::CalculationType::kAppsExtensions:
+ return "storage-apps-size-changed";
+ case calculator::SizeCalculator::CalculationType::kCrostini:
+ return "storage-crostini-size-changed";
+ case calculator::SizeCalculator::CalculationType::kOtherUsers:
+ return "storage-other-users-size-changed";
+ }
+ NOTREACHED();
+ return "";
+}
+
} // namespace
StorageHandler::StorageHandler(Profile* profile,
content::WebUIDataSource* html_source)
- : browser_cache_size_(-1),
- has_browser_cache_size_(false),
- browser_site_data_size_(-1),
- has_browser_site_data_size_(false),
- updating_downloads_size_(false),
- updating_browsing_data_size_(false),
- updating_android_size_(false),
- updating_crostini_size_(false),
- updating_other_users_size_(false),
- is_android_running_(false),
+ : size_stat_calculator_(profile),
+ my_files_size_calculator_(profile),
+ browsing_data_size_calculator_(profile),
+ apps_size_calculator_(profile),
+ crostini_size_calculator_(profile),
+ other_users_size_calculator_(),
profile_(profile),
source_name_(html_source->GetSource()),
arc_observer_(this),
@@ -101,11 +73,7 @@ StorageHandler::StorageHandler(Profile* profile,
}
StorageHandler::~StorageHandler() {
- DiskMountManager::GetInstance()->RemoveObserver(this);
- arc::ArcServiceManager::Get()
- ->arc_bridge_service()
- ->storage_manager()
- ->RemoveObserver(this);
+ StopObservingEvents();
}
void StorageHandler::RegisterMessages() {
@@ -120,8 +88,8 @@ void StorageHandler::RegisterMessages() {
base::BindRepeating(&StorageHandler::HandleUpdateStorageInfo,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
- "openDownloads", base::BindRepeating(&StorageHandler::HandleOpenDownloads,
- base::Unretained(this)));
+ "openMyFiles", base::BindRepeating(&StorageHandler::HandleOpenMyFiles,
+ base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"openArcStorage",
base::BindRepeating(&StorageHandler::HandleOpenArcStorage,
@@ -136,35 +104,48 @@ void StorageHandler::OnJavascriptAllowed() {
if (base::FeatureList::IsEnabled(arc::kUsbStorageUIFeature))
arc_observer_.Add(arc::ArcSessionManager::Get());
- // Start observing the mojo connection UpdateAndroidSize() relies on. Note
- // that OnConnectionReady() will be called immediately if the connection has
- // already been established.
- arc::ArcServiceManager::Get()
- ->arc_bridge_service()
- ->storage_manager()
- ->AddObserver(this);
-
// Start observing mount/unmount events to update the connected device list.
DiskMountManager::GetInstance()->AddObserver(this);
+
+ // Start observing calculators.
+ size_stat_calculator_.AddObserver(this);
+ my_files_size_calculator_.AddObserver(this);
+ browsing_data_size_calculator_.AddObserver(this);
+ apps_size_calculator_.AddObserver(this);
+ crostini_size_calculator_.AddObserver(this);
+ other_users_size_calculator_.AddObserver(this);
}
void StorageHandler::OnJavascriptDisallowed() {
// Ensure that pending callbacks do not complete and cause JS to be evaluated.
weak_ptr_factory_.InvalidateWeakPtrs();
- // Stop observing mount/unmount events to update the connected device list.
- DiskMountManager::GetInstance()->RemoveObserver(this);
-
- // Stop observing the mojo connection so that OnConnectionReady() and
- // OnConnectionClosed() that use FireWebUIListener() won't be called while JS
- // is disabled.
- arc::ArcServiceManager::Get()
- ->arc_bridge_service()
- ->storage_manager()
- ->RemoveObserver(this);
-
if (base::FeatureList::IsEnabled(arc::kUsbStorageUIFeature))
arc_observer_.Remove(arc::ArcSessionManager::Get());
+
+ StopObservingEvents();
+}
+
+int64_t StorageHandler::RoundByteSize(int64_t bytes) {
+ if (bytes < 0) {
+ NOTREACHED() << "Negative bytes value";
+ return -1;
+ }
+
+ // Subtract one to the original number of bytes.
+ bytes--;
+ // Set all the lower bits to 1.
+ bytes |= bytes >> 1;
+ bytes |= bytes >> 2;
+ bytes |= bytes >> 4;
+ bytes |= bytes >> 8;
+ bytes |= bytes >> 16;
+ bytes |= bytes >> 32;
+ // Add one. The one bit beyond the highest set bit is set to 1. All the lower
+ // bits are set to 0.
+ bytes++;
+
+ return bytes;
}
void StorageHandler::HandleUpdateAndroidEnabled(
@@ -176,20 +157,18 @@ void StorageHandler::HandleUpdateAndroidEnabled(
void StorageHandler::HandleUpdateStorageInfo(const base::ListValue* args) {
AllowJavascript();
- UpdateSizeStat();
- UpdateDownloadsSize();
- UpdateBrowsingDataSize();
- UpdateAndroidRunning();
- UpdateAndroidSize();
- UpdateCrostiniSize();
- UpdateOtherUsersSize();
+ size_stat_calculator_.StartCalculation();
+ my_files_size_calculator_.StartCalculation();
+ browsing_data_size_calculator_.StartCalculation();
+ apps_size_calculator_.StartCalculation();
+ crostini_size_calculator_.StartCalculation();
+ other_users_size_calculator_.StartCalculation();
}
-void StorageHandler::HandleOpenDownloads(
- const base::ListValue* unused_args) {
- const base::FilePath downloads_path =
- file_manager::util::GetDownloadsFolderForProfile(profile_);
- platform_util::OpenItem(profile_, downloads_path, platform_util::OPEN_FOLDER,
+void StorageHandler::HandleOpenMyFiles(const base::ListValue* unused_args) {
+ const base::FilePath my_files_path =
+ file_manager::util::GetMyFilesFolderForProfile(profile_);
+ platform_util::OpenItem(profile_, my_files_path, platform_util::OPEN_FOLDER,
platform_util::OpenOperationCallback());
}
@@ -206,233 +185,6 @@ void StorageHandler::HandleUpdateExternalStorages(
UpdateExternalStorages();
}
-void StorageHandler::UpdateSizeStat() {
- const base::FilePath downloads_path =
- file_manager::util::GetDownloadsFolderForProfile(profile_);
-
- int64_t* total_size = new int64_t(0);
- int64_t* available_size = new int64_t(0);
- base::PostTaskAndReply(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
- base::Bind(&GetSizeStatBlocking, downloads_path, total_size,
- available_size),
- base::Bind(&StorageHandler::OnGetSizeStat, weak_ptr_factory_.GetWeakPtr(),
- base::Owned(total_size), base::Owned(available_size)));
-}
-
-void StorageHandler::OnGetSizeStat(int64_t* total_size,
- int64_t* available_size) {
- int64_t used_size = *total_size - *available_size;
- base::DictionaryValue size_stat;
- size_stat.SetString("totalSize", ui::FormatBytes(*total_size));
- size_stat.SetString("availableSize", ui::FormatBytes(*available_size));
- size_stat.SetString("usedSize", ui::FormatBytes(used_size));
- size_stat.SetDouble("usedRatio",
- static_cast<double>(used_size) / *total_size);
- int storage_space_state = STORAGE_SPACE_NORMAL;
- if (*available_size < kSpaceCriticallyLowBytes)
- storage_space_state = STORAGE_SPACE_CRITICALLY_LOW;
- else if (*available_size < kSpaceLowBytes)
- storage_space_state = STORAGE_SPACE_LOW;
- size_stat.SetInteger("spaceState", storage_space_state);
-
- FireWebUIListener("storage-size-stat-changed", size_stat);
-}
-
-void StorageHandler::UpdateDownloadsSize() {
- if (updating_downloads_size_)
- return;
- updating_downloads_size_ = true;
-
- const base::FilePath downloads_path =
- file_manager::util::GetDownloadsFolderForProfile(profile_);
-
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
- base::Bind(&base::ComputeDirectorySize, downloads_path),
- base::Bind(&StorageHandler::OnGetDownloadsSize,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void StorageHandler::OnGetDownloadsSize(int64_t size) {
- updating_downloads_size_ = false;
- FireWebUIListener("storage-downloads-size-changed",
- base::Value(ui::FormatBytes(size)));
-}
-
-void StorageHandler::UpdateBrowsingDataSize() {
- if (updating_browsing_data_size_)
- return;
- updating_browsing_data_size_ = true;
-
- has_browser_cache_size_ = false;
- has_browser_site_data_size_ = false;
- // Fetch the size of http cache in browsing data.
- browsing_data::ConditionalCacheCountingHelper::Count(
- content::BrowserContext::GetDefaultStoragePartition(profile_),
- base::Time(), base::Time::Max(),
- base::BindOnce(&StorageHandler::OnGetCacheSize,
- weak_ptr_factory_.GetWeakPtr()));
-
- // Fetch the size of site data in browsing data.
- if (!site_data_size_collector_.get()) {
- content::StoragePartition* storage_partition =
- content::BrowserContext::GetDefaultStoragePartition(profile_);
- site_data_size_collector_ = std::make_unique<SiteDataSizeCollector>(
- storage_partition->GetPath(),
- new BrowsingDataCookieHelper(storage_partition),
- new BrowsingDataDatabaseHelper(profile_),
- new BrowsingDataLocalStorageHelper(profile_),
- new BrowsingDataAppCacheHelper(storage_partition->GetAppCacheService()),
- new BrowsingDataIndexedDBHelper(
- storage_partition->GetIndexedDBContext()),
- BrowsingDataFileSystemHelper::Create(
- storage_partition->GetFileSystemContext()),
- new BrowsingDataServiceWorkerHelper(
- storage_partition->GetServiceWorkerContext()),
- new BrowsingDataCacheStorageHelper(
- storage_partition->GetCacheStorageContext()),
- BrowsingDataFlashLSOHelper::Create(profile_));
- }
- site_data_size_collector_->Fetch(
- base::Bind(&StorageHandler::OnGetBrowsingDataSize,
- weak_ptr_factory_.GetWeakPtr(), true));
-}
-
-void StorageHandler::OnGetCacheSize(bool is_upper_limit, int64_t size) {
- DCHECK(!is_upper_limit);
- OnGetBrowsingDataSize(false, size);
-}
-
-void StorageHandler::OnGetBrowsingDataSize(bool is_site_data, int64_t size) {
- if (is_site_data) {
- has_browser_site_data_size_ = true;
- browser_site_data_size_ = size;
- } else {
- has_browser_cache_size_ = true;
- browser_cache_size_ = size;
- }
- if (has_browser_cache_size_ && has_browser_site_data_size_) {
- base::string16 size_string;
- if (browser_cache_size_ >= 0 && browser_site_data_size_ >= 0) {
- size_string = ui::FormatBytes(
- browser_site_data_size_ + browser_cache_size_);
- } else {
- size_string =
- l10n_util::GetStringUTF16(IDS_SETTINGS_STORAGE_SIZE_UNKNOWN);
- }
- updating_browsing_data_size_ = false;
- FireWebUIListener("storage-browsing-data-size-changed",
- base::Value(size_string));
- }
-}
-
-void StorageHandler::UpdateAndroidRunning() {
- FireWebUIListener("storage-android-running-changed",
- base::Value(is_android_running_));
-}
-
-void StorageHandler::UpdateAndroidSize() {
- if (!is_android_running_)
- return;
-
- if (updating_android_size_)
- return;
- updating_android_size_ = true;
-
- bool success = false;
- auto* arc_storage_manager =
- arc::ArcStorageManager::GetForBrowserContext(profile_);
- if (arc_storage_manager) {
- success = arc_storage_manager->GetApplicationsSize(base::BindOnce(
- &StorageHandler::OnGetAndroidSize, weak_ptr_factory_.GetWeakPtr()));
- }
- if (!success)
- updating_android_size_ = false;
-}
-
-void StorageHandler::OnGetAndroidSize(bool succeeded,
- arc::mojom::ApplicationsSizePtr size) {
- base::string16 size_string;
- if (succeeded) {
- uint64_t total_bytes = size->total_code_bytes + size->total_data_bytes +
- size->total_cache_bytes;
- size_string = ui::FormatBytes(total_bytes);
- } else {
- size_string = l10n_util::GetStringUTF16(IDS_SETTINGS_STORAGE_SIZE_UNKNOWN);
- }
- updating_android_size_ = false;
- FireWebUIListener("storage-android-size-changed", base::Value(size_string));
-}
-
-void StorageHandler::UpdateCrostiniSize() {
- if (!crostini::CrostiniFeatures::Get()->IsEnabled(profile_)) {
- return;
- }
-
- if (updating_crostini_size_)
- return;
- updating_crostini_size_ = true;
-
- crostini::CrostiniManager::GetForProfile(profile_)->ListVmDisks(
- base::BindOnce(&StorageHandler::OnGetCrostiniSize,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void StorageHandler::OnGetCrostiniSize(crostini::CrostiniResult result,
- int64_t size) {
- updating_crostini_size_ = false;
- FireWebUIListener("storage-crostini-size-changed",
- base::Value(ui::FormatBytes(size)));
-}
-
-void StorageHandler::UpdateOtherUsersSize() {
- if (updating_other_users_size_)
- return;
- updating_other_users_size_ = true;
-
- other_users_.clear();
- user_sizes_.clear();
- const user_manager::UserList& users =
- user_manager::UserManager::Get()->GetUsers();
- for (auto* user : users) {
- if (user->is_active())
- continue;
- other_users_.push_back(user);
- CryptohomeClient::Get()->GetAccountDiskUsage(
- cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId()),
- base::BindOnce(&StorageHandler::OnGetOtherUserSize,
- weak_ptr_factory_.GetWeakPtr()));
- }
- // We should show "0 B" if there is no other user.
- if (other_users_.empty()) {
- updating_other_users_size_ = false;
- FireWebUIListener("storage-other-users-size-changed",
- base::Value(ui::FormatBytes(0)));
- }
-}
-
-void StorageHandler::OnGetOtherUserSize(
- base::Optional<cryptohome::BaseReply> reply) {
- user_sizes_.push_back(cryptohome::AccountDiskUsageReplyToUsageSize(reply));
- if (user_sizes_.size() == other_users_.size()) {
- base::string16 size_string;
- // If all the requests succeed, shows the total bytes in the UI.
- if (std::count(user_sizes_.begin(), user_sizes_.end(), -1) == 0) {
- size_string = ui::FormatBytes(
- std::accumulate(user_sizes_.begin(), user_sizes_.end(), 0LL));
- } else {
- size_string =
- l10n_util::GetStringUTF16(IDS_SETTINGS_STORAGE_SIZE_UNKNOWN);
- }
- updating_other_users_size_ = false;
- FireWebUIListener("storage-other-users-size-changed",
- base::Value(size_string));
- }
-}
-
void StorageHandler::UpdateExternalStorages() {
base::Value devices(base::Value::Type::LIST);
for (const auto& itr : DiskMountManager::GetInstance()->mount_points()) {
@@ -463,19 +215,7 @@ void StorageHandler::UpdateExternalStorages() {
FireWebUIListener("onExternalStoragesUpdated", devices);
}
-void StorageHandler::OnConnectionReady() {
- is_android_running_ = true;
- UpdateAndroidRunning();
- UpdateAndroidSize();
-}
-
-void StorageHandler::OnConnectionClosed() {
- is_android_running_ = false;
- UpdateAndroidRunning();
-}
-
void StorageHandler::OnArcPlayStoreEnabledChanged(bool enabled) {
- FireWebUIListener("storage-android-enabled-changed", base::Value(enabled));
auto update = std::make_unique<base::DictionaryValue>();
update->SetKey(kAndroidEnabled, base::Value(enabled));
content::WebUIDataSource::Update(profile_, source_name_, std::move(update));
@@ -494,6 +234,114 @@ void StorageHandler::OnMountEvent(
UpdateExternalStorages();
}
+void StorageHandler::OnSizeCalculated(
+ const calculator::SizeCalculator::CalculationType& calculation_type,
+ int64_t total_bytes,
+ const base::Optional<int64_t>& available_bytes) {
+ if (available_bytes) {
+ UpdateSizeStat(calculation_type, total_bytes, available_bytes.value());
+ } else {
+ UpdateStorageItem(calculation_type, total_bytes);
+ }
+}
+
+void StorageHandler::StopObservingEvents() {
+ // Stop observing mount/unmount events to update the connected device list.
+ DiskMountManager::GetInstance()->RemoveObserver(this);
+
+ // Stop observing calculators.
+ size_stat_calculator_.RemoveObserver(this);
+ my_files_size_calculator_.RemoveObserver(this);
+ browsing_data_size_calculator_.RemoveObserver(this);
+ apps_size_calculator_.RemoveObserver(this);
+ crostini_size_calculator_.RemoveObserver(this);
+ other_users_size_calculator_.RemoveObserver(this);
+}
+
+void StorageHandler::UpdateStorageItem(
+ const calculator::SizeCalculator::CalculationType& calculation_type,
+ int64_t total_bytes) {
+ // When the system size has been calculated, UpdateSystemSize calls this
+ // method with the calculation type kSystem. This check prevents an infinite
+ // loop.
+ if (calculation_type != calculator::SizeCalculator::CalculationType::kSystem)
+ UpdateSystemSize(calculation_type, total_bytes);
+
+ base::string16 message;
+ if (total_bytes < 0) {
+ message = l10n_util::GetStringUTF16(IDS_SETTINGS_STORAGE_SIZE_UNKNOWN);
+ } else {
+ message = ui::FormatBytes(total_bytes);
+ }
+
+ if (calculation_type ==
+ calculator::SizeCalculator::CalculationType::kOtherUsers) {
+ bool no_other_users = (total_bytes == 0);
+ FireWebUIListener(CalculationTypeToEventName(calculation_type),
+ base::Value(message), base::Value(no_other_users));
+ } else {
+ FireWebUIListener(CalculationTypeToEventName(calculation_type),
+ base::Value(message));
+ }
+}
+
+void StorageHandler::UpdateSizeStat(
+ const calculator::SizeCalculator::CalculationType& calculation_type,
+ int64_t total_bytes,
+ int64_t available_bytes) {
+ int64_t rounded_total_bytes = RoundByteSize(total_bytes);
+ int64_t in_use_total_bytes_ = rounded_total_bytes - available_bytes;
+
+ UpdateSystemSize(calculation_type, in_use_total_bytes_);
+
+ base::DictionaryValue size_stat;
+ size_stat.SetString("availableSize", ui::FormatBytes(available_bytes));
+ size_stat.SetString("usedSize", ui::FormatBytes(in_use_total_bytes_));
+ size_stat.SetDouble("usedRatio", static_cast<double>(in_use_total_bytes_) /
+ rounded_total_bytes);
+ int storage_space_state =
+ static_cast<int>(StorageSpaceState::kStorageSpaceNormal);
+ if (available_bytes < kSpaceCriticallyLowBytes)
+ storage_space_state =
+ static_cast<int>(StorageSpaceState::kStorageSpaceCriticallyLow);
+ else if (available_bytes < kSpaceLowBytes)
+ storage_space_state = static_cast<int>(StorageSpaceState::kStorageSpaceLow);
+ size_stat.SetInteger("spaceState", storage_space_state);
+
+ FireWebUIListener(CalculationTypeToEventName(calculation_type), size_stat);
+}
+
+void StorageHandler::UpdateSystemSize(
+ const calculator::SizeCalculator::CalculationType& calculation_type,
+ int64_t total_bytes) {
+ const int item_index = static_cast<int>(calculation_type);
+ storage_items_total_bytes_[item_index] = total_bytes > 0 ? total_bytes : 0;
+ calculation_state_.set(item_index);
+
+ // Update system size. We only display the total system size when the size of
+ // all categories has been updated. If some size calculations are pending,
+ // return early and wait for all calculations to complete.
+ if (!calculation_state_.all())
+ return;
+
+ int64_t system_bytes = 0;
+ for (int i = 0; i < calculator::SizeCalculator::kCalculationTypeCount; ++i) {
+ int64_t total_bytes_for_current_item = storage_items_total_bytes_[i];
+ // If the storage is in use, add to the system's total storage.
+ if (i ==
+ static_cast<int>(calculator::SizeCalculator::CalculationType::kInUse)) {
+ system_bytes += total_bytes_for_current_item;
+ continue;
+ }
+ // Otherwise, this storage amount counts against the total storage
+ // amount.
+ system_bytes -= total_bytes_for_current_item;
+ }
+
+ OnSizeCalculated(calculator::SizeCalculator::CalculationType::kSystem,
+ system_bytes);
+}
+
bool StorageHandler::IsEligibleForAndroidStorage(std::string source_path) {
// Android's StorageManager volume concept relies on assumption that it is
// local filesystem. Hence, special volumes like DriveFS should not be
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h
index 4c901c9913a..cdd352797a6 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h
@@ -5,25 +5,12 @@
#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_STORAGE_HANDLER_H_
#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_STORAGE_HANDLER_H_
-#include <stdint.h>
-
-#include <memory>
#include <string>
-#include <vector>
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/optional.h"
-#include "base/scoped_observer.h"
-#include "chrome/browser/browsing_data/site_data_size_collector.h"
#include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
+#include "chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
-#include "chromeos/dbus/cryptohome/rpc.pb.h"
#include "chromeos/disks/disk_mount_manager.h"
-#include "components/arc/mojom/storage_manager.mojom.h"
-#include "components/arc/session/connection_observer.h"
-#include "components/arc/storage_manager/arc_storage_manager.h"
-#include "components/user_manager/user.h"
#include "third_party/re2/src/re2/re2.h"
class Profile;
@@ -39,20 +26,25 @@ enum class CrostiniResult;
namespace chromeos {
namespace settings {
-class StorageHandler
- : public ::settings::SettingsPageUIHandler,
- public arc::ConnectionObserver<arc::mojom::StorageManagerInstance>,
- public arc::ArcSessionManager::Observer,
- public chromeos::disks::DiskMountManager::Observer {
- public:
- // Enumeration for device state about remaining space. These values must be
- // kept in sync with settings.StorageSpaceState in JS code.
- enum StorageSpaceState {
- STORAGE_SPACE_NORMAL = 0,
- STORAGE_SPACE_LOW = 1,
- STORAGE_SPACE_CRITICALLY_LOW = 2,
- };
+// Enumeration for device state about remaining space. These values must be
+// kept in sync with settings.StorageSpaceState in JS code.
+enum class StorageSpaceState {
+ kStorageSpaceNormal = 0,
+ kStorageSpaceLow = 1,
+ kStorageSpaceCriticallyLow = 2,
+};
+
+// Threshold to show a message indicating space is critically low (512 MB).
+const int64_t kSpaceCriticallyLowBytes = 512 * 1024 * 1024;
+// Threshold to show a message indicating space is low (1 GB).
+const int64_t kSpaceLowBytes = 1 * 1024 * 1024 * 1024;
+
+class StorageHandler : public ::settings::SettingsPageUIHandler,
+ public arc::ArcSessionManager::Observer,
+ public chromeos::disks::DiskMountManager::Observer,
+ public calculator::SizeCalculator::Observer {
+ public:
StorageHandler(Profile* profile, content::WebUIDataSource* html_source);
~StorageHandler() override;
@@ -61,10 +53,6 @@ class StorageHandler
void OnJavascriptAllowed() override;
void OnJavascriptDisallowed() override;
- // arc::ConnectionObserver<arc::mojom::StorageManagerInstance>:
- void OnConnectionReady() override;
- void OnConnectionClosed() override;
-
// arc::ArcSessionManager::Observer:
void OnArcPlayStoreEnabledChanged(bool enabled) override;
@@ -74,56 +62,42 @@ class StorageHandler
const chromeos::disks::DiskMountManager::MountPointInfo&
mount_info) override;
+ // chromeos::settings::calculator::SizeCalculator::Observer:
+ void OnSizeCalculated(
+ const calculator::SizeCalculator::CalculationType& calculation_type,
+ int64_t total_bytes,
+ const base::Optional<int64_t>& available_bytes = base::nullopt) override;
+
+ // Remove the handler from the list of observers of every observed instances.
+ void StopObservingEvents();
+
+ protected:
+ // Round a given number of bytes up to the next power of 2.
+ // Ex: 14 => 16, 150 => 256.
+ int64_t RoundByteSize(int64_t bytes);
+
private:
// Handlers of JS messages.
void HandleUpdateAndroidEnabled(const base::ListValue* unused_args);
void HandleUpdateStorageInfo(const base::ListValue* unused_args);
- void HandleOpenDownloads(const base::ListValue* unused_args);
+ void HandleOpenMyFiles(const base::ListValue* unused_args);
void HandleOpenArcStorage(const base::ListValue* unused_args);
void HandleUpdateExternalStorages(const base::ListValue* unused_args);
- // Requests updating disk space information.
- void UpdateSizeStat();
-
- // Callback to update the UI about disk space information.
- void OnGetSizeStat(int64_t* total_size, int64_t* available_size);
-
- // Requests updating the size of Downloads directory.
- void UpdateDownloadsSize();
-
- // Callback to update the UI about the size of Downloads directory.
- void OnGetDownloadsSize(int64_t size);
-
- // Requests updating the size of browsing data.
- void UpdateBrowsingDataSize();
-
- // Callback to receive the cache size.
- void OnGetCacheSize(bool is_upper_limit, int64_t size);
-
- // Callback to update the UI about the size of browsing data.
- void OnGetBrowsingDataSize(bool is_site_data, int64_t size);
-
- // Requests updating the flag that hides the Android size UI.
- void UpdateAndroidRunning();
-
- // Requests updating the space size used by Android apps and cache.
- void UpdateAndroidSize();
-
- // Callback to update the UI about Android apps and cache.
- void OnGetAndroidSize(bool succeeded, arc::mojom::ApplicationsSizePtr size);
-
- // Requests updating the space size used by Crostini VMs and their apps and
- // cache.
- void UpdateCrostiniSize();
-
- // Callback to update the UI about Crostini VMs and their apps and cache.
- void OnGetCrostiniSize(crostini::CrostiniResult result, int64_t size);
-
- // Requests updating the total size of other users' data.
- void UpdateOtherUsersSize();
-
- // Callback to save the fetched user sizes and update the UI.
- void OnGetOtherUserSize(base::Optional<cryptohome::BaseReply> reply);
+ // Update storage sizes on the UI.
+ void UpdateStorageItem(
+ const calculator::SizeCalculator::CalculationType& calculation_type,
+ int64_t total_bytes);
+ void UpdateSizeStat(
+ const calculator::SizeCalculator::CalculationType& calculation_type,
+ int64_t total_bytes,
+ int64_t available_bytes);
+
+ // Marks the size of |item| as calculated. When all storage items have been
+ // calculated, then "System" size can be calculated.
+ void UpdateSystemSize(
+ const calculator::SizeCalculator::CalculationType& calculation_type,
+ int64_t total_bytes);
// Updates list of external storages.
void UpdateExternalStorages();
@@ -132,38 +106,21 @@ class StorageHandler
// storage.
bool IsEligibleForAndroidStorage(std::string source_path);
- // Total size of cache data in browsing data.
- int64_t browser_cache_size_;
-
- // True if we have already received the size of http cache.
- bool has_browser_cache_size_;
-
- // Total size of site data in browsing data.
- int64_t browser_site_data_size_;
-
- // True if we have already received the size of site data.
- bool has_browser_site_data_size_;
-
- // Helper to compute the total size of all types of site date.
- std::unique_ptr<SiteDataSizeCollector> site_data_size_collector_;
-
- // The list of other users whose directory sizes will be accumulated as the
- // size of "Other users".
- user_manager::UserList other_users_;
-
- // Fetched sizes of user directories.
- std::vector<int64_t> user_sizes_;
-
- // Flags indicating fetch operations for storage sizes are ongoing.
- bool updating_downloads_size_;
- bool updating_browsing_data_size_;
- bool updating_android_size_;
- bool updating_crostini_size_;
- bool updating_other_users_size_;
-
- // A flag for keeping track of the mojo connection status to the ARC
- // container.
- bool is_android_running_;
+ // Instances calculating the size of each storage items.
+ calculator::SizeStatCalculator size_stat_calculator_;
+ calculator::MyFilesSizeCalculator my_files_size_calculator_;
+ calculator::BrowsingDataSizeCalculator browsing_data_size_calculator_;
+ calculator::AppsSizeCalculator apps_size_calculator_;
+ calculator::CrostiniSizeCalculator crostini_size_calculator_;
+ calculator::OtherUsersSizeCalculator other_users_size_calculator_;
+
+ // Controls if the size of each storage item has been calculated.
+ std::bitset<calculator::SizeCalculator::kCalculationTypeCount>
+ calculation_state_;
+
+ // Keeps track of the size of each storage item.
+ int64_t storage_items_total_bytes_
+ [calculator::SizeCalculator::kCalculationTypeCount] = {0};
Profile* const profile_;
const std::string source_name_;
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
new file mode 100644
index 00000000000..57c1ab89f3c
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc
@@ -0,0 +1,516 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/files/file.h"
+#include "base/files/file_util.h"
+#include "base/path_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/system/sys_info.h"
+#include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
+#include "chrome/browser/chromeos/arc/test/test_arc_session_manager.h"
+#include "chrome/browser/chromeos/file_manager/fake_disk_mount_manager.h"
+#include "chrome/browser/chromeos/file_manager/path_util.h"
+#include "chrome/browser/chromeos/scoped_set_running_on_chromeos_for_testing.h"
+#include "chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "components/arc/arc_service_manager.h"
+#include "components/arc/test/fake_arc_session.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_web_ui.h"
+#include "storage/browser/file_system/external_mount_points.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/text/bytes_formatting.h"
+
+namespace chromeos {
+namespace settings {
+
+namespace {
+
+const char kLsbRelease[] =
+ "CHROMEOS_RELEASE_NAME=Chrome OS\n"
+ "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
+
+class TestStorageHandler : public StorageHandler {
+ public:
+ explicit TestStorageHandler(Profile* profile,
+ content::WebUIDataSource* html_source)
+ : StorageHandler(profile, html_source) {}
+
+ // Pull WebUIMessageHandler::set_web_ui() into public so tests can call it.
+ using StorageHandler::RoundByteSize;
+ using StorageHandler::set_web_ui;
+};
+
+class StorageHandlerTest : public testing::Test {
+ public:
+ StorageHandlerTest() = default;
+ ~StorageHandlerTest() override = default;
+
+ void SetUp() override {
+ // The storage handler requires an instance of DiskMountManager,
+ // ArcServiceManager and ArcSessionManager.
+ chromeos::disks::DiskMountManager::InitializeForTesting(
+ new file_manager::FakeDiskMountManager);
+ arc_service_manager_ = std::make_unique<arc::ArcServiceManager>();
+ arc_session_manager_ = arc::CreateTestArcSessionManager(
+ std::make_unique<arc::ArcSessionRunner>(
+ base::BindRepeating(arc::FakeArcSession::Create)));
+
+ // Initialize profile.
+ profile_manager_ = std::make_unique<TestingProfileManager>(
+ TestingBrowserProcess::GetGlobal());
+ ASSERT_TRUE(profile_manager_->SetUp());
+ profile_ = profile_manager_->CreateTestingProfile("p1");
+
+ // Initialize storage handler.
+ content::WebUIDataSource* html_source =
+ content::WebUIDataSource::Create(chrome::kChromeUIOSSettingsHost);
+ handler_ = std::make_unique<TestStorageHandler>(profile_, html_source);
+ handler_->set_web_ui(&web_ui_);
+ handler_->AllowJavascriptForTesting();
+
+ // Initialize tests APIs.
+ size_stat_test_api_ = std::make_unique<calculator::SizeStatTestAPI>(
+ handler_.get(), new calculator::SizeStatCalculator(profile_));
+ my_files_size_test_api_ = std::make_unique<calculator::MyFilesSizeTestAPI>(
+ handler_.get(), new calculator::MyFilesSizeCalculator(profile_));
+ browsing_data_size_test_api_ =
+ std::make_unique<calculator::BrowsingDataSizeTestAPI>(
+ handler_.get(),
+ new calculator::BrowsingDataSizeCalculator(profile_));
+ apps_size_test_api_ = std::make_unique<calculator::AppsSizeTestAPI>(
+ handler_.get(), new calculator::AppsSizeCalculator(profile_));
+ crostini_size_test_api_ = std::make_unique<calculator::CrostiniSizeTestAPI>(
+ handler_.get(), new calculator::CrostiniSizeCalculator(profile_));
+ other_users_size_test_api_ =
+ std::make_unique<calculator::OtherUsersSizeTestAPI>(
+ handler_.get(), new calculator::OtherUsersSizeCalculator());
+
+ // Create and register My files directory.
+ // By emulating chromeos running, GetMyFilesFolderForProfile will return the
+ // profile's temporary location instead of $HOME/Downloads.
+ chromeos::ScopedSetRunningOnChromeOSForTesting fake_release(kLsbRelease,
+ base::Time());
+ const base::FilePath my_files_path =
+ file_manager::util::GetMyFilesFolderForProfile(profile_);
+ CHECK(base::CreateDirectory(my_files_path));
+ CHECK(storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ file_manager::util::GetDownloadsMountPointName(profile_),
+ storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(),
+ my_files_path));
+ }
+
+ void TearDown() override {
+ handler_.reset();
+ size_stat_test_api_.reset();
+ my_files_size_test_api_.reset();
+ browsing_data_size_test_api_.reset();
+ apps_size_test_api_.reset();
+ crostini_size_test_api_.reset();
+ other_users_size_test_api_.reset();
+ chromeos::disks::DiskMountManager::Shutdown();
+ storage::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems();
+ }
+
+ protected:
+ // From a given amount of total size and available size as input, returns the
+ // space state determined by the OnGetSizeState function.
+ int GetSpaceState(int64_t* total_size, int64_t* available_size) {
+ size_stat_test_api_->SimulateOnGetSizeStat(total_size, available_size);
+ task_environment_.RunUntilIdle();
+ const base::Value* dictionary =
+ GetWebUICallbackMessage("storage-size-stat-changed");
+ EXPECT_TRUE(dictionary) << "No 'storage-size-stat-changed' callback";
+ int space_state = dictionary->FindKey("spaceState")->GetInt();
+ return space_state;
+ }
+
+ // Expects a callback message with a given |event_name|. A non null
+ // base::Value is returned if the callback message is found and has associated
+ // data.
+ const base::Value* GetWebUICallbackMessage(const std::string& event_name) {
+ for (auto it = web_ui_.call_data().rbegin();
+ it != web_ui_.call_data().rend(); ++it) {
+ const content::TestWebUI::CallData* data = it->get();
+ std::string name;
+ if (data->function_name() != "cr.webUIListenerCallback" ||
+ !data->arg1()->GetAsString(&name)) {
+ continue;
+ }
+ if (name == event_name)
+ return data->arg2();
+ }
+ return nullptr;
+ }
+
+ // Get the path to file manager's test data directory.
+ base::FilePath GetTestDataFilePath(const std::string& file_name) {
+ // Get the path to file manager's test data directory.
+ base::FilePath source_dir;
+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &source_dir));
+ base::FilePath test_data_dir = source_dir.AppendASCII("chrome")
+ .AppendASCII("test")
+ .AppendASCII("data")
+ .AppendASCII("chromeos")
+ .AppendASCII("file_manager");
+
+ // Return full test data path to the given |file_name|.
+ return test_data_dir.Append(base::FilePath::FromUTF8Unsafe(file_name));
+ }
+
+ // Copy a file from the file manager's test data directory to the specified
+ // target_path.
+ void AddFile(const std::string& file_name,
+ int64_t expected_size,
+ base::FilePath target_path) {
+ const base::FilePath entry_path = GetTestDataFilePath(file_name);
+ target_path = target_path.AppendASCII(file_name);
+ ASSERT_TRUE(base::CopyFile(entry_path, target_path))
+ << "Copy from " << entry_path.value() << " to " << target_path.value()
+ << " failed.";
+ // Verify file size.
+ base::stat_wrapper_t stat;
+ const int res = base::File::Lstat(target_path.value().c_str(), &stat);
+ ASSERT_FALSE(res < 0) << "Couldn't stat" << target_path.value();
+ ASSERT_EQ(expected_size, stat.st_size);
+ }
+
+ std::unique_ptr<TestStorageHandler> handler_;
+ content::TestWebUI web_ui_;
+ content::BrowserTaskEnvironment task_environment_;
+ std::unique_ptr<TestingProfileManager> profile_manager_;
+ Profile* profile_;
+ std::unique_ptr<calculator::SizeStatTestAPI> size_stat_test_api_;
+ std::unique_ptr<calculator::MyFilesSizeTestAPI> my_files_size_test_api_;
+ std::unique_ptr<calculator::BrowsingDataSizeTestAPI>
+ browsing_data_size_test_api_;
+ std::unique_ptr<calculator::AppsSizeTestAPI> apps_size_test_api_;
+ std::unique_ptr<calculator::CrostiniSizeTestAPI> crostini_size_test_api_;
+ std::unique_ptr<calculator::OtherUsersSizeTestAPI> other_users_size_test_api_;
+
+ private:
+ std::unique_ptr<arc::ArcServiceManager> arc_service_manager_;
+ std::unique_ptr<arc::ArcSessionManager> arc_session_manager_;
+ DISALLOW_COPY_AND_ASSIGN(StorageHandlerTest);
+};
+
+TEST_F(StorageHandlerTest, RoundByteSize) {
+ static const struct {
+ int64_t bytes;
+ const char* expected;
+ } cases[] = {
+ {0, "0 B"},
+ {3, "4 B"},
+ {4, "4 B"},
+ {5, "8 B"},
+ {8 * 1024 - 1, "8.0 KB"},
+ {8 * 1024, "8.0 KB"},
+ {8 * 1024 + 1, "16.0 KB"},
+ {31 * 1024 * 1024, "32.0 MB"},
+ {32 * 1024 * 1024, "32.0 MB"},
+ {50 * 1024 * 1024, "64.0 MB"},
+ {65LL * 1024 * 1024 * 1024, "128 GB"},
+ {130LL * 1024 * 1024 * 1024, "256 GB"},
+ {130LL * 1024 * 1024 * 1024, "256 GB"},
+ {1LL * 1024 * 1024 * 1024 * 1024, "1.0 TB"},
+ {1LL * 1024 * 1024 * 1024 * 1024 + 1, "2.0 TB"},
+ {(1LL << 61) + 1, "4,096 PB"},
+ };
+
+ for (auto& c : cases) {
+ int64_t rounded_bytes = handler_->RoundByteSize(c.bytes);
+ EXPECT_EQ(base::ASCIIToUTF16(c.expected), ui::FormatBytes(rounded_bytes));
+ }
+}
+
+TEST_F(StorageHandlerTest, GlobalSizeStat) {
+ // Get local filesystem storage statistics.
+ const base::FilePath mount_path =
+ file_manager::util::GetMyFilesFolderForProfile(profile_);
+ int64_t total_size = base::SysInfo::AmountOfTotalDiskSpace(mount_path);
+ int64_t available_size = base::SysInfo::AmountOfFreeDiskSpace(mount_path);
+
+ // Round the total size.
+ int64_t rounded_total_size = handler_->RoundByteSize(total_size);
+ int64_t used_size = rounded_total_size - available_size;
+ double used_ratio = static_cast<double>(used_size) / rounded_total_size;
+
+ // Get statistics from storage handler's UpdateSizeStat.
+ size_stat_test_api_->StartCalculation();
+ task_environment_.RunUntilIdle();
+
+ const base::Value* dictionary =
+ GetWebUICallbackMessage("storage-size-stat-changed");
+ ASSERT_TRUE(dictionary) << "No 'storage-size-stat-changed' callback";
+
+ const std::string& storage_handler_available_size =
+ dictionary->FindKey("availableSize")->GetString();
+ const std::string& storage_handler_used_size =
+ dictionary->FindKey("usedSize")->GetString();
+ double storage_handler_used_ratio =
+ dictionary->FindKey("usedRatio")->GetDouble();
+
+ EXPECT_EQ(ui::FormatBytes(available_size),
+ base::ASCIIToUTF16(storage_handler_available_size));
+ EXPECT_EQ(ui::FormatBytes(used_size),
+ base::ASCIIToUTF16(storage_handler_used_size));
+ double diff = used_ratio > storage_handler_used_ratio
+ ? used_ratio - storage_handler_used_ratio
+ : storage_handler_used_ratio - used_ratio;
+ // Running the test while writing data on disk (~400MB/s), the difference
+ // between the values returned by the two AmountOfFreeDiskSpace calls is never
+ // more than 100KB. By expecting diff to be less than 100KB /
+ // rounded_total_size, the test is very unlikely to be flaky.
+ EXPECT_LE(diff, static_cast<double>(100 * 1024) / rounded_total_size);
+}
+
+TEST_F(StorageHandlerTest, StorageSpaceState) {
+ // Less than 512 MB available, space state is critically low.
+ int64_t total_size = 1024 * 1024 * 1024;
+ int64_t available_size = 512 * 1024 * 1024 - 1;
+ int space_state = GetSpaceState(&total_size, &available_size);
+ EXPECT_EQ(static_cast<int>(StorageSpaceState::kStorageSpaceCriticallyLow),
+ space_state);
+
+ // Less than 1GB available, space state is low.
+ available_size = 512 * 1024 * 1024;
+ space_state = GetSpaceState(&total_size, &available_size);
+ EXPECT_EQ(static_cast<int>(StorageSpaceState::kStorageSpaceLow), space_state);
+ available_size = 1024 * 1024 * 1024 - 1;
+ space_state = GetSpaceState(&total_size, &available_size);
+ EXPECT_EQ(static_cast<int>(StorageSpaceState::kStorageSpaceLow), space_state);
+
+ // From 1GB, normal space state.
+ available_size = 1024 * 1024 * 1024;
+ space_state = GetSpaceState(&total_size, &available_size);
+ EXPECT_EQ(static_cast<int>(StorageSpaceState::kStorageSpaceNormal),
+ space_state);
+}
+
+TEST_F(StorageHandlerTest, MyFilesSize) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+
+ const base::FilePath my_files_path =
+ file_manager::util::GetMyFilesFolderForProfile(profile_);
+ const base::FilePath downloads_path =
+ file_manager::util::GetDownloadsFolderForProfile(profile_);
+ const base::FilePath android_files_path =
+ profile_->GetPath().Append("AndroidFiles");
+ const base::FilePath android_files_download_path =
+ android_files_path.Append("Download");
+
+ // Create directories.
+ CHECK(base::CreateDirectory(downloads_path));
+ CHECK(base::CreateDirectory(android_files_path));
+ CHECK(base::CreateDirectory(android_files_download_path));
+
+ // Register android files mount point.
+ CHECK(storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+ file_manager::util::GetAndroidFilesMountPointName(),
+ storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(),
+ android_files_path));
+
+ // Add files in My files and android files.
+ AddFile("random.bin", 8092, my_files_path); // ~7.9 KB
+ AddFile("tall.pdf", 15271, android_files_path); // ~14.9 KB
+ // Add file in Downloads and simulate bind mount with
+ // [android files]/Download.
+ AddFile("video.ogv", 59943, downloads_path); // ~58.6 KB
+ AddFile("video.ogv", 59943, android_files_download_path);
+
+ // Calculate My files size.
+ my_files_size_test_api_->StartCalculation();
+ task_environment_.RunUntilIdle();
+
+ const base::Value* callback =
+ GetWebUICallbackMessage("storage-my-files-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-my-files-size-changed' callback";
+
+ // Check return value.
+ EXPECT_EQ("81.4 KB", callback->GetString());
+}
+
+TEST_F(StorageHandlerTest, AppsExtensionsSize) {
+ // The data for apps and extensions apps_size_test_api_installed from the
+ // webstore is stored in the Extensions folder. Add data at a random location
+ // in the Extensions folder and check UI callback message.
+ const base::FilePath extensions_data_path =
+ profile_->GetPath()
+ .AppendASCII("Extensions")
+ .AppendASCII("fake_extension_id");
+ CHECK(base::CreateDirectory(extensions_data_path));
+ AddFile("id3Audio.mp3", 180999, extensions_data_path); // ~177 KB
+
+ // Calculate web store apps and extensions size.
+ apps_size_test_api_->StartCalculation();
+ task_environment_.RunUntilIdle();
+
+ const base::Value* callback =
+ GetWebUICallbackMessage("storage-apps-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-apps-size-changed' callback";
+
+ // Check return value.
+ EXPECT_EQ("177 KB", callback->GetString());
+
+ // Simulate android apps size callback.
+ // 592840 + 25284 + 9987 = 628111 ~613 KB.
+ apps_size_test_api_->SimulateOnGetAndroidAppsSize(true /* succeeded */,
+ 592840, 25284, 9987);
+ task_environment_.RunUntilIdle();
+
+ callback = GetWebUICallbackMessage("storage-apps-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-apps-size-changed' callback";
+
+ // Check return value.
+ EXPECT_EQ("790 KB", callback->GetString());
+
+ // Add more data in the Extensions folder. Android is not running and the size
+ // of android apps is back down to 0 B.
+ AddFile("video_long.ogv", 230096, extensions_data_path); // ~225 KB
+
+ // Calculate web store apps and extensions size.
+ apps_size_test_api_->StartCalculation();
+ task_environment_.RunUntilIdle();
+
+ callback = GetWebUICallbackMessage("storage-apps-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-apps-size-changed' callback";
+
+ // Check return value.
+ EXPECT_EQ("401 KB", callback->GetString());
+}
+
+TEST_F(StorageHandlerTest, SystemSize) {
+ // The "System" row on the storage page displays the difference between the
+ // total amount of used space and the sum of the sizes of the different
+ // storage items of the storage page (My files, Browsing data, apps etc...)
+ // This test simulates callbacks from each one of these storage items; the
+ // calculation of the "System" size should only happen when all of the other
+ // storage items have been calculated.
+ const int64_t KB = 1024;
+ const int64_t MB = 1024 * KB;
+ const int64_t GB = 1024 * MB;
+ const int64_t TB = 1024 * GB;
+
+ // Simulate size stat callback.
+ int64_t total_size = TB;
+ int64_t available_size = 100 * GB;
+ size_stat_test_api_->SimulateOnGetSizeStat(&total_size, &available_size);
+ const base::Value* callback =
+ GetWebUICallbackMessage("storage-size-stat-changed");
+ ASSERT_TRUE(callback) << "No 'storage-size-stat-changed' callback";
+ EXPECT_EQ("100 GB", callback->FindKey("availableSize")->GetString());
+ EXPECT_EQ("924 GB", callback->FindKey("usedSize")->GetString());
+ // Expect no system size callback until every other item has been updated.
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed"));
+
+ // Simulate my files size callback.
+ my_files_size_test_api_->SimulateOnGetTotalBytes(400 * GB);
+ callback = GetWebUICallbackMessage("storage-my-files-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-my-files-size-changed' callback";
+ EXPECT_EQ("400 GB", callback->GetString());
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed"));
+
+ // Simulate browsing data callbacks. Has to be called with
+ // both |is_data_site| = true and false.
+ browsing_data_size_test_api_->SimulateOnGetBrowsingDataSize(
+ true /* is_site_data */, 10 * GB);
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-browsing-data-size-changed"));
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed"));
+ browsing_data_size_test_api_->SimulateOnGetBrowsingDataSize(
+ false /* is_site_data */, 14 * GB);
+ callback = GetWebUICallbackMessage("storage-browsing-data-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-browsing-data-size-changed' callback";
+ EXPECT_EQ("24.0 GB", callback->GetString());
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed"));
+
+ // Simulate apps and extensions size callbacks.
+ apps_size_test_api_->SimulateOnGetAppsSize(29 * GB);
+ apps_size_test_api_->SimulateOnGetAndroidAppsSize(false, 0, 0, 0);
+ callback = GetWebUICallbackMessage("storage-apps-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-apps-size-changed' callback";
+ EXPECT_EQ("29.0 GB", callback->GetString());
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed"));
+ apps_size_test_api_->SimulateOnGetAndroidAppsSize(
+ true /* succeeded */, 724 * MB, 100 * MB, 200 * MB);
+ callback = GetWebUICallbackMessage("storage-apps-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-apps-size-changed' callback";
+ EXPECT_EQ("30.0 GB", callback->GetString());
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed"));
+
+ // Simulate crostini size callback.
+ crostini_size_test_api_->SimulateOnGetCrostiniSize(70 * GB);
+ callback = GetWebUICallbackMessage("storage-crostini-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-crostini-size-changed' callback";
+ EXPECT_EQ("70.0 GB", callback->GetString());
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed"));
+
+ // Simulate other users size callback. No callback message until the sizes of
+ // every users is calculated.
+ std::vector<int64_t> other_user_sizes =
+ std::vector<int64_t>{200 * GB, 50 * GB, 50 * GB};
+ other_users_size_test_api_->InitializeOtherUserSize(other_user_sizes.size());
+ for (std::size_t i = 0; i < other_user_sizes.size(); i++) {
+ cryptohome::BaseReply result;
+ result.set_error(cryptohome::CRYPTOHOME_ERROR_NOT_SET);
+ cryptohome::GetAccountDiskUsageReply* usage_reply =
+ result.MutableExtension(cryptohome::GetAccountDiskUsageReply::reply);
+ usage_reply->set_size(other_user_sizes[i]);
+ base::Optional<cryptohome::BaseReply> reply = std::move(result);
+ other_users_size_test_api_->SimulateOnGetOtherUserSize(reply);
+ if (i < other_user_sizes.size() - 1) {
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-other-users-size-changed"));
+ ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed"));
+ } else {
+ // When the size of the last user's cryptohome is calculated, we expect a
+ // callback with the "Other users" size.
+ callback = GetWebUICallbackMessage("storage-other-users-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-other-users-size-changed' callback";
+ EXPECT_EQ("300 GB", callback->GetString());
+ // Every item size has been calculated, system size should also be
+ // updated.
+ callback = GetWebUICallbackMessage("storage-system-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-system-size-changed' callback";
+ EXPECT_EQ("100 GB", callback->GetString());
+ }
+ }
+
+ // If there's an error while calculating the size of browsing data, the size
+ // of browsing data and system should be displayed as "Unknown".
+ browsing_data_size_test_api_->SimulateOnGetBrowsingDataSize(
+ true /* is_site_data */, -1);
+ callback = GetWebUICallbackMessage("storage-browsing-data-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-browsing-data-size-changed' callback";
+ EXPECT_EQ("Unknown", callback->GetString());
+ // The missing 24.0 GB of browsing data should be reflected in the system
+ // section instead. We expect the displayed size to be 100 + 24 GB.
+ callback = GetWebUICallbackMessage("storage-system-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-system-size-changed' callback";
+ EXPECT_EQ("124 GB", callback->GetString());
+
+ // No error while recalculating browsing data size, the UI should be updated
+ // with the right sizes.
+ browsing_data_size_test_api_->SimulateOnGetBrowsingDataSize(
+ true /* is_site_data */, 10 * GB);
+ callback = GetWebUICallbackMessage("storage-browsing-data-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-browsing-data-size-changed' callback";
+ EXPECT_EQ("24.0 GB", callback->GetString());
+ callback = GetWebUICallbackMessage("storage-system-size-changed");
+ ASSERT_TRUE(callback) << "No 'storage-system-size-changed' callback";
+ EXPECT_EQ("100 GB", callback->GetString());
+}
+
+} // namespace
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
index 601eeaf2435..0a90a0e3039 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc
@@ -20,9 +20,7 @@
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "components/prefs/pref_service.h"
-#include "content/public/browser/system_connector.h"
-#include "services/device/public/mojom/constants.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
+#include "content/public/browser/device_service.h"
#include "ui/base/l10n/l10n_util.h"
using session_manager::SessionManager;
@@ -57,8 +55,8 @@ std::unique_ptr<base::DictionaryValue> GetFingerprintsInfo(
} // namespace
FingerprintHandler::FingerprintHandler(Profile* profile) : profile_(profile) {
- content::GetSystemConnector()->Connect(
- device::mojom::kServiceName, fp_service_.BindNewPipeAndPassReceiver());
+ content::GetDeviceService().BindFingerprint(
+ fp_service_.BindNewPipeAndPassReceiver());
user_id_ = ProfileHelper::Get()->GetUserIdHashFromProfile(profile);
}
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
index e75796ecd32..bd301cfcb91 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc
@@ -143,7 +143,8 @@ void InternetHandler::ConfigureThirdPartyVpn(const base::ListValue* args) {
return;
}
if (network->type() != shill::kTypeVPN) {
- NET_LOG(ERROR) << "ConfigureThirdPartyVpn: Network is not a VPN: " << guid;
+ NET_LOG(ERROR) << "ConfigureThirdPartyVpn: Network is not a VPN: "
+ << NetworkId(network);
return;
}
@@ -169,7 +170,8 @@ void InternetHandler::ConfigureThirdPartyVpn(const base::ListValue* args) {
}
NET_LOG(ERROR) << "ConfigureThirdPartyVpn: Unsupported VPN type: "
- << network->GetVpnProviderType() << " For: " << guid;
+ << network->GetVpnProviderType()
+ << " For: " << NetworkId(network);
}
void InternetHandler::RequestGmsCoreNotificationsDisabledDeviceNames(
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.cc
new file mode 100644
index 00000000000..90a75cf7418
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.cc
@@ -0,0 +1,252 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.h"
+
+#include "ash/public/cpp/network_config_service.h"
+#include "base/bind.h"
+#include "base/no_destructor.h"
+#include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/webui_util.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "chromeos/strings/grit/chromeos_strings.h"
+#include "components/strings/grit/components_strings.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
+
+namespace chromeos {
+namespace settings {
+namespace {
+
+const std::vector<SearchConcept>& GetNetworkSearchConcepts() {
+ static const base::NoDestructor<std::vector<SearchConcept>> tags({
+ {IDS_SETTINGS_TAG_NETWORK_SETTINGS,
+ chrome::kNetworksSubPage,
+ mojom::SearchResultIcon::kWifi,
+ {IDS_SETTINGS_TAG_NETWORK_SETTINGS_ALT1, SearchConcept::kAltTagEnd}},
+ });
+ return *tags;
+}
+
+const std::vector<SearchConcept>& GetEthernetSearchConcepts() {
+ static const base::NoDestructor<std::vector<SearchConcept>> tags({
+ {IDS_SETTINGS_TAG_ETHERNET_SETTINGS,
+ chrome::kEthernetSettingsSubPage,
+ mojom::SearchResultIcon::kEthernet,
+ {IDS_SETTINGS_TAG_ETHERNET_SETTINGS_ALT1, SearchConcept::kAltTagEnd}},
+ });
+ return *tags;
+}
+
+const std::vector<SearchConcept>& GetWifiSearchConcepts() {
+ static const base::NoDestructor<std::vector<SearchConcept>> tags({
+ {IDS_SETTINGS_TAG_WIFI_SETTINGS, chrome::kWiFiSettingsSubPage,
+ mojom::SearchResultIcon::kWifi},
+ {IDS_SETTINGS_TAG_TURN_ON_WIFI,
+ chrome::kWiFiSettingsSubPage,
+ mojom::SearchResultIcon::kWifi,
+ {IDS_SETTINGS_TAG_TURN_ON_WIFI_ALT1, SearchConcept::kAltTagEnd}},
+ {IDS_SETTINGS_TAG_TURN_OFF_WIFI,
+ chrome::kWiFiSettingsSubPage,
+ mojom::SearchResultIcon::kWifi,
+ {IDS_SETTINGS_TAG_TURN_OFF_WIFI_ALT1, SearchConcept::kAltTagEnd}},
+ {IDS_SETTINGS_TAG_CONNECT_WIFI, chrome::kWiFiSettingsSubPage,
+ mojom::SearchResultIcon::kWifi},
+ {IDS_SETTINGS_TAG_DISCONNECT_WIFI, chrome::kWiFiSettingsSubPage,
+ mojom::SearchResultIcon::kWifi},
+ });
+ return *tags;
+}
+
+} // namespace
+
+InternetStringsProvider::InternetStringsProvider(Profile* profile,
+ Delegate* per_page_delegate)
+ : OsSettingsPerPageStringsProvider(profile, per_page_delegate) {
+ // General network search tags are always added.
+ delegate()->AddSearchTags(GetNetworkSearchConcepts());
+
+ // Receive updates when devices (e.g., Ethernet, Wi-Fi) go on/offline.
+ ash::GetNetworkConfigService(
+ cros_network_config_.BindNewPipeAndPassReceiver());
+ cros_network_config_->AddObserver(receiver_.BindNewPipeAndPassRemote());
+
+ // Fetch initial list of devices.
+ FetchDeviceList();
+}
+
+InternetStringsProvider::~InternetStringsProvider() = default;
+
+void InternetStringsProvider::AddUiStrings(
+ content::WebUIDataSource* html_source) const {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"internetAddConnection", IDS_SETTINGS_INTERNET_ADD_CONNECTION},
+ {"internetAddConnectionExpandA11yLabel",
+ IDS_SETTINGS_INTERNET_ADD_CONNECTION_EXPAND_ACCESSIBILITY_LABEL},
+ {"internetAddConnectionNotAllowed",
+ IDS_SETTINGS_INTERNET_ADD_CONNECTION_NOT_ALLOWED},
+ {"internetAddThirdPartyVPN", IDS_SETTINGS_INTERNET_ADD_THIRD_PARTY_VPN},
+ {"internetAddVPN", IDS_SETTINGS_INTERNET_ADD_VPN},
+ {"internetAddWiFi", IDS_SETTINGS_INTERNET_ADD_WIFI},
+ {"internetConfigName", IDS_SETTINGS_INTERNET_CONFIG_NAME},
+ {"internetDetailPageTitle", IDS_SETTINGS_INTERNET_DETAIL},
+ {"internetDeviceEnabling", IDS_SETTINGS_INTERNET_DEVICE_ENABLING},
+ {"internetDeviceInitializing", IDS_SETTINGS_INTERNET_DEVICE_INITIALIZING},
+ {"internetJoinType", IDS_SETTINGS_INTERNET_JOIN_TYPE},
+ {"internetKnownNetworksPageTitle", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS},
+ {"internetMobileSearching", IDS_SETTINGS_INTERNET_MOBILE_SEARCH},
+ {"internetNoNetworks", IDS_SETTINGS_INTERNET_NO_NETWORKS},
+ {"internetPageTitle", IDS_SETTINGS_INTERNET},
+ {"internetSummaryButtonA11yLabel",
+ IDS_SETTINGS_INTERNET_SUMMARY_BUTTON_ACCESSIBILITY_LABEL},
+ {"internetToggleMobileA11yLabel",
+ IDS_SETTINGS_INTERNET_TOGGLE_MOBILE_ACCESSIBILITY_LABEL},
+ {"internetToggleTetherLabel", IDS_SETTINGS_INTERNET_TOGGLE_TETHER_LABEL},
+ {"internetToggleTetherSubtext",
+ IDS_SETTINGS_INTERNET_TOGGLE_TETHER_SUBTEXT},
+ {"internetToggleWiFiA11yLabel",
+ IDS_SETTINGS_INTERNET_TOGGLE_WIFI_ACCESSIBILITY_LABEL},
+ {"knownNetworksAll", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_ALL},
+ {"knownNetworksButton", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_BUTTON},
+ {"knownNetworksMessage", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MESSAGE},
+ {"knownNetworksPreferred",
+ IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_PREFFERED},
+ {"knownNetworksMenuAddPreferred",
+ IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MENU_ADD_PREFERRED},
+ {"knownNetworksMenuRemovePreferred",
+ IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MENU_REMOVE_PREFERRED},
+ {"knownNetworksMenuForget",
+ IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MENU_FORGET},
+ {"networkAllowDataRoaming",
+ IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING},
+ {"networkAllowDataRoamingEnabledHome",
+ IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_ENABLED_HOME},
+ {"networkAllowDataRoamingEnabledRoaming",
+ IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_ENABLED_ROAMING},
+ {"networkAllowDataRoamingDisabled",
+ IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_DISABLED},
+ {"networkAlwaysOnVpn", IDS_SETTINGS_INTERNET_NETWORK_ALWAYS_ON_VPN},
+ {"networkAutoConnect", IDS_SETTINGS_INTERNET_NETWORK_AUTO_CONNECT},
+ {"networkAutoConnectCellular",
+ IDS_SETTINGS_INTERNET_NETWORK_AUTO_CONNECT_CELLULAR},
+ {"networkButtonActivate", IDS_SETTINGS_INTERNET_BUTTON_ACTIVATE},
+ {"networkButtonConfigure", IDS_SETTINGS_INTERNET_BUTTON_CONFIGURE},
+ {"networkButtonConnect", IDS_SETTINGS_INTERNET_BUTTON_CONNECT},
+ {"networkButtonDisconnect", IDS_SETTINGS_INTERNET_BUTTON_DISCONNECT},
+ {"networkButtonForget", IDS_SETTINGS_INTERNET_BUTTON_FORGET},
+ {"networkButtonViewAccount", IDS_SETTINGS_INTERNET_BUTTON_VIEW_ACCOUNT},
+ {"networkConnectNotAllowed", IDS_SETTINGS_INTERNET_CONNECT_NOT_ALLOWED},
+ {"networkIPAddress", IDS_SETTINGS_INTERNET_NETWORK_IP_ADDRESS},
+ {"networkIPConfigAuto", IDS_SETTINGS_INTERNET_NETWORK_IP_CONFIG_AUTO},
+ {"networkNameserversLearnMore", IDS_LEARN_MORE},
+ {"networkPrefer", IDS_SETTINGS_INTERNET_NETWORK_PREFER},
+ {"networkPrimaryUserControlled",
+ IDS_SETTINGS_INTERNET_NETWORK_PRIMARY_USER_CONTROLLED},
+ {"networkScanningLabel", IDS_NETWORK_SCANNING_MESSAGE},
+ {"networkSectionAdvanced",
+ IDS_SETTINGS_INTERNET_NETWORK_SECTION_ADVANCED},
+ {"networkSectionAdvancedA11yLabel",
+ IDS_SETTINGS_INTERNET_NETWORK_SECTION_ADVANCED_ACCESSIBILITY_LABEL},
+ {"networkSectionNetwork", IDS_SETTINGS_INTERNET_NETWORK_SECTION_NETWORK},
+ {"networkSectionNetworkExpandA11yLabel",
+ IDS_SETTINGS_INTERNET_NETWORK_SECTION_NETWORK_ACCESSIBILITY_LABEL},
+ {"networkSectionProxy", IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY},
+ {"networkSectionProxyExpandA11yLabel",
+ IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY_ACCESSIBILITY_LABEL},
+ {"networkShared", IDS_SETTINGS_INTERNET_NETWORK_SHARED},
+ {"networkVpnBuiltin", IDS_NETWORK_TYPE_VPN_BUILTIN},
+ {"networkOutOfRange", IDS_SETTINGS_INTERNET_WIFI_NETWORK_OUT_OF_RANGE},
+ {"cellularContactSpecificCarrier",
+ IDS_SETTINGS_INTERNET_CELLULAR_CONTACT_SPECIFIC_CARRIER},
+ {"cellularContactDefaultCarrier",
+ IDS_SETTINGS_INTERNET_CELLULAR_CONTACT_DEFAULT_CARRIER},
+ {"tetherPhoneOutOfRange",
+ IDS_SETTINGS_INTERNET_TETHER_PHONE_OUT_OF_RANGE},
+ {"gmscoreNotificationsTitle",
+ IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_TITLE},
+ {"gmscoreNotificationsOneDeviceSubtitle",
+ IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_ONE_DEVICE_SUBTITLE},
+ {"gmscoreNotificationsTwoDevicesSubtitle",
+ IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_TWO_DEVICES_SUBTITLE},
+ {"gmscoreNotificationsManyDevicesSubtitle",
+ IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_MANY_DEVICES_SUBTITLE},
+ {"gmscoreNotificationsFirstStep",
+ IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_FIRST_STEP},
+ {"gmscoreNotificationsSecondStep",
+ IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_SECOND_STEP},
+ {"gmscoreNotificationsThirdStep",
+ IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_THIRD_STEP},
+ {"gmscoreNotificationsFourthStep",
+ IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_FOURTH_STEP},
+ {"tetherConnectionDialogTitle",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DIALOG_TITLE},
+ {"tetherConnectionAvailableDeviceTitle",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_AVAILABLE_DEVICE_TITLE},
+ {"tetherConnectionBatteryPercentage",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_BATTERY_PERCENTAGE},
+ {"tetherConnectionExplanation",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_EXPLANATION},
+ {"tetherConnectionCarrierWarning",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_CARRIER_WARNING},
+ {"tetherConnectionDescriptionTitle",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DESCRIPTION_TITLE},
+ {"tetherConnectionDescriptionMobileData",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DESCRIPTION_MOBILE_DATA},
+ {"tetherConnectionDescriptionBattery",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DESCRIPTION_BATTERY},
+ {"tetherConnectionDescriptionWiFi",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DESCRIPTION_WIFI},
+ {"tetherConnectionNotNowButton",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_NOT_NOW_BUTTON},
+ {"tetherConnectionConnectButton",
+ IDS_SETTINGS_INTERNET_TETHER_CONNECTION_CONNECT_BUTTON},
+ {"tetherEnableBluetooth", IDS_ENABLE_BLUETOOTH},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ chromeos::network_element::AddLocalizedStrings(html_source);
+ chromeos::network_element::AddOncLocalizedStrings(html_source);
+ chromeos::network_element::AddDetailsLocalizedStrings(html_source);
+ chromeos::network_element::AddConfigLocalizedStrings(html_source);
+ chromeos::network_element::AddErrorLocalizedStrings(html_source);
+
+ html_source->AddString("networkGoogleNameserversLearnMoreUrl",
+ chrome::kGoogleNameserversLearnMoreURL);
+ html_source->AddString(
+ "internetNoNetworksMobileData",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_INTERNET_LOOKING_FOR_MOBILE_NETWORK,
+ GetHelpUrlWithBoard(chrome::kInstantTetheringLearnMoreURL)));
+}
+
+void InternetStringsProvider::OnDeviceStateListChanged() {
+ FetchDeviceList();
+}
+
+void InternetStringsProvider::FetchDeviceList() {
+ cros_network_config_->GetDeviceStateList(base::BindOnce(
+ &InternetStringsProvider::OnDeviceList, base::Unretained(this)));
+}
+
+void InternetStringsProvider::OnDeviceList(
+ std::vector<network_config::mojom::DeviceStatePropertiesPtr> devices) {
+ // Start with no search tags.
+ delegate()->RemoveSearchTags(GetEthernetSearchConcepts());
+ delegate()->RemoveSearchTags(GetWifiSearchConcepts());
+
+ // Add a search tag each time we see a device type.
+ for (const auto& device : devices) {
+ if (device->type == network_config::mojom::NetworkType::kEthernet)
+ delegate()->AddSearchTags(GetEthernetSearchConcepts());
+ else if (device->type == network_config::mojom::NetworkType::kWiFi)
+ delegate()->AddSearchTags(GetWifiSearchConcepts());
+ }
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.h b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.h
new file mode 100644
index 00000000000..4a0e2a2511e
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.h
@@ -0,0 +1,59 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_INTERNET_STRINGS_PROVIDER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_INTERNET_STRINGS_PROVIDER_H_
+
+#include <vector>
+
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.h"
+#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+class Profile;
+
+namespace content {
+class WebUIDataSource;
+} // namespace content
+
+namespace chromeos {
+namespace settings {
+
+class InternetStringsProvider
+ : public OsSettingsPerPageStringsProvider,
+ public network_config::mojom::CrosNetworkConfigObserver {
+ public:
+ InternetStringsProvider(Profile* profile, Delegate* per_page_delegate);
+ ~InternetStringsProvider() override;
+
+ private:
+ // OsSettingsPerPageStringsProvider:
+ void AddUiStrings(content::WebUIDataSource* html_source) const override;
+
+ // network_config::mojom::CrosNetworkConfigObserver:
+ void OnActiveNetworksChanged(
+ std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks)
+ override {}
+ void OnNetworkStateChanged(
+ chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
+ override {}
+ void OnNetworkStateListChanged() override {}
+ void OnVpnProvidersChanged() override {}
+ void OnNetworkCertificatesChanged() override {}
+ void OnDeviceStateListChanged() override;
+
+ void FetchDeviceList();
+ void OnDeviceList(
+ std::vector<network_config::mojom::DeviceStatePropertiesPtr> devices);
+
+ mojo::Receiver<network_config::mojom::CrosNetworkConfigObserver> receiver_{
+ this};
+ mojo::Remote<network_config::mojom::CrosNetworkConfig> cros_network_config_;
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_INTERNET_STRINGS_PROVIDER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h
index 8ee0b692ac1..a103760bd1e 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h
@@ -13,7 +13,7 @@
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
#include "chromeos/components/multidevice/remote_device_ref.h"
#include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
-#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
+#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom-forward.h"
#include "components/prefs/pref_change_registrar.h"
class PrefService;
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc
new file mode 100644
index 00000000000..653188ccf20
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.cc
@@ -0,0 +1,2136 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h"
+
+#include "ash/public/cpp/ash_features.h"
+#include "ash/public/mojom/assistant_state_controller.mojom.h"
+#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/i18n/number_formatting.h"
+#include "base/no_destructor.h"
+#include "base/strings/strcat.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/system/sys_info.h"
+#include "build/branding_buildflags.h"
+#include "build/build_config.h"
+#include "build/buildflag.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/chromeos/account_manager/account_manager_util.h"
+#include "chrome/browser/chromeos/arc/arc_util.h"
+#include "chrome/browser/chromeos/assistant/assistant_util.h"
+#include "chrome/browser/chromeos/crostini/crostini_features.h"
+#include "chrome/browser/chromeos/crostini/crostini_util.h"
+#include "chrome/browser/chromeos/kerberos/kerberos_credentials_manager.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/policy/profile_policy_connector.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/supervised_user/supervised_user_service.h"
+#include "chrome/browser/supervised_user/supervised_user_service_factory.h"
+#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h"
+#include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/management_ui.h"
+#include "chrome/browser/ui/webui/policy_indicator_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/settings/chromeos/internet_strings_provider.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_concept.h"
+#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/webui_util.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "chrome/grit/locale_settings.h"
+#include "chrome/services/local_search_service/public/mojom/types.mojom.h"
+#include "chromeos/constants/chromeos_features.h"
+#include "chromeos/constants/chromeos_switches.h"
+#include "chromeos/services/assistant/public/features.h"
+#include "chromeos/services/multidevice_setup/public/cpp/url_provider.h"
+#include "chromeos/strings/grit/chromeos_strings.h"
+#include "components/google/core/common/google_util.h"
+#include "components/prefs/pref_service.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/version_ui/version_ui_constants.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/content_features.h"
+#include "content/public/common/content_switches.h"
+#include "device/bluetooth/strings/grit/bluetooth_strings.h"
+#include "media/base/media_switches.h"
+#include "ui/accessibility/accessibility_switches.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
+#include "ui/chromeos/devicetype_utils.h"
+#include "ui/chromeos/events/keyboard_layout_util.h"
+#include "ui/display/display_features.h"
+#include "ui/display/display_switches.h"
+#include "ui/display/manager/touch_device_manager.h"
+
+namespace chromeos {
+namespace settings {
+namespace {
+
+std::vector<local_search_service::mojom::DataPtr> ConceptVectorToDataPtrVector(
+ const std::vector<SearchConcept>& tags_group) {
+ std::vector<local_search_service::mojom::DataPtr> data_list;
+
+ for (const auto& concept : tags_group) {
+ std::vector<base::string16> search_tags;
+
+ // Add the canonical tag.
+ search_tags.push_back(
+ l10n_util::GetStringUTF16(concept.canonical_message_id));
+
+ // Add all alternate tags.
+ for (size_t i = 0; i < SearchConcept::kMaxAltTagsPerConcept; ++i) {
+ int curr_alt_tag = concept.alt_tag_ids[i];
+ if (curr_alt_tag == SearchConcept::kAltTagEnd)
+ break;
+ search_tags.push_back(l10n_util::GetStringUTF16(curr_alt_tag));
+ }
+
+ // Note: A stringified version of the canonical tag message ID is used as
+ // the identifier for this search data.
+ data_list.push_back(local_search_service::mojom::Data::New(
+ base::NumberToString(concept.canonical_message_id), search_tags));
+ }
+
+ return data_list;
+}
+
+// Generates a Google Help URL which includes a "board type" parameter. Some
+// help pages need to be adjusted depending on the type of CrOS device that is
+// accessing the page.
+base::string16 GetHelpUrlWithBoard(const std::string& original_url) {
+ return base::ASCIIToUTF16(original_url +
+ "&b=" + base::SysInfo::GetLsbReleaseBoard());
+}
+
+bool IsDeviceManaged() {
+ policy::BrowserPolicyConnectorChromeOS* connector =
+ g_browser_process->platform_part()->browser_policy_connector_chromeos();
+ return connector->IsEnterpriseManaged();
+}
+
+bool IsProfileManaged(Profile* profile) {
+ return profile->GetProfilePolicyConnector()->IsManaged();
+}
+
+void AddCommonStrings(content::WebUIDataSource* html_source, Profile* profile) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"add", IDS_ADD},
+ {"advancedPageTitle", IDS_SETTINGS_ADVANCED},
+ {"back", IDS_ACCNAME_BACK},
+ {"basicPageTitle", IDS_SETTINGS_BASIC},
+ {"cancel", IDS_CANCEL},
+ {"clear", IDS_SETTINGS_CLEAR},
+ {"close", IDS_CLOSE},
+ {"confirm", IDS_CONFIRM},
+ {"continue", IDS_SETTINGS_CONTINUE},
+ {"controlledByExtension", IDS_SETTINGS_CONTROLLED_BY_EXTENSION},
+ {"custom", IDS_SETTINGS_CUSTOM},
+ {"delete", IDS_SETTINGS_DELETE},
+ {"deviceOff", IDS_SETTINGS_DEVICE_OFF},
+ {"deviceOn", IDS_SETTINGS_DEVICE_ON},
+ {"disable", IDS_DISABLE},
+ {"done", IDS_DONE},
+ {"edit", IDS_SETTINGS_EDIT},
+ {"extensionsLinkTooltip", IDS_SETTINGS_MENU_EXTENSIONS_LINK_TOOLTIP},
+ {"learnMore", IDS_LEARN_MORE},
+ {"menu", IDS_MENU},
+ {"menuButtonLabel", IDS_SETTINGS_MENU_BUTTON_LABEL},
+ {"moreActions", IDS_SETTINGS_MORE_ACTIONS},
+ {"ok", IDS_OK},
+ {"restart", IDS_SETTINGS_RESTART},
+ {"save", IDS_SAVE},
+ {"searchResultBubbleText", IDS_SEARCH_RESULT_BUBBLE_TEXT},
+ {"searchResultsBubbleText", IDS_SEARCH_RESULTS_BUBBLE_TEXT},
+ {"settings", IDS_SETTINGS_SETTINGS},
+ {"settingsAltPageTitle", IDS_SETTINGS_ALT_PAGE_TITLE},
+ {"subpageArrowRoleDescription", IDS_SETTINGS_SUBPAGE_BUTTON},
+ {"notValidWebAddress", IDS_SETTINGS_NOT_VALID_WEB_ADDRESS},
+ {"notValidWebAddressForContentType",
+ IDS_SETTINGS_NOT_VALID_WEB_ADDRESS_FOR_CONTENT_TYPE},
+
+ // Common font related strings shown in a11y and appearance sections.
+ {"quickBrownFox", IDS_SETTINGS_QUICK_BROWN_FOX},
+ {"verySmall", IDS_SETTINGS_VERY_SMALL_FONT},
+ {"small", IDS_SETTINGS_SMALL_FONT},
+ {"medium", IDS_SETTINGS_MEDIUM_FONT},
+ {"large", IDS_SETTINGS_LARGE_FONT},
+ {"veryLarge", IDS_SETTINGS_VERY_LARGE_FONT},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddBoolean(
+ "isGuest",
+ user_manager::UserManager::Get()->IsLoggedInAsGuest() ||
+ user_manager::UserManager::Get()->IsLoggedInAsPublicAccount());
+
+ html_source->AddBoolean("isSupervised", profile->IsSupervised());
+}
+
+void AddA11yStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"a11yPageTitle", IDS_SETTINGS_ACCESSIBILITY},
+ {"a11yWebStore", IDS_SETTINGS_ACCESSIBILITY_WEB_STORE},
+ {"moreFeaturesLinkDescription",
+ IDS_SETTINGS_MORE_FEATURES_LINK_DESCRIPTION},
+ {"accessibleImageLabelsTitle",
+ IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_TITLE},
+ {"accessibleImageLabelsSubtitle",
+ IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_SUBTITLE},
+ {"settingsSliderRoleDescription",
+ IDS_SETTINGS_SLIDER_MIN_MAX_ARIA_ROLE_DESCRIPTION},
+ {"manageAccessibilityFeatures",
+ IDS_SETTINGS_ACCESSIBILITY_MANAGE_ACCESSIBILITY_FEATURES},
+ {"optionsInMenuLabel", IDS_SETTINGS_OPTIONS_IN_MENU_LABEL},
+ {"largeMouseCursorLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_LABEL},
+ {"largeMouseCursorSizeLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_LABEL},
+ {"largeMouseCursorSizeDefaultLabel",
+ IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_DEFAULT_LABEL},
+ {"largeMouseCursorSizeLargeLabel",
+ IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_LARGE_LABEL},
+ {"highContrastLabel", IDS_SETTINGS_HIGH_CONTRAST_LABEL},
+ {"stickyKeysLabel", IDS_SETTINGS_STICKY_KEYS_LABEL},
+ {"chromeVoxLabel", IDS_SETTINGS_CHROMEVOX_LABEL},
+ {"chromeVoxOptionsLabel", IDS_SETTINGS_CHROMEVOX_OPTIONS_LABEL},
+ {"screenMagnifierLabel", IDS_SETTINGS_SCREEN_MAGNIFIER_LABEL},
+ {"screenMagnifierZoomLabel", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_LABEL},
+ {"dockedMagnifierLabel", IDS_SETTINGS_DOCKED_MAGNIFIER_LABEL},
+ {"dockedMagnifierZoomLabel", IDS_SETTINGS_DOCKED_MAGNIFIER_ZOOM_LABEL},
+ {"screenMagnifierZoom2x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_2_X},
+ {"screenMagnifierZoom4x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_4_X},
+ {"screenMagnifierZoom6x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_6_X},
+ {"screenMagnifierZoom8x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_8_X},
+ {"screenMagnifierZoom10x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_10_X},
+ {"screenMagnifierZoom12x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_12_X},
+ {"screenMagnifierZoom14x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_14_X},
+ {"screenMagnifierZoom16x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_16_X},
+ {"screenMagnifierZoom18x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_18_X},
+ {"screenMagnifierZoom20x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_20_X},
+ {"tapDraggingLabel", IDS_SETTINGS_TAP_DRAGGING_LABEL},
+ {"clickOnStopLabel", IDS_SETTINGS_CLICK_ON_STOP_LABEL},
+ {"delayBeforeClickLabel", IDS_SETTINGS_DELAY_BEFORE_CLICK_LABEL},
+ {"delayBeforeClickExtremelyShort",
+ IDS_SETTINGS_DELAY_BEFORE_CLICK_EXTREMELY_SHORT},
+ {"delayBeforeClickVeryShort", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_SHORT},
+ {"delayBeforeClickShort", IDS_SETTINGS_DELAY_BEFORE_CLICK_SHORT},
+ {"delayBeforeClickLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_LONG},
+ {"delayBeforeClickVeryLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_LONG},
+ {"autoclickRevertToLeftClick",
+ IDS_SETTINGS_AUTOCLICK_REVERT_TO_LEFT_CLICK},
+ {"autoclickStabilizeCursorPosition",
+ IDS_SETTINGS_AUTOCLICK_STABILIZE_CURSOR_POSITION},
+ {"autoclickMovementThresholdLabel",
+ IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LABEL},
+ {"autoclickMovementThresholdExtraSmall",
+ IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_EXTRA_SMALL},
+ {"autoclickMovementThresholdSmall",
+ IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_SMALL},
+ {"autoclickMovementThresholdDefault",
+ IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_DEFAULT},
+ {"autoclickMovementThresholdLarge",
+ IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LARGE},
+ {"autoclickMovementThresholdExtraLarge",
+ IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_EXTRA_LARGE},
+ {"dictationDescription",
+ IDS_SETTINGS_ACCESSIBILITY_DICTATION_DESCRIPTION},
+ {"dictationLabel", IDS_SETTINGS_ACCESSIBILITY_DICTATION_LABEL},
+ {"onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL},
+ {"monoAudioLabel", IDS_SETTINGS_MONO_AUDIO_LABEL},
+ {"startupSoundLabel", IDS_SETTINGS_STARTUP_SOUND_LABEL},
+ {"a11yExplanation", IDS_SETTINGS_ACCESSIBILITY_EXPLANATION},
+ {"caretHighlightLabel",
+ IDS_SETTINGS_ACCESSIBILITY_CARET_HIGHLIGHT_DESCRIPTION},
+ {"cursorHighlightLabel",
+ IDS_SETTINGS_ACCESSIBILITY_CURSOR_HIGHLIGHT_DESCRIPTION},
+ {"focusHighlightLabel",
+ IDS_SETTINGS_ACCESSIBILITY_FOCUS_HIGHLIGHT_DESCRIPTION},
+ {"selectToSpeakTitle", IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_TITLE},
+ {"selectToSpeakDisabledDescription",
+ IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DISABLED_DESCRIPTION},
+ {"selectToSpeakDescription",
+ IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION},
+ {"selectToSpeakDescriptionWithoutKeyboard",
+ IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION_WITHOUT_KEYBOARD},
+ {"selectToSpeakOptionsLabel",
+ IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_OPTIONS_LABEL},
+ {"switchAccessLabel",
+ IDS_SETTINGS_ACCESSIBILITY_SWITCH_ACCESS_DESCRIPTION},
+ {"switchAccessOptionsLabel",
+ IDS_SETTINGS_ACCESSIBILITY_SWITCH_ACCESS_OPTIONS_LABEL},
+ {"manageSwitchAccessSettings",
+ IDS_SETTINGS_MANAGE_SWITCH_ACCESS_SETTINGS},
+ {"switchAssignmentHeading", IDS_SETTINGS_SWITCH_ASSIGNMENT_HEADING},
+ {"switchAssignOptionNone", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_NONE},
+ {"switchAssignOptionSpace", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_SPACE},
+ {"switchAssignOptionEnter", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_ENTER},
+ {"assignSelectSwitchLabel", IDS_SETTINGS_ASSIGN_SELECT_SWITCH_LABEL},
+ {"assignNextSwitchLabel", IDS_SETTINGS_ASSIGN_NEXT_SWITCH_LABEL},
+ {"assignPreviousSwitchLabel", IDS_SETTINGS_ASSIGN_PREVIOUS_SWITCH_LABEL},
+ {"switchAccessAutoScanHeading",
+ IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_HEADING},
+ {"switchAccessAutoScanLabel", IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_LABEL},
+ {"switchAccessAutoScanSpeedLabel",
+ IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_SPEED_LABEL},
+ {"switchAccessAutoScanKeyboardSpeedLabel",
+ IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_KEYBOARD_SPEED_LABEL},
+ {"durationInSeconds", IDS_SETTINGS_DURATION_IN_SECONDS},
+ {"manageAccessibilityFeatures",
+ IDS_SETTINGS_ACCESSIBILITY_MANAGE_ACCESSIBILITY_FEATURES},
+ {"textToSpeechHeading",
+ IDS_SETTINGS_ACCESSIBILITY_TEXT_TO_SPEECH_HEADING},
+ {"displayHeading", IDS_SETTINGS_ACCESSIBILITY_DISPLAY_HEADING},
+ {"displaySettingsTitle",
+ IDS_SETTINGS_ACCESSIBILITY_DISPLAY_SETTINGS_TITLE},
+ {"displaySettingsDescription",
+ IDS_SETTINGS_ACCESSIBILITY_DISPLAY_SETTINGS_DESCRIPTION},
+ {"appearanceSettingsTitle",
+ IDS_SETTINGS_ACCESSIBILITY_APPEARANCE_SETTINGS_TITLE},
+ {"appearanceSettingsDescription",
+ IDS_SETTINGS_ACCESSIBILITY_APPEARANCE_SETTINGS_DESCRIPTION},
+ {"keyboardAndTextInputHeading",
+ IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_AND_TEXT_INPUT_HEADING},
+ {"keyboardSettingsTitle",
+ IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_SETTINGS_TITLE},
+ {"keyboardSettingsDescription",
+ IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_SETTINGS_DESCRIPTION},
+ {"mouseAndTouchpadHeading",
+ IDS_SETTINGS_ACCESSIBILITY_MOUSE_AND_TOUCHPAD_HEADING},
+ {"mouseSettingsTitle", IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_TITLE},
+ {"mouseSettingsDescription",
+ IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_DESCRIPTION},
+ {"audioAndCaptionsHeading",
+ IDS_SETTINGS_ACCESSIBILITY_AUDIO_AND_CAPTIONS_HEADING},
+ {"additionalFeaturesTitle",
+ IDS_SETTINGS_ACCESSIBILITY_ADDITIONAL_FEATURES_TITLE},
+ {"manageTtsSettings", IDS_SETTINGS_MANAGE_TTS_SETTINGS},
+ {"ttsSettingsLinkDescription", IDS_SETTINGS_TTS_LINK_DESCRIPTION},
+ {"textToSpeechVoices", IDS_SETTINGS_TEXT_TO_SPEECH_VOICES},
+ {"textToSpeechNoVoicesMessage",
+ IDS_SETTINGS_TEXT_TO_SPEECH_NO_VOICES_MESSAGE},
+ {"textToSpeechMoreLanguages", IDS_SETTINGS_TEXT_TO_SPEECH_MORE_LANGUAGES},
+ {"textToSpeechProperties", IDS_SETTINGS_TEXT_TO_SPEECH_PROPERTIES},
+ {"textToSpeechRate", IDS_SETTINGS_TEXT_TO_SPEECH_RATE},
+ {"textToSpeechRateMinimumLabel",
+ IDS_SETTINGS_TEXT_TO_SPEECH_RATE_MINIMUM_LABEL},
+ {"textToSpeechRateMaximumLabel",
+ IDS_SETTINGS_TEXT_TO_SPEECH_RATE_MAXIMUM_LABEL},
+ {"textToSpeechPitch", IDS_SETTINGS_TEXT_TO_SPEECH_PITCH},
+ {"textToSpeechPitchMinimumLabel",
+ IDS_SETTINGS_TEXT_TO_SPEECH_PITCH_MINIMUM_LABEL},
+ {"textToSpeechPitchMaximumLabel",
+ IDS_SETTINGS_TEXT_TO_SPEECH_PITCH_MAXIMUM_LABEL},
+ {"textToSpeechVolume", IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME},
+ {"textToSpeechVolumeMinimumLabel",
+ IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME_MINIMUM_LABEL},
+ {"textToSpeechVolumeMaximumLabel",
+ IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME_MAXIMUM_LABEL},
+ {"percentage", IDS_SETTINGS_PERCENTAGE},
+ {"defaultPercentage", IDS_SETTINGS_DEFAULT_PERCENTAGE},
+ {"textToSpeechPreviewHeading",
+ IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_HEADING},
+ {"textToSpeechPreviewInputLabel",
+ IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_INPUT_LABEL},
+ {"textToSpeechPreviewInput", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_INPUT},
+ {"textToSpeechPreviewVoice", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_VOICE},
+ {"textToSpeechPreviewPlay", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_PLAY},
+ {"textToSpeechEngines", IDS_SETTINGS_TEXT_TO_SPEECH_ENGINES},
+ {"tabletModeShelfNavigationButtonsSettingLabel",
+ IDS_SETTINGS_A11Y_TABLET_MODE_SHELF_BUTTONS_LABEL},
+ {"tabletModeShelfNavigationButtonsSettingDescription",
+ IDS_SETTINGS_A11Y_TABLET_MODE_SHELF_BUTTONS_DESCRIPTION},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString("accountManagerLearnMoreUrl",
+ chrome::kAccountManagerLearnMoreURL);
+ html_source->AddString("a11yLearnMoreUrl",
+ chrome::kChromeAccessibilityHelpURL);
+
+ base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess();
+ html_source->AddBoolean(
+ "showExperimentalAccessibilitySwitchAccess",
+ cmd.HasSwitch(::switches::kEnableExperimentalAccessibilitySwitchAccess));
+
+ html_source->AddBoolean(
+ "showExperimentalAccessibilitySwitchAccessImprovedTextInput",
+ cmd.HasSwitch(
+ ::switches::kEnableExperimentalAccessibilitySwitchAccessText));
+
+ html_source->AddBoolean("showExperimentalA11yLabels",
+ base::FeatureList::IsEnabled(
+ ::features::kExperimentalAccessibilityLabels));
+
+ html_source->AddBoolean(
+ "showTabletModeShelfNavigationButtonsSettings",
+ ash::features::IsHideShelfControlsInTabletModeEnabled());
+
+ html_source->AddString("tabletModeShelfNavigationButtonsLearnMoreUrl",
+ chrome::kTabletModeGesturesLearnMoreURL);
+
+ html_source->AddBoolean("enableLiveCaption",
+ base::FeatureList::IsEnabled(media::kLiveCaption));
+
+ ::settings::AddCaptionSubpageStrings(html_source);
+}
+
+void AddLanguagesStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"orderLanguagesInstructions",
+ IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_ORDERING_INSTRUCTIONS},
+ {"osLanguagesPageTitle", IDS_OS_SETTINGS_LANGUAGES_AND_INPUT_PAGE_TITLE},
+ {"osLanguagesListTitle", IDS_OS_SETTINGS_LANGUAGES_LIST_TITLE},
+ {"inputMethodsListTitle",
+ IDS_SETTINGS_LANGUAGES_INPUT_METHODS_LIST_TITLE},
+ {"inputMethodEnabled", IDS_SETTINGS_LANGUAGES_INPUT_METHOD_ENABLED},
+ {"inputMethodsExpandA11yLabel",
+ IDS_SETTINGS_LANGUAGES_INPUT_METHODS_EXPAND_ACCESSIBILITY_LABEL},
+ {"inputMethodsManagedbyPolicy",
+ IDS_SETTINGS_LANGUAGES_INPUT_METHODS_MANAGED_BY_POLICY},
+ {"manageInputMethods", IDS_SETTINGS_LANGUAGES_INPUT_METHODS_MANAGE},
+ {"manageInputMethodsPageTitle",
+ IDS_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_TITLE},
+ {"showImeMenu", IDS_SETTINGS_LANGUAGES_SHOW_IME_MENU},
+ {"displayLanguageRestart",
+ IDS_SETTINGS_LANGUAGES_RESTART_TO_DISPLAY_LANGUAGE},
+ {"moveDown", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_MOVE_DOWN},
+ {"displayInThisLanguage",
+ IDS_SETTINGS_LANGUAGES_DISPLAY_IN_THIS_LANGUAGE},
+ {"searchLanguages", IDS_SETTINGS_LANGUAGE_SEARCH},
+ {"addLanguagesDialogTitle",
+ IDS_SETTINGS_LANGUAGES_MANAGE_LANGUAGES_TITLE},
+ {"moveToTop", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_MOVE_TO_TOP},
+ {"isDisplayedInThisLanguage",
+ IDS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE},
+ {"removeLanguage", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_REMOVE},
+ {"addLanguages", IDS_SETTINGS_LANGUAGES_LANGUAGES_ADD},
+ {"moveUp", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_MOVE_UP},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString(
+ "languagesLearnMoreURL",
+ base::ASCIIToUTF16(chrome::kLanguageSettingsLearnMoreUrl));
+}
+
+void AddPersonalizationStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"ambientModeTitle", IDS_OS_SETTINGS_AMBIENT_MODE_TITLE},
+ {"ambientModeEnabled", IDS_OS_SETTINGS_AMBIENT_MODE_ENABLED},
+ {"ambientModeDisabled", IDS_OS_SETTINGS_AMBIENT_MODE_DISABLED},
+ {"ambientModeOn", IDS_OS_SETTINGS_AMBIENT_MODE_ON},
+ {"ambientModeOff", IDS_OS_SETTINGS_AMBIENT_MODE_OFF},
+ {"ambientModeTopicSourceTitle",
+ IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_TITLE},
+ {"ambientModeTopicSourceGooglePhotos",
+ IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_GOOGLE_PHOTOS},
+ {"ambientModeTopicSourceArtGallery",
+ IDS_OS_SETTINGS_AMBIENT_MODE_TOPIC_SOURCE_ART_GALLERY},
+ {"changePictureTitle", IDS_OS_SETTINGS_CHANGE_PICTURE_TITLE},
+ {"openWallpaperApp", IDS_OS_SETTINGS_OPEN_WALLPAPER_APP},
+ {"personalizationPageTitle", IDS_OS_SETTINGS_PERSONALIZATION},
+ {"setWallpaper", IDS_OS_SETTINGS_SET_WALLPAPER},
+ {"takePhoto", IDS_SETTINGS_CHANGE_PICTURE_TAKE_PHOTO},
+ {"captureVideo", IDS_SETTINGS_CHANGE_PICTURE_CAPTURE_VIDEO},
+ {"discardPhoto", IDS_SETTINGS_CHANGE_PICTURE_DISCARD_PHOTO},
+ {"previewAltText", IDS_SETTINGS_CHANGE_PICTURE_PREVIEW_ALT},
+ {"switchModeToVideo", IDS_SETTINGS_CHANGE_PICTURE_SWITCH_MODE_TO_VIDEO},
+ {"profilePhoto", IDS_SETTINGS_CHANGE_PICTURE_PROFILE_PHOTO},
+ {"changePicturePageDescription", IDS_SETTINGS_CHANGE_PICTURE_DIALOG_TEXT},
+ {"switchModeToCamera", IDS_SETTINGS_CHANGE_PICTURE_SWITCH_MODE_TO_CAMERA},
+ {"chooseFile", IDS_SETTINGS_CHANGE_PICTURE_CHOOSE_FILE},
+ {"oldPhoto", IDS_SETTINGS_CHANGE_PICTURE_OLD_PHOTO},
+ {"oldVideo", IDS_SETTINGS_CHANGE_PICTURE_OLD_VIDEO},
+ {"authorCreditText", IDS_SETTINGS_CHANGE_PICTURE_AUTHOR_CREDIT_TEXT},
+ {"photoCaptureAccessibleText",
+ IDS_SETTINGS_PHOTO_CAPTURE_ACCESSIBLE_TEXT},
+ {"photoDiscardAccessibleText",
+ IDS_SETTINGS_PHOTO_DISCARD_ACCESSIBLE_TEXT},
+ {"photoModeAccessibleText", IDS_SETTINGS_PHOTO_MODE_ACCESSIBLE_TEXT},
+ {"videoModeAccessibleText", IDS_SETTINGS_VIDEO_MODE_ACCESSIBLE_TEXT},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddBoolean(
+ "changePictureVideoModeEnabled",
+ base::FeatureList::IsEnabled(::features::kChangePictureVideoMode));
+ html_source->AddBoolean("isAmbientModeEnabled",
+ chromeos::features::IsAmbientModeEnabled());
+}
+
+void AddFingerprintListStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"lockScreenAddFingerprint",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_ADD_FINGERPRINT_BUTTON},
+ {"lockScreenRegisteredFingerprints",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_REGISTERED_FINGERPRINTS_LABEL},
+ {"lockScreenFingerprintWarning",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_LESS_SECURE},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddSetupPinDialogStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"configurePinChoosePinTitle",
+ IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CHOOSE_PIN_TITLE},
+ {"configurePinConfirmPinTitle",
+ IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CONFIRM_PIN_TITLE},
+ {"configurePinMismatched", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_MISMATCHED},
+ {"configurePinTooShort", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT},
+ {"configurePinTooLong", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_LONG},
+ {"configurePinWeakPin", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_WEAK_PIN},
+ {"pinKeyboardPlaceholderPin", IDS_PIN_KEYBOARD_HINT_TEXT_PIN},
+ {"pinKeyboardPlaceholderPinPassword",
+ IDS_PIN_KEYBOARD_HINT_TEXT_PIN_PASSWORD},
+ {"pinKeyboardDeleteAccessibleName",
+ IDS_PIN_KEYBOARD_DELETE_ACCESSIBLE_NAME},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ // Format numbers to be used on the pin keyboard.
+ for (int j = 0; j <= 9; j++) {
+ html_source->AddString("pinKeyboard" + base::NumberToString(j),
+ base::FormatNumber(int64_t{j}));
+ }
+}
+
+void AddSetupFingerprintDialogStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"configureFingerprintTitle", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TITLE},
+ {"configureFingerprintAddAnotherButton",
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_ADD_ANOTHER_BUTTON},
+ {"configureFingerprintInstructionReadyStep",
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_READY},
+ {"configureFingerprintLiftFinger",
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_LIFT_FINGER},
+ {"configureFingerprintTryAgain",
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TRY_AGAIN},
+ {"configureFingerprintImmobile",
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_FINGER_IMMOBILE},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddFingerprintStrings(content::WebUIDataSource* html_source) {
+ int instruction_id, aria_label_id;
+ using FingerprintLocation = chromeos::quick_unlock::FingerprintLocation;
+ switch (chromeos::quick_unlock::GetFingerprintLocation()) {
+ case FingerprintLocation::TABLET_POWER_BUTTON:
+ instruction_id =
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_POWER_BUTTON;
+ aria_label_id =
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_POWER_BUTTON_ARIA_LABEL;
+ break;
+ case FingerprintLocation::KEYBOARD_BOTTOM_LEFT:
+ instruction_id =
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD;
+ aria_label_id =
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD_BOTTOM_LEFT_ARIA_LABEL;
+ break;
+ case FingerprintLocation::KEYBOARD_BOTTOM_RIGHT:
+ instruction_id =
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD;
+ aria_label_id =
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD_BOTTOM_RIGHT_ARIA_LABEL;
+ break;
+ case FingerprintLocation::KEYBOARD_TOP_RIGHT:
+ instruction_id =
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD;
+ aria_label_id =
+ IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD_TOP_RIGHT_ARIA_LABEL;
+ break;
+ }
+ html_source->AddLocalizedString(
+ "configureFingerprintInstructionLocateScannerStep", instruction_id);
+ html_source->AddLocalizedString("configureFingerprintScannerStepAriaLabel",
+ aria_label_id);
+}
+
+void AddAccountManagerPageStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"accountManagerDescription", IDS_SETTINGS_ACCOUNT_MANAGER_DESCRIPTION},
+ {"accountManagerChildDescription",
+ IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_DESCRIPTION},
+ {"accountListHeader", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER},
+ {"accountManagerPrimaryAccountTooltip",
+ IDS_SETTINGS_ACCOUNT_MANAGER_PRIMARY_ACCOUNT_TOOLTIP},
+ {"accountManagerEducationAccountLabel",
+ IDS_SETTINGS_ACCOUNT_MANAGER_EDUCATION_ACCOUNT},
+ {"removeAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_REMOVE_ACCOUNT_LABEL},
+ {"addAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_ADD_ACCOUNT_LABEL},
+ {"addSchoolAccountLabel",
+ IDS_SETTINGS_ACCOUNT_MANAGER_ADD_SCHOOL_ACCOUNT_LABEL},
+ {"accountManagerSecondaryAccountsDisabledText",
+ IDS_SETTINGS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_TEXT},
+ {"accountManagerSecondaryAccountsDisabledChildText",
+ IDS_SETTINGS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_CHILD_TEXT},
+ {"accountManagerSignedOutAccountName",
+ IDS_SETTINGS_ACCOUNT_MANAGER_SIGNED_OUT_ACCOUNT_PLACEHOLDER},
+ {"accountManagerUnmigratedAccountName",
+ IDS_SETTINGS_ACCOUNT_MANAGER_UNMIGRATED_ACCOUNT_PLACEHOLDER},
+ {"accountManagerMigrationLabel",
+ IDS_SETTINGS_ACCOUNT_MANAGER_MIGRATION_LABEL},
+ {"accountManagerReauthenticationLabel",
+ IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_LABEL},
+ {"accountManagerMigrationTooltip",
+ IDS_SETTINGS_ACCOUNT_MANAGER_MIGRATION_TOOLTIP},
+ {"accountManagerReauthenticationTooltip",
+ IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_TOOLTIP},
+ {"accountManagerMoreActionsTooltip",
+ IDS_SETTINGS_ACCOUNT_MANAGER_MORE_ACTIONS_TOOLTIP},
+ {"accountManagerManagedLabel",
+ IDS_SETTINGS_ACCOUNT_MANAGER_MANAGEMENT_STATUS_MANAGED_ACCOUNT},
+ {"accountManagerUnmanagedLabel",
+ IDS_SETTINGS_ACCOUNT_MANAGER_MANAGEMENT_STATUS_UNMANAGED_ACCOUNT},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddSyncControlsStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"syncEverythingCheckboxLabel",
+ IDS_SETTINGS_SYNC_EVERYTHING_CHECKBOX_LABEL},
+ {"wallpaperCheckboxLabel", IDS_OS_SETTINGS_WALLPAPER_CHECKBOX_LABEL},
+ {"osSyncTurnOff", IDS_OS_SETTINGS_SYNC_TURN_OFF},
+ {"osSyncSettingsCheckboxLabel",
+ IDS_OS_SETTINGS_SYNC_SETTINGS_CHECKBOX_LABEL},
+ {"wifiConfigurationsCheckboxLabel",
+ IDS_SETTINGS_WIFI_CONFIGURATIONS_CHECKBOX_LABEL},
+ {"osSyncAppsCheckboxLabel", IDS_OS_SETTINGS_SYNC_APPS_CHECKBOX_LABEL},
+ {"osSyncTurnOn", IDS_OS_SETTINGS_SYNC_TURN_ON},
+ {"osSyncFeatureLabel", IDS_OS_SETTINGS_SYNC_FEATURE_LABEL},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString(
+ "browserSettingsSyncSetupUrl",
+ base::StrCat({chrome::kChromeUISettingsURL, chrome::kSyncSetupSubPage}));
+}
+
+void AddCrostiniStrings(content::WebUIDataSource* html_source,
+ Profile* profile) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"crostiniPageTitle", IDS_SETTINGS_CROSTINI_TITLE},
+ {"crostiniPageLabel", IDS_SETTINGS_CROSTINI_LABEL},
+ {"crostiniEnable", IDS_SETTINGS_TURN_ON},
+ {"crostiniSharedPaths", IDS_SETTINGS_CROSTINI_SHARED_PATHS},
+ {"crostiniSharedPathsListHeading",
+ IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_HEADING},
+ {"crostiniSharedPathsInstructionsAdd",
+ IDS_SETTINGS_CROSTINI_SHARED_PATHS_INSTRUCTIONS_ADD},
+ {"crostiniSharedPathsInstructionsRemove",
+ IDS_SETTINGS_CROSTINI_SHARED_PATHS_INSTRUCTIONS_REMOVE},
+ {"crostiniSharedPathsRemoveSharing",
+ IDS_SETTINGS_CROSTINI_SHARED_PATHS_REMOVE_SHARING},
+ {"crostiniSharedPathsRemoveFailureDialogMessage",
+ IDS_SETTINGS_CROSTINI_SHARED_PATHS_REMOVE_FAILURE_DIALOG_MESSAGE},
+ {"crostiniSharedPathsRemoveFailureDialogTitle",
+ IDS_SETTINGS_CROSTINI_SHARED_PATHS_REMOVE_FAILURE_DIALOG_TITLE},
+ {"crostiniSharedPathsRemoveFailureTryAgain",
+ IDS_SETTINGS_CROSTINI_SHARED_PATHS_REMOVE_FAILURE_TRY_AGAIN},
+ {"crostiniSharedPathsListEmptyMessage",
+ IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_EMPTY_MESSAGE},
+ {"crostiniExportImportTitle", IDS_SETTINGS_CROSTINI_EXPORT_IMPORT_TITLE},
+ {"crostiniExport", IDS_SETTINGS_CROSTINI_EXPORT},
+ {"crostiniExportLabel", IDS_SETTINGS_CROSTINI_EXPORT_LABEL},
+ {"crostiniImport", IDS_SETTINGS_CROSTINI_IMPORT},
+ {"crostiniImportLabel", IDS_SETTINGS_CROSTINI_IMPORT_LABEL},
+ {"crostiniImportConfirmationDialogTitle",
+ IDS_SETTINGS_CROSTINI_CONFIRM_IMPORT_DIALOG_WINDOW_TITLE},
+ {"crostiniImportConfirmationDialogMessage",
+ IDS_SETTINGS_CROSTINI_CONFIRM_IMPORT_DIALOG_WINDOW_MESSAGE},
+ {"crostiniImportConfirmationDialogConfirmationButton",
+ IDS_SETTINGS_CROSTINI_IMPORT},
+ {"crostiniRemoveButton", IDS_SETTINGS_CROSTINI_REMOVE_BUTTON},
+ {"crostiniSharedUsbDevicesLabel",
+ IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_LABEL},
+ {"crostiniSharedUsbDevicesDescription",
+ IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_DESCRIPTION},
+ {"crostiniSharedUsbDevicesExtraDescription",
+ IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_EXTRA_DESCRIPTION},
+ {"crostiniSharedUsbDevicesListEmptyMessage",
+ IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_LIST_EMPTY_MESSAGE},
+ {"crostiniArcAdbTitle", IDS_SETTINGS_CROSTINI_ARC_ADB_TITLE},
+ {"crostiniArcAdbDescription", IDS_SETTINGS_CROSTINI_ARC_ADB_DESCRIPTION},
+ {"crostiniArcAdbLabel", IDS_SETTINGS_CROSTINI_ARC_ADB_LABEL},
+ {"crostiniArcAdbRestartButton",
+ IDS_SETTINGS_CROSTINI_ARC_ADB_RESTART_BUTTON},
+ {"crostiniArcAdbConfirmationTitleEnable",
+ IDS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_TITLE_ENABLE},
+ {"crostiniArcAdbConfirmationTitleDisable",
+ IDS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_TITLE_DISABLE},
+ {"crostiniContainerUpgrade",
+ IDS_SETTINGS_CROSTINI_CONTAINER_UPGRADE_MESSAGE},
+ {"crostiniContainerUpgradeSubtext",
+ IDS_SETTINGS_CROSTINI_CONTAINER_UPGRADE_SUBTEXT},
+ {"crostiniContainerUpgradeButton",
+ IDS_SETTINGS_CROSTINI_CONTAINER_UPGRADE_BUTTON},
+ {"crostiniPortForwarding", IDS_SETTINGS_CROSTINI_PORT_FORWARDING},
+ {"crostiniPortForwardingDescription",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_DESCRIPTION},
+ {"crostiniPortForwardingNoPorts",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_NO_PORTS},
+ {"crostiniPortForwardingTableTitle",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_TABLE_TITLE},
+ {"crostiniPortForwardingListPortNumber",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_LIST_PORT_NUMBER},
+ {"crostiniPortForwardingListLabel",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_LIST_LABEL},
+ {"crostiniPortForwardingAddPortButton",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_BUTTON},
+ {"crostiniPortForwardingAddPortButtonDescription",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_BUTTON_DESCRIPTION},
+ {"crostiniPortForwardingAddPortDialogTitle",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_DIALOG_TITLE},
+ {"crostiniPortForwardingAddPortDialogLabel",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_DIALOG_LABEL},
+ {"crostiniPortForwardingTCP", IDS_SETTINGS_CROSTINI_PORT_FORWARDING_TCP},
+ {"crostiniPortForwardingUDP", IDS_SETTINGS_CROSTINI_PORT_FORWARDING_UDP},
+ {"crostiniPortForwardingAddError",
+ IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_ERROR},
+ {"crostiniDiskResizeTitle", IDS_SETTINGS_CROSTINI_DISK_RESIZE_TITLE},
+ {"crostiniDiskResizeShowButton",
+ IDS_SETTINGS_CROSTINI_DISK_RESIZE_SHOW_BUTTON},
+ {"crostiniDiskResizeLabel", IDS_SETTINGS_CROSTINI_DISK_RESIZE_LABEL},
+ {"crostiniDiskResizeUnsupported",
+ IDS_SETTINGS_CROSTINI_DISK_RESIZE_UNSUPPORTED},
+ {"crostiniDiskResizeLoading", IDS_SETTINGS_CROSTINI_DISK_RESIZE_LOADING},
+ {"crostiniDiskResizeError", IDS_SETTINGS_CROSTINI_DISK_RESIZE_ERROR},
+ {"crostiniDiskResizeErrorRetry",
+ IDS_SETTINGS_CROSTINI_DISK_RESIZE_ERROR_RETRY},
+ {"crostiniDiskResizeCancel", IDS_SETTINGS_CROSTINI_DISK_RESIZE_CANCEL},
+ {"crostiniDiskResizeGoButton",
+ IDS_SETTINGS_CROSTINI_DISK_RESIZE_GO_BUTTON},
+ {"crostiniDiskResizeInProgress",
+ IDS_SETTINGS_CROSTINI_DISK_RESIZE_IN_PROGRESS},
+ {"crostiniDiskResizeResizingError",
+ IDS_SETTINGS_CROSTINI_DISK_RESIZE_RESIZING_ERROR},
+ {"crostiniDiskResizeDone", IDS_SETTINGS_CROSTINI_DISK_RESIZE_DONE},
+ {"crostiniMicTitle", IDS_SETTINGS_CROSTINI_MIC_TITLE},
+ {"crostiniMicDialogTitle", IDS_SETTINGS_CROSTINI_MIC_DIALOG_TITLE},
+ {"crostiniMicDialogLabel", IDS_SETTINGS_CROSTINI_MIC_DIALOG_LABEL},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+ html_source->AddString(
+ "crostiniSubtext",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CROSTINI_SUBTEXT, ui::GetChromeOSDeviceName(),
+ GetHelpUrlWithBoard(chrome::kLinuxAppsLearnMoreURL)));
+ html_source->AddString(
+ "crostiniArcAdbPowerwashRequiredSublabel",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CROSTINI_ARC_ADB_POWERWASH_REQUIRED_SUBLABEL,
+ base::ASCIIToUTF16(chrome::kArcAdbSideloadingLearnMoreURL)));
+ html_source->AddString("crostiniRemove", l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CROSTINI_REMOVE,
+ ui::GetChromeOSDeviceName()));
+ html_source->AddString(
+ "crostiniArcAdbConfirmationMessageEnable",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_MESSAGE_ENABLE,
+ ui::GetChromeOSDeviceName()));
+ html_source->AddString(
+ "crostiniArcAdbConfirmationMessageDisable",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_MESSAGE_DISABLE,
+ ui::GetChromeOSDeviceName()));
+ html_source->AddString(
+ "crostiniSharedPathsInstructionsLocate",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CROSTINI_SHARED_PATHS_INSTRUCTIONS_LOCATE,
+ base::ASCIIToUTF16(
+ crostini::ContainerChromeOSBaseDirectory().value())));
+ html_source->AddBoolean(
+ "showCrostiniExportImport",
+ crostini::CrostiniFeatures::Get()->IsExportImportUIAllowed(profile));
+ html_source->AddBoolean("arcAdbSideloadingSupported",
+ base::FeatureList::IsEnabled(
+ chromeos::features::kArcAdbSideloadingFeature));
+ html_source->AddBoolean("showCrostiniPortForwarding",
+ base::FeatureList::IsEnabled(
+ chromeos::features::kCrostiniPortForwarding));
+ html_source->AddBoolean("isOwnerProfile",
+ chromeos::ProfileHelper::IsOwnerProfile(profile));
+ html_source->AddBoolean("isEnterpriseManaged",
+ IsDeviceManaged() || IsProfileManaged(profile));
+ html_source->AddBoolean(
+ "canChangeAdbSideloading",
+ crostini::CrostiniFeatures::Get()->CanChangeAdbSideloading(profile));
+ html_source->AddBoolean("showCrostiniContainerUpgrade",
+ crostini::ShouldAllowContainerUpgrade(profile));
+ html_source->AddBoolean(
+ "showCrostiniDiskResize",
+ base::FeatureList::IsEnabled(chromeos::features::kCrostiniDiskResizing));
+ html_source->AddBoolean("showCrostiniMic",
+ base::FeatureList::IsEnabled(
+ chromeos::features::kCrostiniShowMicSetting));
+}
+
+void AddPluginVmStrings(content::WebUIDataSource* html_source,
+ Profile* profile) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"pluginVmPageTitle", IDS_SETTINGS_PLUGIN_VM_PAGE_TITLE},
+ {"pluginVmPageLabel", IDS_SETTINGS_PLUGIN_VM_PAGE_LABEL},
+ {"pluginVmPageSubtext", IDS_SETTINGS_PLUGIN_VM_PAGE_SUBTEXT},
+ {"pluginVmPageEnable", IDS_SETTINGS_TURN_ON},
+ {"pluginVmPrinterAccess", IDS_SETTINGS_PLUGIN_VM_PRINTER_ACCESS},
+ {"pluginVmSharedPaths", IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS},
+ {"pluginVmSharedPathsListHeading",
+ IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS_LIST_HEADING},
+ {"pluginVmSharedPathsInstructionsAdd",
+ IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS_INSTRUCTIONS_ADD},
+ {"pluginVmSharedPathsInstructionsRemove",
+ IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS_INSTRUCTIONS_REMOVE},
+ {"pluginVmSharedPathsRemoveSharing",
+ IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS_REMOVE_SHARING},
+ {"pluginVmRemove", IDS_SETTINGS_PLUGIN_VM_REMOVE_LABEL},
+ {"pluginVmRemoveButton", IDS_SETTINGS_PLUGIN_VM_REMOVE_BUTTON},
+ {"pluginVmRemoveConfirmationDialogMessage",
+ IDS_SETTINGS_PLUGIN_VM_CONFIRM_REMOVE_DIALOG_BODY},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddAndroidAppStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"androidAppsPageLabel", IDS_SETTINGS_ANDROID_APPS_LABEL},
+ {"androidAppsEnable", IDS_SETTINGS_TURN_ON},
+ {"androidAppsManageApps", IDS_SETTINGS_ANDROID_APPS_MANAGE_APPS},
+ {"androidAppsRemove", IDS_SETTINGS_ANDROID_APPS_REMOVE},
+ {"androidAppsRemoveButton", IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON},
+ {"androidAppsDisableDialogTitle",
+ IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_TITLE},
+ {"androidAppsDisableDialogMessage",
+ IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE},
+ {"androidAppsDisableDialogRemove",
+ IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_REMOVE},
+ {"androidAppsManageAppLinks", IDS_SETTINGS_ANDROID_APPS_MANAGE_APP_LINKS},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+ html_source->AddLocalizedString("androidAppsPageTitle",
+ arc::IsPlayStoreAvailable()
+ ? IDS_SETTINGS_ANDROID_APPS_TITLE
+ : IDS_SETTINGS_ANDROID_SETTINGS_TITLE);
+ html_source->AddString(
+ "androidAppsSubtext",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_ANDROID_APPS_SUBTEXT, ui::GetChromeOSDeviceName(),
+ GetHelpUrlWithBoard(chrome::kAndroidAppsLearnMoreURL)));
+}
+
+void AddAppsStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"appsPageTitle", IDS_SETTINGS_APPS_TITLE},
+ {"appManagementTitle", IDS_SETTINGS_APPS_LINK_TEXT},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddAppManagementStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"appManagementAppInstalledByPolicyLabel",
+ IDS_APP_MANAGEMENT_POLICY_APP_POLICY_STRING},
+ {"appManagementCameraPermissionLabel", IDS_APP_MANAGEMENT_CAMERA},
+ {"appManagementContactsPermissionLabel", IDS_APP_MANAGEMENT_CONTACTS},
+ {"appManagementLocationPermissionLabel", IDS_APP_MANAGEMENT_LOCATION},
+ {"appManagementMicrophonePermissionLabel", IDS_APP_MANAGEMENT_MICROPHONE},
+ {"appManagementMoreSettingsLabel", IDS_APP_MANAGEMENT_MORE_SETTINGS},
+ {"appManagementNoAppsFound", IDS_APP_MANAGEMENT_NO_APPS_FOUND},
+ {"appManagementNoPermissions",
+ IDS_APPLICATION_INFO_APP_NO_PERMISSIONS_TEXT},
+ {"appManagementNotificationsLabel", IDS_APP_MANAGEMENT_NOTIFICATIONS},
+ {"appManagementPermissionsLabel", IDS_APP_MANAGEMENT_PERMISSIONS},
+ {"appManagementPinToShelfLabel", IDS_APP_MANAGEMENT_PIN_TO_SHELF},
+ {"appManagementSearchPrompt", IDS_APP_MANAGEMENT_SEARCH_PROMPT},
+ {"appManagementStoragePermissionLabel", IDS_APP_MANAGEMENT_STORAGE},
+ {"appManagementUninstallLabel", IDS_APP_MANAGEMENT_UNINSTALL_APP},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddParentalControlStrings(content::WebUIDataSource* html_source,
+ Profile* profile) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"parentalControlsPageTitle", IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_TITLE},
+ {"parentalControlsPageSetUpLabel",
+ IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_SET_UP_LABEL},
+ {"parentalControlsPageViewSettingsLabel",
+ IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_VIEW_SETTINGS_LABEL},
+ {"parentalControlsPageConnectToInternetLabel",
+ IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_CONNECT_TO_INTERNET_LABEL},
+ {"parentalControlsSetUpButtonLabel",
+ IDS_SETTINGS_PARENTAL_CONTROLS_SET_UP_BUTTON_LABEL},
+ {"parentalControlsSetUpButtonRole",
+ IDS_SETTINGS_PARENTAL_CONTROLS_SET_UP_BUTTON_ROLE},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddBoolean(
+ "isChild", user_manager::UserManager::Get()->IsLoggedInAsChildUser());
+
+ if (user_manager::UserManager::Get()->IsLoggedInAsChildUser()) {
+ SupervisedUserService* supervised_user_service =
+ SupervisedUserServiceFactory::GetForProfile(profile);
+ std::string custodian = supervised_user_service->GetCustodianName();
+ std::string second_custodian =
+ supervised_user_service->GetSecondCustodianName();
+
+ base::string16 child_managed_tooltip;
+ if (second_custodian.empty()) {
+ child_managed_tooltip = l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_ONE_PARENT_TOOLTIP,
+ base::UTF8ToUTF16(custodian));
+ } else {
+ child_managed_tooltip = l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_TWO_PARENTS_TOOLTIP,
+ base::UTF8ToUTF16(custodian), base::UTF8ToUTF16(second_custodian));
+ }
+ html_source->AddString("accountManagerPrimaryAccountChildManagedTooltip",
+ child_managed_tooltip);
+ }
+}
+
+void AddBluetoothStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"bluetoothConnected", IDS_SETTINGS_BLUETOOTH_CONNECTED},
+ {"bluetoothConnectedWithBattery",
+ IDS_SETTINGS_BLUETOOTH_CONNECTED_WITH_BATTERY},
+ {"bluetoothConnecting", IDS_SETTINGS_BLUETOOTH_CONNECTING},
+ {"bluetoothDeviceListPaired", IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_PAIRED},
+ {"bluetoothDeviceListUnpaired",
+ IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_UNPAIRED},
+ {"bluetoothConnect", IDS_SETTINGS_BLUETOOTH_CONNECT},
+ {"bluetoothDisconnect", IDS_SETTINGS_BLUETOOTH_DISCONNECT},
+ {"bluetoothToggleA11yLabel",
+ IDS_SETTINGS_BLUETOOTH_TOGGLE_ACCESSIBILITY_LABEL},
+ {"bluetoothExpandA11yLabel",
+ IDS_SETTINGS_BLUETOOTH_EXPAND_ACCESSIBILITY_LABEL},
+ {"bluetoothNoDevices", IDS_SETTINGS_BLUETOOTH_NO_DEVICES},
+ {"bluetoothNoDevicesFound", IDS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND},
+ {"bluetoothNotConnected", IDS_SETTINGS_BLUETOOTH_NOT_CONNECTED},
+ {"bluetoothPageTitle", IDS_SETTINGS_BLUETOOTH},
+ {"bluetoothPairDevicePageTitle",
+ IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE},
+ {"bluetoothRemove", IDS_SETTINGS_BLUETOOTH_REMOVE},
+ {"bluetoothPrimaryUserControlled",
+ IDS_SETTINGS_BLUETOOTH_PRIMARY_USER_CONTROLLED},
+ {"bluetoothDeviceType_computer",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_COMPUTER},
+ {"bluetoothDeviceType_phone",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_PHONE},
+ {"bluetoothDeviceType_modem",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_MODEM},
+ {"bluetoothDeviceType_audio",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_AUDIO},
+ {"bluetoothDeviceType_carAudio",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_CAR_AUDIO},
+ {"bluetoothDeviceType_video",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_VIDEO},
+ {"bluetoothDeviceType_peripheral",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_PERIPHERAL},
+ {"bluetoothDeviceType_joystick",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_JOYSTICK},
+ {"bluetoothDeviceType_gamepad",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_GAMEPAD},
+ {"bluetoothDeviceType_keyboard",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_KEYBOARD},
+ {"bluetoothDeviceType_mouse",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_MOUSE},
+ {"bluetoothDeviceType_tablet",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_TABLET},
+ {"bluetoothDeviceType_keyboardMouseCombo",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_KEYBOARD_MOUSE_COMBO},
+ {"bluetoothDeviceType_unknown",
+ IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_UNKNOWN},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+ chromeos::bluetooth_dialog::AddLocalizedStrings(html_source);
+}
+
+void AddChromeOSUserStrings(content::WebUIDataSource* html_source,
+ Profile* profile) {
+ user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+
+ const user_manager::User* user =
+ chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
+ const user_manager::User* primary_user = user_manager->GetPrimaryUser();
+ std::string primary_user_email = primary_user->GetAccountId().GetUserEmail();
+ html_source->AddString("primaryUserEmail", primary_user_email);
+ html_source->AddString("browserSettingsBannerText",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_BROWSER_SETTINGS_BANNER,
+ base::ASCIIToUTF16(chrome::kChromeUISettingsURL)));
+ html_source->AddBoolean("isActiveDirectoryUser",
+ user && user->IsActiveDirectoryUser());
+ html_source->AddBoolean(
+ "isSecondaryUser",
+ user && user->GetAccountId() != primary_user->GetAccountId());
+ html_source->AddString(
+ "secondaryUserBannerText",
+ l10n_util::GetStringFUTF16(IDS_SETTINGS_SECONDARY_USER_BANNER,
+ base::ASCIIToUTF16(primary_user_email)));
+
+ if (!IsDeviceManaged() && !user_manager->IsCurrentUserOwner()) {
+ html_source->AddString("ownerEmail",
+ user_manager->GetOwnerAccountId().GetUserEmail());
+ }
+}
+
+void AddDevicePointersStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kPointersStrings[] = {
+ {"mouseTitle", IDS_SETTINGS_MOUSE_TITLE},
+ {"touchpadTitle", IDS_SETTINGS_TOUCHPAD_TITLE},
+ {"mouseAndTouchpadTitle", IDS_SETTINGS_MOUSE_AND_TOUCHPAD_TITLE},
+ {"touchpadTapToClickEnabledLabel",
+ IDS_SETTINGS_TOUCHPAD_TAP_TO_CLICK_ENABLED_LABEL},
+ {"touchpadSpeed", IDS_SETTINGS_TOUCHPAD_SPEED_LABEL},
+ {"pointerSlow", IDS_SETTINGS_POINTER_SPEED_SLOW_LABEL},
+ {"pointerFast", IDS_SETTINGS_POINTER_SPEED_FAST_LABEL},
+ {"mouseScrollSpeed", IDS_SETTINGS_MOUSE_SCROLL_SPEED_LABEL},
+ {"mouseSpeed", IDS_SETTINGS_MOUSE_SPEED_LABEL},
+ {"mouseSwapButtons", IDS_SETTINGS_MOUSE_SWAP_BUTTONS_LABEL},
+ {"mouseReverseScroll", IDS_SETTINGS_MOUSE_REVERSE_SCROLL_LABEL},
+ {"mouseAccelerationLabel", IDS_SETTINGS_MOUSE_ACCELERATION_LABEL},
+ {"mouseScrollAccelerationLabel",
+ IDS_SETTINGS_MOUSE_SCROLL_ACCELERATION_LABEL},
+ {"touchpadAccelerationLabel", IDS_SETTINGS_TOUCHPAD_ACCELERATION_LABEL},
+ {"touchpadScrollAccelerationLabel",
+ IDS_SETTINGS_TOUCHPAD_SCROLL_ACCELERATION_LABEL},
+ {"touchpadScrollSpeed", IDS_SETTINGS_TOUCHPAD_SCROLL_SPEED_LABEL},
+ };
+ AddLocalizedStringsBulk(html_source, kPointersStrings);
+
+ html_source->AddString("naturalScrollLearnMoreLink",
+ GetHelpUrlWithBoard(chrome::kNaturalScrollHelpURL));
+
+ html_source->AddBoolean(
+ "allowDisableMouseAcceleration",
+ base::FeatureList::IsEnabled(::features::kAllowDisableMouseAcceleration));
+ html_source->AddBoolean(
+ "allowScrollSettings",
+ base::FeatureList::IsEnabled(features::kAllowScrollSettings));
+}
+
+void AddDeviceKeyboardStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString keyboard_strings[] = {
+ {"keyboardTitle", IDS_SETTINGS_KEYBOARD_TITLE},
+ {"keyboardKeyCtrl", IDS_SETTINGS_KEYBOARD_KEY_LEFT_CTRL},
+ {"keyboardKeyAlt", IDS_SETTINGS_KEYBOARD_KEY_LEFT_ALT},
+ {"keyboardKeyCapsLock", IDS_SETTINGS_KEYBOARD_KEY_CAPS_LOCK},
+ {"keyboardKeyCommand", IDS_SETTINGS_KEYBOARD_KEY_COMMAND},
+ {"keyboardKeyDiamond", IDS_SETTINGS_KEYBOARD_KEY_DIAMOND},
+ {"keyboardKeyEscape", IDS_SETTINGS_KEYBOARD_KEY_ESCAPE},
+ {"keyboardKeyBackspace", IDS_SETTINGS_KEYBOARD_KEY_BACKSPACE},
+ {"keyboardKeyAssistant", IDS_SETTINGS_KEYBOARD_KEY_ASSISTANT},
+ {"keyboardKeyDisabled", IDS_SETTINGS_KEYBOARD_KEY_DISABLED},
+ {"keyboardKeyExternalCommand",
+ IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_COMMAND},
+ {"keyboardKeyExternalMeta", IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_META},
+ {"keyboardKeyMeta", IDS_SETTINGS_KEYBOARD_KEY_META},
+ {"keyboardSendFunctionKeys", IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS},
+ {"keyboardEnableAutoRepeat", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_ENABLE},
+ {"keyRepeatDelay", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY},
+ {"keyRepeatDelayLong", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_LONG},
+ {"keyRepeatDelayShort", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_SHORT},
+ {"keyRepeatRate", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE},
+ {"keyRepeatRateSlow", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE_SLOW},
+ {"keyRepeatRateFast", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_FAST},
+ {"showKeyboardShortcutViewer",
+ IDS_SETTINGS_KEYBOARD_SHOW_SHORTCUT_VIEWER},
+ {"keyboardShowLanguageAndInput",
+ IDS_SETTINGS_KEYBOARD_SHOW_LANGUAGE_AND_INPUT},
+ };
+ AddLocalizedStringsBulk(html_source, keyboard_strings);
+
+ html_source->AddLocalizedString("keyboardKeySearch",
+ ui::DeviceUsesKeyboardLayout2()
+ ? IDS_SETTINGS_KEYBOARD_KEY_LAUNCHER
+ : IDS_SETTINGS_KEYBOARD_KEY_SEARCH);
+ html_source->AddLocalizedString(
+ "keyboardSendFunctionKeysDescription",
+ ui::DeviceUsesKeyboardLayout2()
+ ? IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_LAYOUT2_DESCRIPTION
+ : IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_DESCRIPTION);
+}
+
+void AddDeviceStylusStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kStylusStrings[] = {
+ {"stylusTitle", IDS_SETTINGS_STYLUS_TITLE},
+ {"stylusEnableStylusTools", IDS_SETTINGS_STYLUS_ENABLE_STYLUS_TOOLS},
+ {"stylusAutoOpenStylusTools", IDS_SETTINGS_STYLUS_AUTO_OPEN_STYLUS_TOOLS},
+ {"stylusFindMoreAppsPrimary", IDS_SETTINGS_STYLUS_FIND_MORE_APPS_PRIMARY},
+ {"stylusFindMoreAppsSecondary",
+ IDS_SETTINGS_STYLUS_FIND_MORE_APPS_SECONDARY},
+ {"stylusNoteTakingApp", IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_LABEL},
+ {"stylusNoteTakingAppEnabledOnLockScreen",
+ IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_LOCK_SCREEN_CHECKBOX},
+ {"stylusNoteTakingAppKeepsLastNoteOnLockScreen",
+ IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_KEEP_LATEST_NOTE},
+ {"stylusNoteTakingAppLockScreenSettingsHeader",
+ IDS_SETTINGS_STYLUS_LOCK_SCREEN_NOTES_TITLE},
+ {"stylusNoteTakingAppNoneAvailable",
+ IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_NONE_AVAILABLE},
+ {"stylusNoteTakingAppWaitingForAndroid",
+ IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_WAITING_FOR_ANDROID}};
+ AddLocalizedStringsBulk(html_source, kStylusStrings);
+}
+
+void AddDeviceDisplayStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kDisplayStrings[] = {
+ {"displayTitle", IDS_SETTINGS_DISPLAY_TITLE},
+ {"displayArrangementText", IDS_SETTINGS_DISPLAY_ARRANGEMENT_TEXT},
+ {"displayArrangementTitle", IDS_SETTINGS_DISPLAY_ARRANGEMENT_TITLE},
+ {"displayMirror", IDS_SETTINGS_DISPLAY_MIRROR},
+ {"displayMirrorDisplayName", IDS_SETTINGS_DISPLAY_MIRROR_DISPLAY_NAME},
+ {"displayAmbientColorTitle", IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_TITLE},
+ {"displayAmbientColorSubtitle",
+ IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_SUBTITLE},
+ {"displayNightLightLabel", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_LABEL},
+ {"displayNightLightOnAtSunset",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_ON_AT_SUNSET},
+ {"displayNightLightOffAtSunrise",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_OFF_AT_SUNRISE},
+ {"displayNightLightScheduleCustom",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_CUSTOM},
+ {"displayNightLightScheduleLabel",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_LABEL},
+ {"displayNightLightScheduleNever",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_NEVER},
+ {"displayNightLightScheduleSunsetToSunRise",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_SUNSET_TO_SUNRISE},
+ {"displayNightLightStartTime",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_START_TIME},
+ {"displayNightLightStopTime", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_STOP_TIME},
+ {"displayNightLightText", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEXT},
+ {"displayNightLightTemperatureLabel",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMPERATURE_LABEL},
+ {"displayNightLightTempSliderMaxLabel",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MAX_LABEL},
+ {"displayNightLightTempSliderMinLabel",
+ IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MIN_LABEL},
+ {"displayUnifiedDesktop", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP},
+ {"displayUnifiedDesktopOn", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP_ON},
+ {"displayUnifiedDesktopOff", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP_OFF},
+ {"displayResolutionTitle", IDS_SETTINGS_DISPLAY_RESOLUTION_TITLE},
+ {"displayResolutionText", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT},
+ {"displayResolutionTextBest", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_BEST},
+ {"displayResolutionTextNative",
+ IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_NATIVE},
+ {"displayResolutionSublabel", IDS_SETTINGS_DISPLAY_RESOLUTION_SUBLABEL},
+ {"displayResolutionMenuItem", IDS_SETTINGS_DISPLAY_RESOLUTION_MENU_ITEM},
+ {"displayResolutionInterlacedMenuItem",
+ IDS_SETTINGS_DISPLAY_RESOLUTION_INTERLACED_MENU_ITEM},
+ {"displayZoomTitle", IDS_SETTINGS_DISPLAY_ZOOM_TITLE},
+ {"displayZoomSublabel", IDS_SETTINGS_DISPLAY_ZOOM_SUBLABEL},
+ {"displayZoomValue", IDS_SETTINGS_DISPLAY_ZOOM_VALUE},
+ {"displayZoomLogicalResolutionText",
+ IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_TEXT},
+ {"displayZoomNativeLogicalResolutionNativeText",
+ IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_NATIVE_TEXT},
+ {"displayZoomLogicalResolutionDefaultText",
+ IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_DEFAULT_TEXT},
+ {"displaySizeSliderMinLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MINIMUM},
+ {"displaySizeSliderMaxLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MAXIMUM},
+ {"displayScreenTitle", IDS_SETTINGS_DISPLAY_SCREEN},
+ {"displayScreenExtended", IDS_SETTINGS_DISPLAY_SCREEN_EXTENDED},
+ {"displayScreenPrimary", IDS_SETTINGS_DISPLAY_SCREEN_PRIMARY},
+ {"displayOrientation", IDS_SETTINGS_DISPLAY_ORIENTATION},
+ {"displayOrientationStandard", IDS_SETTINGS_DISPLAY_ORIENTATION_STANDARD},
+ {"displayOrientationAutoRotate",
+ IDS_SETTINGS_DISPLAY_ORIENTATION_AUTO_ROTATE},
+ {"displayOverscanPageText", IDS_SETTINGS_DISPLAY_OVERSCAN_TEXT},
+ {"displayOverscanPageTitle", IDS_SETTINGS_DISPLAY_OVERSCAN_TITLE},
+ {"displayOverscanSubtitle", IDS_SETTINGS_DISPLAY_OVERSCAN_SUBTITLE},
+ {"displayOverscanInstructions",
+ IDS_SETTINGS_DISPLAY_OVERSCAN_INSTRUCTIONS},
+ {"displayOverscanResize", IDS_SETTINGS_DISPLAY_OVERSCAN_RESIZE},
+ {"displayOverscanPosition", IDS_SETTINGS_DISPLAY_OVERSCAN_POSITION},
+ {"displayOverscanReset", IDS_SETTINGS_DISPLAY_OVERSCAN_RESET},
+ {"displayTouchCalibrationTitle",
+ IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TITLE},
+ {"displayTouchCalibrationText",
+ IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TEXT}};
+ AddLocalizedStringsBulk(html_source, kDisplayStrings);
+
+ base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess();
+ html_source->AddBoolean("unifiedDesktopAvailable",
+ cmd.HasSwitch(::switches::kEnableUnifiedDesktop));
+
+ html_source->AddBoolean("listAllDisplayModes",
+ display::features::IsListAllDisplayModesEnabled());
+
+ html_source->AddBoolean("deviceSupportsAmbientColor",
+ ash::features::IsAllowAmbientEQEnabled());
+
+ html_source->AddBoolean(
+ "enableTouchCalibrationSetting",
+ cmd.HasSwitch(chromeos::switches::kEnableTouchCalibrationSetting));
+
+ html_source->AddBoolean("hasExternalTouchDevice",
+ display::HasExternalTouchscreenDevice());
+}
+
+void AddDeviceStorageStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kStorageStrings[] = {
+ {"storageTitle", IDS_SETTINGS_STORAGE_TITLE},
+ {"storageItemInUse", IDS_SETTINGS_STORAGE_ITEM_IN_USE},
+ {"storageItemAvailable", IDS_SETTINGS_STORAGE_ITEM_AVAILABLE},
+ {"storageItemSystem", IDS_SETTINGS_STORAGE_ITEM_SYSTEM},
+ {"storageItemMyFiles", IDS_SETTINGS_STORAGE_ITEM_MY_FILES},
+ {"storageItemBrowsingData", IDS_SETTINGS_STORAGE_ITEM_BROWSING_DATA},
+ {"storageItemApps", IDS_SETTINGS_STORAGE_ITEM_APPS},
+ {"storageItemCrostini", IDS_SETTINGS_STORAGE_ITEM_CROSTINI},
+ {"storageItemOtherUsers", IDS_SETTINGS_STORAGE_ITEM_OTHER_USERS},
+ {"storageSizeComputing", IDS_SETTINGS_STORAGE_SIZE_CALCULATING},
+ {"storageSizeUnknown", IDS_SETTINGS_STORAGE_SIZE_UNKNOWN},
+ {"storageSpaceLowMessageTitle",
+ IDS_SETTINGS_STORAGE_SPACE_LOW_MESSAGE_TITLE},
+ {"storageSpaceLowMessageLine1",
+ IDS_SETTINGS_STORAGE_SPACE_LOW_MESSAGE_LINE_1},
+ {"storageSpaceLowMessageLine2",
+ IDS_SETTINGS_STORAGE_SPACE_LOW_MESSAGE_LINE_2},
+ {"storageSpaceCriticallyLowMessageTitle",
+ IDS_SETTINGS_STORAGE_SPACE_CRITICALLY_LOW_MESSAGE_TITLE},
+ {"storageSpaceCriticallyLowMessageLine1",
+ IDS_SETTINGS_STORAGE_SPACE_CRITICALLY_LOW_MESSAGE_LINE_1},
+ {"storageSpaceCriticallyLowMessageLine2",
+ IDS_SETTINGS_STORAGE_SPACE_CRITICALLY_LOW_MESSAGE_LINE_2},
+ {"storageExternal", IDS_SETTINGS_STORAGE_EXTERNAL},
+ {"storageExternalStorageEmptyListHeader",
+ IDS_SETTINGS_STORAGE_EXTERNAL_STORAGE_EMPTY_LIST_HEADER},
+ {"storageExternalStorageListHeader",
+ IDS_SETTINGS_STORAGE_EXTERNAL_STORAGE_LIST_HEADER},
+ {"storageOverviewAriaLabel", IDS_SETTINGS_STORAGE_OVERVIEW_ARIA_LABEL}};
+ AddLocalizedStringsBulk(html_source, kStorageStrings);
+
+ html_source->AddString(
+ "storageAndroidAppsExternalDrivesNote",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_STORAGE_ANDROID_APPS_ACCESS_EXTERNAL_DRIVES_NOTE,
+ base::ASCIIToUTF16(chrome::kArcExternalStorageLearnMoreURL)));
+}
+
+void AddDevicePowerStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kPowerStrings[] = {
+ {"powerTitle", IDS_SETTINGS_POWER_TITLE},
+ {"powerSourceLabel", IDS_SETTINGS_POWER_SOURCE_LABEL},
+ {"powerSourceBattery", IDS_SETTINGS_POWER_SOURCE_BATTERY},
+ {"powerSourceAcAdapter", IDS_SETTINGS_POWER_SOURCE_AC_ADAPTER},
+ {"powerSourceLowPowerCharger",
+ IDS_SETTINGS_POWER_SOURCE_LOW_POWER_CHARGER},
+ {"calculatingPower", IDS_SETTINGS_POWER_SOURCE_CALCULATING},
+ {"powerIdleLabel", IDS_SETTINGS_POWER_IDLE_LABEL},
+ {"powerIdleWhileChargingLabel",
+ IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_LABEL},
+ {"powerIdleWhileChargingAriaLabel",
+ IDS_SETTINGS_POWER_IDLE_WHILE_CHARGING_ARIA_LABEL},
+ {"powerIdleWhileOnBatteryLabel",
+ IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_LABEL},
+ {"powerIdleWhileOnBatteryAriaLabel",
+ IDS_SETTINGS_POWER_IDLE_WHILE_ON_BATTERY_ARIA_LABEL},
+ {"powerIdleDisplayOffSleep", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF_SLEEP},
+ {"powerIdleDisplayOff", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF},
+ {"powerIdleDisplayOn", IDS_SETTINGS_POWER_IDLE_DISPLAY_ON},
+ {"powerIdleOther", IDS_SETTINGS_POWER_IDLE_OTHER},
+ {"powerLidSleepLabel", IDS_SETTINGS_POWER_LID_CLOSED_SLEEP_LABEL},
+ {"powerLidSignOutLabel", IDS_SETTINGS_POWER_LID_CLOSED_SIGN_OUT_LABEL},
+ {"powerLidShutDownLabel", IDS_SETTINGS_POWER_LID_CLOSED_SHUT_DOWN_LABEL},
+ };
+ AddLocalizedStringsBulk(html_source, kPowerStrings);
+}
+
+void AddDeviceStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kDeviceStrings[] = {
+ {"devicePageTitle", IDS_SETTINGS_DEVICE_TITLE},
+ {"scrollLabel", IDS_SETTINGS_SCROLL_LABEL},
+ {"touchPadScrollLabel", IDS_OS_SETTINGS_TOUCHPAD_REVERSE_SCROLL_LABEL},
+ };
+ AddLocalizedStringsBulk(html_source, kDeviceStrings);
+
+ AddDevicePointersStrings(html_source);
+ AddDeviceKeyboardStrings(html_source);
+ AddDeviceStylusStrings(html_source);
+ AddDeviceDisplayStrings(html_source);
+ AddDeviceStorageStrings(html_source);
+ AddDevicePowerStrings(html_source);
+}
+
+void AddFilesStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"disconnectGoogleDriveAccount", IDS_SETTINGS_DISCONNECT_GOOGLE_DRIVE},
+ {"filesPageTitle", IDS_OS_SETTINGS_FILES},
+ {"smbSharesTitle", IDS_SETTINGS_DOWNLOADS_SMB_SHARES},
+ {"smbSharesLearnMoreLabel",
+ IDS_SETTINGS_DOWNLOADS_SMB_SHARES_LEARN_MORE_LABEL},
+ {"addSmbShare", IDS_SETTINGS_DOWNLOADS_SMB_SHARES_ADD_SHARE},
+ {"smbShareAddedSuccessfulMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_SUCCESS_MESSAGE},
+ {"smbShareAddedErrorMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_ERROR_MESSAGE},
+ {"smbShareAddedAuthFailedMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_AUTH_FAILED_MESSAGE},
+ {"smbShareAddedNotFoundMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_NOT_FOUND_MESSAGE},
+ {"smbShareAddedUnsupportedDeviceMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_UNSUPPORTED_DEVICE_MESSAGE},
+ {"smbShareAddedMountExistsMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE},
+ {"smbShareAddedTooManyMountsMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_TOO_MANY_MOUNTS_MESSAGE},
+ {"smbShareAddedInvalidURLMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE},
+ {"smbShareAddedInvalidSSOURLMessage",
+ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_SSO_URL_MESSAGE},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ chromeos::smb_dialog::AddLocalizedStrings(html_source);
+
+ html_source->AddString("smbSharesLearnMoreURL",
+ GetHelpUrlWithBoard(chrome::kSmbSharesLearnMoreURL));
+}
+
+void AddEasyUnlockStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"easyUnlockSectionTitle", IDS_SETTINGS_EASY_UNLOCK_SECTION_TITLE},
+ {"easyUnlockUnlockDeviceOnly",
+ IDS_SETTINGS_EASY_UNLOCK_UNLOCK_DEVICE_ONLY},
+ {"easyUnlockUnlockDeviceAndAllowSignin",
+ IDS_SETTINGS_EASY_UNLOCK_UNLOCK_DEVICE_AND_ALLOW_SIGNIN},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddMultideviceStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"multidevicePageTitle", IDS_SETTINGS_MULTIDEVICE},
+ {"multideviceSetupButton", IDS_SETTINGS_MULTIDEVICE_SETUP_BUTTON},
+ {"multideviceVerifyButton", IDS_SETTINGS_MULTIDEVICE_VERIFY_BUTTON},
+ {"multideviceSetupItemHeading",
+ IDS_SETTINGS_MULTIDEVICE_SETUP_ITEM_HEADING},
+ {"multideviceEnabled", IDS_SETTINGS_MULTIDEVICE_ENABLED},
+ {"multideviceDisabled", IDS_SETTINGS_MULTIDEVICE_DISABLED},
+ {"multideviceSmartLockItemTitle", IDS_SETTINGS_EASY_UNLOCK_SECTION_TITLE},
+ {"multideviceInstantTetheringItemTitle",
+ IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING},
+ {"multideviceInstantTetheringItemSummary",
+ IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING_SUMMARY},
+ {"multideviceAndroidMessagesItemTitle",
+ IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES},
+ {"multideviceForgetDevice", IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE},
+ {"multideviceSmartLockOptions",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOCK},
+ {"multideviceForgetDeviceDisconnect",
+ IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_DISCONNECT},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString(
+ "multideviceForgetDeviceSummary",
+ ui::SubstituteChromeOSDeviceType(
+ IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_EXPLANATION));
+ html_source->AddString(
+ "multideviceForgetDeviceDialogMessage",
+ ui::SubstituteChromeOSDeviceType(
+ IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_MESSAGE));
+ html_source->AddString(
+ "multideviceVerificationText",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_MULTIDEVICE_VERIFICATION_TEXT,
+ base::UTF8ToUTF16(
+ chromeos::multidevice_setup::
+ GetBoardSpecificBetterTogetherSuiteLearnMoreUrl()
+ .spec())));
+ html_source->AddString(
+ "multideviceSetupSummary",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_MULTIDEVICE_SETUP_SUMMARY, ui::GetChromeOSDeviceName(),
+ base::UTF8ToUTF16(
+ chromeos::multidevice_setup::
+ GetBoardSpecificBetterTogetherSuiteLearnMoreUrl()
+ .spec())));
+ html_source->AddString(
+ "multideviceNoHostText",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_MULTIDEVICE_NO_ELIGIBLE_HOSTS,
+ base::UTF8ToUTF16(
+ chromeos::multidevice_setup::
+ GetBoardSpecificBetterTogetherSuiteLearnMoreUrl()
+ .spec())));
+ html_source->AddString(
+ "multideviceAndroidMessagesItemSummary",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES_SUMMARY,
+ ui::GetChromeOSDeviceName(),
+ base::UTF8ToUTF16(chromeos::multidevice_setup::
+ GetBoardSpecificMessagesLearnMoreUrl()
+ .spec())));
+ html_source->AddString(
+ "multideviceSmartLockItemSummary",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_MULTIDEVICE_SMART_LOCK_SUMMARY,
+ ui::GetChromeOSDeviceName(),
+ GetHelpUrlWithBoard(chrome::kEasyUnlockLearnMoreUrl)));
+
+ AddEasyUnlockStrings(html_source);
+}
+
+void AddKerberosAccountsPageStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"kerberosAccountsAddAccountLabel",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_ADD_ACCOUNT_LABEL},
+ {"kerberosAccountsRefreshNowLabel",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_REFRESH_NOW_LABEL},
+ {"kerberosAccountsSetAsActiveAccountLabel",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_SET_AS_ACTIVE_ACCOUNT_LABEL},
+ {"kerberosAccountsSignedOut", IDS_SETTINGS_KERBEROS_ACCOUNTS_SIGNED_OUT},
+ {"kerberosAccountsListHeader",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_LIST_HEADER},
+ {"kerberosAccountsRemoveAccountLabel",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_REMOVE_ACCOUNT_LABEL},
+ {"kerberosAccountsReauthenticationLabel",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_REAUTHENTICATION_LABEL},
+ {"kerberosAccountsTicketActive",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_TICKET_ACTIVE},
+ {"kerberosAccountsAccountRemovedTip",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_ACCOUNT_REMOVED_TIP},
+ {"kerberosAccountsAccountRefreshedTip",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_ACCOUNT_REFRESHED_TIP},
+ {"kerberosAccountsSignedIn", IDS_SETTINGS_KERBEROS_ACCOUNTS_SIGNED_IN},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ PrefService* local_state = g_browser_process->local_state();
+
+ // Whether new Kerberos accounts may be added.
+ html_source->AddBoolean(
+ "kerberosAddAccountsAllowed",
+ local_state->GetBoolean(prefs::kKerberosAddAccountsAllowed));
+
+ // Kerberos accounts page with "Learn more" link.
+ html_source->AddString(
+ "kerberosAccountsDescription",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_DESCRIPTION,
+ GetHelpUrlWithBoard(chrome::kKerberosAccountsLearnMoreURL)));
+}
+
+void AddKerberosAddAccountDialogStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"kerberosAccountsAdvancedConfigLabel",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_ADVANCED_CONFIG_LABEL},
+ {"kerberosAdvancedConfigTitle",
+ IDS_SETTINGS_KERBEROS_ADVANCED_CONFIG_TITLE},
+ {"kerberosAdvancedConfigDesc",
+ IDS_SETTINGS_KERBEROS_ADVANCED_CONFIG_DESC},
+ {"addKerberosAccountRememberPassword",
+ IDS_SETTINGS_ADD_KERBEROS_ACCOUNT_REMEMBER_PASSWORD},
+ {"kerberosPassword", IDS_SETTINGS_KERBEROS_PASSWORD},
+ {"kerberosUsername", IDS_SETTINGS_KERBEROS_USERNAME},
+ {"addKerberosAccountDescription",
+ IDS_SETTINGS_ADD_KERBEROS_ACCOUNT_DESCRIPTION},
+ {"kerberosErrorNetworkProblem",
+ IDS_SETTINGS_KERBEROS_ERROR_NETWORK_PROBLEM},
+ {"kerberosErrorUsernameInvalid",
+ IDS_SETTINGS_KERBEROS_ERROR_USERNAME_INVALID},
+ {"kerberosErrorUsernameUnknown",
+ IDS_SETTINGS_KERBEROS_ERROR_USERNAME_UNKNOWN},
+ {"kerberosErrorDuplicatePrincipalName",
+ IDS_SETTINGS_KERBEROS_ERROR_DUPLICATE_PRINCIPAL_NAME},
+ {"kerberosErrorContactingServer",
+ IDS_SETTINGS_KERBEROS_ERROR_CONTACTING_SERVER},
+ {"kerberosErrorPasswordInvalid",
+ IDS_SETTINGS_KERBEROS_ERROR_PASSWORD_INVALID},
+ {"kerberosErrorPasswordExpired",
+ IDS_SETTINGS_KERBEROS_ERROR_PASSWORD_EXPIRED},
+ {"kerberosErrorKdcEncType", IDS_SETTINGS_KERBEROS_ERROR_KDC_ENC_TYPE},
+ {"kerberosErrorGeneral", IDS_SETTINGS_KERBEROS_ERROR_GENERAL},
+ {"kerberosConfigErrorSectionNestedInGroup",
+ IDS_SETTINGS_KERBEROS_CONFIG_ERROR_SECTION_NESTED_IN_GROUP},
+ {"kerberosConfigErrorSectionSyntax",
+ IDS_SETTINGS_KERBEROS_CONFIG_ERROR_SECTION_SYNTAX},
+ {"kerberosConfigErrorExpectedOpeningCurlyBrace",
+ IDS_SETTINGS_KERBEROS_CONFIG_ERROR_EXPECTED_OPENING_CURLY_BRACE},
+ {"kerberosConfigErrorExtraCurlyBrace",
+ IDS_SETTINGS_KERBEROS_CONFIG_ERROR_EXTRA_CURLY_BRACE},
+ {"kerberosConfigErrorRelationSyntax",
+ IDS_SETTINGS_KERBEROS_CONFIG_ERROR_RELATION_SYNTAX_ERROR},
+ {"kerberosConfigErrorKeyNotSupported",
+ IDS_SETTINGS_KERBEROS_CONFIG_ERROR_KEY_NOT_SUPPORTED},
+ {"kerberosConfigErrorSectionNotSupported",
+ IDS_SETTINGS_KERBEROS_CONFIG_ERROR_SECTION_NOT_SUPPORTED},
+ {"kerberosConfigErrorKrb5FailedToParse",
+ IDS_SETTINGS_KERBEROS_CONFIG_ERROR_KRB5_FAILED_TO_PARSE},
+ {"addKerberosAccountRefreshButtonLabel",
+ IDS_SETTINGS_ADD_KERBEROS_ACCOUNT_REFRESH_BUTTON_LABEL},
+ {"addKerberosAccount", IDS_SETTINGS_ADD_KERBEROS_ACCOUNT},
+ {"refreshKerberosAccount", IDS_SETTINGS_REFRESH_KERBEROS_ACCOUNT},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ PrefService* local_state = g_browser_process->local_state();
+
+ // Whether the 'Remember password' checkbox is enabled.
+ html_source->AddBoolean(
+ "kerberosRememberPasswordEnabled",
+ local_state->GetBoolean(prefs::kKerberosRememberPasswordEnabled));
+
+ // Kerberos default configuration.
+ html_source->AddString(
+ "defaultKerberosConfig",
+ chromeos::KerberosCredentialsManager::GetDefaultKerberosConfig());
+}
+
+void AddLockScreenPageStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"lockScreenNotificationTitle",
+ IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_TITLE},
+ {"lockScreenNotificationHideSensitive",
+ IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE_SENSITIVE},
+ {"enableScreenlock", IDS_SETTINGS_PEOPLE_ENABLE_SCREENLOCK},
+ {"lockScreenNotificationShow",
+ IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_SHOW},
+ {"lockScreenPinOrPassword",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_OR_PASSWORD},
+ {"lockScreenSetupFingerprintButton",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SETUP_BUTTON},
+ {"lockScreenNotificationHide",
+ IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE},
+ {"lockScreenEditFingerprints",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS},
+ {"lockScreenPasswordOnly", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_ONLY},
+ {"lockScreenChangePinButton",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_CHANGE_PIN_BUTTON},
+ {"lockScreenEditFingerprintsDescription",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS_DESCRIPTION},
+ {"lockScreenNumberFingerprints",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NUM_FINGERPRINTS},
+ {"lockScreenNone", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NONE},
+ {"lockScreenFingerprintNewName",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME},
+ {"lockScreenDeleteFingerprintLabel",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_DELETE_FINGERPRINT_ARIA_LABEL},
+ {"lockScreenOptionsLock", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOCK},
+ {"lockScreenOptionsLoginLock",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOGIN_LOCK},
+ {"lockScreenSetupPinButton",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_SETUP_PIN_BUTTON},
+ {"lockScreenTitleLock", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOCK},
+ {"lockScreenTitleLoginLock",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOGIN_LOCK},
+ {"passwordPromptEnterPasswordLock",
+ IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOCK},
+ {"passwordPromptEnterPasswordLoginLock",
+ IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOGIN_LOCK},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddUsersStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"usersModifiedByOwnerLabel", IDS_SETTINGS_USERS_MODIFIED_BY_OWNER_LABEL},
+ {"guestBrowsingLabel", IDS_SETTINGS_USERS_GUEST_BROWSING_LABEL},
+ {"settingsManagedLabel", IDS_SETTINGS_USERS_MANAGED_LABEL},
+ {"showOnSigninLabel", IDS_SETTINGS_USERS_SHOW_ON_SIGNIN_LABEL},
+ {"restrictSigninLabel", IDS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL},
+ {"deviceOwnerLabel", IDS_SETTINGS_USERS_DEVICE_OWNER_LABEL},
+ {"removeUserTooltip", IDS_SETTINGS_USERS_REMOVE_USER_TOOLTIP},
+ {"addUsers", IDS_SETTINGS_USERS_ADD_USERS},
+ {"addUsersEmail", IDS_SETTINGS_USERS_ADD_USERS_EMAIL},
+ {"userExistsError", IDS_SETTINGS_USER_EXISTS_ERROR},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddGoogleAssistantStrings(content::WebUIDataSource* html_source,
+ Profile* profile) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"googleAssistantPageTitle", IDS_SETTINGS_GOOGLE_ASSISTANT},
+ {"googleAssistantEnableContext", IDS_ASSISTANT_SCREEN_CONTEXT_TITLE},
+ {"googleAssistantEnableContextDescription",
+ IDS_ASSISTANT_SCREEN_CONTEXT_DESC},
+ {"googleAssistantEnableHotword",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD},
+ {"googleAssistantEnableHotwordDescription",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_DESCRIPTION},
+ {"googleAssistantVoiceSettings",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_VOICE_SETTINGS},
+ {"googleAssistantVoiceSettingsDescription",
+ IDS_ASSISTANT_VOICE_MATCH_RECORDING},
+ {"googleAssistantVoiceSettingsRetrainButton",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_VOICE_SETTINGS_RETRAIN},
+ {"googleAssistantEnableHotwordWithoutDspDescription",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_WITHOUT_DSP_DESCRIPTION},
+ {"googleAssistantEnableHotwordWithoutDspRecommended",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_WITHOUT_DSP_RECOMMENDED},
+ {"googleAssistantEnableHotwordWithoutDspAlwaysOn",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_WITHOUT_DSP_ALWAYS_ON},
+ {"googleAssistantEnableHotwordWithoutDspOff",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_WITHOUT_DSP_OFF},
+ {"googleAssistantEnableNotification",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION},
+ {"googleAssistantEnableNotificationDescription",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION_DESCRIPTION},
+ {"googleAssistantLaunchWithMicOpen",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN},
+ {"googleAssistantLaunchWithMicOpenDescription",
+ IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN_DESCRIPTION},
+ {"googleAssistantSettings", IDS_SETTINGS_GOOGLE_ASSISTANT_SETTINGS},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddBoolean("hotwordDspAvailable",
+ chromeos::IsHotwordDspAvailable());
+ html_source->AddBoolean(
+ "voiceMatchDisabled",
+ chromeos::assistant::features::IsVoiceMatchDisabled());
+}
+
+void AddPrintingStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"printingPageTitle", IDS_SETTINGS_PRINTING},
+ {"cupsPrintersTitle", IDS_SETTINGS_PRINTING_CUPS_PRINTERS},
+ {"cupsPrintersLearnMoreLabel",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTERS_LEARN_MORE_LABEL},
+ {"addCupsPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_ADD_PRINTER},
+ {"editPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_EDIT},
+ {"removePrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_REMOVE},
+ {"setupPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SETUP_BUTTON},
+ {"setupPrinterAria",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_SETUP_BUTTON_ARIA},
+ {"savePrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SAVE_BUTTON},
+ {"savePrinterAria", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SAVE_BUTTON_ARIA},
+ {"searchLabel", IDS_SETTINGS_PRINTING_CUPS_SEARCH_LABEL},
+ {"noSearchResults", IDS_SEARCH_NO_RESULTS},
+ {"printerDetailsTitle", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_TITLE},
+ {"printerName", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_NAME},
+ {"printerModel", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_MODEL},
+ {"printerQueue", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_QUEUE},
+ {"savedPrintersTitle", IDS_SETTINGS_PRINTING_CUPS_SAVED_PRINTERS_TITLE},
+ {"savedPrintersCountMany",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTERS_SAVED_PRINTERS_COUNT_MANY},
+ {"savedPrintersCountOne",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTERS_SAVED_PRINTERS_COUNT_ONE},
+ {"savedPrintersCountNone",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTERS_SAVED_PRINTERS_COUNT_NONE},
+ {"showMorePrinters", IDS_SETTINGS_PRINTING_CUPS_SHOW_MORE},
+ {"addPrintersNearbyTitle",
+ IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTERS_NEARBY_TITLE},
+ {"addPrintersManuallyTitle",
+ IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTERS_MANUALLY_TITLE},
+ {"manufacturerAndModelDialogTitle",
+ IDS_SETTINGS_PRINTING_CUPS_SELECT_MANUFACTURER_AND_MODEL_TITLE},
+ {"nearbyPrintersListTitle",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTERS},
+ {"nearbyPrintersCountMany",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTERS_COUNT_MANY},
+ {"nearbyPrintersCountOne",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTER_COUNT_ONE},
+ {"nearbyPrintersCountNone",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTER_COUNT_NONE},
+ {"nearbyPrintersListDescription",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTERS_ADD_DETECTED_OR_NEW_PRINTER},
+ {"manufacturerAndModelAdditionalInformation",
+ IDS_SETTINGS_PRINTING_CUPS_MANUFACTURER_MODEL_ADDITIONAL_INFORMATION},
+ {"addPrinterButtonText",
+ IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTER_BUTTON_ADD},
+ {"printerDetailsAdvanced", IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED},
+ {"printerDetailsA11yLabel",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED_ACCESSIBILITY_LABEL},
+ {"printerAddress", IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED_ADDRESS},
+ {"printerProtocol", IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED_PROTOCOL},
+ {"printerURI", IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED_URI},
+ {"manuallyAddPrinterButtonText",
+ IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTER_BUTTON_MANUAL_ADD},
+ {"discoverPrintersButtonText",
+ IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTER_BUTTON_DISCOVER_PRINTERS},
+ {"printerProtocolIpp", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_IPP},
+ {"printerProtocolIpps", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_IPPS},
+ {"printerProtocolHttp", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_HTTP},
+ {"printerProtocolHttps",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_HTTPS},
+ {"printerProtocolAppSocket",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_APP_SOCKET},
+ {"printerProtocolLpd", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_LPD},
+ {"printerProtocolUsb", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_USB},
+ {"printerProtocolIppUsb",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_IPPUSB},
+ {"printerConfiguringMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_CONFIGURING_MESSAGE},
+ {"printerManufacturer", IDS_SETTINGS_PRINTING_CUPS_PRINTER_MANUFACTURER},
+ {"selectDriver", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SELECT_DRIVER},
+ {"selectDriverButtonText",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_BUTTON_SELECT_DRIVER},
+ {"selectDriverButtonAriaLabel",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_BUTTON_SELECT_DRIVER_ARIA_LABEL},
+ {"selectDriverErrorMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_INVALID_DRIVER},
+ {"printerAddedSuccessfulMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_DONE_MESSAGE},
+ {"printerEditedSuccessfulMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_EDITED_PRINTER_DONE_MESSAGE},
+ {"printerUnavailableMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_UNAVAILABLE_MESSAGE},
+ {"noPrinterNearbyMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_NO_PRINTER_NEARBY},
+ {"searchingNearbyPrinters",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_SEARCHING_NEARBY_PRINTER},
+ {"printerAddedFailedMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_ERROR_MESSAGE},
+ {"printerAddedFatalErrorMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_FATAL_ERROR_MESSAGE},
+ {"printerAddedUnreachableMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_PRINTER_UNREACHABLE_MESSAGE},
+ {"printerAddedPpdTooLargeMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_PPD_TOO_LARGE_MESSAGE},
+ {"printerAddedInvalidPpdMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_INVALID_PPD_MESSAGE},
+ {"printerAddedPpdNotFoundMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_PPD_NOT_FOUND},
+ {"printerAddedPpdUnretrievableMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_PPD_UNRETRIEVABLE},
+ {"printerAddedNativePrintersNotAllowedMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_NATIVE_PRINTERS_NOT_ALLOWED_MESSAGE},
+ {"editPrinterInvalidPrinterUpdate",
+ IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_INVALID_PRINTER_UPDATE},
+ {"requireNetworkMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_REQUIRE_INTERNET_MESSAGE},
+ {"checkNetworkMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_CHECK_CONNECTION_MESSAGE},
+ {"noInternetConnection",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_NO_INTERNET_CONNECTION},
+ {"checkNetworkAndTryAgain",
+ IDS_SETTINGS_PRINTING_CUPS_PRINTER_CONNECT_TO_NETWORK_SUBTEXT},
+ {"editPrinterDialogTitle",
+ IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_DIALOG_TITLE},
+ {"editPrinterButtonText", IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_BUTTON},
+ {"currentPpdMessage",
+ IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_CURRENT_PPD_MESSAGE},
+ {"printerEulaNotice", IDS_SETTINGS_PRINTING_CUPS_EULA_NOTICE},
+ {"ippPrinterUnreachable", IDS_SETTINGS_PRINTING_CUPS_IPP_URI_UNREACHABLE},
+ {"generalPrinterDialogError",
+ IDS_SETTINGS_PRINTING_CUPS_DIALOG_GENERAL_ERROR},
+ {"printServerButtonText", IDS_SETTINGS_PRINTING_CUPS_PRINT_SERVER},
+ {"addPrintServerTitle",
+ IDS_SETTINGS_PRINTING_CUPS_ADD_PRINT_SERVER_TITLE},
+ {"printServerAddress", IDS_SETTINGS_PRINTING_CUPS_PRINT_SERVER_ADDRESS},
+ {"printServerFoundZeroPrinters",
+ IDS_SETTINGS_PRINTING_CUPS_PRINT_SERVER_FOUND_ZERO_PRINTERS},
+ {"printServerFoundOnePrinter",
+ IDS_SETTINGS_PRINTING_CUPS_PRINT_SERVER_FOUND_ONE_PRINTER},
+ {"printServerFoundManyPrinters",
+ IDS_SETTINGS_PRINTING_CUPS_PRINT_SERVER_FOUND_MANY_PRINTERS},
+ {"printServerInvalidUrlAddress",
+ IDS_SETTINGS_PRINTING_CUPS_PRINT_SERVER_INVALID_URL_ADDRESS},
+ {"printServerConnectionError",
+ IDS_SETTINGS_PRINTING_CUPS_PRINT_SERVER_CONNECTION_ERROR},
+ {"printServerConfigurationErrorMessage",
+ IDS_SETTINGS_PRINTING_CUPS_PRINT_SERVER_REACHABLE_BUT_CANNOT_ADD},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString("printingCUPSPrintLearnMoreUrl",
+ GetHelpUrlWithBoard(chrome::kCupsPrintLearnMoreURL));
+ html_source->AddString(
+ "printingCUPSPrintPpdLearnMoreUrl",
+ GetHelpUrlWithBoard(chrome::kCupsPrintPPDLearnMoreURL));
+ html_source->AddBoolean(
+ "consumerPrintServerUiEnabled",
+ base::FeatureList::IsEnabled(::features::kPrintServerUi));
+}
+
+void AddSearchInSettingsStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"searchPrompt", IDS_SETTINGS_SEARCH_PROMPT},
+ {"searchNoResults", IDS_SEARCH_NO_RESULTS},
+ {"searchResults", IDS_SEARCH_RESULTS},
+ // TODO(dpapad): IDS_DOWNLOAD_CLEAR_SEARCH and IDS_HISTORY_CLEAR_SEARCH
+ // are identical, merge them to one and re-use here.
+ {"clearSearch", IDS_DOWNLOAD_CLEAR_SEARCH},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString(
+ "searchNoOsResultsHelp",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_SEARCH_NO_RESULTS_HELP,
+ base::ASCIIToUTF16(chrome::kOsSettingsSearchHelpURL)));
+
+ html_source->AddBoolean(
+ "newOsSettingsSearch",
+ base::FeatureList::IsEnabled(chromeos::features::kNewOsSettingsSearch));
+}
+
+void AddDateTimeStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"dateTimePageTitle", IDS_SETTINGS_DATE_TIME},
+ {"timeZone", IDS_SETTINGS_TIME_ZONE},
+ {"selectTimeZoneResolveMethod",
+ IDS_SETTINGS_SELECT_TIME_ZONE_RESOLVE_METHOD},
+ {"timeZoneGeolocation", IDS_SETTINGS_TIME_ZONE_GEOLOCATION},
+ {"timeZoneButton", IDS_SETTINGS_TIME_ZONE_BUTTON},
+ {"timeZoneSubpageTitle", IDS_SETTINGS_TIME_ZONE_SUBPAGE_TITLE},
+ {"setTimeZoneAutomaticallyDisabled",
+ IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_DISABLED},
+ {"setTimeZoneAutomaticallyOn",
+ IDS_SETTINGS_TIME_ZONE_DETECTION_SET_AUTOMATICALLY},
+ {"setTimeZoneAutomaticallyOff",
+ IDS_SETTINGS_TIME_ZONE_DETECTION_CHOOSE_FROM_LIST},
+ {"setTimeZoneAutomaticallyIpOnlyDefault",
+ IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_IP_ONLY_DEFAULT},
+ {"setTimeZoneAutomaticallyWithWiFiAccessPointsData",
+ IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_WIFI_AP},
+ {"setTimeZoneAutomaticallyWithAllLocationInfo",
+ IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_ALL_INFO},
+ {"use24HourClock", IDS_SETTINGS_USE_24_HOUR_CLOCK},
+ {"setDateTime", IDS_SETTINGS_SET_DATE_TIME},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString(
+ "timeZoneSettingsLearnMoreURL",
+ base::ASCIIToUTF16(base::StringPrintf(
+ chrome::kTimeZoneSettingsLearnMoreURL,
+ g_browser_process->GetApplicationLocale().c_str())));
+}
+
+void AddAboutStrings(content::WebUIDataSource* html_source, Profile* profile) {
+ // Top level About page strings.
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"aboutProductLogoAlt", IDS_SHORT_PRODUCT_LOGO_ALT_TEXT},
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ {"aboutReportAnIssue", IDS_SETTINGS_ABOUT_PAGE_REPORT_AN_ISSUE},
+#endif
+ {"aboutRelaunch", IDS_SETTINGS_ABOUT_PAGE_RELAUNCH},
+ {"aboutUpgradeCheckStarted", IDS_SETTINGS_ABOUT_UPGRADE_CHECK_STARTED},
+ {"aboutUpgradeRelaunch", IDS_SETTINGS_UPGRADE_SUCCESSFUL_RELAUNCH},
+ {"aboutUpgradeUpdating", IDS_SETTINGS_UPGRADE_UPDATING},
+ {"aboutUpgradeUpdatingPercent", IDS_SETTINGS_UPGRADE_UPDATING_PERCENT},
+ {"aboutGetHelpUsingChrome", IDS_SETTINGS_GET_HELP_USING_CHROME},
+ {"aboutPageTitle", IDS_SETTINGS_ABOUT_PROGRAM},
+ {"aboutProductTitle", IDS_PRODUCT_NAME},
+
+ {"aboutEndOfLifeTitle", IDS_SETTINGS_ABOUT_PAGE_END_OF_LIFE_TITLE},
+ {"aboutRelaunchAndPowerwash",
+ IDS_SETTINGS_ABOUT_PAGE_RELAUNCH_AND_POWERWASH},
+ {"aboutRollbackInProgress", IDS_SETTINGS_UPGRADE_ROLLBACK_IN_PROGRESS},
+ {"aboutRollbackSuccess", IDS_SETTINGS_UPGRADE_ROLLBACK_SUCCESS},
+ {"aboutUpgradeUpdatingChannelSwitch",
+ IDS_SETTINGS_UPGRADE_UPDATING_CHANNEL_SWITCH},
+ {"aboutUpgradeSuccessChannelSwitch",
+ IDS_SETTINGS_UPGRADE_SUCCESSFUL_CHANNEL_SWITCH},
+ {"aboutTPMFirmwareUpdateTitle",
+ IDS_SETTINGS_ABOUT_TPM_FIRMWARE_UPDATE_TITLE},
+ {"aboutTPMFirmwareUpdateDescription",
+ IDS_SETTINGS_ABOUT_TPM_FIRMWARE_UPDATE_DESCRIPTION},
+
+ // About page, channel switcher dialog.
+ {"aboutChangeChannel", IDS_SETTINGS_ABOUT_PAGE_CHANGE_CHANNEL},
+ {"aboutChangeChannelAndPowerwash",
+ IDS_SETTINGS_ABOUT_PAGE_CHANGE_CHANNEL_AND_POWERWASH},
+ {"aboutDelayedWarningMessage",
+ IDS_SETTINGS_ABOUT_PAGE_DELAYED_WARNING_MESSAGE},
+ {"aboutDelayedWarningTitle", IDS_SETTINGS_ABOUT_PAGE_DELAYED_WARNING_TITLE},
+ {"aboutPowerwashWarningMessage",
+ IDS_SETTINGS_ABOUT_PAGE_POWERWASH_WARNING_MESSAGE},
+ {"aboutPowerwashWarningTitle",
+ IDS_SETTINGS_ABOUT_PAGE_POWERWASH_WARNING_TITLE},
+ {"aboutUnstableWarningMessage",
+ IDS_SETTINGS_ABOUT_PAGE_UNSTABLE_WARNING_MESSAGE},
+ {"aboutUnstableWarningTitle",
+ IDS_SETTINGS_ABOUT_PAGE_UNSTABLE_WARNING_TITLE},
+ {"aboutChannelDialogBeta", IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_BETA},
+ {"aboutChannelDialogDev", IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_DEV},
+ {"aboutChannelDialogStable", IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_STABLE},
+
+ // About page, update warning dialog.
+ {"aboutUpdateWarningMessage",
+ IDS_SETTINGS_ABOUT_PAGE_UPDATE_WARNING_MESSAGE},
+ {"aboutUpdateWarningTitle", IDS_SETTINGS_ABOUT_PAGE_UPDATE_WARNING_TITLE},
+
+ // Detailed build information
+ {"aboutBuildDetailsTitle", IDS_OS_SETTINGS_ABOUT_PAGE_BUILD_DETAILS},
+ {"aboutChannelBeta", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_BETA},
+ {"aboutChannelCanary", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_CANARY},
+ {"aboutChannelDev", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_DEV},
+ {"aboutChannelLabel", IDS_SETTINGS_ABOUT_PAGE_CHANNEL},
+ {"aboutChannelStable", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_STABLE},
+ {"aboutCheckForUpdates", IDS_SETTINGS_ABOUT_PAGE_CHECK_FOR_UPDATES},
+ {"aboutCurrentlyOnChannel", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL},
+ {"aboutDetailedBuildInfo", IDS_SETTINGS_ABOUT_PAGE_DETAILED_BUILD_INFO},
+ {version_ui::kApplicationLabel, IDS_PRODUCT_NAME},
+ {version_ui::kPlatform, IDS_PLATFORM_LABEL},
+ {version_ui::kFirmwareVersion, IDS_VERSION_UI_FIRMWARE_VERSION},
+ {version_ui::kARC, IDS_ARC_LABEL},
+ {"aboutBuildDetailsCopyTooltipLabel",
+ IDS_OS_SETTINGS_ABOUT_PAGE_BUILD_DETAILS_COPY_TOOLTIP_LABEL},
+ {"aboutIsArcStatusTitle", IDS_OS_SETTINGS_ABOUT_ARC_STATUS_TITLE},
+ {"aboutIsDeveloperModeTitle", IDS_OS_SETTINGS_ABOUT_DEVELOPER_MODE},
+ {"isEnterpriseManagedTitle",
+ IDS_OS_SETTINGS_ABOUT_PAGE_ENTERPRISE_ENNROLLED_TITLE},
+ {"aboutOsPageTitle", IDS_SETTINGS_ABOUT_OS},
+ {"aboutGetHelpUsingChromeOs", IDS_SETTINGS_GET_HELP_USING_CHROME_OS},
+ {"aboutOsProductTitle", IDS_PRODUCT_OS_NAME},
+ {"aboutReleaseNotesOffline", IDS_SETTINGS_ABOUT_PAGE_RELEASE_NOTES},
+ {"aboutShowReleaseNotes", IDS_SETTINGS_ABOUT_PAGE_SHOW_RELEASE_NOTES},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString("aboutTPMFirmwareUpdateLearnMoreURL",
+ chrome::kTPMFirmwareUpdateLearnMoreURL);
+ html_source->AddString(
+ "aboutUpgradeUpToDate",
+ ui::SubstituteChromeOSDeviceType(IDS_SETTINGS_UPGRADE_UP_TO_DATE));
+ html_source->AddString("managementPage",
+ ManagementUI::GetManagementPageSubtitle(profile));
+}
+
+void AddResetStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"resetPageTitle", IDS_SETTINGS_RESET},
+ {"powerwashTitle", IDS_SETTINGS_FACTORY_RESET},
+ {"powerwashDialogTitle", IDS_SETTINGS_FACTORY_RESET_HEADING},
+ {"powerwashDialogButton", IDS_SETTINGS_RESTART},
+ {"powerwashButton", IDS_SETTINGS_FACTORY_RESET_BUTTON_LABEL},
+ {"powerwashDialogExplanation", IDS_SETTINGS_FACTORY_RESET_WARNING},
+ {"powerwashLearnMoreUrl", IDS_FACTORY_RESET_HELP_URL},
+ {"powerwashButtonRoleDescription",
+ IDS_SETTINGS_FACTORY_RESET_BUTTON_ROLE},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString(
+ "powerwashDescription",
+ l10n_util::GetStringFUTF16(IDS_SETTINGS_FACTORY_RESET_DESCRIPTION,
+ l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
+}
+
+void AddSearchStrings(content::WebUIDataSource* html_source, Profile* profile) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"osSearchEngineLabel", IDS_OS_SETTINGS_SEARCH_ENGINE_LABEL},
+ {"searchGoogleAssistant", IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT},
+ {"searchGoogleAssistantEnabled",
+ IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_ENABLED},
+ {"searchGoogleAssistantDisabled",
+ IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_DISABLED},
+ {"searchGoogleAssistantOn", IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_ON},
+ {"searchGoogleAssistantOff", IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_OFF},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ // NOTE: This will be false when the flag is disabled.
+ const bool is_assistant_allowed =
+ ::assistant::IsAssistantAllowedForProfile(profile) ==
+ ash::mojom::AssistantAllowedState::ALLOWED;
+ html_source->AddBoolean("isAssistantAllowed", is_assistant_allowed);
+ html_source->AddLocalizedString("osSearchPageTitle",
+ is_assistant_allowed
+ ? IDS_SETTINGS_SEARCH_AND_ASSISTANT
+ : IDS_SETTINGS_SEARCH);
+ html_source->AddString("searchExplanation",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_SEARCH_EXPLANATION,
+ base::ASCIIToUTF16(chrome::kOmniboxLearnMoreURL)));
+ html_source->AddString(
+ "osSearchEngineTooltip",
+ ui::SubstituteChromeOSDeviceType(IDS_OS_SETTINGS_SEARCH_ENGINE_TOOLTIP));
+}
+
+void AddPrivacyStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"privacyPageTitle", IDS_SETTINGS_PRIVACY},
+ {"enableLogging", IDS_SETTINGS_ENABLE_LOGGING_PREF},
+ {"enableLoggingDesc", IDS_SETTINGS_ENABLE_LOGGING_PREF_DESC},
+ {"wakeOnWifi", IDS_SETTINGS_WAKE_ON_WIFI_DESCRIPTION},
+ {"enableContentProtectionAttestation",
+ IDS_SETTINGS_ENABLE_CONTENT_PROTECTION_ATTESTATION},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString("syncAndGoogleServicesLearnMoreURL",
+ chrome::kSyncAndGoogleServicesLearnMoreURL);
+ ::settings::AddPersonalizationOptionsStrings(html_source);
+}
+
+void AddPeoplePageStrings(content::WebUIDataSource* html_source,
+ Profile* profile) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"osPeoplePageTitle", IDS_OS_SETTINGS_PEOPLE},
+ {"accountManagerSubMenuLabel",
+ IDS_SETTINGS_ACCOUNT_MANAGER_SUBMENU_LABEL},
+ {"accountManagerPageTitle", IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE},
+ {"kerberosAccountsSubMenuLabel",
+ IDS_SETTINGS_KERBEROS_ACCOUNTS_SUBMENU_LABEL},
+ {"accountManagerPageTitle", IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE},
+ {"kerberosAccountsPageTitle", IDS_SETTINGS_KERBEROS_ACCOUNTS_PAGE_TITLE},
+ {"lockScreenFingerprintTitle",
+ IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SUBPAGE_TITLE},
+ {"manageOtherPeople", IDS_SETTINGS_PEOPLE_MANAGE_OTHER_PEOPLE},
+ {"osSyncPageTitle", IDS_OS_SETTINGS_SYNC_PAGE_TITLE},
+ {"syncAndNonPersonalizedServices",
+ IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES},
+ {"syncDisconnectConfirm", IDS_SETTINGS_SYNC_DISCONNECT_CONFIRM},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ // Toggles the Chrome OS Account Manager submenu in the People section.
+ html_source->AddBoolean("isAccountManagerEnabled",
+ chromeos::IsAccountManagerAvailable(profile));
+
+ if (chromeos::features::IsSplitSyncConsentEnabled()) {
+ static constexpr webui::LocalizedString kTurnOffStrings[] = {
+ {"syncDisconnect", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF},
+ {"syncDisconnectTitle",
+ IDS_SETTINGS_TURN_OFF_SYNC_AND_SIGN_OUT_DIALOG_TITLE},
+ };
+ AddLocalizedStringsBulk(html_source, kTurnOffStrings);
+ } else {
+ static constexpr webui::LocalizedString kSignOutStrings[] = {
+ {"syncDisconnect", IDS_SETTINGS_PEOPLE_SIGN_OUT},
+ {"syncDisconnectTitle", IDS_SETTINGS_SYNC_DISCONNECT_TITLE},
+ };
+ AddLocalizedStringsBulk(html_source, kSignOutStrings);
+ }
+
+ std::string sync_dashboard_url =
+ google_util::AppendGoogleLocaleParam(
+ GURL(chrome::kSyncGoogleDashboardURL),
+ g_browser_process->GetApplicationLocale())
+ .spec();
+
+ html_source->AddString(
+ "syncDisconnectExplanation",
+ l10n_util::GetStringFUTF8(IDS_SETTINGS_SYNC_DISCONNECT_EXPLANATION,
+ base::ASCIIToUTF16(sync_dashboard_url)));
+
+ AddAccountManagerPageStrings(html_source);
+ AddKerberosAccountsPageStrings(html_source);
+ AddKerberosAddAccountDialogStrings(html_source);
+ AddLockScreenPageStrings(html_source);
+ AddFingerprintListStrings(html_source);
+ AddFingerprintStrings(html_source);
+ AddSetupFingerprintDialogStrings(html_source);
+ AddSetupPinDialogStrings(html_source);
+ AddSyncControlsStrings(html_source);
+
+ ::settings::AddSyncControlsStrings(html_source);
+ ::settings::AddSyncAccountControlStrings(html_source);
+ ::settings::AddPasswordPromptDialogStrings(html_source);
+ ::settings::AddSyncPageStrings(html_source);
+}
+
+void AddPageVisibilityStrings(content::WebUIDataSource* html_source) {
+ PrefService* local_state = g_browser_process->local_state();
+ // Toggles the Chrome OS Kerberos Accounts submenu in the People section.
+ // Note that the handler is also dependent on this pref.
+ html_source->AddBoolean("isKerberosEnabled",
+ local_state->GetBoolean(prefs::kKerberosEnabled));
+}
+
+} // namespace
+
+OsSettingsLocalizedStringsProvider::OsSettingsLocalizedStringsProvider(
+ Profile* profile,
+ local_search_service::mojom::LocalSearchService* local_search_service) {
+ local_search_service->GetIndex(
+ local_search_service::mojom::LocalSearchService::IndexId::CROS_SETTINGS,
+ index_remote_.BindNewPipeAndPassReceiver());
+
+ // Add per-page string providers.
+ // TODO(khorimoto): Add providers for the remaining pages.
+ per_page_providers_.push_back(
+ std::make_unique<InternetStringsProvider>(profile, /*delegate=*/this));
+}
+
+OsSettingsLocalizedStringsProvider::~OsSettingsLocalizedStringsProvider() =
+ default;
+
+void OsSettingsLocalizedStringsProvider::AddOsLocalizedStrings(
+ content::WebUIDataSource* html_source,
+ Profile* profile) {
+ for (const auto& per_page_provider : per_page_providers_)
+ per_page_provider->AddUiStrings(html_source);
+
+ // TODO(khorimoto): Migrate these to OsSettingsPerPageStringsProvider
+ // instances.
+ AddAboutStrings(html_source, profile);
+ AddA11yStrings(html_source);
+ AddAndroidAppStrings(html_source);
+ AddAppManagementStrings(html_source);
+ AddAppsStrings(html_source);
+ AddBluetoothStrings(html_source);
+ AddChromeOSUserStrings(html_source, profile);
+ AddCommonStrings(html_source, profile);
+ AddCrostiniStrings(html_source, profile);
+ AddDateTimeStrings(html_source);
+ AddDeviceStrings(html_source);
+ AddFilesStrings(html_source);
+ AddGoogleAssistantStrings(html_source, profile);
+ AddLanguagesStrings(html_source);
+ AddMultideviceStrings(html_source);
+ AddParentalControlStrings(html_source, profile);
+ AddPageVisibilityStrings(html_source);
+ AddPeoplePageStrings(html_source, profile);
+ AddPersonalizationStrings(html_source);
+ AddPluginVmStrings(html_source, profile);
+ AddPrintingStrings(html_source);
+ AddPrivacyStrings(html_source);
+ AddResetStrings(html_source);
+ AddSearchInSettingsStrings(html_source);
+ AddSearchStrings(html_source, profile);
+ AddUsersStrings(html_source);
+
+ policy_indicator::AddLocalizedStrings(html_source);
+
+ html_source->UseStringsJs();
+}
+
+const SearchConcept*
+OsSettingsLocalizedStringsProvider::GetCanonicalTagMetadata(
+ int canonical_message_id) const {
+ const auto it = canonical_id_to_metadata_map_.find(canonical_message_id);
+ if (it == canonical_id_to_metadata_map_.end())
+ return nullptr;
+ return it->second;
+}
+
+void OsSettingsLocalizedStringsProvider::Shutdown() {
+ index_remote_.reset();
+}
+
+void OsSettingsLocalizedStringsProvider::AddSearchTags(
+ const std::vector<SearchConcept>& tags_group) {
+ index_remote_->AddOrUpdate(ConceptVectorToDataPtrVector(tags_group),
+ /*callback=*/base::DoNothing());
+
+ // Add each concept to the map. Note that it is safe to take the address of
+ // each concept because all concepts are allocated via static
+ // base::NoDestructor objects in the Get*SearchConcepts() helper functions.
+ for (const auto& concept : tags_group)
+ canonical_id_to_metadata_map_[concept.canonical_message_id] = &concept;
+}
+
+void OsSettingsLocalizedStringsProvider::RemoveSearchTags(
+ const std::vector<SearchConcept>& tags_group) {
+ std::vector<std::string> ids;
+ for (const auto& concept : tags_group) {
+ canonical_id_to_metadata_map_.erase(concept.canonical_message_id);
+ ids.push_back(base::NumberToString(concept.canonical_message_id));
+ }
+
+ index_remote_->Delete(ids, /*callback=*/base::DoNothing());
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h
new file mode 100644
index 00000000000..c0d8c5adcd2
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h
@@ -0,0 +1,91 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.h"
+#include "chrome/services/local_search_service/public/mojom/local_search_service.mojom.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+class Profile;
+
+namespace content {
+class WebUIDataSource;
+} // namespace content
+
+namespace chromeos {
+namespace settings {
+
+struct SearchConcept;
+
+// Provides two types of localized strings for OS settings:
+//
+// (1) UI strings: Strings displayed in the normal settings UI. This contains
+// strings such as headers, labels, instructional notes, etc. These strings
+// are added directly to the settings app's WebUIDataSource before the app
+// starts up via the static AddOsLocalizedStrings() function and are
+// accessible within settings via loadTimeData.
+//
+// (2) Search tags: Strings used as potential matches for user search queries
+// within settings. These strings don't appear in the normal UI; instead,
+// they specify actions which can be taken in settings. When a user types a
+// search query in settings, we compare the query against these strings to
+// look for potential matches. For each potential search result, there is a
+// "canonical" tag which represents a common phrase, and zero or more
+// alternate phrases (e.g., canonical: "Display settings", alternate:
+// "Monitor settings").
+//
+// Since some of the settings sections may be unavailable (e.g., we don't
+// show Bluetooth settings unless the device has Bluetooth capabilities),
+// these strings are added/removed according to the Add/Remove*SearchTags()
+// instance functions.
+class OsSettingsLocalizedStringsProvider
+ : public KeyedService,
+ public OsSettingsPerPageStringsProvider::Delegate {
+ public:
+ OsSettingsLocalizedStringsProvider(
+ Profile* profile,
+ local_search_service::mojom::LocalSearchService* local_search_service);
+ OsSettingsLocalizedStringsProvider(
+ const OsSettingsLocalizedStringsProvider& other) = delete;
+ OsSettingsLocalizedStringsProvider& operator=(
+ const OsSettingsLocalizedStringsProvider& other) = delete;
+ ~OsSettingsLocalizedStringsProvider() override;
+
+ // Adds the strings needed by the OS settings page to |html_source|
+ // This function causes |html_source| to expose a strings.js file from its
+ // source which contains a mapping from string's name to its translated value.
+ void AddOsLocalizedStrings(content::WebUIDataSource* html_source,
+ Profile* profile);
+
+ // Returns the tag metadata associated with |canonical_message_id|, which must
+ // be one of the canonical IDS_SETTINGS_TAG_* identifiers used for a search
+ // tag. If no metadata is available or if |canonical_message_id| instead
+ // refers to an alternate tag's ID, null is returned.
+ const SearchConcept* GetCanonicalTagMetadata(int canonical_message_id) const;
+
+ private:
+ // KeyedService:
+ void Shutdown() override;
+
+ // OsSettingsPerPageStringsProvider::Delegate:
+ void AddSearchTags(const std::vector<SearchConcept>& tags_group) override;
+ void RemoveSearchTags(const std::vector<SearchConcept>& tags_group) override;
+
+ std::vector<std::unique_ptr<OsSettingsPerPageStringsProvider>>
+ per_page_providers_;
+ mojo::Remote<local_search_service::mojom::Index> index_remote_;
+ std::unordered_map<int, const SearchConcept*> canonical_id_to_metadata_map_;
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.cc
new file mode 100644
index 00000000000..8375790e5ca
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.cc
@@ -0,0 +1,66 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.h"
+
+#include "chrome/browser/local_search_service/local_search_service_proxy.h"
+#include "chrome/browser/local_search_service/local_search_service_proxy_factory.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace chromeos {
+namespace settings {
+
+// static
+OsSettingsLocalizedStringsProvider*
+OsSettingsLocalizedStringsProviderFactory::GetForProfile(Profile* profile) {
+ return static_cast<OsSettingsLocalizedStringsProvider*>(
+ OsSettingsLocalizedStringsProviderFactory::GetInstance()
+ ->GetServiceForBrowserContext(profile, /*create=*/true));
+}
+
+// static
+OsSettingsLocalizedStringsProviderFactory*
+OsSettingsLocalizedStringsProviderFactory::GetInstance() {
+ return base::Singleton<OsSettingsLocalizedStringsProviderFactory>::get();
+}
+
+OsSettingsLocalizedStringsProviderFactory::
+ OsSettingsLocalizedStringsProviderFactory()
+ : BrowserContextKeyedServiceFactory(
+ "OsSettingsLocalizedStringsProvider",
+ BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(
+ local_search_service::LocalSearchServiceProxyFactory::GetInstance());
+}
+
+OsSettingsLocalizedStringsProviderFactory::
+ ~OsSettingsLocalizedStringsProviderFactory() = default;
+
+KeyedService*
+OsSettingsLocalizedStringsProviderFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ Profile* profile = Profile::FromBrowserContext(context);
+ return new OsSettingsLocalizedStringsProvider(
+ profile,
+ local_search_service::LocalSearchServiceProxyFactory::GetForProfile(
+ Profile::FromBrowserContext(profile))
+ ->GetLocalSearchService());
+}
+
+bool OsSettingsLocalizedStringsProviderFactory::ServiceIsNULLWhileTesting()
+ const {
+ return true;
+}
+
+content::BrowserContext*
+OsSettingsLocalizedStringsProviderFactory::GetBrowserContextToUse(
+ content::BrowserContext* context) const {
+ return chrome::GetBrowserContextOwnInstanceInIncognito(context);
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.h
new file mode 100644
index 00000000000..d1b7df331e2
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.h
@@ -0,0 +1,47 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_LOCALIZED_STRINGS_PROVIDER_FACTORY_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_LOCALIZED_STRINGS_PROVIDER_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class Profile;
+
+namespace chromeos {
+namespace settings {
+
+class OsSettingsLocalizedStringsProvider;
+
+class OsSettingsLocalizedStringsProviderFactory
+ : public BrowserContextKeyedServiceFactory {
+ public:
+ static OsSettingsLocalizedStringsProvider* GetForProfile(Profile* profile);
+ static OsSettingsLocalizedStringsProviderFactory* GetInstance();
+
+ private:
+ friend struct base::DefaultSingletonTraits<
+ OsSettingsLocalizedStringsProviderFactory>;
+
+ OsSettingsLocalizedStringsProviderFactory();
+ ~OsSettingsLocalizedStringsProviderFactory() override;
+
+ OsSettingsLocalizedStringsProviderFactory(
+ const OsSettingsLocalizedStringsProviderFactory&) = delete;
+ OsSettingsLocalizedStringsProviderFactory& operator=(
+ const OsSettingsLocalizedStringsProviderFactory&) = delete;
+
+ // BrowserContextKeyedServiceFactory:
+ KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const override;
+ bool ServiceIsNULLWhileTesting() const override;
+ content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const override;
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_LOCALIZED_STRINGS_PROVIDER_FACTORY_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_unittest.cc
new file mode 100644
index 00000000000..c8eb26b6746
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_unittest.cc
@@ -0,0 +1,104 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h"
+
+#include "base/run_loop.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_concept.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/generated_resources.h"
+#include "chrome/services/local_search_service/local_search_service_impl.h"
+#include "chrome/services/local_search_service/public/mojom/local_search_service.mojom-test-utils.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/network/network_state_test_helper.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
+#include "content/public/test/browser_task_environment.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
+
+namespace chromeos {
+namespace settings {
+
+class OsSettingsLocalizedStringsProviderTest : public testing::Test {
+ protected:
+ OsSettingsLocalizedStringsProviderTest()
+ : profile_manager_(TestingBrowserProcess::GetGlobal()) {}
+ ~OsSettingsLocalizedStringsProviderTest() override = default;
+
+ // testing::Test:
+ void SetUp() override {
+ ASSERT_TRUE(profile_manager_.SetUp());
+
+ provider_ = std::make_unique<OsSettingsLocalizedStringsProvider>(
+ profile_manager_.CreateTestingProfile("TestingProfile"),
+ &local_search_service_);
+
+ local_search_service_.GetIndex(
+ local_search_service::mojom::LocalSearchService::IndexId::CROS_SETTINGS,
+ index_remote_.BindNewPipeAndPassReceiver());
+
+ // Allow asynchronous networking code to complete (networking functionality
+ // is tested below).
+ base::RunLoop().RunUntilIdle();
+ }
+
+ content::BrowserTaskEnvironment task_environment_;
+ TestingProfileManager profile_manager_;
+ chromeos::network_config::CrosNetworkConfigTestHelper network_config_helper_;
+ mojo::Remote<local_search_service::mojom::Index> index_remote_;
+ local_search_service::LocalSearchServiceImpl local_search_service_;
+ std::unique_ptr<OsSettingsLocalizedStringsProvider> provider_;
+};
+
+// To prevent this from becoming a change-detector test, this test simply
+// verifies that when the provider starts up, it adds *some* strings without
+// checking the exact number. It also checks one specific canonical tag.
+TEST_F(OsSettingsLocalizedStringsProviderTest, WifiTags) {
+ uint64_t initial_num_items = 0;
+ local_search_service::mojom::IndexAsyncWaiter(index_remote_.get())
+ .GetSize(&initial_num_items);
+ EXPECT_GT(initial_num_items, 0u);
+
+ const SearchConcept* network_settings_concept =
+ provider_->GetCanonicalTagMetadata(IDS_SETTINGS_TAG_NETWORK_SETTINGS);
+ ASSERT_TRUE(network_settings_concept);
+ EXPECT_EQ(chrome::kNetworksSubPage,
+ network_settings_concept->url_path_with_parameters);
+ EXPECT_EQ(mojom::SearchResultIcon::kWifi, network_settings_concept->icon);
+
+ // Ethernet is not present by default, so no Ethernet concepts have yet been
+ // added.
+ const SearchConcept* ethernet_settings_concept =
+ provider_->GetCanonicalTagMetadata(IDS_SETTINGS_TAG_ETHERNET_SETTINGS);
+ ASSERT_FALSE(ethernet_settings_concept);
+
+ // Add Ethernet and let asynchronous handlers run. This should cause Ethernet
+ // tags to be added.
+ network_config_helper_.network_state_helper().device_test()->AddDevice(
+ "/device/stub_eth_device", shill::kTypeEthernet, "stub_eth_device");
+ base::RunLoop().RunUntilIdle();
+
+ uint64_t num_items_after_adding_ethernet = 0;
+ local_search_service::mojom::IndexAsyncWaiter(index_remote_.get())
+ .GetSize(&num_items_after_adding_ethernet);
+ EXPECT_GT(num_items_after_adding_ethernet, initial_num_items);
+
+ ethernet_settings_concept =
+ provider_->GetCanonicalTagMetadata(IDS_SETTINGS_TAG_ETHERNET_SETTINGS);
+ ASSERT_TRUE(ethernet_settings_concept);
+ EXPECT_EQ(chrome::kEthernetSettingsSubPage,
+ ethernet_settings_concept->url_path_with_parameters);
+ EXPECT_EQ(mojom::SearchResultIcon::kEthernet,
+ ethernet_settings_concept->icon);
+}
+
+// Note that other tests do not need to be added for different group of tags,
+// since these tests would only be verifying the contents of
+// os_settings_localized_strings_provider.cc.
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.cc
new file mode 100644
index 00000000000..26ac31b8cf6
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.cc
@@ -0,0 +1,32 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.h"
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/system/sys_info.h"
+
+namespace chromeos {
+namespace settings {
+
+// static
+base::string16 OsSettingsPerPageStringsProvider::GetHelpUrlWithBoard(
+ const std::string& original_url) {
+ return base::ASCIIToUTF16(original_url +
+ "&b=" + base::SysInfo::GetLsbReleaseBoard());
+}
+
+OsSettingsPerPageStringsProvider::~OsSettingsPerPageStringsProvider() = default;
+
+OsSettingsPerPageStringsProvider::OsSettingsPerPageStringsProvider(
+ Profile* profile,
+ Delegate* delegate)
+ : profile_(profile), delegate_(delegate) {
+ DCHECK(profile);
+ DCHECK(delegate);
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.h
new file mode 100644
index 00000000000..c2a6771c85b
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_per_page_strings_provider.h
@@ -0,0 +1,73 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_PER_PAGE_STRINGS_PROVIDER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_PER_PAGE_STRINGS_PROVIDER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_concept.h"
+
+class Profile;
+
+namespace content {
+class WebUIDataSource;
+} // namespace content
+
+namespace chromeos {
+namespace settings {
+
+// Provides strings for an individual page in OS settings (i.e., each subpage is
+// expected to have its own implementation. Responsible for two types of
+// strings:
+//
+// (1) UI strings: Strings (e.g., headers, labels) displayed in the settings UI.
+// Added to a WebUIDataSource via the pure virtual AddUiStrings() function.
+//
+// (2) Search tags: Strings used as potential matches for user search queries
+// within settings. Added/removed via the {Add|Remove}SearchTagsGroup
+// delegate functions. Tags which are always searchable should be added in
+// the class' constructor; however, tags which apply to content which is
+// dynamically shown/hidden should be added when that content is visible and
+// removed when the content is no longer visible.
+class OsSettingsPerPageStringsProvider {
+ public:
+ class Delegate {
+ public:
+ ~Delegate() = default;
+ virtual void AddSearchTags(
+ const std::vector<SearchConcept>& tags_group) = 0;
+ virtual void RemoveSearchTags(
+ const std::vector<SearchConcept>& tags_group) = 0;
+ };
+
+ virtual ~OsSettingsPerPageStringsProvider();
+
+ OsSettingsPerPageStringsProvider(
+ const OsSettingsPerPageStringsProvider& other) = delete;
+ OsSettingsPerPageStringsProvider& operator=(
+ const OsSettingsPerPageStringsProvider& other) = delete;
+
+ // Adds strings to be displayed in the UI via loadTimeData.
+ virtual void AddUiStrings(content::WebUIDataSource* html_source) const = 0;
+
+ protected:
+ static base::string16 GetHelpUrlWithBoard(const std::string& original_url);
+
+ OsSettingsPerPageStringsProvider(Profile* profile, Delegate* delegate);
+
+ Profile* profile() { return profile_; }
+ Delegate* delegate() { return delegate_; }
+
+ private:
+ Profile* profile_;
+ Delegate* delegate_;
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_PER_PAGE_STRINGS_PROVIDER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
index a91606bde11..dd4edc8807a 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
@@ -11,14 +11,32 @@
#include <utility>
#include <vector>
+#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/network_config_service.h"
#include "ash/public/cpp/resources/grit/ash_public_unscaled_resources.h"
+#include "ash/public/cpp/stylus_utils.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/feature_list.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_functions.h"
#include "build/build_config.h"
-#include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/chromeos/account_manager/account_manager_util.h"
+#include "chrome/browser/chromeos/arc/arc_util.h"
+#include "chrome/browser/chromeos/crostini/crostini_features.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
+#include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h"
+#include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h"
+#include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/webui/app_management/app_management.mojom.h"
#include "chrome/browser/ui/webui/app_management/app_management_page_handler.h"
+#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h"
#include "chrome/browser/ui/webui/chromeos/sync/os_sync_handler.h"
#include "chrome/browser/ui/webui/managed_ui_handler.h"
#include "chrome/browser/ui/webui/metrics_handler.h"
@@ -26,7 +44,33 @@
#include "chrome/browser/ui/webui/settings/about_handler.h"
#include "chrome/browser/ui/webui/settings/accessibility_main_handler.h"
#include "chrome/browser/ui/webui/settings/browser_lifetime_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/crostini_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/date_time_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/internet_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.h"
#include "chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/pref_names.h"
+#include "chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_handler.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.h"
#include "chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.h"
#include "chrome/browser/ui/webui/settings/downloads_handler.h"
#include "chrome/browser/ui/webui/settings/extension_control_handler.h"
@@ -40,7 +84,9 @@
#include "chrome/browser/ui/webui/settings/settings_cookies_view_handler.h"
#include "chrome/browser/ui/webui/settings/settings_localized_strings_provider.h"
#include "chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.h"
-#include "chrome/browser/ui/webui/settings/settings_ui.h"
+#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/settings/tts_handler.h"
+#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/browser/web_applications/system_web_app_manager.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/webui_url_constants.h"
@@ -48,17 +94,36 @@
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/os_settings_resources.h"
#include "chrome/grit/os_settings_resources_map.h"
+#include "chromeos/components/account_manager/account_manager.h"
+#include "chromeos/components/account_manager/account_manager_factory.h"
+#include "chromeos/components/web_applications/manifest_request_filter.h"
#include "chromeos/constants/chromeos_features.h"
+#include "chromeos/constants/chromeos_pref_names.h"
+#include "chromeos/login/auth/password_visibility_utils.h"
+#include "chromeos/services/multidevice_setup/public/cpp/prefs.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
#include "components/password_manager/core/common/password_manager_features.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "media/base/media_switches.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "ui/base/webui/web_ui_util.h"
+#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
+#include "ui/resources/grit/webui_resources.h"
namespace chromeos {
namespace settings {
+// static
+void OSSettingsUI::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterBooleanPref(prefs::kSyncOsWallpaper, false);
+}
+
OSSettingsUI::OSSettingsUI(content::WebUI* web_ui)
: ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true),
+ time_when_opened_(base::TimeTicks::Now()),
webui_load_timer_(web_ui->GetWebContents(),
"ChromeOS.Settings.LoadDocumentTime",
"ChromeOS.Settings.LoadCompletedTime") {
@@ -66,7 +131,7 @@ OSSettingsUI::OSSettingsUI(content::WebUI* web_ui)
content::WebUIDataSource* html_source =
content::WebUIDataSource::Create(chrome::kChromeUIOSSettingsHost);
- ::settings::SettingsUI::InitOSWebUIHandlers(profile, web_ui, html_source);
+ InitOSWebUIHandlers(html_source);
// This handler is for chrome://os-settings.
html_source->AddBoolean("isOSSettings", true);
@@ -78,6 +143,9 @@ OSSettingsUI::OSSettingsUI(content::WebUI* web_ui)
html_source->AddBoolean(
"showParentalControls",
chromeos::settings::ShouldShowParentalControls(profile));
+ html_source->AddBoolean(
+ "syncSetupFriendlySettings",
+ base::FeatureList::IsEnabled(::features::kSyncSetupFriendlySettings));
AddSettingsPageUIHandler(
std::make_unique<::settings::AccessibilityMainHandler>());
@@ -103,19 +171,17 @@ OSSettingsUI::OSSettingsUI(content::WebUI* web_ui)
std::make_unique<::settings::ProtocolHandlersHandler>());
AddSettingsPageUIHandler(
std::make_unique<::settings::SearchEnginesHandler>(profile));
- AddSettingsPageUIHandler(
- std::make_unique<chromeos::settings::WallpaperHandler>(web_ui));
html_source->AddBoolean("showAppManagement", base::FeatureList::IsEnabled(
::features::kAppManagement));
html_source->AddBoolean("splitSettingsSyncEnabled",
chromeos::features::IsSplitSettingsSyncEnabled());
+ html_source->AddBoolean("splitSyncConsent",
+ chromeos::features::IsSplitSyncConsentEnabled());
-#if defined(OS_CHROMEOS)
html_source->AddBoolean(
"isSupportedArcVersion",
AppManagementPageHandler::IsCurrentArcVersionSupported(profile));
-#endif // OS_CHROMEOS
AddSettingsPageUIHandler(
base::WrapUnique(::settings::AboutHandler::Create(html_source, profile)));
@@ -126,7 +192,6 @@ OSSettingsUI::OSSettingsUI(content::WebUI* web_ui)
web_ui->AddMessageHandler(std::make_unique<MetricsHandler>());
// Add the System Web App resources for Settings.
- // TODO(jamescook|calamity): Migrate to chromeos::settings::OSSettingsUI.
if (web_app::SystemWebAppManager::IsEnabled()) {
html_source->AddResourcePath("icon-192.png", IDR_SETTINGS_LOGO_192);
html_source->AddResourcePath("pwa.html", IDR_PWA_HTML);
@@ -151,18 +216,37 @@ OSSettingsUI::OSSettingsUI(content::WebUI* web_ui)
#endif
html_source->AddResourcePath("app-management/app_management.mojom-lite.js",
- IDR_APP_MANAGEMENT_MOJO_LITE_JS);
- html_source->AddResourcePath("app-management/types.mojom-lite.js",
- IDR_APP_MANAGEMENT_TYPES_MOJO_LITE_JS);
- html_source->AddResourcePath("app-management/bitmap.mojom-lite.js",
- IDR_APP_MANAGEMENT_BITMAP_MOJO_LITE_JS);
- html_source->AddResourcePath("app-management/image.mojom-lite.js",
- IDR_APP_MANAGEMENT_IMAGE_MOJO_LITE_JS);
- html_source->AddResourcePath("app-management/image_info.mojom-lite.js",
- IDR_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS);
-
- ::settings::AddLocalizedStrings(html_source, profile,
- web_ui->GetWebContents());
+ IDR_OS_SETTINGS_APP_MANAGEMENT_MOJO_LITE_JS);
+ html_source->AddResourcePath(
+ "app-management/types.mojom-lite.js",
+ IDR_OS_SETTINGS_APP_MANAGEMENT_TYPES_MOJO_LITE_JS);
+ html_source->AddResourcePath(
+ "app-management/bitmap.mojom-lite.js",
+ IDR_OS_SETTINGS_APP_MANAGEMENT_BITMAP_MOJO_LITE_JS);
+ html_source->AddResourcePath(
+ "app-management/file_path.mojom-lite.js",
+ IDR_OS_SETTINGS_APP_MANAGEMENT_FILE_PATH_MOJO_LITE_JS);
+ html_source->AddResourcePath(
+ "app-management/image.mojom-lite.js",
+ IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_MOJO_LITE_JS);
+ html_source->AddResourcePath(
+ "app-management/image_info.mojom-lite.js",
+ IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS);
+
+ html_source->AddResourcePath(
+ "search/user_action_recorder.mojom-lite.js",
+ IDR_OS_SETTINGS_USER_ACTION_RECORDER_MOJOM_LITE_JS);
+ html_source->AddResourcePath(
+ "search/search_result_icon.mojom-lite.js",
+ IDR_OS_SETTINGS_SEARCH_RESULT_ICON_MOJOM_LITE_JS);
+ html_source->AddResourcePath("search/search.mojom-lite.js",
+ IDR_OS_SETTINGS_SEARCH_MOJOM_LITE_JS);
+
+ // AddOsLocalizedStrings must be added after AddBrowserLocalizedStrings
+ // as repeated keys used by the OS strings should override the same keys
+ // that may be used in the Browser string provider.
+ OsSettingsLocalizedStringsProviderFactory::GetForProfile(profile)
+ ->AddOsLocalizedStrings(html_source, profile);
auto plural_string_handler = std::make_unique<PluralStringHandler>();
plural_string_handler->AddLocalizedString("profileLabel",
@@ -173,16 +257,210 @@ OSSettingsUI::OSSettingsUI(content::WebUI* web_ui)
content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
html_source);
+}
- AddHandlerToRegistry(base::BindRepeating(&OSSettingsUI::BindCrosNetworkConfig,
- base::Unretained(this)));
-
- AddHandlerToRegistry(
- base::BindRepeating(&OSSettingsUI::BindAppManagementPageHandlerFactory,
- base::Unretained(this)));
+OSSettingsUI::~OSSettingsUI() {
+ // Note: OSSettingsUI lifetime is tied to the lifetime of the browser window.
+ base::UmaHistogramCustomTimes("ChromeOS.Settings.WindowOpenDuration",
+ base::TimeTicks::Now() - time_when_opened_,
+ /*min=*/base::TimeDelta::FromMicroseconds(500),
+ /*max=*/base::TimeDelta::FromHours(1),
+ /*buckets=*/50);
}
-OSSettingsUI::~OSSettingsUI() = default;
+void OSSettingsUI::InitOSWebUIHandlers(content::WebUIDataSource* html_source) {
+ Profile* profile = Profile::FromWebUI(web_ui());
+
+ // TODO(jamescook): Sort out how account management is split between Chrome OS
+ // and browser settings.
+ if (chromeos::IsAccountManagerAvailable(profile)) {
+ chromeos::AccountManagerFactory* factory =
+ g_browser_process->platform_part()->GetAccountManagerFactory();
+ chromeos::AccountManager* account_manager =
+ factory->GetAccountManager(profile->GetPath().value());
+ DCHECK(account_manager);
+
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::AccountManagerUIHandler>(
+ account_manager, IdentityManagerFactory::GetForProfile(profile)));
+ html_source->AddBoolean(
+ "secondaryGoogleAccountSigninAllowed",
+ profile->GetPrefs()->GetBoolean(
+ chromeos::prefs::kSecondaryGoogleAccountSigninAllowed));
+ html_source->AddBoolean("isEduCoexistenceEnabled",
+ features::IsEduCoexistenceEnabled());
+ }
+
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::ChangePictureHandler>());
+
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::AccessibilityHandler>(profile));
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::AndroidAppsHandler>(profile));
+ if (crostini::CrostiniFeatures::Get()->IsUIAllowed(profile,
+ /*check_policy=*/false)) {
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::CrostiniHandler>(profile));
+ }
+ web_ui()->AddMessageHandler(
+ chromeos::settings::CupsPrintersHandler::Create(web_ui()));
+ web_ui()->AddMessageHandler(base::WrapUnique(
+ chromeos::settings::DateTimeHandler::Create(html_source)));
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::FingerprintHandler>(profile));
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::GoogleAssistantHandler>(profile));
+
+ std::unique_ptr<chromeos::settings::KerberosAccountsHandler>
+ kerberos_accounts_handler =
+ chromeos::settings::KerberosAccountsHandler::CreateIfKerberosEnabled(
+ profile);
+ if (kerberos_accounts_handler) {
+ // Note that the UI is enabled only if Kerberos is enabled.
+ web_ui()->AddMessageHandler(std::move(kerberos_accounts_handler));
+ }
+
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::KeyboardHandler>());
+
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::WallpaperHandler>(web_ui()));
+
+ // If |!allow_plugin_vm| we still want to |show_plugin_vm| if the VM image is
+ // on disk, so that users are still able to delete the image at will.
+ const bool allow_plugin_vm = plugin_vm::IsPluginVmAllowedForProfile(profile);
+ const bool show_plugin_vm =
+ allow_plugin_vm ||
+ profile->GetPrefs()->GetBoolean(plugin_vm::prefs::kPluginVmImageExists);
+
+ if (show_plugin_vm) {
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::PluginVmHandler>(profile));
+ }
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::PointerHandler>());
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::QuickUnlockHandler>());
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::StorageHandler>(profile,
+ html_source));
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::StylusHandler>());
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::InternetHandler>(profile));
+ web_ui()->AddMessageHandler(std::make_unique<::settings::TtsHandler>());
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::smb_dialog::SmbHandler>(profile,
+ base::DoNothing()));
+
+ if (!profile->IsGuestSession()) {
+ chromeos::android_sms::AndroidSmsService* android_sms_service =
+ chromeos::android_sms::AndroidSmsServiceFactory::GetForBrowserContext(
+ profile);
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::MultideviceHandler>(
+ profile->GetPrefs(),
+ chromeos::multidevice_setup::MultiDeviceSetupClientFactory::
+ GetForProfile(profile),
+ android_sms_service
+ ? android_sms_service->android_sms_pairing_state_tracker()
+ : nullptr,
+ android_sms_service ? android_sms_service->android_sms_app_manager()
+ : nullptr));
+ if (chromeos::settings::ShouldShowParentalControls(profile)) {
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::ParentalControlsHandler>(
+ profile));
+ }
+
+ if (chromeos::features::IsAmbientModeEnabled()) {
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::AmbientModeHandler>());
+ }
+ }
+
+ html_source->AddBoolean(
+ "privacySettingsRedesignEnabled",
+ base::FeatureList::IsEnabled(::features::kPrivacySettingsRedesign));
+
+ html_source->AddBoolean(
+ "multideviceAllowedByPolicy",
+ chromeos::multidevice_setup::AreAnyMultiDeviceFeaturesAllowed(
+ profile->GetPrefs()));
+ html_source->AddBoolean(
+ "quickUnlockEnabled",
+ chromeos::quick_unlock::IsPinEnabled(profile->GetPrefs()));
+ html_source->AddBoolean(
+ "quickUnlockDisabledByPolicy",
+ chromeos::quick_unlock::IsPinDisabledByPolicy(profile->GetPrefs()));
+ html_source->AddBoolean(
+ "userCannotManuallyEnterPassword",
+ !chromeos::password_visibility::AccountHasUserFacingPassword(
+ chromeos::ProfileHelper::Get()
+ ->GetUserByProfile(profile)
+ ->GetAccountId()));
+ const bool fingerprint_unlock_enabled =
+ chromeos::quick_unlock::IsFingerprintEnabled(profile);
+ html_source->AddBoolean("fingerprintUnlockEnabled",
+ fingerprint_unlock_enabled);
+ if (fingerprint_unlock_enabled) {
+ html_source->AddInteger(
+ "fingerprintReaderLocation",
+ static_cast<int32_t>(chromeos::quick_unlock::GetFingerprintLocation()));
+
+ // To use lottie, the worker-src CSP needs to be updated for the web ui that
+ // is using it. Since as of now there are only a couple of webuis using
+ // lottie animations, this update has to be performed manually. As the usage
+ // increases, set this as the default so manual override is no longer
+ // required.
+ html_source->OverrideContentSecurityPolicyWorkerSrc(
+ "worker-src blob: 'self';");
+ html_source->AddResourcePath("finger_print.json",
+ IDR_LOGIN_FINGER_PRINT_TABLET_ANIMATION);
+ }
+ html_source->AddBoolean("lockScreenNotificationsEnabled",
+ ash::features::IsLockScreenNotificationsEnabled());
+ html_source->AddBoolean(
+ "lockScreenHideSensitiveNotificationsSupported",
+ ash::features::IsLockScreenHideSensitiveNotificationsSupported());
+ html_source->AddBoolean("showTechnologyBadge",
+ !ash::features::IsSeparateNetworkIconsEnabled());
+ html_source->AddBoolean("hasInternalStylus",
+ ash::stylus_utils::HasInternalStylus());
+
+ html_source->AddBoolean("showCrostini",
+ crostini::CrostiniFeatures::Get()->IsUIAllowed(
+ profile, /*check_policy=*/false));
+
+ html_source->AddBoolean(
+ "allowCrostini", crostini::CrostiniFeatures::Get()->IsUIAllowed(profile));
+
+ html_source->AddBoolean("allowPluginVm", allow_plugin_vm);
+ html_source->AddBoolean("showPluginVm", show_plugin_vm);
+
+ html_source->AddBoolean("isDemoSession",
+ chromeos::DemoSession::IsDeviceInDemoMode());
+
+ // We have 2 variants of Android apps settings. Default case, when the Play
+ // Store app exists we show expandable section that allows as to
+ // enable/disable the Play Store and link to Android settings which is
+ // available once settings app is registered in the system.
+ // For AOSP images we don't have the Play Store app. In last case we Android
+ // apps settings consists only from root link to Android settings and only
+ // visible once settings app is registered.
+ html_source->AddBoolean("androidAppsVisible",
+ arc::IsArcAllowedForProfile(profile));
+ html_source->AddBoolean("havePlayStoreApp", arc::IsPlayStoreAvailable());
+
+ html_source->AddBoolean("enablePowerSettings", true);
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::PowerHandler>(profile->GetPrefs()));
+
+ html_source->AddBoolean(
+ "showParentalControlsSettings",
+ chromeos::settings::ShouldShowParentalControls(profile));
+}
void OSSettingsUI::AddSettingsPageUIHandler(
std::unique_ptr<content::WebUIMessageHandler> handler) {
@@ -190,12 +468,24 @@ void OSSettingsUI::AddSettingsPageUIHandler(
web_ui()->AddMessageHandler(std::move(handler));
}
-void OSSettingsUI::BindCrosNetworkConfig(
+void OSSettingsUI::BindInterface(
mojo::PendingReceiver<network_config::mojom::CrosNetworkConfig> receiver) {
ash::GetNetworkConfigService(std::move(receiver));
}
-void OSSettingsUI::BindAppManagementPageHandlerFactory(
+void OSSettingsUI::BindInterface(
+ mojo::PendingReceiver<mojom::UserActionRecorder> receiver) {
+ user_action_recorder_ =
+ std::make_unique<SettingsUserActionTracker>(std::move(receiver));
+}
+
+void OSSettingsUI::BindInterface(
+ mojo::PendingReceiver<mojom::SearchHandler> receiver) {
+ SearchHandlerFactory::GetForProfile(Profile::FromWebUI(web_ui()))
+ ->BindInterface(std::move(receiver));
+}
+
+void OSSettingsUI::BindInterface(
mojo::PendingReceiver<app_management::mojom::PageHandlerFactory> receiver) {
if (!app_management_page_handler_factory_) {
app_management_page_handler_factory_ =
@@ -205,5 +495,7 @@ void OSSettingsUI::BindAppManagementPageHandlerFactory(
app_management_page_handler_factory_->Bind(std::move(receiver));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(OSSettingsUI)
+
} // namespace settings
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h
index ff325c20bc3..c72c6b57c22 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h
@@ -8,40 +8,75 @@
#include <memory>
#include "base/macros.h"
+#include "base/time/time.h"
#include "chrome/browser/ui/webui/app_management/app_management.mojom-forward.h"
#include "chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom-forward.h"
#include "chrome/browser/ui/webui/webui_load_timer.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
namespace content {
+class WebUIDataSource;
class WebUIMessageHandler;
-}
+} // namespace content
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+} // namespace user_prefs
namespace chromeos {
namespace settings {
+namespace mojom {
+class SearchHandler;
+} // namespace mojom
+
// The WebUI handler for chrome://os-settings.
class OSSettingsUI : public ui::MojoWebUIController {
public:
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
explicit OSSettingsUI(content::WebUI* web_ui);
~OSSettingsUI() override;
- private:
- void AddSettingsPageUIHandler(
- std::unique_ptr<content::WebUIMessageHandler> handler);
- void BindCrosNetworkConfig(
+ // Initializes the WebUI message handlers for OS-specific settings.
+ void InitOSWebUIHandlers(content::WebUIDataSource* html_source);
+
+ // Instantiates implementor of the mojom::CrosNetworkConfig mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<network_config::mojom::CrosNetworkConfig> receiver);
- void BindAppManagementPageHandlerFactory(
+
+ // Instantiates implementor of the mojom::UserActionRecorder mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(mojo::PendingReceiver<mojom::UserActionRecorder> receiver);
+
+ // Instantiates implementor of the mojom::SearchHandler mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(mojo::PendingReceiver<mojom::SearchHandler> receiver);
+
+ // Instantiates implementor of the mojom::PageHandlerFactory mojo interface
+ // passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<app_management::mojom::PageHandlerFactory>
receiver);
+ private:
+ void AddSettingsPageUIHandler(
+ std::unique_ptr<content::WebUIMessageHandler> handler);
+
+ base::TimeTicks time_when_opened_;
+
WebuiLoadTimer webui_load_timer_;
+ std::unique_ptr<mojom::UserActionRecorder> user_action_recorder_;
std::unique_ptr<AppManagementPageHandlerFactory>
app_management_page_handler_factory_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(OSSettingsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc
index 715782b0b11..db5d9d79e67 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc
@@ -12,6 +12,8 @@
#include "base/bind_helpers.h"
#include "chrome/browser/chromeos/file_manager/path_util.h"
#include "chrome/browser/chromeos/guest_os/guest_os_share_path.h"
+#include "chrome/browser/chromeos/plugin_vm/plugin_vm_manager.h"
+#include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/browser_thread.h"
@@ -32,6 +34,14 @@ void PluginVmHandler::RegisterMessages() {
"removePluginVmSharedPath",
base::BindRepeating(&PluginVmHandler::HandleRemovePluginVmSharedPath,
weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "removePluginVm",
+ base::BindRepeating(&PluginVmHandler::HandleRemovePluginVm,
+ weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "requestPluginVmInstallerView",
+ base::BindRepeating(&PluginVmHandler::HandleRequestPluginVmInstallerView,
+ weak_ptr_factory_.GetWeakPtr()));
}
void PluginVmHandler::HandleGetPluginVmSharedPathsDisplayText(
@@ -68,5 +78,28 @@ void PluginVmHandler::HandleRemovePluginVmSharedPath(
path));
}
+void PluginVmHandler::HandleRemovePluginVm(const base::ListValue* args) {
+ CHECK_EQ(0U, args->GetSize());
+
+ auto* manager = plugin_vm::PluginVmManager::GetForProfile(profile_);
+ if (!manager) {
+ LOG(ERROR) << "removePluginVm called from an invalid profile.";
+ return;
+ }
+ manager->UninstallPluginVm();
+}
+
+void PluginVmHandler::HandleRequestPluginVmInstallerView(
+ const base::ListValue* args) {
+ CHECK(args->empty());
+
+ if (plugin_vm::IsPluginVmEnabled(profile_)) {
+ LOG(ERROR) << "requestPluginVmInstallerView called from a profile which "
+ "already has Plugin VM installed.";
+ return;
+ }
+ plugin_vm::ShowPluginVmInstallerView(profile_);
+}
+
} // namespace settings
} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h
index d57b34da1db..b003a9e3e11 100644
--- a/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h
@@ -32,6 +32,10 @@ class PluginVmHandler : public ::settings::SettingsPageUIHandler {
void HandleGetPluginVmSharedPathsDisplayText(const base::ListValue* args);
// Remove a specified path from being shared.
void HandleRemovePluginVmSharedPath(const base::ListValue* args);
+ // Remove Plugin VM.
+ void HandleRemovePluginVm(const base::ListValue* args);
+ // Show the Plugin VM installer view if Plugin VM is not currently installed.
+ void HandleRequestPluginVmInstallerView(const base::ListValue* args);
Profile* profile_;
// weak_ptr_factory_ should always be last member.
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/pref_names.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/pref_names.cc
new file mode 100644
index 00000000000..c36221f6270
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/pref_names.cc
@@ -0,0 +1,20 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/pref_names.h"
+
+namespace chromeos {
+namespace settings {
+namespace prefs {
+
+// Boolean specifying whether OS wallpaper sync is enabled. This is stored
+// separately from the other OS sync preferences because it's an edge case;
+// wallpaper does not have its own ModelType, so it cannot be part of
+// UserSelectableOsType like the other OS sync types.
+// TODO(https://crbug.com/967987): Break this dependency.
+const char kSyncOsWallpaper[] = "sync.os_wallpaper";
+
+} // namespace prefs
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/pref_names.h b/chromium/chrome/browser/ui/webui/settings/chromeos/pref_names.h
new file mode 100644
index 00000000000..df2e7dce599
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/pref_names.h
@@ -0,0 +1,18 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_PREF_NAMES_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_PREF_NAMES_H_
+
+namespace chromeos {
+namespace settings {
+namespace prefs {
+
+extern const char kSyncOsWallpaper[];
+
+} // namespace prefs
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_PREF_NAMES_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc
new file mode 100644
index 00000000000..f74ec2b9c89
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc
@@ -0,0 +1,38 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h"
+
+#include "base/bind.h"
+#include "chrome/browser/chromeos/login/quick_unlock/pin_backend.h"
+#include "content/public/browser/web_ui.h"
+
+namespace chromeos {
+namespace settings {
+
+QuickUnlockHandler::QuickUnlockHandler() = default;
+
+QuickUnlockHandler::~QuickUnlockHandler() = default;
+
+void QuickUnlockHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "RequestPinLoginState",
+ base::BindRepeating(&QuickUnlockHandler::HandleRequestPinLoginState,
+ base::Unretained(this)));
+}
+
+void QuickUnlockHandler::HandleRequestPinLoginState(
+ const base::ListValue* args) {
+ AllowJavascript();
+ quick_unlock::PinBackend::GetInstance()->HasLoginSupport(
+ base::BindOnce(&QuickUnlockHandler::OnPinLoginAvailable,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void QuickUnlockHandler::OnPinLoginAvailable(bool is_available) {
+ FireWebUIListener("pin-login-available-changed", base::Value(is_available));
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h
new file mode 100644
index 00000000000..4796c99ce3c
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h
@@ -0,0 +1,42 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_QUICK_UNLOCK_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_QUICK_UNLOCK_HANDLER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+
+namespace base {
+class ListValue;
+} // namespace base
+
+namespace chromeos {
+namespace settings {
+
+// Settings WebUI handler for quick unlock settings.
+class QuickUnlockHandler : public ::settings::SettingsPageUIHandler {
+ public:
+ QuickUnlockHandler();
+ QuickUnlockHandler(const QuickUnlockHandler&) = delete;
+ QuickUnlockHandler& operator=(const QuickUnlockHandler&) = delete;
+ ~QuickUnlockHandler() override;
+
+ // SettingsPageUIHandler:
+ void RegisterMessages() override;
+ void OnJavascriptAllowed() override {}
+ void OnJavascriptDisallowed() override {}
+
+ private:
+ void HandleRequestPinLoginState(const base::ListValue* args);
+
+ void OnPinLoginAvailable(bool is_available);
+
+ base::WeakPtrFactory<QuickUnlockHandler> weak_ptr_factory_{this};
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_QUICK_UNLOCK_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/BUILD.gn b/chromium/chrome/browser/ui/webui/settings/chromeos/search/BUILD.gn
new file mode 100644
index 00000000000..b4554acf90b
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+assert(is_chromeos)
+
+mojom("mojo_bindings") {
+ sources = [
+ "search.mojom",
+ "search_result_icon.mojom",
+ "user_action_recorder.mojom",
+ ]
+
+ public_deps = [ "//mojo/public/mojom/base" ]
+}
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/OWNERS b/chromium/chrome/browser/ui/webui/settings/chromeos/search/OWNERS
new file mode 100644
index 00000000000..2d3d2668edc
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/OWNERS
@@ -0,0 +1,7 @@
+khorimoto@chromium.org
+zentaro@chromium.org
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+# COMPONENT: OS>Systems>Settings
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search.mojom b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search.mojom
new file mode 100644
index 00000000000..d319e8d1079
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search.mojom
@@ -0,0 +1,33 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module chromeos.settings.mojom;
+
+import "chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom";
+import "mojo/public/mojom/base/string16.mojom";
+
+// Search result metadata.
+struct SearchResult {
+ // String to be displayed as a result in the UI. Meant to be displayed
+ // directly (i.e., not an ID but rather the actual text).
+ mojo_base.mojom.String16 result_text;
+
+ // The URL path containing the relevant setting, which may or may not contain
+ // URL parameters. For example, the Wi-Fi list settings page is
+ // chrome://os-settings/networks?type=WiFi, so the field would be
+ // "networks?type=WiFi" for this page.
+ string url_path_with_parameters;
+
+ // Icon to display for the search result.
+ SearchResultIcon icon;
+};
+
+// Provides settings search results. Implemented in the browser process;
+// intended to be called from settings JS and Launcher C++.
+interface SearchHandler {
+ // Searches settings for the given query and returns a list of results, sorted
+ // from most relevant to least relevant. An empty array indicates no relevant
+ // results.
+ Search(mojo_base.mojom.String16 query) => (array<SearchResult> results);
+};
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_concept.h b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_concept.h
new file mode 100644
index 00000000000..f6dc3b8c6f6
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_concept.h
@@ -0,0 +1,62 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_CONCEPT_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_CONCEPT_H_
+
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom.h"
+
+namespace chromeos {
+namespace settings {
+
+// Represents a potential search result. In this context, "concept" refers to
+// the fact that this search result represents an idea which may be described
+// by more than just one phrase. For example, a concept of "Display settings"
+// may also be described as "Monitor settings".
+//
+// Each concept has a canonical description search tag as well as up to
+// |kMaxAltTagsPerConcept| alternate descriptions search tags.
+struct SearchConcept {
+ static constexpr size_t kMaxAltTagsPerConcept = 4;
+ static constexpr int kAltTagEnd = 0;
+
+ SearchConcept(const SearchConcept& other) = default;
+ SearchConcept& operator=(const SearchConcept& other) = default;
+
+ // Message ID (from os_settings_search_tag_strings.grdp) corresponding to the
+ // canonical search tag for this concept.
+ int canonical_message_id;
+
+ // URL path corresponding to the settings subpage at which the user can
+ // change a setting associated with the tag. This string can also contain
+ // URL parameters.
+ //
+ // Example 1 - Display settings (chrome://os-settings/device/display):
+ // ==> "device/display".
+ // Example 2 - Wi-Fi settings (chrome://os-settings/networks?type=WiFi):
+ // ==> "networks?type=WiFi"
+ const char* url_path_with_parameters;
+
+ // Icon to display for search results associated with this concept.
+ mojom::SearchResultIcon icon;
+
+ // Alternate message IDs (from os_settings_search_tag_strings.grdp)
+ // corresponding to this concept. These IDs refer to messages which represent
+ // an alternate way of describing the same concept (e.g., "Monitor settings"
+ // is an alternate phrase for "Display settings").
+ //
+ // This field provides up to |kMaxAltTagsPerConcept| alternate tags, but not
+ // all concepts will require this many. A value of kAltTagEnd is used to
+ // indicate that there are no further tags.
+ //
+ // Example 1 - Four alternate tags: [1234, 1235, 1236, 1237]
+ // Example 2 - Two alternate tags: [1234, 1235, kAltTagEnd, _]
+ // Example 3 - Zero alternate tags: [kAltTagEnd, _, _, _]
+ int alt_tag_ids[kMaxAltTagsPerConcept] = {kAltTagEnd};
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_CONCEPT_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc
new file mode 100644
index 00000000000..a94db926427
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc
@@ -0,0 +1,107 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_handler.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_concept.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom.h"
+#include "chrome/services/local_search_service/local_search_service_impl.h"
+#include "chrome/services/local_search_service/public/mojom/types.mojom.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace chromeos {
+namespace settings {
+namespace {
+
+const int32_t kLocalSearchServiceMaxResults = 10;
+
+} // namespace
+
+// static
+const size_t SearchHandler::kNumMaxResults = 5;
+
+SearchHandler::SearchHandler(
+ OsSettingsLocalizedStringsProvider* strings_provider,
+ local_search_service::LocalSearchServiceImpl* local_search_service)
+ : strings_provider_(strings_provider),
+ index_(local_search_service->GetIndexImpl(
+ local_search_service::IndexId::kCrosSettings)) {}
+
+SearchHandler::~SearchHandler() = default;
+
+void SearchHandler::BindInterface(
+ mojo::PendingReceiver<mojom::SearchHandler> pending_receiver) {
+ receivers_.Add(this, std::move(pending_receiver));
+}
+
+std::vector<mojom::SearchResultPtr> SearchHandler::Search(
+ const base::string16& query) {
+ std::vector<local_search_service::Result> local_search_service_results;
+ local_search_service::ResponseStatus response_status = index_->Find(
+ query, kLocalSearchServiceMaxResults, &local_search_service_results);
+
+ if (response_status != local_search_service::ResponseStatus::kSuccess) {
+ LOG(ERROR) << "Cannot search; LocalSearchService returned "
+ << static_cast<int>(response_status)
+ << ". Returning empty results array.";
+ return {};
+ }
+
+ return GenerateSearchResultsArray(local_search_service_results);
+}
+
+void SearchHandler::Search(const base::string16& query,
+ SearchCallback callback) {
+ std::move(callback).Run(Search(query));
+}
+
+std::vector<mojom::SearchResultPtr> SearchHandler::GenerateSearchResultsArray(
+ const std::vector<local_search_service::Result>&
+ local_search_service_results) {
+ std::vector<mojom::SearchResultPtr> search_results;
+ for (const auto& result : local_search_service_results) {
+ mojom::SearchResultPtr result_ptr = ResultToSearchResult(result);
+ if (result_ptr)
+ search_results.push_back(std::move(result_ptr));
+
+ // Limit the number of results to return.
+ if (search_results.size() == kNumMaxResults)
+ break;
+ }
+
+ return search_results;
+}
+
+mojom::SearchResultPtr SearchHandler::ResultToSearchResult(
+ const local_search_service::Result& result) {
+ int message_id;
+
+ // The result's ID is expected to be a stringified int.
+ if (!base::StringToInt(result.id, &message_id))
+ return nullptr;
+
+ const SearchConcept* concept =
+ strings_provider_->GetCanonicalTagMetadata(message_id);
+
+ // If the concept was not registered, no metadata is available. This can occur
+ // if the search tag was dynamically unregistered during the asynchronous
+ // Find() call.
+ if (!concept)
+ return nullptr;
+
+ return mojom::SearchResult::New(l10n_util::GetStringUTF16(message_id),
+ concept->url_path_with_parameters,
+ concept->icon);
+}
+
+void SearchHandler::Shutdown() {
+ strings_provider_ = nullptr;
+ index_ = nullptr;
+ receivers_.Clear();
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.h
new file mode 100644
index 00000000000..36df7ed4bb2
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.h
@@ -0,0 +1,77 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_HANDLER_H_
+
+#include <vector>
+
+#include "base/optional.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search.mojom.h"
+#include "chrome/services/local_search_service/index_impl.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace local_search_service {
+class LocalSearchServiceImpl;
+} // namespace local_search_service
+
+namespace chromeos {
+namespace settings {
+
+class OsSettingsLocalizedStringsProvider;
+
+// Handles search queries for Chrome OS settings. Search() is expected to be
+// invoked by the settings UI as well as the the Launcher search UI. Search
+// results are obtained by matching the provided query against search tags
+// indexed in the LocalSearchService and cross-referencing results with
+// OsSettingsLocalizedStringsProvider.
+//
+// SearchHandler returns at most |kNumMaxResults| results; searches which do not
+// provide any matches result in an empty results array.
+class SearchHandler : public mojom::SearchHandler, public KeyedService {
+ public:
+ // Maximum number of results returned by a Search() call.
+ static const size_t kNumMaxResults;
+
+ SearchHandler(
+ OsSettingsLocalizedStringsProvider* strings_provider,
+ local_search_service::LocalSearchServiceImpl* local_search_service);
+ ~SearchHandler() override;
+
+ SearchHandler(const SearchHandler& other) = delete;
+ SearchHandler& operator=(const SearchHandler& other) = delete;
+
+ void BindInterface(
+ mojo::PendingReceiver<mojom::SearchHandler> pending_receiver);
+
+ // Synchronous search implementation (for in-process clients).
+ std::vector<mojom::SearchResultPtr> Search(const base::string16& query);
+
+ // mojom::SearchHandler:
+ void Search(const base::string16& query, SearchCallback callback) override;
+
+ private:
+ // KeyedService:
+ void Shutdown() override;
+
+ std::vector<mojom::SearchResultPtr> GenerateSearchResultsArray(
+ const std::vector<local_search_service::Result>&
+ local_search_service_results);
+ mojom::SearchResultPtr ResultToSearchResult(
+ const local_search_service::Result& result);
+
+ OsSettingsLocalizedStringsProvider* strings_provider_;
+ local_search_service::IndexImpl* index_;
+
+ // Note: Expected to have multiple clients, so a ReceiverSet is used.
+ mojo::ReceiverSet<mojom::SearchHandler> receivers_;
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.cc
new file mode 100644
index 00000000000..fba87783738
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.cc
@@ -0,0 +1,61 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.h"
+
+#include "chrome/browser/local_search_service/local_search_service_proxy.h"
+#include "chrome/browser/local_search_service/local_search_service_proxy_factory.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider_factory.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_handler.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace chromeos {
+namespace settings {
+
+// static
+SearchHandler* SearchHandlerFactory::GetForProfile(Profile* profile) {
+ return static_cast<SearchHandler*>(
+ SearchHandlerFactory::GetInstance()->GetServiceForBrowserContext(
+ profile, /*create=*/true));
+}
+
+// static
+SearchHandlerFactory* SearchHandlerFactory::GetInstance() {
+ return base::Singleton<SearchHandlerFactory>::get();
+}
+
+SearchHandlerFactory::SearchHandlerFactory()
+ : BrowserContextKeyedServiceFactory(
+ "SearchHandler",
+ BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(
+ local_search_service::LocalSearchServiceProxyFactory::GetInstance());
+ DependsOn(OsSettingsLocalizedStringsProviderFactory::GetInstance());
+}
+
+SearchHandlerFactory::~SearchHandlerFactory() = default;
+
+KeyedService* SearchHandlerFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ Profile* profile = Profile::FromBrowserContext(context);
+ return new SearchHandler(
+ OsSettingsLocalizedStringsProviderFactory::GetForProfile(profile),
+ local_search_service::LocalSearchServiceProxyFactory::GetForProfile(
+ Profile::FromBrowserContext(profile))
+ ->GetLocalSearchServiceImpl());
+}
+
+bool SearchHandlerFactory::ServiceIsNULLWhileTesting() const {
+ return true;
+}
+
+content::BrowserContext* SearchHandlerFactory::GetBrowserContextToUse(
+ content::BrowserContext* context) const {
+ return chrome::GetBrowserContextOwnInstanceInIncognito(context);
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.h b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.h
new file mode 100644
index 00000000000..9b69e5f161c
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_factory.h
@@ -0,0 +1,45 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_HANDLER_FACTORY_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_HANDLER_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class Profile;
+
+namespace chromeos {
+namespace settings {
+
+class SearchHandler;
+
+// Factory for SearchHandler; available for incognito and multi-profile cases to
+// support settings search in those contexts.
+class SearchHandlerFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ static SearchHandler* GetForProfile(Profile* profile);
+ static SearchHandlerFactory* GetInstance();
+
+ private:
+ friend struct base::DefaultSingletonTraits<SearchHandlerFactory>;
+
+ SearchHandlerFactory();
+ ~SearchHandlerFactory() override;
+
+ SearchHandlerFactory(const SearchHandlerFactory&) = delete;
+ SearchHandlerFactory& operator=(const SearchHandlerFactory&) = delete;
+
+ // BrowserContextKeyedServiceFactory:
+ KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const override;
+ bool ServiceIsNULLWhileTesting() const override;
+ content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const override;
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_HANDLER_FACTORY_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_unittest.cc
new file mode 100644
index 00000000000..cc04fb87193
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_unittest.cc
@@ -0,0 +1,78 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/search/search_handler.h"
+
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/webui/settings/chromeos/os_settings_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/search.mojom-test-utils.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/services/local_search_service/local_search_service_impl.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
+#include "content/public/test/browser_task_environment.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace settings {
+
+class SearchHandlerTest : public testing::Test {
+ protected:
+ SearchHandlerTest() : profile_manager_(TestingBrowserProcess::GetGlobal()) {}
+ ~SearchHandlerTest() override = default;
+
+ // testing::Test:
+ void SetUp() override {
+ ASSERT_TRUE(profile_manager_.SetUp());
+
+ provider_ = std::make_unique<OsSettingsLocalizedStringsProvider>(
+ profile_manager_.CreateTestingProfile("TestingProfile"),
+ &local_search_service_);
+
+ handler_ = std::make_unique<SearchHandler>(provider_.get(),
+ &local_search_service_);
+ handler_->BindInterface(handler_remote_.BindNewPipeAndPassReceiver());
+
+ // Allow asynchronous networking code to complete; specifically, let code
+ // which adds Wi-Fi to the system run so that Wi-Fi search tags can be
+ // queried below.
+ base::RunLoop().RunUntilIdle();
+ }
+
+ content::BrowserTaskEnvironment task_environment_;
+ TestingProfileManager profile_manager_;
+ chromeos::network_config::CrosNetworkConfigTestHelper network_config_helper_;
+ mojo::Remote<mojom::SearchHandler> handler_remote_;
+ local_search_service::LocalSearchServiceImpl local_search_service_;
+ std::unique_ptr<OsSettingsLocalizedStringsProvider> provider_;
+ std::unique_ptr<SearchHandler> handler_;
+};
+
+TEST_F(SearchHandlerTest, Success) {
+ // Search for "Wi-Fi".
+ std::vector<mojom::SearchResultPtr> search_results;
+ mojom::SearchHandlerAsyncWaiter(handler_remote_.get())
+ .Search(base::ASCIIToUTF16("Wi-Fi"), &search_results);
+
+ // Multiple results should be available, and they should have Wi-Fi metadata.
+ EXPECT_GT(search_results.size(), 0u);
+ for (const auto& result : search_results) {
+ EXPECT_EQ(chrome::kWiFiSettingsSubPage, result->url_path_with_parameters);
+ EXPECT_EQ(mojom::SearchResultIcon::kWifi, result->icon);
+ }
+}
+
+TEST_F(SearchHandlerTest, NoResults) {
+ std::vector<mojom::SearchResultPtr> search_results;
+ mojom::SearchHandlerAsyncWaiter(handler_remote_.get())
+ .Search(base::ASCIIToUTF16("QueryWithNoResults"), &search_results);
+ EXPECT_TRUE(search_results.empty());
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom
new file mode 100644
index 00000000000..ea4605ed09f
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom
@@ -0,0 +1,14 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module chromeos.settings.mojom;
+
+// Icon types associated with a settings search result.
+enum SearchResultIcon {
+ kCellular,
+ kEthernet,
+ // Note: Wi-Fi icon is used by default for networking tasks which may not be
+ // specifically tied to Wi-Fi.
+ kWifi
+}; \ No newline at end of file
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.cc
new file mode 100644
index 00000000000..49b774039a7
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.cc
@@ -0,0 +1,131 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.h"
+
+#include "base/metrics/histogram_functions.h"
+
+namespace chromeos {
+namespace settings {
+
+namespace {
+
+// The maximum amount of time that the settings window can be blurred to be
+// considered short enough for the "first change" metric.
+constexpr base::TimeDelta kShortBlurTimeLimit = base::TimeDelta::FromMinutes(1);
+
+// The minimum amount of time between a setting change and a subsequent setting
+// change. If two changes occur les than this amount of time from each other,
+// they are ignored by metrics. See https://crbug.com/1073714 for details.
+constexpr base::TimeDelta kMinSubsequentChange =
+ base::TimeDelta::FromMilliseconds(200);
+
+// Min/max values for the duration metrics. Note that these values are tied to
+// the metrics defined below; if these ever change, the metric names must also
+// be updated.
+constexpr base::TimeDelta kMinDurationMetric =
+ base::TimeDelta::FromMilliseconds(100);
+constexpr base::TimeDelta kMaxDurationMetric = base::TimeDelta::FromMinutes(10);
+
+void LogDurationMetric(const char* metric_name, base::TimeDelta duration) {
+ base::UmaHistogramCustomTimes(metric_name, duration, kMinDurationMetric,
+ kMaxDurationMetric, /*buckets=*/50);
+}
+
+} // namespace
+
+SettingsUserActionTracker::SettingsUserActionTracker(
+ mojo::PendingReceiver<mojom::UserActionRecorder> pending_receiver)
+ : SettingsUserActionTracker() {
+ receiver_.Bind(std::move(pending_receiver));
+}
+
+SettingsUserActionTracker::SettingsUserActionTracker()
+ : metric_start_time_(base::TimeTicks::Now()) {}
+
+SettingsUserActionTracker::~SettingsUserActionTracker() = default;
+
+void SettingsUserActionTracker::RecordPageFocus() {
+ if (last_blur_timestamp_.is_null())
+ return;
+
+ // Log the duration of being blurred.
+ const base::TimeDelta blurred_duration =
+ base::TimeTicks::Now() - last_blur_timestamp_;
+ LogDurationMetric("ChromeOS.Settings.BlurredWindowDuration",
+ blurred_duration);
+
+ // If the window was blurred for more than |kShortBlurTimeLimit|,
+ // the user was away from the window for long enough that we consider the
+ // user coming back to the window a new session for the purpose of metrics.
+ if (blurred_duration >= kShortBlurTimeLimit) {
+ ResetMetricsCountersAndTimestamp();
+ last_record_setting_changed_timestamp_ = base::TimeTicks();
+ }
+}
+
+void SettingsUserActionTracker::RecordPageBlur() {
+ last_blur_timestamp_ = base::TimeTicks::Now();
+}
+
+void SettingsUserActionTracker::RecordClick() {
+ ++num_clicks_since_start_time_;
+}
+
+void SettingsUserActionTracker::RecordNavigation() {
+ ++num_navigations_since_start_time_;
+}
+
+void SettingsUserActionTracker::RecordSearch() {
+ ++num_searches_since_start_time_;
+}
+
+void SettingsUserActionTracker::RecordSettingChange() {
+ base::TimeTicks now = base::TimeTicks::Now();
+
+ if (!last_record_setting_changed_timestamp_.is_null()) {
+ // If it has been less than |kMinSubsequentChange| since the last recorded
+ // setting change, this change is discarded. See https://crbug.com/1073714
+ // for details.
+ if (now - last_record_setting_changed_timestamp_ < kMinSubsequentChange)
+ return;
+
+ base::UmaHistogramCounts1000(
+ "ChromeOS.Settings.NumClicksUntilChange.SubsequentChange",
+ num_clicks_since_start_time_);
+ base::UmaHistogramCounts1000(
+ "ChromeOS.Settings.NumNavigationsUntilChange.SubsequentChange",
+ num_navigations_since_start_time_);
+ base::UmaHistogramCounts1000(
+ "ChromeOS.Settings.NumSearchesUntilChange.SubsequentChange",
+ num_searches_since_start_time_);
+ LogDurationMetric("ChromeOS.Settings.TimeUntilChange.SubsequentChange",
+ now - metric_start_time_);
+ } else {
+ base::UmaHistogramCounts1000(
+ "ChromeOS.Settings.NumClicksUntilChange.FirstChange",
+ num_clicks_since_start_time_);
+ base::UmaHistogramCounts1000(
+ "ChromeOS.Settings.NumNavigationsUntilChange.FirstChange",
+ num_navigations_since_start_time_);
+ base::UmaHistogramCounts1000(
+ "ChromeOS.Settings.NumSearchesUntilChange.FirstChange",
+ num_searches_since_start_time_);
+ LogDurationMetric("ChromeOS.Settings.TimeUntilChange.FirstChange",
+ now - metric_start_time_);
+ }
+
+ ResetMetricsCountersAndTimestamp();
+ last_record_setting_changed_timestamp_ = now;
+}
+
+void SettingsUserActionTracker::ResetMetricsCountersAndTimestamp() {
+ metric_start_time_ = base::TimeTicks::Now();
+ num_clicks_since_start_time_ = 0u;
+ num_navigations_since_start_time_ = 0u;
+ num_searches_since_start_time_ = 0u;
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.h b/chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.h
new file mode 100644
index 00000000000..f355bcd524e
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.h
@@ -0,0 +1,74 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SETTINGS_USER_ACTION_TRACKER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SETTINGS_USER_ACTION_TRACKER_H_
+
+#include "base/time/time.h"
+#include "chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+
+namespace chromeos {
+namespace settings {
+
+// Records user actions which measure the effort required to change a setting.
+// This class is only meant to track actions from an individual settings
+// session; if the settings window is closed and reopened again, a new instance
+// should be created for that new session.
+class SettingsUserActionTracker : public mojom::UserActionRecorder {
+ public:
+ explicit SettingsUserActionTracker(
+ mojo::PendingReceiver<mojom::UserActionRecorder> pending_receiver);
+ SettingsUserActionTracker(const SettingsUserActionTracker& other) = delete;
+ SettingsUserActionTracker& operator=(const SettingsUserActionTracker& other) =
+ delete;
+ ~SettingsUserActionTracker() override;
+
+ // mojom::UserActionRecorder:
+ void RecordPageFocus() override;
+ void RecordPageBlur() override;
+ void RecordClick() override;
+ void RecordNavigation() override;
+ void RecordSearch() override;
+ void RecordSettingChange() override;
+
+ private:
+ friend class SettingsUserActionTrackerTest;
+
+ // For unit tests.
+ SettingsUserActionTracker();
+
+ void ResetMetricsCountersAndTimestamp();
+
+ // Time at which the last setting change metric was recorded since the window
+ // has been focused, or null if no setting change has been recorded since the
+ // window has been focused. Note that if the user blurs the window then
+ // refocuses it in less than a minute, this value remains non-null; i.e., it
+ // flips back to null only when the user has blurred the window for over a
+ // minute.
+ base::TimeTicks last_record_setting_changed_timestamp_;
+
+ // Time at which recording the current metric has started. If
+ // |has_changed_setting_| is true, we're currently measuring the "subsequent
+ // setting change" metric; otherwise, we're measuring the "first setting
+ // change" metric.
+ base::TimeTicks metric_start_time_;
+
+ // Counters associated with the current metric.
+ size_t num_clicks_since_start_time_ = 0u;
+ size_t num_navigations_since_start_time_ = 0u;
+ size_t num_searches_since_start_time_ = 0u;
+
+ // The last time at which a page blur event was received; if no blur events
+ // have been received, this field is_null().
+ base::TimeTicks last_blur_timestamp_;
+
+ mojo::Receiver<mojom::UserActionRecorder> receiver_{this};
+};
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SETTINGS_USER_ACTION_TRACKER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker_unittest.cc
new file mode 100644
index 00000000000..74a0c9cb0b2
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker_unittest.cc
@@ -0,0 +1,176 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/search/settings_user_action_tracker.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace settings {
+
+class SettingsUserActionTrackerTest : public testing::Test {
+ protected:
+ SettingsUserActionTrackerTest() = default;
+ ~SettingsUserActionTrackerTest() override = default;
+
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+ base::HistogramTester histogram_tester_;
+ SettingsUserActionTracker tracker_;
+};
+
+TEST_F(SettingsUserActionTrackerTest, TestRecordMetrics) {
+ // Focus the page, perform some tasks, and change a setting.
+ tracker_.RecordPageFocus();
+ tracker_.RecordClick();
+ tracker_.RecordNavigation();
+ tracker_.RecordSearch();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(10));
+ tracker_.RecordSettingChange();
+
+ // The "first change" metrics should have been logged.
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumClicksUntilChange.FirstChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumNavigationsUntilChange.FirstChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumSearchesUntilChange.FirstChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTimeBucketCount(
+ "ChromeOS.Settings.TimeUntilChange.FirstChange",
+ /*sample=*/base::TimeDelta::FromSeconds(10),
+ /*count=*/1);
+
+ // Without leaving the page, perform some more tasks, and change another
+ // setting.
+ tracker_.RecordClick();
+ tracker_.RecordNavigation();
+ tracker_.RecordSearch();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(10));
+ tracker_.RecordSettingChange();
+
+ // The "subsequent change" metrics should have been logged.
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumClicksUntilChange.SubsequentChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumNavigationsUntilChange.SubsequentChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumSearchesUntilChange.SubsequentChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTimeBucketCount(
+ "ChromeOS.Settings.TimeUntilChange.SubsequentChange",
+ /*sample=*/base::TimeDelta::FromSeconds(10),
+ /*count=*/1);
+
+ // Repeat this, but only after 100ms. This is lower than the minimum value
+ // required for this metric, so it should be ignored.
+ tracker_.RecordClick();
+ tracker_.RecordNavigation();
+ tracker_.RecordSearch();
+ task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(100));
+ tracker_.RecordSettingChange();
+
+ // No additional logging should have occurred, so make the same verifications
+ // as above.
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumClicksUntilChange.SubsequentChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumNavigationsUntilChange.SubsequentChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumSearchesUntilChange.SubsequentChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTimeBucketCount(
+ "ChromeOS.Settings.TimeUntilChange.SubsequentChange",
+ /*sample=*/base::TimeDelta::FromSeconds(10),
+ /*count=*/1);
+
+ // Repeat this once more, and verify that the counts increased.
+ tracker_.RecordClick();
+ tracker_.RecordNavigation();
+ tracker_.RecordSearch();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(10));
+ tracker_.RecordSettingChange();
+
+ // The "subsequent change" metrics should have been logged.
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumClicksUntilChange.SubsequentChange",
+ /*count=*/2);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumNavigationsUntilChange.SubsequentChange",
+ /*count=*/2);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumSearchesUntilChange.SubsequentChange",
+ /*count=*/2);
+ histogram_tester_.ExpectTimeBucketCount(
+ "ChromeOS.Settings.TimeUntilChange.SubsequentChange",
+ /*sample=*/base::TimeDelta::FromSeconds(10),
+ /*count=*/2);
+}
+
+TEST_F(SettingsUserActionTrackerTest, TestBlurAndFocus) {
+ // Focus the page, click, and change a setting.
+ tracker_.RecordPageFocus();
+ tracker_.RecordClick();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+ tracker_.RecordSettingChange();
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumClicksUntilChange.FirstChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTimeBucketCount(
+ "ChromeOS.Settings.TimeUntilChange.FirstChange",
+ /*sample=*/base::TimeDelta::FromSeconds(1),
+ /*count=*/1);
+
+ // Blur for 59 seconds (not quite a minute), click, and change a setting.
+ // Since the blur was under a minute, this should count for the "subsequent
+ // change" metrics.
+ tracker_.RecordPageBlur();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(59));
+ tracker_.RecordPageFocus();
+ tracker_.RecordClick();
+ tracker_.RecordSettingChange();
+ histogram_tester_.ExpectTimeBucketCount(
+ "ChromeOS.Settings.BlurredWindowDuration",
+ /*sample=*/base::TimeDelta::FromSeconds(59),
+ /*count=*/1);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumClicksUntilChange.SubsequentChange",
+ /*count=*/1);
+ histogram_tester_.ExpectTimeBucketCount(
+ "ChromeOS.Settings.TimeUntilChange.SubsequentChange",
+ /*sample=*/base::TimeDelta::FromSeconds(59),
+ /*count=*/1);
+
+ // Now, blur for a full minute, click, and change a setting. Since the blur
+ // was a full minute, this should count for the "first change" metrics.
+ tracker_.RecordPageBlur();
+ task_environment_.FastForwardBy(base::TimeDelta::FromMinutes(1));
+ tracker_.RecordPageFocus();
+ task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(5));
+ tracker_.RecordClick();
+ tracker_.RecordSettingChange();
+ histogram_tester_.ExpectTimeBucketCount(
+ "ChromeOS.Settings.BlurredWindowDuration",
+ /*sample=*/base::TimeDelta::FromMinutes(1),
+ /*count=*/2);
+ histogram_tester_.ExpectTotalCount(
+ "ChromeOS.Settings.NumClicksUntilChange.FirstChange",
+ /*count=*/2);
+ histogram_tester_.ExpectTimeBucketCount(
+ "ChromeOS.Settings.TimeUntilChange.FirstChange",
+ /*sample=*/base::TimeDelta::FromSeconds(5),
+ /*count=*/1);
+}
+
+} // namespace settings.
+} // namespace chromeos.
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom b/chromium/chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom
new file mode 100644
index 00000000000..1f151fc028d
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module chromeos.settings.mojom;
+
+// Records user actions within OS settings. Implemented in the browser process;
+// intended to be called from settings JS.
+interface UserActionRecorder {
+ // Records that the settings window has been focused.
+ RecordPageFocus();
+
+ // Records that the settings window has been blurred (i.e., no longer
+ // focused).
+ RecordPageBlur();
+
+ // Records that the user has clicked within the settings page.
+ RecordClick();
+
+ // Records that the user has navigated to a settings subpage.
+ RecordNavigation();
+
+ // Records that the user has completed a search attempt.
+ RecordSearch();
+
+ // Records that the user has changed a setting.
+ RecordSettingChange();
+};
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.cc
new file mode 100644
index 00000000000..005d006a42c
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.cc
@@ -0,0 +1,73 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.h"
+
+#include "url/gurl.h"
+
+namespace {
+
+// Returns an updated |gurl| with the specified components from the params. If
+// |scheme| is not empty, returns an updated GURL with the specified scheme. If
+// |replace_port| is true, returns an updated GURL with 631 as the port. 631 is
+// the default port for IPP.
+GURL UpdateServerPrinterGURL(const GURL& gurl,
+ const std::string& scheme,
+ bool replace_ipp_port) {
+ GURL::Replacements replacement;
+ if (!scheme.empty())
+ replacement.SetSchemeStr(scheme);
+ if (replace_ipp_port)
+ replacement.SetPortStr("631");
+ return gurl.ReplaceComponents(replacement);
+}
+
+} // namespace
+
+namespace chromeos {
+namespace settings {
+
+bool HasValidServerPrinterScheme(const GURL& gurl) {
+ return gurl.SchemeIsHTTPOrHTTPS() || gurl.SchemeIs("ipp") ||
+ gurl.SchemeIs("ipps");
+}
+
+base::Optional<GURL> GenerateServerPrinterUrlWithValidScheme(
+ const std::string& url) {
+ base::Optional<GURL> gurl = base::make_optional(GURL(url));
+ if (!HasValidServerPrinterScheme(*gurl)) {
+ // If we're missing a valid scheme, try querying with IPPS first.
+ gurl = GURL("ipps://" + url);
+ }
+
+ if (!gurl->is_valid())
+ return base::nullopt;
+
+ // Replaces IPP/IPPS by HTTP/HTTPS. IPP standard describes protocol built
+ // on top of HTTP, so both types of addresses have the same meaning in the
+ // context of IPP interface. Moreover, the URL must have HTTP/HTTPS scheme
+ // to pass IsStandard() test from GURL library (see "Validation of the URL
+ // address" below).
+ if (gurl->SchemeIs("ipp")) {
+ gurl = UpdateServerPrinterGURL(*gurl, "http",
+ /*replace_ipp_port=*/false);
+ // The default port for IPP is 631. If the schema IPP is replaced by HTTP
+ // and the port is not explicitly defined in the URL, we have to overwrite
+ // the default HTTP port with the default IPP port. For IPPS we do nothing
+ // because implementers use the same port for IPPS and HTTPS.
+ if (gurl->IntPort() == url::PORT_UNSPECIFIED) {
+ gurl = UpdateServerPrinterGURL(*gurl, /*scheme=*/"",
+ /*replace_ipp_port=*/true);
+ }
+ } else if (gurl->SchemeIs("ipps")) {
+ gurl = UpdateServerPrinterGURL(*gurl, "https",
+ /*replace_ipp_port=*/false);
+ }
+
+ // Check validation of the URL address and return |gurl| if valid.
+ return gurl->IsStandard() ? gurl : base::nullopt;
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.h b/chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.h
new file mode 100644
index 00000000000..ad118c14f4b
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.h
@@ -0,0 +1,30 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SERVER_PRINTER_URL_UTIL_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SERVER_PRINTER_URL_UTIL_H_
+
+#include <string>
+
+#include "base/optional.h"
+
+class GURL;
+
+namespace chromeos {
+namespace settings {
+
+// Returns true if |gurl| has any the following scheme: HTTP, HTTPS, IPP, or
+// IPPS. Returns false for an empty or any other scheme.
+bool HasValidServerPrinterScheme(const GURL& gurl);
+
+// Returns a GURL from the input |url|. Returns base::nullopt if
+// either |url| is invalid or constructing the GURL failed. This will also
+// default the server printer URI to use HTTPS if it detects a missing scheme.
+base::Optional<GURL> GenerateServerPrinterUrlWithValidScheme(
+ const std::string& url);
+
+} // namespace settings
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SERVER_PRINTER_URL_UTIL_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util_unittest.cc
new file mode 100644
index 00000000000..26e2ec17433
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/chromeos/server_printer_url_util_unittest.cc
@@ -0,0 +1,89 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/chromeos/server_printer_url_util.h"
+
+#include <string>
+
+#include "base/optional.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace chromeos {
+namespace settings {
+
+class ServerPrinterUrlUtilTest : public testing::Test {
+ public:
+ ServerPrinterUrlUtilTest() = default;
+ ~ServerPrinterUrlUtilTest() override = default;
+};
+
+TEST_F(ServerPrinterUrlUtilTest, IsValidScheme) {
+ GURL gurl1("ipp://123.123.11.11:123");
+ ASSERT_TRUE(HasValidServerPrinterScheme(gurl1));
+
+ GURL gurl2("http://123.123.11.11:123");
+ ASSERT_TRUE(HasValidServerPrinterScheme(gurl2));
+
+ GURL gurl3("ipps://123.123.11.11:123");
+ ASSERT_TRUE(HasValidServerPrinterScheme(gurl3));
+
+ GURL gurl4("https://123.123.11.11:123");
+ ASSERT_TRUE(HasValidServerPrinterScheme(gurl4));
+
+ // Missing scheme.
+ GURL gurl5("123.123.11.11:123");
+ ASSERT_FALSE(HasValidServerPrinterScheme(gurl5));
+
+ // Invalid scheme.
+ GURL gurl6("test://123.123.11.11:123");
+ ASSERT_FALSE(HasValidServerPrinterScheme(gurl6));
+}
+
+TEST_F(ServerPrinterUrlUtilTest, ConvertToGURL) {
+ // Test that a GURL is created with |gurl1| as its source.
+ std::string url1("http://123.123.11.11:631");
+ base::Optional<GURL> gurl1 = GenerateServerPrinterUrlWithValidScheme(url1);
+ DCHECK(gurl1);
+ ASSERT_EQ("http://123.123.11.11:631/", gurl1->spec());
+ ASSERT_EQ("http", gurl1->scheme());
+ ASSERT_EQ("631", gurl1->port());
+
+ // Test that HTTPS is the default scheme if a scheme is not provided.
+ std::string url2("123.123.11.11:631");
+ base::Optional<GURL> gurl2 = GenerateServerPrinterUrlWithValidScheme(url2);
+ DCHECK(gurl2);
+ ASSERT_EQ("https", gurl2->scheme());
+ ASSERT_EQ("https://123.123.11.11:631/", gurl2->spec());
+
+ // Test that if a URL has IPP as its scheme, it will create a new GURL with
+ // HTTP as its scheme and 631 as its port.
+ std::string url3("ipp://123.123.11.11");
+ base::Optional<GURL> gurl3 = GenerateServerPrinterUrlWithValidScheme(url3);
+ DCHECK(gurl3);
+ ASSERT_EQ("http", gurl3->scheme());
+ ASSERT_EQ("631", gurl3->port());
+ ASSERT_EQ("http://123.123.11.11:631/", gurl3->spec());
+
+ // Test that if a URL has IPP as its scheme and a specified port, it will
+ // create a new GURL with HTTP as the scheme and keeps the same port.
+ std::string url4("ipp://123.123.11.11:321");
+ base::Optional<GURL> gurl4 = GenerateServerPrinterUrlWithValidScheme(url4);
+ DCHECK(gurl4);
+ ASSERT_EQ("http", gurl4->scheme());
+ ASSERT_EQ("321", gurl4->port());
+ ASSERT_EQ("http://123.123.11.11:321/", gurl4->spec());
+
+ // Test that if a URL has IPPS as its scheme and a specified port, a new GURL
+ // is created with the scheme as HTTPS and keeps the same port.
+ std::string url5("ipps://123.123.11.11:555");
+ base::Optional<GURL> gurl5 = GenerateServerPrinterUrlWithValidScheme(url5);
+ DCHECK(gurl5);
+ ASSERT_EQ("https", gurl5->scheme());
+ ASSERT_EQ("555", gurl5->port());
+ ASSERT_EQ("https://123.123.11.11:555/", gurl5->spec());
+}
+
+} // namespace settings
+} // namespace chromeos
diff --git a/chromium/chrome/browser/ui/webui/settings/font_handler.cc b/chromium/chrome/browser/ui/webui/settings/font_handler.cc
index 062eb45fb0f..8fac7613e07 100644
--- a/chromium/chrome/browser/ui/webui/settings/font_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/font_handler.cc
@@ -13,28 +13,17 @@
#include "base/bind_helpers.h"
#include "base/i18n/rtl.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/font_list_async.h"
#include "content/public/browser/web_ui.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/common/extension_urls.h"
#if defined(OS_MACOSX)
#include "chrome/browser/ui/webui/settings_utils.h"
#endif
-namespace {
-
-const char kAdvancedFontSettingsExtensionId[] =
- "caclkomlalccbpcdllchkeecicepbmbm";
-
-} // namespace
-
namespace settings {
FontHandler::FontHandler(content::WebUI* webui)
@@ -51,78 +40,23 @@ void FontHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"fetchFontsData", base::BindRepeating(&FontHandler::HandleFetchFontsData,
base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "observeAdvancedFontExtensionAvailable",
- base::BindRepeating(
- &FontHandler::HandleObserveAdvancedFontExtensionAvailable,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "openAdvancedFontSettings",
- base::BindRepeating(&FontHandler::HandleOpenAdvancedFontSettings,
- base::Unretained(this)));
}
-void FontHandler::OnJavascriptAllowed() {
- extension_registry_observer_.Add(
- extensions::ExtensionRegistry::Get(profile_));
-}
+void FontHandler::OnJavascriptAllowed() {}
-void FontHandler::OnJavascriptDisallowed() {
- extension_registry_observer_.RemoveAll();
-}
+void FontHandler::OnJavascriptDisallowed() {}
void FontHandler::HandleFetchFontsData(const base::ListValue* args) {
CHECK_EQ(1U, args->GetSize());
std::string callback_id;
CHECK(args->GetString(0, &callback_id));
+ AllowJavascript();
content::GetFontListAsync(base::Bind(&FontHandler::FontListHasLoaded,
weak_ptr_factory_.GetWeakPtr(),
callback_id));
}
-void FontHandler::HandleObserveAdvancedFontExtensionAvailable(
- const base::ListValue* /*args*/) {
- AllowJavascript();
- NotifyAdvancedFontSettingsAvailability();
-}
-
-void FontHandler::HandleOpenAdvancedFontSettings(
- const base::ListValue* /*args*/) {
- const extensions::Extension* extension = GetAdvancedFontSettingsExtension();
- if (!extension)
- return;
- extensions::ExtensionTabUtil::OpenOptionsPage(
- extension,
- chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()));
-}
-
-const extensions::Extension* FontHandler::GetAdvancedFontSettingsExtension() {
- extensions::ExtensionService* service =
- extensions::ExtensionSystem::Get(profile_)->extension_service();
- if (!service->IsExtensionEnabled(kAdvancedFontSettingsExtensionId))
- return nullptr;
- extensions::ExtensionRegistry* registry =
- extensions::ExtensionRegistry::Get(profile_);
- return registry->GetInstalledExtension(kAdvancedFontSettingsExtensionId);
-}
-
-void FontHandler::NotifyAdvancedFontSettingsAvailability() {
- FireWebUIListener("advanced-font-settings-installed",
- base::Value(GetAdvancedFontSettingsExtension() != nullptr));
-}
-
-void FontHandler::OnExtensionLoaded(content::BrowserContext*,
- const extensions::Extension*) {
- NotifyAdvancedFontSettingsAvailability();
-}
-
-void FontHandler::OnExtensionUnloaded(content::BrowserContext*,
- const extensions::Extension*,
- extensions::UnloadedExtensionReason) {
- NotifyAdvancedFontSettingsAvailability();
-}
-
void FontHandler::FontListHasLoaded(std::string callback_id,
std::unique_ptr<base::ListValue> list) {
// Font list. Selects the directionality for the fonts in the given list.
@@ -142,11 +76,6 @@ void FontHandler::FontListHasLoaded(std::string callback_id,
base::DictionaryValue response;
response.Set("fontList", std::move(list));
- GURL extension_url(extension_urls::GetWebstoreItemDetailURLPrefix());
- response.SetString(
- "extensionUrl",
- extension_url.Resolve(kAdvancedFontSettingsExtensionId).spec());
-
ResolveJavascriptCallback(base::Value(callback_id), response);
}
diff --git a/chromium/chrome/browser/ui/webui/settings/font_handler.h b/chromium/chrome/browser/ui/webui/settings/font_handler.h
index 3c0a284ca9e..6864cb5381c 100644
--- a/chromium/chrome/browser/ui/webui/settings/font_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/font_handler.h
@@ -12,8 +12,6 @@
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/browser/extension_registry_observer.h"
namespace base {
class ListValue;
@@ -23,17 +21,12 @@ namespace content {
class WebUI;
}
-namespace extensions {
-class Extension;
-}
-
class Profile;
namespace settings {
// Handle OS font list and font preference settings.
-class FontHandler : public SettingsPageUIHandler,
- public extensions::ExtensionRegistryObserver {
+class FontHandler : public SettingsPageUIHandler {
public:
explicit FontHandler(content::WebUI* webui);
~FontHandler() override;
@@ -43,36 +36,14 @@ class FontHandler : public SettingsPageUIHandler,
void OnJavascriptAllowed() override;
void OnJavascriptDisallowed() override;
- // ExtensionRegistryObserver implementation.
- void OnExtensionLoaded(content::BrowserContext* browser_context,
- const extensions::Extension* extension) override;
- void OnExtensionUnloaded(content::BrowserContext* browser_context,
- const extensions::Extension* extension,
- extensions::UnloadedExtensionReason reason) override;
-
private:
// Handler for script asking for font information.
void HandleFetchFontsData(const base::ListValue* args);
- // Listen for changes to whether the advanced font extension is available.
- // An initial update will be sent when observation begins.
- void HandleObserveAdvancedFontExtensionAvailable(const base::ListValue* args);
-
- // Open the advanced font settings page.
- void HandleOpenAdvancedFontSettings(const base::ListValue* args);
-
// Callback to handle fonts loading.
void FontListHasLoaded(std::string callback_id,
std::unique_ptr<base::ListValue> list);
- const extensions::Extension* GetAdvancedFontSettingsExtension();
-
- void NotifyAdvancedFontSettingsAvailability();
-
- ScopedObserver<extensions::ExtensionRegistry,
- extensions::ExtensionRegistryObserver>
- extension_registry_observer_{this};
-
Profile* profile_; // Weak pointer.
base::WeakPtrFactory<FontHandler> weak_ptr_factory_{this};
diff --git a/chromium/chrome/browser/ui/webui/settings/hats_handler.cc b/chromium/chrome/browser/ui/webui/settings/hats_handler.cc
new file mode 100644
index 00000000000..74723f1b870
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/hats_handler.cc
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/hats_handler.h"
+
+#include "base/bind.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/hats/hats_service.h"
+#include "chrome/browser/ui/hats/hats_service_factory.h"
+#include "content/public/browser/visibility.h"
+#include "content/public/browser/web_contents.h"
+
+namespace settings {
+
+HatsHandler::HatsHandler() = default;
+
+HatsHandler::~HatsHandler() = default;
+
+void HatsHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "tryShowHatsSurvey",
+ base::BindRepeating(&HatsHandler::HandleTryShowHatsSurvey,
+ base::Unretained(this)));
+}
+
+void HatsHandler::HandleTryShowHatsSurvey(const base::ListValue* args) {
+ HatsService* hats_service = HatsServiceFactory::GetForProfile(
+ Profile::FromWebUI(web_ui()), /* create_if_necessary = */ true);
+ if (hats_service) {
+ hats_service->LaunchDelayedSurveyForWebContents(
+ kHatsSurveyTriggerSettingsPrivacy, web_ui()->GetWebContents(), 20000);
+ }
+}
+
+} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/hats_handler.h b/chromium/chrome/browser/ui/webui/settings/hats_handler.h
new file mode 100644
index 00000000000..f2e22b4a0c5
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/hats_handler.h
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_HATS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_HATS_HANDLER_H_
+
+#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+
+namespace settings {
+
+// Settings page UI handler that shows HaTS surveys.
+class HatsHandler : public SettingsPageUIHandler {
+ public:
+ HatsHandler();
+
+ // Not copyable or movable
+ HatsHandler(const HatsHandler&) = delete;
+ HatsHandler& operator=(const HatsHandler&) = delete;
+
+ ~HatsHandler() override;
+
+ // WebUIMessageHandler implementation.
+ void RegisterMessages() override;
+
+ void HandleTryShowHatsSurvey(const base::ListValue* args);
+
+ private:
+ friend class HatsHandlerTest;
+ FRIEND_TEST_ALL_PREFIXES(HatsHandlerTest, HandleTryShowHatsSurvey);
+
+ // SettingsPageUIHandler implementation.
+ void OnJavascriptAllowed() override {}
+ void OnJavascriptDisallowed() override {}
+};
+
+} // namespace settings
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_HATS_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/hats_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/hats_handler_unittest.cc
new file mode 100644
index 00000000000..dc459945792
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/hats_handler_unittest.cc
@@ -0,0 +1,65 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/hats_handler.h"
+
+#include <memory>
+#include <string>
+
+#include "base/values.h"
+#include "chrome/browser/ui/hats/hats_service.h"
+#include "chrome/browser/ui/hats/hats_service_factory.h"
+#include "chrome/browser/ui/hats/mock_hats_service.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "content/public/test/test_web_ui.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+class Profile;
+
+namespace settings {
+
+class HatsHandlerTest : public ChromeRenderViewHostTestHarness {
+ public:
+ void SetUp() override {
+ ChromeRenderViewHostTestHarness::SetUp();
+
+ web_ui_ = std::make_unique<content::TestWebUI>();
+ web_ui_->set_web_contents(web_contents());
+ handler_ = std::make_unique<HatsHandler>();
+ handler_->set_web_ui(web_ui());
+ handler_->AllowJavascript();
+ web_ui_->ClearTrackedCalls();
+
+ mock_hats_service_ = static_cast<MockHatsService*>(
+ HatsServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+ profile(), base::BindRepeating(&BuildMockHatsService)));
+ }
+
+ void TearDown() override {
+ handler_->set_web_ui(nullptr);
+ handler_.reset();
+ web_ui_.reset();
+
+ ChromeRenderViewHostTestHarness::TearDown();
+ }
+
+ content::TestWebUI* web_ui() { return web_ui_.get(); }
+ HatsHandler* handler() { return handler_.get(); }
+ MockHatsService* mock_hats_service_;
+
+ private:
+ std::unique_ptr<content::TestWebUI> web_ui_;
+ std::unique_ptr<HatsHandler> handler_;
+};
+
+TEST_F(HatsHandlerTest, HandleTryShowHatsSurvey) {
+ EXPECT_CALL(*mock_hats_service_,
+ LaunchDelayedSurveyForWebContents(
+ kHatsSurveyTriggerSettingsPrivacy, web_contents(), 20000));
+ base::ListValue args;
+ handler()->HandleTryShowHatsSurvey(&args);
+ task_environment()->RunUntilIdle();
+}
+
+} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_import_data_handler.cc b/chromium/chrome/browser/ui/webui/settings/import_data_handler.cc
index b2e78bd722b..1637dc014a7 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_import_data_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/import_data_handler.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 "chrome/browser/ui/webui/settings/settings_import_data_handler.h"
+#include "chrome/browser/ui/webui/settings/import_data_handler.h"
#include <stddef.h>
@@ -38,10 +38,10 @@ namespace {
const char kImportStatusInProgress[] = "inProgress";
const char kImportStatusSucceeded[] = "succeeded";
const char kImportStatusFailed[] = "failed";
-}
+} // namespace
ImportDataHandler::ImportDataHandler()
- : importer_host_(NULL), import_did_succeed_(false) {
+ : importer_host_(nullptr), import_did_succeed_(false) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
@@ -49,7 +49,7 @@ ImportDataHandler::~ImportDataHandler() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (importer_host_)
- importer_host_->set_observer(NULL);
+ importer_host_->set_observer(nullptr);
if (select_file_dialog_.get())
select_file_dialog_->ListenerDestroyed();
@@ -60,14 +60,14 @@ void ImportDataHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"initializeImportDialog",
- base::BindRepeating(&ImportDataHandler::InitializeDialog,
+ base::BindRepeating(&ImportDataHandler::HandleInitializeImportDialog,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
- "importData", base::BindRepeating(&ImportDataHandler::ImportData,
+ "importData", base::BindRepeating(&ImportDataHandler::HandleImportData,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"importFromBookmarksFile",
- base::BindRepeating(&ImportDataHandler::HandleChooseBookmarksFile,
+ base::BindRepeating(&ImportDataHandler::HandleImportFromBookmarksFile,
base::Unretained(this)));
}
@@ -77,7 +77,7 @@ void ImportDataHandler::OnJavascriptDisallowed() {
// Stops listening to updates from any ongoing imports.
if (importer_host_)
- importer_host_->set_observer(NULL);
+ importer_host_->set_observer(nullptr);
}
void ImportDataHandler::StartImport(
@@ -90,7 +90,7 @@ void ImportDataHandler::StartImport(
// If another import is already ongoing, let it finish silently.
if (importer_host_)
- importer_host_->set_observer(NULL);
+ importer_host_->set_observer(nullptr);
FireWebUIListener("import-data-status-changed",
base::Value(kImportStatusInProgress));
@@ -99,32 +99,32 @@ void ImportDataHandler::StartImport(
importer_host_ = new ExternalProcessImporterHost();
importer_host_->set_observer(this);
Profile* profile = Profile::FromWebUI(web_ui());
- importer_host_->StartImportSettings(source_profile, profile,
- imported_items,
+ importer_host_->StartImportSettings(source_profile, profile, imported_items,
new ProfileWriter(profile));
importer::LogImporterUseToMetrics("ImportDataHandler",
source_profile.importer_type);
}
-void ImportDataHandler::ImportData(const base::ListValue* args) {
+void ImportDataHandler::HandleImportData(const base::ListValue* args) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
int browser_index;
CHECK(args->GetInteger(0, &browser_index));
- PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
+ const base::DictionaryValue* types = nullptr;
+ CHECK(args->GetDictionary(1, &types));
uint16_t selected_items = importer::NONE;
- if (prefs->GetBoolean(prefs::kImportDialogAutofillFormData))
+ if (*types->FindBoolKey(prefs::kImportDialogAutofillFormData))
selected_items |= importer::AUTOFILL_FORM_DATA;
- if (prefs->GetBoolean(prefs::kImportDialogBookmarks))
+ if (*types->FindBoolKey(prefs::kImportDialogBookmarks))
selected_items |= importer::FAVORITES;
- if (prefs->GetBoolean(prefs::kImportDialogHistory))
+ if (*types->FindBoolKey(prefs::kImportDialogHistory))
selected_items |= importer::HISTORY;
- if (prefs->GetBoolean(prefs::kImportDialogSavedPasswords))
+ if (*types->FindBoolKey(prefs::kImportDialogSavedPasswords))
selected_items |= importer::PASSWORDS;
- if (prefs->GetBoolean(prefs::kImportDialogSearchEngine))
+ if (*types->FindBoolKey(prefs::kImportDialogSearchEngine))
selected_items |= importer::SEARCH_ENGINES;
const importer::SourceProfile& source_profile =
@@ -136,11 +136,12 @@ void ImportDataHandler::ImportData(const base::ListValue* args) {
StartImport(source_profile, imported_items);
} else {
LOG(WARNING) << "There were no settings to import from '"
- << source_profile.importer_name << "'.";
+ << source_profile.importer_name << "'.";
}
}
-void ImportDataHandler::InitializeDialog(const base::ListValue* args) {
+void ImportDataHandler::HandleInitializeImportDialog(
+ const base::ListValue* args) {
AllowJavascript();
CHECK_EQ(1U, args->GetSize());
@@ -155,6 +156,28 @@ void ImportDataHandler::InitializeDialog(const base::ListValue* args) {
base::Unretained(this), callback_id));
}
+void ImportDataHandler::HandleImportFromBookmarksFile(
+ const base::ListValue* args) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ DCHECK(args && args->empty());
+ select_file_dialog_ = ui::SelectFileDialog::Create(
+ this,
+ std::make_unique<ChromeSelectFilePolicy>(web_ui()->GetWebContents()));
+
+ ui::SelectFileDialog::FileTypeInfo file_type_info;
+ file_type_info.extensions.resize(1);
+ file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
+
+ Browser* browser =
+ chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
+
+ select_file_dialog_->SelectFile(
+ ui::SelectFileDialog::SELECT_OPEN_FILE, base::string16(),
+ base::FilePath(), &file_type_info, 0, base::FilePath::StringType(),
+ browser->window()->GetNativeWindow(), nullptr);
+}
+
void ImportDataHandler::SendBrowserProfileData(const std::string& callback_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -168,14 +191,15 @@ void ImportDataHandler::SendBrowserProfileData(const std::string& callback_id) {
new base::DictionaryValue());
browser_profile->SetString("name", source_profile.importer_name);
browser_profile->SetInteger("index", i);
+ browser_profile->SetString("profileName", source_profile.profile);
browser_profile->SetBoolean("history",
- (browser_services & importer::HISTORY) != 0);
+ (browser_services & importer::HISTORY) != 0);
browser_profile->SetBoolean("favorites",
- (browser_services & importer::FAVORITES) != 0);
+ (browser_services & importer::FAVORITES) != 0);
browser_profile->SetBoolean("passwords",
- (browser_services & importer::PASSWORDS) != 0);
- browser_profile->SetBoolean("search",
- (browser_services & importer::SEARCH_ENGINES) != 0);
+ (browser_services & importer::PASSWORDS) != 0);
+ browser_profile->SetBoolean(
+ "search", (browser_services & importer::SEARCH_ENGINES) != 0);
browser_profile->SetBoolean(
"autofillFormData",
(browser_services & importer::AUTOFILL_FORM_DATA) != 0);
@@ -206,8 +230,8 @@ void ImportDataHandler::ImportItemEnded(importer::ImportItem item) {
void ImportDataHandler::ImportEnded() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- importer_host_->set_observer(NULL);
- importer_host_ = NULL;
+ importer_host_->set_observer(nullptr);
+ importer_host_ = nullptr;
FireWebUIListener("import-data-status-changed",
base::Value(import_did_succeed_ ? kImportStatusSucceeded
@@ -226,29 +250,4 @@ void ImportDataHandler::FileSelected(const base::FilePath& path,
StartImport(source_profile, importer::FAVORITES);
}
-void ImportDataHandler::HandleChooseBookmarksFile(const base::ListValue* args) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- DCHECK(args && args->empty());
- select_file_dialog_ = ui::SelectFileDialog::Create(
- this,
- std::make_unique<ChromeSelectFilePolicy>(web_ui()->GetWebContents()));
-
- ui::SelectFileDialog::FileTypeInfo file_type_info;
- file_type_info.extensions.resize(1);
- file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("html"));
-
- Browser* browser =
- chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
-
- select_file_dialog_->SelectFile(ui::SelectFileDialog::SELECT_OPEN_FILE,
- base::string16(),
- base::FilePath(),
- &file_type_info,
- 0,
- base::FilePath::StringType(),
- browser->window()->GetNativeWindow(),
- NULL);
-}
-
} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_import_data_handler.h b/chromium/chrome/browser/ui/webui/settings/import_data_handler.h
index 68c9c7519e5..6ee9d1a99a8 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_import_data_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/import_data_handler.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 CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_IMPORT_DATA_HANDLER_H_
-#define CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_IMPORT_DATA_HANDLER_H_
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_IMPORT_DATA_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_IMPORT_DATA_HANDLER_H_
#include <stdint.h>
@@ -38,9 +38,18 @@ class ImportDataHandler : public SettingsPageUIHandler,
void StartImport(const importer::SourceProfile& source_profile,
uint16_t imported_items);
- void ImportData(const base::ListValue* args);
+ // Handler for the "importData" message. First argument is the selected
+ // browser index, and second argument is the types of data to import.
+ void HandleImportData(const base::ListValue* args);
+
+ // Handler for the "initializeImportDialog" message. First argument is a
+ // callback id.
+ void HandleInitializeImportDialog(const base::ListValue* args);
+
+ // Handler for the "importFromBookmarksFile" message. Opens a file selection
+ // dialog to choose the bookmarks HTML file.
+ void HandleImportFromBookmarksFile(const base::ListValue* args);
- void InitializeDialog(const base::ListValue* args);
void SendBrowserProfileData(const std::string& callback_id);
// importer::ImporterProgressObserver:
@@ -54,9 +63,6 @@ class ImportDataHandler : public SettingsPageUIHandler,
int index,
void* params) override;
- // Opens a file selection dialog to choose the bookmarks HTML file.
- void HandleChooseBookmarksFile(const base::ListValue* args);
-
std::unique_ptr<ImporterList> importer_list_;
// If non-null it means importing is in progress. ImporterHost takes care
@@ -72,4 +78,4 @@ class ImportDataHandler : public SettingsPageUIHandler,
} // namespace settings
-#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_IMPORT_DATA_HANDLER_H_
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_IMPORT_DATA_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler.cc b/chromium/chrome/browser/ui/webui/settings/people_handler.cc
index 6dc8e03ca5a..57cd1e34ebb 100644
--- a/chromium/chrome/browser/ui/webui/settings/people_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/people_handler.cc
@@ -18,11 +18,13 @@
#include "build/build_config.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/profiles/profile_metrics.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/signin_error_controller_factory.h"
#include "chrome/browser/signin/signin_promo.h"
#include "chrome/browser/signin/signin_ui_util.h"
+#include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/sync/sync_ui_util.h"
#include "chrome/browser/ui/browser_finder.h"
@@ -32,6 +34,7 @@
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/common/url_constants.h"
+#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "components/autofill/core/common/autofill_prefs.h"
#include "components/prefs/pref_service.h"
@@ -39,6 +42,7 @@
#include "components/signin/public/base/signin_metrics.h"
#include "components/signin/public/base/signin_pref_names.h"
#include "components/signin/public/identity_manager/accounts_mutator.h"
+#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/primary_account_mutator.h"
#include "components/strings/grit/components_strings.h"
@@ -51,26 +55,23 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "google_apis/gaia/gaia_auth_util.h"
+#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/webui/web_ui_util.h"
+#include "ui/gfx/image/image.h"
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/quick_unlock/pin_backend.h"
-#else
-#include "chrome/browser/signin/signin_util.h"
+#if !defined(OS_CHROMEOS)
#include "chrome/browser/ui/webui/profile_helper.h"
#endif
#if BUILDFLAG(ENABLE_DICE_SUPPORT)
-#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/signin/account_consistency_mode_manager.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/image/image.h"
#endif
using content::WebContents;
using l10n_util::GetStringFUTF16;
using l10n_util::GetStringUTF16;
+using signin::ConsentLevel;
namespace {
@@ -88,11 +89,7 @@ struct SyncConfigInfo {
};
bool IsSyncSubpage(const GURL& current_url) {
- return (current_url == chrome::GetSettingsUrl(chrome::kSyncSetupSubPage)
-#if defined(OS_CHROMEOS)
- || current_url == chrome::GetOSSettingsUrl(chrome::kSyncSetupSubPage)
-#endif // defined(OS_CHROMEOS)
- );
+ return current_url == chrome::GetSettingsUrl(chrome::kSyncSetupSubPage);
}
SyncConfigInfo::SyncConfigInfo()
@@ -182,7 +179,6 @@ std::string GetSyncErrorAction(sync_ui_util::ActionType action_type) {
}
}
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
// Returns the base::Value associated with the account, to use in the stored
// accounts list.
base::Value GetAccountValue(const AccountInfo& account) {
@@ -198,7 +194,6 @@ base::Value GetAccountValue(const AccountInfo& account) {
}
return dictionary;
}
-#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
base::string16 GetEnterPassphraseBody(syncer::PassphraseType passphrase_type,
base::Time passphrase_time) {
@@ -254,9 +249,7 @@ base::string16 GetFullEncryptionBody(syncer::PassphraseType passphrase_type,
namespace settings {
// static
-const char PeopleHandler::kSpinnerPageStatus[] = "spinner";
const char PeopleHandler::kConfigurePageStatus[] = "configure";
-const char PeopleHandler::kTimeoutPageStatus[] = "timeout";
const char PeopleHandler::kDonePageStatus[] = "done";
const char PeopleHandler::kPassphraseFailedPageStatus[] = "passphraseFailed";
@@ -308,9 +301,11 @@ void PeopleHandler::RegisterMessages() {
base::BindRepeating(&PeopleHandler::HandleAttemptUserExit,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
- "RequestPinLoginState",
- base::BindRepeating(&PeopleHandler::HandleRequestPinLoginState,
- base::Unretained(this)));
+ "TurnOnSync", base::BindRepeating(&PeopleHandler::HandleTurnOnSync,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "TurnOffSync", base::BindRepeating(&PeopleHandler::HandleTurnOffSync,
+ base::Unretained(this)));
#else
web_ui()->RegisterMessageCallback(
"SyncSetupSignout", base::BindRepeating(&PeopleHandler::HandleSignout,
@@ -323,7 +318,6 @@ void PeopleHandler::RegisterMessages() {
base::BindRepeating(&PeopleHandler::HandleStartSignin,
base::Unretained(this)));
#endif
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
web_ui()->RegisterMessageCallback(
"SyncSetupGetStoredAccounts",
base::BindRepeating(&PeopleHandler::HandleGetStoredAccounts,
@@ -332,7 +326,6 @@ void PeopleHandler::RegisterMessages() {
"SyncSetupStartSyncingWithEmail",
base::BindRepeating(&PeopleHandler::HandleStartSyncingWithEmail,
base::Unretained(this)));
-#endif
web_ui()->RegisterMessageCallback(
"SyncStartKeyRetrieval",
base::BindRepeating(&PeopleHandler::HandleStartKeyRetrieval,
@@ -415,12 +408,6 @@ void PeopleHandler::DisplayGaiaLoginInNewTabOrWindow(
}
#endif
-#if defined(OS_CHROMEOS)
-void PeopleHandler::OnPinLoginAvailable(bool is_available) {
- FireWebUIListener("pin-login-available-changed", base::Value(is_available));
-}
-#endif
-
void PeopleHandler::OnDidClosePage(const base::ListValue* args) {
// Don't mark setup as complete if "didAbort" is true, or if authentication
// is still needed.
@@ -432,7 +419,7 @@ void PeopleHandler::OnDidClosePage(const base::ListValue* args) {
}
syncer::SyncService* PeopleHandler::GetSyncService() const {
- return profile_->IsSyncAllowed()
+ return ProfileSyncServiceFactory::IsSyncAllowed(profile_)
? ProfileSyncServiceFactory::GetForProfile(profile_)
: nullptr;
}
@@ -457,6 +444,11 @@ void PeopleHandler::HandleSetDatatypes(const base::ListValue* args) {
return;
}
+ // Don't enable non-registered types (for example, kApps may not be registered
+ // on Chrome OS).
+ configuration.selected_types.RetainAll(
+ service->GetUserSettings()->GetRegisteredSelectableTypes());
+
service->GetUserSettings()->SetSelectedTypes(configuration.sync_everything,
configuration.selected_types);
@@ -468,8 +460,8 @@ void PeopleHandler::HandleSetDatatypes(const base::ListValue* args) {
ProfileMetrics::LogProfileSyncInfo(ProfileMetrics::SYNC_CHOOSE);
}
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
void PeopleHandler::HandleGetStoredAccounts(const base::ListValue* args) {
+ AllowJavascript();
CHECK_EQ(1U, args->GetSize());
const base::Value* callback_id;
CHECK(args->Get(0, &callback_id));
@@ -487,30 +479,33 @@ void PeopleHandler::OnExtendedAccountInfoRemoved(const AccountInfo& info) {
base::Value PeopleHandler::GetStoredAccountsList() {
base::Value accounts(base::Value::Type::LIST);
- const bool dice_enabled =
- AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_);
-
- if (dice_enabled) {
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+ if (AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_)) {
// If dice is enabled, show all the accounts.
- for (auto const& account :
+ for (const auto& account :
signin_ui_util::GetAccountsForDicePromos(profile_)) {
accounts.Append(GetAccountValue(account));
}
- } else {
- // If dice is disabled (and unified consent enabled), show only the primary
- // account.
- auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_);
- base::Optional<AccountInfo> primary_account_info =
- identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken(
- identity_manager->GetPrimaryAccountInfo());
- if (primary_account_info.has_value())
- accounts.Append(GetAccountValue(primary_account_info.value()));
+ return accounts;
}
-
+#endif
+ // Guest mode does not have a primary account (or an IdentityManager).
+ if (profile_->IsGuestSession())
+ return base::ListValue();
+ // If DICE is disabled for this profile or unsupported on this platform (e.g.
+ // Chrome OS), then show only the primary account, whether or not that account
+ // has consented to sync.
+ auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_);
+ base::Optional<AccountInfo> primary_account_info =
+ identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken(
+ identity_manager->GetPrimaryAccountInfo(ConsentLevel::kNotRequired));
+ if (primary_account_info.has_value())
+ accounts.Append(GetAccountValue(primary_account_info.value()));
return accounts;
}
void PeopleHandler::HandleStartSyncingWithEmail(const base::ListValue* args) {
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
DCHECK(AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_));
const base::Value* email;
const base::Value* is_default_promo_account;
@@ -530,8 +525,11 @@ void PeopleHandler::HandleStartSyncingWithEmail(const base::ListValue* args) {
maybe_account.has_value() ? maybe_account.value() : AccountInfo(),
signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS,
is_default_promo_account->GetBool());
-}
+#else
+ // TODO(jamescook): Enable sync on non-DICE platforms (e.g. Chrome OS).
+ NOTIMPLEMENTED();
#endif
+}
void PeopleHandler::HandleSetEncryption(const base::ListValue* args) {
SyncConfigInfo configuration;
@@ -577,6 +575,11 @@ void PeopleHandler::HandleSetEncryption(const base::ListValue* args) {
// data types.
passphrase_failed = !service->GetUserSettings()->SetDecryptionPassphrase(
configuration.passphrase);
+ } else if (service->GetUserSettings()->IsTrustedVaultKeyRequired()) {
+ // There are pending keys due to trusted vault keys being required, likely
+ // because something changed since the UI was displayed. A passphrase
+ // cannot be set in such circumstances.
+ passphrase_failed = true;
} else {
// OK, the user sent us a passphrase, but we don't have pending keys. So
// it either means that the pending keys were resolved somehow since the
@@ -646,13 +649,22 @@ void PeopleHandler::HandleAttemptUserExit(const base::ListValue* args) {
chrome::AttemptUserExit();
}
-void PeopleHandler::HandleRequestPinLoginState(const base::ListValue* args) {
- AllowJavascript();
- chromeos::quick_unlock::PinBackend::GetInstance()->HasLoginSupport(
- base::BindOnce(&PeopleHandler::OnPinLoginAvailable,
- weak_factory_.GetWeakPtr()));
+void PeopleHandler::HandleTurnOnSync(const base::ListValue* args) {
+ // TODO(https://crbug.com/1050677)
+ NOTIMPLEMENTED();
}
-#endif
+
+void PeopleHandler::HandleTurnOffSync(const base::ListValue* args) {
+ auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_);
+ DCHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSync));
+ DCHECK(signin_util::IsUserSignoutAllowedForProfile(profile_));
+
+ if (GetSyncService())
+ syncer::RecordSyncEvent(syncer::STOP_FROM_OPTIONS);
+
+ identity_manager->GetPrimaryAccountMutator()->RevokeSyncConsent();
+}
+#endif // defined(OS_CHROMEOS)
#if !defined(OS_CHROMEOS)
void PeopleHandler::HandleStartSignin(const base::ListValue* args) {
@@ -807,6 +819,10 @@ void PeopleHandler::InitializeSyncBlocker() {
if (!service)
return;
+ // The user opened settings directly to the syncSetup sub-page, because they
+ // clicked "Settings" in the browser sync consent dialog or because they
+ // clicked "Review sync options" in the Chrome OS out-of-box experience.
+ // Don't start syncing until they finish setup.
if (IsSyncSubpage(web_contents->GetVisibleURL())) {
sync_blocker_ = service->GetSetupInProgressHandle();
}
@@ -860,7 +876,6 @@ std::unique_ptr<base::DictionaryValue> PeopleHandler::GetSyncStatusDictionary()
if (profile_->IsGuestSession()) {
// Cannot display signin status when running in guest mode on chromeos
// because there is no IdentityManager.
- sync_status->SetBoolean("signinAllowed", false);
return sync_status;
}
@@ -870,7 +885,6 @@ std::unique_ptr<base::DictionaryValue> PeopleHandler::GetSyncStatusDictionary()
auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_);
DCHECK(identity_manager);
-#if !defined(OS_CHROMEOS)
// Signout is not allowed if the user has policy (crbug.com/172204).
if (!signin_util::IsUserSignoutAllowedForProfile(profile_)) {
std::string username = identity_manager->GetPrimaryAccountInfo().email;
@@ -880,7 +894,6 @@ std::unique_ptr<base::DictionaryValue> PeopleHandler::GetSyncStatusDictionary()
if (!username.empty())
sync_status->SetString("domain", gaia::ExtractDomainName(username));
}
-#endif
// This is intentionally not using GetSyncService(), in order to access more
// nuanced information, since GetSyncService() returns nullptr if anything
@@ -890,8 +903,6 @@ std::unique_ptr<base::DictionaryValue> PeopleHandler::GetSyncStatusDictionary()
bool disallowed_by_policy =
service && service->HasDisableReason(
syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY);
- sync_status->SetBoolean(
- "signinAllowed", profile_->GetPrefs()->GetBoolean(prefs::kSigninAllowed));
sync_status->SetBoolean("syncSystemEnabled", (service != nullptr));
sync_status->SetBoolean(
"firstSetupInProgress",
@@ -906,7 +917,7 @@ std::unique_ptr<base::DictionaryValue> PeopleHandler::GetSyncStatusDictionary()
sync_status->SetString("statusText",
GetStringUTF16(status_labels.status_label_string_id));
sync_status->SetString("statusActionText",
- GetStringUTF16(status_labels.link_label_string_id));
+ GetStringUTF16(status_labels.button_string_id));
sync_status->SetBoolean(
"hasError", status_labels.message_type == sync_ui_util::SYNC_ERROR ||
status_labels.message_type ==
@@ -921,6 +932,8 @@ std::unique_ptr<base::DictionaryValue> PeopleHandler::GetSyncStatusDictionary()
sync_status->SetBoolean(
"disabled", !service || disallowed_by_policy ||
!service->GetUserSettings()->IsSyncAllowedByPlatform());
+ // NOTE: This means signed-in for *sync*. It can be false when the user is
+ // signed-in to the content area or to the browser.
sync_status->SetBoolean("signedIn", identity_manager->HasPrimaryAccount());
sync_status->SetString("signedInUsername",
signin_ui_util::GetAuthenticatedUsername(profile_));
@@ -964,13 +977,10 @@ void PeopleHandler::PushSyncPrefs() {
sync_user_settings->GetRegisteredSelectableTypes();
const syncer::UserSelectableTypeSet selected_types =
sync_user_settings->GetSelectedTypes();
- const syncer::UserSelectableTypeSet enforced_types =
- sync_user_settings->GetForcedTypes();
for (syncer::UserSelectableType type : syncer::UserSelectableTypeSet::All()) {
const std::string type_name = syncer::GetUserSelectableTypeName(type);
args.SetBoolean(type_name + "Registered", registered_types.Has(type));
args.SetBoolean(type_name + "Synced", selected_types.Has(type));
- args.SetBoolean(type_name + "Enforced", enforced_types.Has(type));
}
args.SetBoolean("syncAllDataTypes",
sync_user_settings->IsSyncEverythingEnabled());
@@ -988,9 +998,10 @@ void PeopleHandler::PushSyncPrefs() {
args.SetBoolean("passphraseRequired",
sync_user_settings->IsPassphraseRequired());
- args.SetBoolean(
- "trustedVaultKeysRequired",
- sync_user_settings->IsTrustedVaultKeyRequiredForPreferredDataTypes());
+ // Same as above, we call IsTrustedVaultKeyRequired() here instead of.
+ // IsTrustedVaultKeyRequiredForPreferredDataTypes().
+ args.SetBoolean("trustedVaultKeysRequired",
+ sync_user_settings->IsTrustedVaultKeyRequired());
syncer::PassphraseType passphrase_type =
sync_user_settings->GetPassphraseType();
diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler.h b/chromium/chrome/browser/ui/webui/settings/people_handler.h
index 1573a3ce552..50093e129c3 100644
--- a/chromium/chrome/browser/ui/webui/settings/people_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/people_handler.h
@@ -47,13 +47,9 @@ class PeopleHandler : public SettingsPageUIHandler,
public:
// TODO(tommycli): Remove these strings and instead use WebUIListener events.
// These string constants are used from JavaScript (sync_browser_proxy.js).
- static const char kSpinnerPageStatus[];
static const char kConfigurePageStatus[];
- static const char kTimeoutPageStatus[];
static const char kDonePageStatus[];
static const char kPassphraseFailedPageStatus[];
- // TODO(crbug.com/): Remove kSpinnerPageStatus and kTimeoutPageStatus (plus
- // their JS-side handling); they're unused.
explicit PeopleHandler(Profile* profile);
~PeopleHandler() override;
@@ -89,6 +85,7 @@ class PeopleHandler : public SettingsPageUIHandler,
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, ShowSyncSetup);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncEverything);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncAllManually);
+ FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, NonRegisteredType);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestPassphraseStillRequired);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncIndividualTypes);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest,
@@ -97,10 +94,10 @@ class PeopleHandler : public SettingsPageUIHandler,
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, EnterWrongExistingPassphrase);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, EnterBlankExistingPassphrase);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TurnOnEncryptAllDisallowed);
- FRIEND_TEST_ALL_PREFIXES(PeopleHandlerNonCrosTest,
+ FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest,
UnrecoverableErrorInitializingSync);
- FRIEND_TEST_ALL_PREFIXES(PeopleHandlerNonCrosTest, GaiaErrorInitializingSync);
- FRIEND_TEST_ALL_PREFIXES(PeopleHandlerFirstSigninTest, DisplayBasicLogin);
+ FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, GaiaErrorInitializingSync);
+ FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, DisplayBasicLogin);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest,
AcquireSyncBlockerWhenLoadingSyncSettingsSubpage);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, RestartSyncAfterDashboardClear);
@@ -113,6 +110,9 @@ class PeopleHandler : public SettingsPageUIHandler,
DashboardClearWhileSettingsOpen_ConfirmLater);
FRIEND_TEST_ALL_PREFIXES(PeopleHandlerDiceUnifiedConsentTest,
StoredAccountsList);
+ FRIEND_TEST_ALL_PREFIXES(PeopleHandlerGuestModeTest, GetStoredAccountsList);
+ FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TurnOffSync);
+ FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, GetStoredAccountsList);
// SettingsPageUIHandler implementation.
void RegisterMessages() override;
@@ -127,10 +127,8 @@ class PeopleHandler : public SettingsPageUIHandler,
const CoreAccountInfo& primary_account_info) override;
void OnPrimaryAccountCleared(
const CoreAccountInfo& previous_primary_account_info) override;
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
-#endif
// syncer::SyncServiceObserver implementation.
void OnStateChanged(syncer::SyncService* sync) override;
@@ -155,10 +153,11 @@ class PeopleHandler : public SettingsPageUIHandler,
void HandleSetDatatypes(const base::ListValue* args);
void HandleSetEncryption(const base::ListValue* args);
void HandleShowSetupUI(const base::ListValue* args);
- void HandleAttemptUserExit(const base::ListValue* args);
void HandleSyncPrefsDispatch(const base::ListValue* args);
#if defined(OS_CHROMEOS)
- void HandleRequestPinLoginState(const base::ListValue* args);
+ void HandleAttemptUserExit(const base::ListValue* args);
+ void HandleTurnOnSync(const base::ListValue* args);
+ void HandleTurnOffSync(const base::ListValue* args);
#endif
#if !defined(OS_CHROMEOS)
void HandleStartSignin(const base::ListValue* args);
@@ -178,15 +177,9 @@ class PeopleHandler : public SettingsPageUIHandler,
signin_metrics::AccessPoint access_point);
#endif
-#if defined(OS_CHROMEOS)
- void OnPinLoginAvailable(bool is_available);
-#endif
-
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
void HandleGetStoredAccounts(const base::ListValue* args);
void HandleStartSyncingWithEmail(const base::ListValue* args);
base::Value GetStoredAccountsList();
-#endif
// Pushes the updated sync prefs to JavaScript.
void PushSyncPrefs();
@@ -233,9 +226,7 @@ class PeopleHandler : public SettingsPageUIHandler,
ScopedObserver<syncer::SyncService, syncer::SyncServiceObserver>
sync_service_observer_{this};
-#if defined(OS_CHROMEOS)
base::WeakPtrFactory<PeopleHandler> weak_factory_{this};
-#endif
DISALLOW_COPY_AND_ASSIGN(PeopleHandler);
};
diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc
index 60c758ab17d..f2ecedd6377 100644
--- a/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -14,6 +14,7 @@
#include "base/json/json_writer.h"
#include "base/macros.h"
#include "base/stl_util.h"
+#include "base/test/mock_callback.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/defaults.h"
@@ -35,9 +36,11 @@
#include "chrome/test/base/testing_profile.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/identity_manager/accounts_mutator.h"
+#include "components/signin/public/identity_manager/consent_level.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/signin/public/identity_manager/identity_test_utils.h"
#include "components/sync/base/passphrase_enums.h"
+#include "components/sync/base/user_selectable_type.h"
#include "components/sync/driver/mock_sync_service.h"
#include "components/sync/driver/sync_user_settings_impl.h"
#include "components/sync/driver/sync_user_settings_mock.h"
@@ -50,6 +53,7 @@
#include "content/public/test/web_contents_tester.h"
#include "testing/gtest/include/gtest/gtest.h"
+using signin::ConsentLevel;
using ::testing::_;
using ::testing::ByMove;
using ::testing::Const;
@@ -211,19 +215,15 @@ class TestWebUIProvider
class PeopleHandlerTest : public ChromeRenderViewHostTestHarness {
public:
- PeopleHandlerTest() {}
+ PeopleHandlerTest() = default;
+ ~PeopleHandlerTest() override = default;
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
- // Sign in the user.
identity_test_env_adaptor_ =
std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile());
- std::string username = GetTestUser();
- if (!username.empty())
- identity_test_env()->SetPrimaryAccount(username);
-
mock_sync_service_ = static_cast<syncer::MockSyncService*>(
ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
profile(), base::BindRepeating(&BuildMockSyncService)));
@@ -241,13 +241,7 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness {
ON_CALL(*mock_sync_service_, GetSetupInProgressHandle())
.WillByDefault(
Return(ByMove(std::make_unique<syncer::SyncSetupInProgressHandle>(
- base::BindRepeating(
- &PeopleHandlerTest::OnSetupInProgressHandleDestroyed,
- base::Unretained(this))))));
-
- handler_ = std::make_unique<TestingPeopleHandler>(&web_ui_, profile());
- handler_->AllowJavascript();
- web_ui_.set_web_contents(web_contents());
+ mock_on_setup_in_progress_handle_destroyed_.Get()))));
}
void TearDown() override {
@@ -262,10 +256,18 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness {
GetIdentityTestEnvironmentFactories();
}
+ void SigninUser() { identity_test_env()->SetPrimaryAccount(kTestUser); }
+
+ void CreatePeopleHandler() {
+ handler_ = std::make_unique<TestingPeopleHandler>(&web_ui_, profile());
+ handler_->AllowJavascript();
+ web_ui_.set_web_contents(web_contents());
+ }
+
// Setup the expectations for calls made when displaying the config page.
void SetDefaultExpectationsForConfigPage() {
ON_CALL(*mock_sync_service_, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsSyncRequested())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_->GetMockUserSettings(),
@@ -305,17 +307,6 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness {
EXPECT_EQ(expected_status, status);
}
- void ExpectPageStatusChanged(const std::string& expected_status) {
- auto& data = *web_ui_.call_data().back();
- EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
- std::string event;
- ASSERT_TRUE(data.arg1()->GetAsString(&event));
- EXPECT_EQ("page-status-changed", event);
- std::string status;
- ASSERT_TRUE(data.arg2()->GetAsString(&status));
- EXPECT_EQ(expected_status, status);
- }
-
const base::DictionaryValue* ExpectSyncPrefsChanged() {
const content::TestWebUI::CallData& data1 = *web_ui_.call_data().back();
EXPECT_EQ("cr.webUIListenerCallback", data1.function_name());
@@ -329,20 +320,33 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness {
return dictionary;
}
- void NotifySyncStateChanged() {
- handler_->OnStateChanged(mock_sync_service_);
+ const base::DictionaryValue* ExpectSyncStatusChanged() {
+ const content::TestWebUI::CallData& data = *web_ui_.call_data().back();
+ EXPECT_EQ("cr.webUIListenerCallback", data.function_name());
+
+ std::string event;
+ EXPECT_TRUE(data.arg1()->GetAsString(&event));
+ EXPECT_EQ(event, "sync-status-changed");
+
+ const base::DictionaryValue* dictionary = nullptr;
+ EXPECT_TRUE(data.arg2()->GetAsDictionary(&dictionary));
+ return dictionary;
}
- virtual std::string GetTestUser() {
- return std::string(kTestUser);
+ void NotifySyncStateChanged() {
+ handler_->OnStateChanged(mock_sync_service_);
}
signin::IdentityTestEnvironment* identity_test_env() {
return identity_test_env_adaptor_->identity_test_env();
}
- MOCK_METHOD0(OnSetupInProgressHandleDestroyed, void());
+ signin::IdentityManager* identity_manager() {
+ return identity_test_env()->identity_manager();
+ }
+ testing::NiceMock<base::MockCallback<base::RepeatingClosure>>
+ mock_on_setup_in_progress_handle_destroyed_;
syncer::MockSyncService* mock_sync_service_;
std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
identity_test_env_adaptor_;
@@ -354,12 +358,11 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness {
DISALLOW_COPY_AND_ASSIGN(PeopleHandlerTest);
};
-class PeopleHandlerFirstSigninTest : public PeopleHandlerTest {
- std::string GetTestUser() override { return std::string(); }
-};
-
#if !defined(OS_CHROMEOS)
-TEST_F(PeopleHandlerFirstSigninTest, DisplayBasicLogin) {
+TEST_F(PeopleHandlerTest, DisplayBasicLogin) {
+ ASSERT_FALSE(identity_test_env()->identity_manager()->HasPrimaryAccount(
+ ConsentLevel::kSync));
+ CreatePeopleHandler();
// Test that the HandleStartSignin call enables JavaScript.
handler_->DisallowJavascript();
@@ -374,22 +377,24 @@ TEST_F(PeopleHandlerFirstSigninTest, DisplayBasicLogin) {
// Sync setup hands off control to the gaia login tab.
EXPECT_EQ(
- NULL,
+ nullptr,
LoginUIServiceFactory::GetForProfile(profile())->current_login_ui());
ASSERT_FALSE(handler_->is_configuring_sync());
handler_->CloseSyncSetup();
EXPECT_EQ(
- NULL,
+ nullptr,
LoginUIServiceFactory::GetForProfile(profile())->current_login_ui());
}
#endif // !defined(OS_CHROMEOS)
TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndCancel) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsSyncRequested())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsFirstSetupComplete())
@@ -414,7 +419,7 @@ TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndCancel) {
handler_->CloseSyncSetup();
EXPECT_EQ(
- NULL,
+ nullptr,
LoginUIServiceFactory::GetForProfile(profile())->current_login_ui());
}
@@ -422,10 +427,12 @@ TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndCancel) {
// initialized.
TEST_F(PeopleHandlerTest,
DisplayConfigureWithEngineDisabledAndSyncStartupCompleted) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsFirstSetupComplete())
.WillByDefault(Return(false));
ON_CALL(*mock_sync_service_, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsSyncRequested())
.WillByDefault(Return(true));
// Sync engine is stopped initially, and will start up.
@@ -463,8 +470,10 @@ TEST_F(PeopleHandlerTest,
// initialized.
TEST_F(PeopleHandlerTest,
DisplayConfigureWithEngineDisabledAndCancelAfterSigninSuccess) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsSyncRequested())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsFirstSetupComplete())
@@ -484,15 +493,17 @@ TEST_F(PeopleHandlerTest,
// tell it we're through with the setup progress.
testing::InSequence seq;
EXPECT_CALL(*mock_sync_service_, StopAndClear());
- EXPECT_CALL(*this, OnSetupInProgressHandleDestroyed());
+ EXPECT_CALL(mock_on_setup_in_progress_handle_destroyed_, Run());
handler_->CloseSyncSetup();
EXPECT_EQ(
- NULL,
+ nullptr,
LoginUIServiceFactory::GetForProfile(profile())->current_login_ui());
}
TEST_F(PeopleHandlerTest, RestartSyncAfterDashboardClear) {
+ SigninUser();
+ CreatePeopleHandler();
// Clearing sync from the dashboard results in DISABLE_REASON_USER_CHOICE
// being set.
ON_CALL(*mock_sync_service_, GetDisableReasons())
@@ -507,7 +518,7 @@ TEST_F(PeopleHandlerTest, RestartSyncAfterDashboardClear) {
// SetSyncRequested(true) clears DISABLE_REASON_USER_CHOICE, and
// immediately starts initializing the engine.
ON_CALL(*mock_sync_service_, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsSyncRequested())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_, GetTransportState())
@@ -523,6 +534,8 @@ TEST_F(PeopleHandlerTest, RestartSyncAfterDashboardClear) {
TEST_F(PeopleHandlerTest,
RestartSyncAfterDashboardClearWithStandaloneTransport) {
+ SigninUser();
+ CreatePeopleHandler();
// Clearing sync from the dashboard results in DISABLE_REASON_USER_CHOICE
// being set. However, the sync engine has restarted in standalone transport
// mode.
@@ -538,7 +551,7 @@ TEST_F(PeopleHandlerTest,
// SetSyncRequested(true) clears DISABLE_REASON_USER_CHOICE. Since the
// engine is already running, it just gets reconfigured.
ON_CALL(*mock_sync_service_, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsSyncRequested())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_, GetTransportState())
@@ -555,6 +568,8 @@ TEST_F(PeopleHandlerTest,
// Tests that signals not related to user intention to configure sync don't
// trigger sync engine start.
TEST_F(PeopleHandlerTest, OnlyStartEngineWhenConfiguringSync) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_, GetTransportState())
.WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING));
EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(),
@@ -564,6 +579,8 @@ TEST_F(PeopleHandlerTest, OnlyStartEngineWhenConfiguringSync) {
}
TEST_F(PeopleHandlerTest, AcquireSyncBlockerWhenLoadingSyncSettingsSubpage) {
+ SigninUser();
+ CreatePeopleHandler();
// We set up a factory override here to prevent a new web ui from being
// created when we navigate to a page that would normally create one.
test_factory_ = std::make_unique<TestChromeWebUIControllerFactory>();
@@ -584,15 +601,9 @@ TEST_F(PeopleHandlerTest, AcquireSyncBlockerWhenLoadingSyncSettingsSubpage) {
EXPECT_TRUE(handler_->sync_blocker_);
}
-#if !defined(OS_CHROMEOS)
-
-class PeopleHandlerNonCrosTest : public PeopleHandlerTest {
- public:
- PeopleHandlerNonCrosTest() {}
-};
-
-// TODO(kochi): We need equivalent tests for ChromeOS.
-TEST_F(PeopleHandlerNonCrosTest, UnrecoverableErrorInitializingSync) {
+TEST_F(PeopleHandlerTest, UnrecoverableErrorInitializingSync) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_, GetDisableReasons())
.WillByDefault(
Return(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR));
@@ -604,7 +615,9 @@ TEST_F(PeopleHandlerNonCrosTest, UnrecoverableErrorInitializingSync) {
ASSERT_FALSE(handler_->is_configuring_sync());
}
-TEST_F(PeopleHandlerNonCrosTest, GaiaErrorInitializingSync) {
+TEST_F(PeopleHandlerTest, GaiaErrorInitializingSync) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_, GetDisableReasons())
.WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsFirstSetupComplete())
@@ -615,11 +628,11 @@ TEST_F(PeopleHandlerNonCrosTest, GaiaErrorInitializingSync) {
ASSERT_FALSE(handler_->is_configuring_sync());
}
-#endif // #if !defined(OS_CHROMEOS)
-
TEST_F(PeopleHandlerTest, TestSyncEverything) {
- std::string args = GetConfiguration(
- NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
+ SigninUser();
+ CreatePeopleHandler();
+ std::string args = GetConfiguration(nullptr, SYNC_ALL_DATA, GetAllTypes(),
+ std::string(), ENCRYPT_PASSWORDS);
base::ListValue list_args;
list_args.AppendString(kTestCallbackId);
list_args.AppendString(args);
@@ -637,8 +650,10 @@ TEST_F(PeopleHandlerTest, TestSyncEverything) {
}
TEST_F(PeopleHandlerTest, TestPassphraseStillRequired) {
- std::string args = GetConfiguration(
- NULL, SYNC_ALL_DATA, GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
+ SigninUser();
+ CreatePeopleHandler();
+ std::string args = GetConfiguration(nullptr, SYNC_ALL_DATA, GetAllTypes(),
+ std::string(), ENCRYPT_PASSWORDS);
base::ListValue list_args;
list_args.AppendString(kTestCallbackId);
list_args.AppendString(args);
@@ -659,6 +674,8 @@ TEST_F(PeopleHandlerTest, TestPassphraseStillRequired) {
}
TEST_F(PeopleHandlerTest, EnterExistingFrozenImplicitPassword) {
+ SigninUser();
+ CreatePeopleHandler();
base::DictionaryValue dict;
dict.SetBoolean("setNewPassphrase", false);
std::string args = GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(),
@@ -687,6 +704,8 @@ TEST_F(PeopleHandlerTest, EnterExistingFrozenImplicitPassword) {
}
TEST_F(PeopleHandlerTest, SetNewCustomPassphrase) {
+ SigninUser();
+ CreatePeopleHandler();
base::DictionaryValue dict;
dict.SetBoolean("setNewPassphrase", true);
std::string args = GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(),
@@ -714,6 +733,8 @@ TEST_F(PeopleHandlerTest, SetNewCustomPassphrase) {
}
TEST_F(PeopleHandlerTest, EnterWrongExistingPassphrase) {
+ SigninUser();
+ CreatePeopleHandler();
base::DictionaryValue dict;
dict.SetBoolean("setNewPassphrase", false);
std::string args = GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(),
@@ -742,6 +763,8 @@ TEST_F(PeopleHandlerTest, EnterWrongExistingPassphrase) {
}
TEST_F(PeopleHandlerTest, EnterBlankExistingPassphrase) {
+ SigninUser();
+ CreatePeopleHandler();
base::DictionaryValue dict;
dict.SetBoolean("setNewPassphrase", false);
std::string args = GetConfiguration(&dict,
@@ -772,14 +795,15 @@ TEST_F(PeopleHandlerTest, EnterBlankExistingPassphrase) {
// Walks through each user selectable type, and tries to sync just that single
// data type.
TEST_F(PeopleHandlerTest, TestSyncIndividualTypes) {
+ SigninUser();
+ CreatePeopleHandler();
+ SetDefaultExpectationsForConfigPage();
for (syncer::UserSelectableType type : GetAllTypes()) {
syncer::UserSelectableTypeSet type_to_set;
type_to_set.Put(type);
- std::string args = GetConfiguration(NULL,
- CHOOSE_WHAT_TO_SYNC,
- type_to_set,
- std::string(),
- ENCRYPT_PASSWORDS);
+ std::string args =
+ GetConfiguration(nullptr, CHOOSE_WHAT_TO_SYNC, type_to_set,
+ std::string(), ENCRYPT_PASSWORDS);
base::ListValue list_args;
list_args.AppendString(kTestCallbackId);
list_args.AppendString(args);
@@ -799,11 +823,12 @@ TEST_F(PeopleHandlerTest, TestSyncIndividualTypes) {
}
TEST_F(PeopleHandlerTest, TestSyncAllManually) {
- std::string args = GetConfiguration(NULL,
- CHOOSE_WHAT_TO_SYNC,
- GetAllTypes(),
- std::string(),
- ENCRYPT_PASSWORDS);
+ SigninUser();
+ CreatePeopleHandler();
+ SetDefaultExpectationsForConfigPage();
+ std::string args =
+ GetConfiguration(nullptr, CHOOSE_WHAT_TO_SYNC, GetAllTypes(),
+ std::string(), ENCRYPT_PASSWORDS);
base::ListValue list_args;
list_args.AppendString(kTestCallbackId);
list_args.AppendString(args);
@@ -820,7 +845,37 @@ TEST_F(PeopleHandlerTest, TestSyncAllManually) {
ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus);
}
+TEST_F(PeopleHandlerTest, NonRegisteredType) {
+ SigninUser();
+ CreatePeopleHandler();
+ SetDefaultExpectationsForConfigPage();
+
+ // Simulate apps not being registered.
+ syncer::UserSelectableTypeSet registered_types = GetAllTypes();
+ registered_types.Remove(syncer::UserSelectableType::kApps);
+ ON_CALL(*mock_sync_service_->GetMockUserSettings(),
+ GetRegisteredSelectableTypes())
+ .WillByDefault(Return(registered_types));
+ SetupInitializedSyncService();
+
+ // Simulate "Sync everything" being turned off, but all individual
+ // toggles left on.
+ std::string config =
+ GetConfiguration(/*extra_values=*/nullptr, CHOOSE_WHAT_TO_SYNC,
+ GetAllTypes(), std::string(), ENCRYPT_PASSWORDS);
+ base::ListValue list_args;
+ list_args.AppendString(kTestCallbackId);
+ list_args.AppendString(config);
+
+ // Only the registered types are selected.
+ EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(),
+ SetSelectedTypes(/*sync_everything=*/false, registered_types));
+ handler_->HandleSetDatatypes(&list_args);
+}
+
TEST_F(PeopleHandlerTest, ShowSyncSetup) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
.WillByDefault(Return(false));
ON_CALL(*mock_sync_service_->GetMockUserSettings(),
@@ -835,6 +890,8 @@ TEST_F(PeopleHandlerTest, ShowSyncSetup) {
}
TEST_F(PeopleHandlerTest, ShowSetupSyncEverything) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
.WillByDefault(Return(false));
ON_CALL(*mock_sync_service_->GetMockUserSettings(),
@@ -863,6 +920,8 @@ TEST_F(PeopleHandlerTest, ShowSetupSyncEverything) {
}
TEST_F(PeopleHandlerTest, ShowSetupManuallySyncAll) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
.WillByDefault(Return(false));
ON_CALL(*mock_sync_service_->GetMockUserSettings(),
@@ -880,6 +939,8 @@ TEST_F(PeopleHandlerTest, ShowSetupManuallySyncAll) {
}
TEST_F(PeopleHandlerTest, ShowSetupSyncForAllTypesIndividually) {
+ SigninUser();
+ CreatePeopleHandler();
for (syncer::UserSelectableType type : GetAllTypes()) {
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
.WillByDefault(Return(false));
@@ -911,6 +972,8 @@ TEST_F(PeopleHandlerTest, ShowSetupSyncForAllTypesIndividually) {
}
TEST_F(PeopleHandlerTest, ShowSetupOldGaiaPassphraseRequired) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), GetPassphraseType())
@@ -927,6 +990,8 @@ TEST_F(PeopleHandlerTest, ShowSetupOldGaiaPassphraseRequired) {
}
TEST_F(PeopleHandlerTest, ShowSetupCustomPassphraseRequired) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), GetPassphraseType())
@@ -943,8 +1008,10 @@ TEST_F(PeopleHandlerTest, ShowSetupCustomPassphraseRequired) {
}
TEST_F(PeopleHandlerTest, ShowSetupTrustedVaultKeysRequired) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(),
- IsTrustedVaultKeyRequiredForPreferredDataTypes())
+ IsTrustedVaultKeyRequired())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), GetPassphraseType())
.WillByDefault(Return(syncer::PassphraseType::kTrustedVaultPassphrase));
@@ -958,11 +1025,11 @@ TEST_F(PeopleHandlerTest, ShowSetupTrustedVaultKeysRequired) {
CheckBool(dictionary, "passphraseRequired", false);
CheckBool(dictionary, "trustedVaultKeysRequired", true);
EXPECT_FALSE(dictionary->FindKey("enterPassphraseBody"));
- // TODO: See how to verify the appropriate action, once it's actually
- // implemented.
}
TEST_F(PeopleHandlerTest, ShowSetupEncryptAll) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
.WillByDefault(Return(false));
ON_CALL(*mock_sync_service_->GetMockUserSettings(),
@@ -982,6 +1049,8 @@ TEST_F(PeopleHandlerTest, ShowSetupEncryptAll) {
}
TEST_F(PeopleHandlerTest, ShowSetupEncryptAllDisallowed) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired())
.WillByDefault(Return(false));
ON_CALL(*mock_sync_service_->GetMockUserSettings(),
@@ -1002,6 +1071,8 @@ TEST_F(PeopleHandlerTest, ShowSetupEncryptAllDisallowed) {
}
TEST_F(PeopleHandlerTest, TurnOnEncryptAllDisallowed) {
+ SigninUser();
+ CreatePeopleHandler();
ON_CALL(*mock_sync_service_->GetMockUserSettings(),
IsPassphraseRequiredForPreferredDataTypes())
.WillByDefault(Return(false));
@@ -1033,6 +1104,8 @@ TEST_F(PeopleHandlerTest, TurnOnEncryptAllDisallowed) {
}
TEST_F(PeopleHandlerTest, DashboardClearWhileSettingsOpen_ConfirmSoon) {
+ SigninUser();
+ CreatePeopleHandler();
// Sync starts out fully enabled.
SetDefaultExpectationsForConfigPage();
@@ -1062,7 +1135,7 @@ TEST_F(PeopleHandlerTest, DashboardClearWhileSettingsOpen_ConfirmSoon) {
// SetSyncRequested(true) clears DISABLE_REASON_USER_CHOICE, and
// immediately starts initializing the engine.
ON_CALL(*mock_sync_service_, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsSyncRequested())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_, GetTransportState())
@@ -1086,6 +1159,8 @@ TEST_F(PeopleHandlerTest, DashboardClearWhileSettingsOpen_ConfirmSoon) {
}
TEST_F(PeopleHandlerTest, DashboardClearWhileSettingsOpen_ConfirmLater) {
+ SigninUser();
+ CreatePeopleHandler();
// Sync starts out fully enabled.
SetDefaultExpectationsForConfigPage();
@@ -1128,7 +1203,7 @@ TEST_F(PeopleHandlerTest, DashboardClearWhileSettingsOpen_ConfirmLater) {
// SetSyncRequested(true) clears DISABLE_REASON_USER_CHOICE, and
// immediately starts initializing the engine.
ON_CALL(*mock_sync_service_, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsSyncRequested())
.WillByDefault(Return(true));
ON_CALL(*mock_sync_service_, GetTransportState())
@@ -1195,7 +1270,44 @@ TEST(PeopleHandlerDiceUnifiedConsentTest, StoredAccountsList) {
EXPECT_EQ("a@gmail.com", accounts_list[0].FindKey("email")->GetString());
EXPECT_EQ("b@gmail.com", accounts_list[1].FindKey("email")->GetString());
}
-
#endif // BUILDFLAG(ENABLE_DICE_SUPPORT)
+#if defined(OS_CHROMEOS)
+// Regression test for crash in guest mode. https://crbug.com/1040476
+TEST(PeopleHandlerGuestModeTest, GetStoredAccountsList) {
+ content::BrowserTaskEnvironment task_environment;
+ TestingProfile::Builder builder;
+ builder.SetGuestSession();
+ std::unique_ptr<Profile> profile = builder.Build();
+
+ PeopleHandler handler(profile.get());
+ base::Value accounts = handler.GetStoredAccountsList();
+ EXPECT_TRUE(accounts.GetList().empty());
+}
+
+TEST_F(PeopleHandlerTest, TurnOffSync) {
+ // Simulate a user who previously turned on sync.
+ identity_test_env()->MakePrimaryAccountAvailable("user@gmail.com");
+ ASSERT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+
+ CreatePeopleHandler();
+ handler_->HandleTurnOffSync(nullptr);
+ EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+ const base::DictionaryValue* status = ExpectSyncStatusChanged();
+ CheckBool(status, "signedIn", false);
+}
+
+TEST_F(PeopleHandlerTest, GetStoredAccountsList) {
+ // Chrome OS sets an unconsented primary account on login.
+ identity_test_env()->MakeUnconsentedPrimaryAccountAvailable("user@gmail.com");
+ ASSERT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync));
+
+ CreatePeopleHandler();
+ base::Value accounts = handler_->GetStoredAccountsList();
+ base::Value::ListView accounts_list = accounts.GetList();
+ ASSERT_EQ(1u, accounts_list.size());
+ EXPECT_EQ("user@gmail.com", accounts_list[0].FindKey("email")->GetString());
+}
+#endif // defined(OS_CHROMEOS)
+
} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/profile_info_handler.cc b/chromium/chrome/browser/ui/webui/settings/profile_info_handler.cc
index 139f2034b19..922bfc02a41 100644
--- a/chromium/chrome/browser/ui/webui/settings/profile_info_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/profile_info_handler.cc
@@ -150,10 +150,7 @@ ProfileInfoHandler::GetAccountNameAndIcon() const {
if (g_browser_process->profile_manager()
->GetProfileAttributesStorage()
.GetProfileAttributesWithPath(profile_->GetPath(), &entry)) {
- name = base::UTF16ToUTF8(
- ProfileAttributesEntry::ShouldConcatenateGaiaAndProfileName()
- ? entry->GetLocalProfileName()
- : entry->GetName());
+ name = base::UTF16ToUTF8(entry->GetLocalProfileName());
// TODO(crbug.com/710660): return chrome://theme/IDR_PROFILE_AVATAR_*
// and update theme_source.cc to get high res avatar icons. This does less
// work here, sends less over IPC, and is more stable with returned results.
diff --git a/chromium/chrome/browser/ui/webui/settings/safe_browsing_handler.cc b/chromium/chrome/browser/ui/webui/settings/safe_browsing_handler.cc
new file mode 100644
index 00000000000..7403e565a5a
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/safe_browsing_handler.cc
@@ -0,0 +1,130 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/safe_browsing_handler.h"
+
+#include "components/prefs/pref_change_registrar.h"
+#include "components/prefs/pref_service.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/features.h"
+
+namespace settings {
+
+SafeBrowsingHandler::SafeBrowsingHandler(Profile* profile)
+ : profile_(profile) {}
+SafeBrowsingHandler::~SafeBrowsingHandler() = default;
+
+void SafeBrowsingHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "getSafeBrowsingRadioManagedState",
+ base::BindRepeating(
+ &SafeBrowsingHandler::HandleGetSafeBrowsingRadioManagedState,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "validateSafeBrowsingEnhanced",
+ base::BindRepeating(
+ &SafeBrowsingHandler::HandleValidateSafeBrowsingEnhanced,
+ base::Unretained(this)));
+}
+
+void SafeBrowsingHandler::HandleGetSafeBrowsingRadioManagedState(
+ const base::ListValue* args) {
+ AllowJavascript();
+ CHECK_EQ(1U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+
+ auto state = GetSafeBrowsingRadioManagedState(profile_);
+
+ base::Value result(base::Value::Type::DICTIONARY);
+ // TODO(crbug.com/1063265): Move managed state functions out of site_settings.
+ result.SetKey(kSafeBrowsingEnhanced,
+ site_settings::GetValueForManagedState(state.enhanced));
+ result.SetKey(kSafeBrowsingStandard,
+ site_settings::GetValueForManagedState(state.standard));
+ result.SetKey(kSafeBrowsingDisabled,
+ site_settings::GetValueForManagedState(state.disabled));
+
+ ResolveJavascriptCallback(base::Value(callback_id), result);
+}
+
+void SafeBrowsingHandler::HandleValidateSafeBrowsingEnhanced(
+ const base::ListValue* args) {
+ // TODO(crbug.com/1074499) Remove this logic when Enhanced protection is
+ // considered stable.
+ if (!base::FeatureList::IsEnabled(safe_browsing::kEnhancedProtection))
+ profile_->GetPrefs()->SetBoolean(prefs::kSafeBrowsingEnhanced, false);
+}
+
+SafeBrowsingRadioManagedState
+SafeBrowsingHandler::GetSafeBrowsingRadioManagedState(Profile* profile) {
+ // Create a default managed state that is updated based on preferences.
+ SafeBrowsingRadioManagedState managed_state;
+
+ // Computing the effective Safe Browsing managed state requires inspecting
+ // three different preferences. It is possible that these may be in
+ // temporarily conflicting managed states. The enabled preference is always
+ // taken as the canonical source of management.
+ const PrefService::Preference* enabled_pref =
+ profile->GetPrefs()->FindPreference(prefs::kSafeBrowsingEnabled);
+ const bool enabled_enforced = !enabled_pref->IsUserModifiable();
+ const bool enabled_recommended =
+ (enabled_pref && enabled_pref->GetRecommendedValue());
+ const bool enabled_recommended_on =
+ enabled_recommended && enabled_pref->GetRecommendedValue()->GetBool();
+ const auto enabled_policy_indicator =
+ site_settings::GetPolicyIndicatorFromPref(enabled_pref);
+
+ // The enhanced preference may have a recommended setting. This only takes
+ // effect if the enabled preference also has a recommended setting.
+ const PrefService::Preference* enhanced_pref =
+ profile->GetPrefs()->FindPreference(prefs::kSafeBrowsingEnhanced);
+ const bool enhanced_recommended_on =
+ enhanced_pref->GetRecommendedValue() &&
+ enhanced_pref->GetRecommendedValue()->GetBool();
+
+ // A forcefully disabled reporting preference will disallow enhanced from
+ // being selected and thus it must also be considered.
+ const PrefService::Preference* reporting_pref =
+ profile->GetPrefs()->FindPreference(
+ prefs::kSafeBrowsingScoutReportingEnabled);
+ const bool reporting_on = reporting_pref->GetValue()->GetBool();
+ const bool reporting_enforced = !reporting_pref->IsUserModifiable();
+ const auto reporting_policy_indicator =
+ site_settings::GetPolicyIndicatorFromPref(reporting_pref);
+
+ if (!enabled_enforced && !enabled_recommended && !reporting_enforced) {
+ // No relevant policies are applied, return the default state.
+ return managed_state;
+ }
+ if (enabled_enforced) {
+ // All radio controls are managed.
+ managed_state.enhanced.disabled = true;
+ managed_state.enhanced.indicator = enabled_policy_indicator;
+ managed_state.standard.disabled = true;
+ managed_state.standard.indicator = enabled_policy_indicator;
+ managed_state.disabled.disabled = true;
+ managed_state.disabled.indicator = enabled_policy_indicator;
+ return managed_state;
+ }
+ if (enabled_recommended) {
+ if (enhanced_recommended_on) {
+ managed_state.enhanced.indicator = enabled_policy_indicator;
+ } else if (enabled_recommended_on) {
+ managed_state.standard.indicator = enabled_policy_indicator;
+ } else {
+ managed_state.disabled.indicator = enabled_policy_indicator;
+ }
+ return managed_state;
+ }
+ if (reporting_enforced && !reporting_on) {
+ // Disable enhanced protection when reporting has been enforced off.
+ managed_state.enhanced.disabled = true;
+ managed_state.enhanced.indicator = reporting_policy_indicator;
+ return managed_state;
+ }
+
+ return managed_state;
+}
+
+} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/safe_browsing_handler.h b/chromium/chrome/browser/ui/webui/settings/safe_browsing_handler.h
new file mode 100644
index 00000000000..4c27dae0c27
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/safe_browsing_handler.h
@@ -0,0 +1,62 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_SAFE_BROWSING_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_SAFE_BROWSING_HANDLER_H_
+
+#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "chrome/browser/ui/webui/site_settings_helper.h"
+
+#include "chrome/browser/profiles/profile.h"
+
+namespace settings {
+
+constexpr char kSafeBrowsingEnhanced[] = "enhanced";
+constexpr char kSafeBrowsingStandard[] = "standard";
+constexpr char kSafeBrowsingDisabled[] = "disabled";
+
+struct SafeBrowsingRadioManagedState {
+ site_settings::ManagedState enhanced;
+ site_settings::ManagedState standard;
+ site_settings::ManagedState disabled;
+};
+
+// Settings page UI handler that provides representation of Safe Browsing
+// settings.
+class SafeBrowsingHandler : public SettingsPageUIHandler {
+ public:
+ explicit SafeBrowsingHandler(Profile* profile);
+ ~SafeBrowsingHandler() override;
+
+ // WebUIMessageHandler implementation.
+ void RegisterMessages() override;
+
+ // Calculate and return the current Safe Browsing radio buttons.
+ void HandleGetSafeBrowsingRadioManagedState(const base::ListValue* args);
+
+ // Confirm that the current Safe Browsing Enhanced preference is appropriate
+ // for the currently enabled features, updating it if required.
+ void HandleValidateSafeBrowsingEnhanced(const base::ListValue* args);
+
+ private:
+ friend class SafeBrowsingHandlerTest;
+ FRIEND_TEST_ALL_PREFIXES(SafeBrowsingHandlerTest, GenerateRadioManagedState);
+ FRIEND_TEST_ALL_PREFIXES(SafeBrowsingHandlerTest, ProvideRadioManagedState);
+
+ // SettingsPageUIHandler implementation.
+ void OnJavascriptAllowed() override {}
+ void OnJavascriptDisallowed() override {}
+
+ // Calculate the current Safe Browsing control state for the provided profile.
+ static SafeBrowsingRadioManagedState GetSafeBrowsingRadioManagedState(
+ Profile* profile);
+
+ Profile* profile_;
+
+ DISALLOW_COPY_AND_ASSIGN(SafeBrowsingHandler);
+};
+
+} // namespace settings
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_SAFE_BROWSING_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/safe_browsing_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/safe_browsing_handler_unittest.cc
new file mode 100644
index 00000000000..3065bc295e2
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/safe_browsing_handler_unittest.cc
@@ -0,0 +1,248 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/safe_browsing_handler.h"
+
+#include <memory>
+#include <string>
+
+#include "base/test/scoped_feature_list.h"
+#include "base/values.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/prefs/pref_service.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/features.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_web_ui.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace settings {
+
+class SafeBrowsingHandlerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ handler_ = std::make_unique<SafeBrowsingHandler>(profile());
+ handler()->set_web_ui(web_ui());
+ handler()->AllowJavascript();
+ web_ui()->ClearTrackedCalls();
+ }
+
+ TestingProfile* profile() { return &profile_; }
+ content::TestWebUI* web_ui() { return &web_ui_; }
+ SafeBrowsingHandler* handler() { return handler_.get(); }
+
+ private:
+ content::BrowserTaskEnvironment task_environment_;
+ std::unique_ptr<SafeBrowsingHandler> handler_;
+ TestingProfile profile_;
+ content::TestWebUI web_ui_;
+};
+
+// All of the possible managed states for a boolean preference that can be
+// both enforced and recommended.
+// TODO(crbug.com/1063265): Remove duplication with site_settings_helper.
+enum class PrefSetting {
+ kEnforcedOff,
+ kEnforcedOn,
+ kRecommendedOff,
+ kRecommendedOn,
+ kNotSet,
+};
+
+// Possible preference sources supported by TestingPrefService.
+// TODO(crbug.com/1063265): Remove duplication with site_settings_helper.
+enum class PrefSource {
+ kExtension,
+ kDevicePolicy,
+ kRecommended,
+ kNone,
+};
+
+void AssertRadioManagedStateEqual(const SafeBrowsingRadioManagedState& a,
+ const SafeBrowsingRadioManagedState& b) {
+ ASSERT_EQ(a.enhanced.disabled, b.enhanced.disabled);
+ ASSERT_EQ(a.enhanced.indicator, b.enhanced.indicator);
+ ASSERT_EQ(a.standard.disabled, b.standard.disabled);
+ ASSERT_EQ(a.standard.indicator, b.standard.indicator);
+ ASSERT_EQ(a.disabled.disabled, b.disabled.disabled);
+ ASSERT_EQ(a.disabled.indicator, b.disabled.indicator);
+}
+
+struct RadioManagedStateTestCase {
+ PrefSetting safe_browsing_enhanced;
+ PrefSetting safe_browsing_enabled;
+ PrefSetting safe_browsing_reporting;
+ PrefSource preference_source;
+ SafeBrowsingRadioManagedState expected_result;
+};
+
+const std::vector<RadioManagedStateTestCase> test_cases = {
+ {PrefSetting::kNotSet,
+ PrefSetting::kNotSet,
+ PrefSetting::kNotSet,
+ PrefSource::kNone,
+ {{false, site_settings::PolicyIndicatorType::kNone},
+ {false, site_settings::PolicyIndicatorType::kNone},
+ {false, site_settings::PolicyIndicatorType::kNone}}},
+ {PrefSetting::kEnforcedOn,
+ PrefSetting::kEnforcedOn,
+ PrefSetting::kNotSet,
+ PrefSource::kExtension,
+ {{true, site_settings::PolicyIndicatorType::kExtension},
+ {true, site_settings::PolicyIndicatorType::kExtension},
+ {true, site_settings::PolicyIndicatorType::kExtension}}},
+ {PrefSetting::kEnforcedOff,
+ PrefSetting::kEnforcedOff,
+ PrefSetting::kNotSet,
+ PrefSource::kDevicePolicy,
+ {{true, site_settings::PolicyIndicatorType::kDevicePolicy},
+ {true, site_settings::PolicyIndicatorType::kDevicePolicy},
+ {true, site_settings::PolicyIndicatorType::kDevicePolicy}}},
+ {PrefSetting::kEnforcedOff,
+ PrefSetting::kEnforcedOn,
+ PrefSetting::kNotSet,
+ PrefSource::kExtension,
+ {{true, site_settings::PolicyIndicatorType::kExtension},
+ {true, site_settings::PolicyIndicatorType::kExtension},
+ {true, site_settings::PolicyIndicatorType::kExtension}}},
+ {PrefSetting::kRecommendedOn,
+ PrefSetting::kRecommendedOn,
+ PrefSetting::kNotSet,
+ PrefSource::kRecommended,
+ {{false, site_settings::PolicyIndicatorType::kRecommended},
+ {false, site_settings::PolicyIndicatorType::kNone},
+ {false, site_settings::PolicyIndicatorType::kNone}}},
+ {PrefSetting::kRecommendedOff,
+ PrefSetting::kRecommendedOn,
+ PrefSetting::kNotSet,
+ PrefSource::kRecommended,
+ {{false, site_settings::PolicyIndicatorType::kNone},
+ {false, site_settings::PolicyIndicatorType::kRecommended},
+ {false, site_settings::PolicyIndicatorType::kNone}}},
+ {PrefSetting::kRecommendedOff,
+ PrefSetting::kRecommendedOff,
+ PrefSetting::kNotSet,
+ PrefSource::kRecommended,
+ {{false, site_settings::PolicyIndicatorType::kNone},
+ {false, site_settings::PolicyIndicatorType::kNone},
+ {false, site_settings::PolicyIndicatorType::kRecommended}}},
+ {PrefSetting::kNotSet,
+ PrefSetting::kNotSet,
+ PrefSetting::kEnforcedOff,
+ PrefSource::kDevicePolicy,
+ {{true, site_settings::PolicyIndicatorType::kDevicePolicy},
+ {false, site_settings::PolicyIndicatorType::kNone},
+ {false, site_settings::PolicyIndicatorType::kNone}}}};
+
+void SetupTestConditions(TestingProfile* profile,
+ const RadioManagedStateTestCase& test_case) {
+ sync_preferences::TestingPrefServiceSyncable* prefs =
+ profile->GetTestingPrefService();
+ const std::map<const char*, PrefSetting> pref_to_setting = {
+ {prefs::kSafeBrowsingEnhanced, test_case.safe_browsing_enhanced},
+ {prefs::kSafeBrowsingEnabled, test_case.safe_browsing_enabled},
+ {prefs::kSafeBrowsingScoutReportingEnabled,
+ test_case.safe_browsing_reporting}};
+
+ for (const auto& pref_setting : pref_to_setting) {
+ if (pref_setting.second == PrefSetting::kNotSet) {
+ continue;
+ }
+ auto pref_value = std::make_unique<base::Value>(
+ pref_setting.second == PrefSetting::kRecommendedOn ||
+ pref_setting.second == PrefSetting::kEnforcedOn);
+ if (test_case.preference_source == PrefSource::kExtension) {
+ prefs->SetExtensionPref(pref_setting.first, std::move(pref_value));
+ } else if (test_case.preference_source == PrefSource::kDevicePolicy) {
+ prefs->SetManagedPref(pref_setting.first, std::move(pref_value));
+ } else if (test_case.preference_source == PrefSource::kRecommended) {
+ prefs->SetRecommendedPref(pref_setting.first, std::move(pref_value));
+ }
+ }
+}
+
+TEST_F(SafeBrowsingHandlerTest, GenerateRadioManagedState) {
+ int count = 0;
+ for (const auto& test_case : test_cases) {
+ TestingProfile profile;
+ SCOPED_TRACE(base::StringPrintf("Test case %d", count++));
+ SetupTestConditions(&profile, test_case);
+ AssertRadioManagedStateEqual(
+ handler()->GetSafeBrowsingRadioManagedState(&profile),
+ test_case.expected_result);
+ }
+}
+
+TEST_F(SafeBrowsingHandlerTest, ProvideRadioManagedState) {
+ // Test that the handler correctly wraps the generated result.
+ const std::string kNone = "none";
+ const std::string kDevicePolicy = "devicePolicy";
+ const std::string kCallbackId = "callback";
+ const std::vector<std::string> kRadioNames = {"enhanced", "standard",
+ "disabled"};
+
+ // Check that the default radio state is handled correctly.
+ base::ListValue get_args;
+ get_args.AppendString(kCallbackId);
+ handler()->HandleGetSafeBrowsingRadioManagedState(&get_args);
+ {
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIResponse", data.function_name());
+ EXPECT_EQ(kCallbackId, data.arg1()->GetString());
+ ASSERT_TRUE(data.arg2()->GetBool());
+ for (const auto& control_name : kRadioNames) {
+ auto* control_state = data.arg3()->FindPath(control_name);
+ ASSERT_FALSE(control_state->FindKey("disabled")->GetBool());
+ ASSERT_EQ(kNone, control_state->FindKey("indicator")->GetString());
+ }
+ }
+
+ // Create a fully managed state and check it is returned correctly.
+ sync_preferences::TestingPrefServiceSyncable* pref_service =
+ profile()->GetTestingPrefService();
+ pref_service->SetManagedPref(prefs::kSafeBrowsingEnhanced,
+ std::make_unique<base::Value>(true));
+ pref_service->SetManagedPref(prefs::kSafeBrowsingEnabled,
+ std::make_unique<base::Value>(true));
+
+ handler()->HandleGetSafeBrowsingRadioManagedState(&get_args);
+ {
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIResponse", data.function_name());
+ EXPECT_EQ(kCallbackId, data.arg1()->GetString());
+ ASSERT_TRUE(data.arg2()->GetBool());
+ for (const auto& control_name : kRadioNames) {
+ auto* control_state = data.arg3()->FindPath(control_name);
+ ASSERT_TRUE(control_state->FindKey("disabled")->GetBool());
+ ASSERT_EQ(kDevicePolicy,
+ control_state->FindKey("indicator")->GetString());
+ }
+ }
+}
+
+TEST_F(SafeBrowsingHandlerTest, ValidateSafeBrowsingPrefs) {
+ base::ListValue args;
+ base::test::ScopedFeatureList scoped_feature_list_;
+ sync_preferences::TestingPrefServiceSyncable* pref_service =
+ profile()->GetTestingPrefService();
+
+ pref_service->SetBoolean(prefs::kSafeBrowsingEnhanced, true);
+
+ // Ensure the preference is not changed when the Enhanced feature is enabled.
+ scoped_feature_list_.InitWithFeatures({safe_browsing::kEnhancedProtection},
+ {});
+ handler()->HandleValidateSafeBrowsingEnhanced(&args);
+ EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced));
+ scoped_feature_list_.Reset();
+
+ // Ensure the preference is disabled when the Enhanced feature is disabled.
+ scoped_feature_list_.InitWithFeatures({},
+ {safe_browsing::kEnhancedProtection});
+ handler()->HandleValidateSafeBrowsingEnhanced(&args);
+ EXPECT_FALSE(pref_service->GetBoolean(prefs::kSafeBrowsingEnhanced));
+}
+
+} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc b/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc
index be365ff4489..8e954398304 100644
--- a/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc
@@ -5,23 +5,238 @@
#include "chrome/browser/ui/webui/settings/safety_check_handler.h"
#include "base/bind.h"
+#include "base/i18n/number_formatting.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h"
+#include "chrome/browser/password_manager/bulk_leak_check_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/channel_info.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/prefs/pref_service.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/version_info/version_info.h"
+#include "extensions/browser/extension_prefs_factory.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/common/extension_id.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if defined(OS_CHROMEOS)
+#include "ui/chromeos/devicetype_utils.h"
+#endif
+
+namespace {
+
+// Constants for communication with JS.
+constexpr char kUpdatesEvent[] = "safety-check-updates-status-changed";
+constexpr char kPasswordsEvent[] = "safety-check-passwords-status-changed";
+constexpr char kSafeBrowsingEvent[] =
+ "safety-check-safe-browsing-status-changed";
+constexpr char kExtensionsEvent[] = "safety-check-extensions-status-changed";
+constexpr char kPerformSafetyCheck[] = "performSafetyCheck";
+constexpr char kGetParentRanDisplayString[] = "getSafetyCheckRanDisplayString";
+constexpr char kNewState[] = "newState";
+constexpr char kDisplayString[] = "displayString";
+constexpr char kButtonString[] = "buttonString";
+constexpr char kPasswordsCompromised[] = "passwordsCompromised";
+constexpr char kExtensionsReenabledByUser[] = "extensionsReenabledByUser";
+constexpr char kExtensionsReenabledByAdmin[] = "extensionsReenabledByAdmin";
+
+// Converts the VersionUpdater::Status to the UpdateStatus enum to be passed
+// to the safety check frontend. Note: if the VersionUpdater::Status gets
+// changed, this will fail to compile. That is done intentionally to ensure
+// that the states of the safety check are always in sync with the
+// VersionUpdater ones.
+SafetyCheckHandler::UpdateStatus ConvertToUpdateStatus(
+ VersionUpdater::Status status) {
+ switch (status) {
+ case VersionUpdater::CHECKING:
+ return SafetyCheckHandler::UpdateStatus::kChecking;
+ case VersionUpdater::UPDATED:
+ return SafetyCheckHandler::UpdateStatus::kUpdated;
+ case VersionUpdater::UPDATING:
+ return SafetyCheckHandler::UpdateStatus::kUpdating;
+ case VersionUpdater::NEED_PERMISSION_TO_UPDATE:
+ case VersionUpdater::NEARLY_UPDATED:
+ return SafetyCheckHandler::UpdateStatus::kRelaunch;
+ case VersionUpdater::DISABLED_BY_ADMIN:
+ return SafetyCheckHandler::UpdateStatus::kDisabledByAdmin;
+ // The disabled state can only be returned on non Chrome-branded browsers.
+ case VersionUpdater::DISABLED:
+ return SafetyCheckHandler::UpdateStatus::kUnknown;
+ case VersionUpdater::FAILED:
+ case VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED:
+ return SafetyCheckHandler::UpdateStatus::kFailed;
+ case VersionUpdater::FAILED_OFFLINE:
+ return SafetyCheckHandler::UpdateStatus::kFailedOffline;
+ }
+}
+} // namespace
SafetyCheckHandler::SafetyCheckHandler() = default;
SafetyCheckHandler::~SafetyCheckHandler() = default;
void SafetyCheckHandler::PerformSafetyCheck() {
- version_updater_.reset(VersionUpdater::Create(web_ui()->GetWebContents()));
- CheckUpdates(version_updater_.get(),
- base::Bind(&SafetyCheckHandler::OnUpdateCheckResult,
- base::Unretained(this)));
+ AllowJavascript();
+
+ if (!version_updater_) {
+ version_updater_.reset(VersionUpdater::Create(web_ui()->GetWebContents()));
+ }
+ DCHECK(version_updater_);
+ CheckUpdates();
+
+ CheckSafeBrowsing();
+
+ if (!leak_service_) {
+ leak_service_ = BulkLeakCheckServiceFactory::GetForProfile(
+ Profile::FromWebUI(web_ui()));
+ }
+ DCHECK(leak_service_);
+ if (!passwords_delegate_) {
+ passwords_delegate_ =
+ extensions::PasswordsPrivateDelegateFactory::GetForBrowserContext(
+ Profile::FromWebUI(web_ui()), true);
+ }
+ DCHECK(passwords_delegate_);
+ CheckPasswords();
+
+ if (!extension_prefs_) {
+ extension_prefs_ = extensions::ExtensionPrefsFactory::GetForBrowserContext(
+ Profile::FromWebUI(web_ui()));
+ }
+ DCHECK(extension_prefs_);
+ if (!extension_service_) {
+ extension_service_ =
+ extensions::ExtensionSystem::Get(Profile::FromWebUI(web_ui()))
+ ->extension_service();
+ }
+ DCHECK(extension_service_);
+ CheckExtensions();
}
-void SafetyCheckHandler::CheckUpdates(
- VersionUpdater* version_updater,
- const VersionUpdater::StatusCallback& update_callback) {
- version_updater->CheckForUpdate(update_callback,
- VersionUpdater::PromoteCallback());
+SafetyCheckHandler::SafetyCheckHandler(
+ std::unique_ptr<VersionUpdater> version_updater,
+ password_manager::BulkLeakCheckService* leak_service,
+ extensions::PasswordsPrivateDelegate* passwords_delegate,
+ extensions::ExtensionPrefs* extension_prefs,
+ extensions::ExtensionServiceInterface* extension_service)
+ : version_updater_(std::move(version_updater)),
+ leak_service_(leak_service),
+ passwords_delegate_(passwords_delegate),
+ extension_prefs_(extension_prefs),
+ extension_service_(extension_service) {}
+
+void SafetyCheckHandler::HandlePerformSafetyCheck(const base::ListValue* args) {
+ PerformSafetyCheck();
+}
+
+void SafetyCheckHandler::HandleGetParentRanDisplayString(
+ const base::ListValue* args) {
+ const base::Value* callback_id;
+ double timestampRanDouble;
+ CHECK(args->Get(0, &callback_id));
+ CHECK(args->GetDouble(1, &timestampRanDouble));
+
+ ResolveJavascriptCallback(
+ *callback_id, base::Value(GetStringForParentRan(timestampRanDouble)));
+}
+
+void SafetyCheckHandler::CheckUpdates() {
+ // Usage of base::Unretained(this) is safe, because we own `version_updater_`.
+ version_updater_->CheckForUpdate(
+ base::Bind(&SafetyCheckHandler::OnUpdateCheckResult,
+ base::Unretained(this)),
+ VersionUpdater::PromoteCallback());
+}
+
+void SafetyCheckHandler::CheckSafeBrowsing() {
+ PrefService* pref_service = Profile::FromWebUI(web_ui())->GetPrefs();
+ const PrefService::Preference* pref =
+ pref_service->FindPreference(prefs::kSafeBrowsingEnabled);
+ SafeBrowsingStatus status;
+ if (pref_service->GetBoolean(prefs::kSafeBrowsingEnabled)) {
+ status = SafeBrowsingStatus::kEnabled;
+ } else if (pref->IsManaged()) {
+ status = SafeBrowsingStatus::kDisabledByAdmin;
+ } else if (pref->IsExtensionControlled()) {
+ status = SafeBrowsingStatus::kDisabledByExtension;
+ } else {
+ status = SafeBrowsingStatus::kDisabled;
+ }
+ OnSafeBrowsingCheckResult(status);
+}
+
+void SafetyCheckHandler::CheckPasswords() {
+ // Remove |this| as an existing observer for BulkLeakCheck if it is
+ // registered. This takes care of an edge case when safety check starts twice
+ // on the same page. Normally this should not happen, but if it does, the
+ // browser should not crash.
+ observed_leak_check_.RemoveAll();
+ observed_leak_check_.Add(leak_service_);
+ passwords_delegate_->StartPasswordCheck(base::BindOnce(
+ &SafetyCheckHandler::OnStateChanged, weak_ptr_factory_.GetWeakPtr()));
+}
+
+void SafetyCheckHandler::CheckExtensions() {
+ extensions::ExtensionIdList extensions;
+ extension_prefs_->GetExtensions(&extensions);
+ int blocklisted = 0;
+ int reenabled_by_user = 0;
+ int reenabled_by_admin = 0;
+ for (auto extension_id : extensions) {
+ extensions::BlacklistState state =
+ extension_prefs_->GetExtensionBlacklistState(extension_id);
+ if (state == extensions::BLACKLISTED_UNKNOWN) {
+ // If any of the extensions are in the unknown blacklist state, that means
+ // there was an error the last time the blacklist was fetched. That means
+ // the results cannot be relied upon.
+ OnExtensionsCheckResult(ExtensionsStatus::kError, Blocklisted(0),
+ ReenabledUser(0), ReenabledAdmin(0));
+ return;
+ }
+ if (state == extensions::NOT_BLACKLISTED) {
+ continue;
+ }
+ ++blocklisted;
+ if (!extension_service_->IsExtensionEnabled(extension_id)) {
+ continue;
+ }
+ if (extension_service_->UserCanDisableInstalledExtension(extension_id)) {
+ ++reenabled_by_user;
+ } else {
+ ++reenabled_by_admin;
+ }
+ }
+ if (blocklisted == 0) {
+ OnExtensionsCheckResult(ExtensionsStatus::kNoneBlocklisted, Blocklisted(0),
+ ReenabledUser(0), ReenabledAdmin(0));
+ } else if (reenabled_by_user == 0 && reenabled_by_admin == 0) {
+ OnExtensionsCheckResult(ExtensionsStatus::kBlocklistedAllDisabled,
+ Blocklisted(blocklisted), ReenabledUser(0),
+ ReenabledAdmin(0));
+ } else if (reenabled_by_user > 0 && reenabled_by_admin == 0) {
+ OnExtensionsCheckResult(ExtensionsStatus::kBlocklistedReenabledAllByUser,
+ Blocklisted(blocklisted),
+ ReenabledUser(reenabled_by_user),
+ ReenabledAdmin(0));
+ } else if (reenabled_by_admin > 0 && reenabled_by_user == 0) {
+ OnExtensionsCheckResult(ExtensionsStatus::kBlocklistedReenabledAllByAdmin,
+ Blocklisted(blocklisted), ReenabledUser(0),
+ ReenabledAdmin(reenabled_by_admin));
+ } else {
+ OnExtensionsCheckResult(ExtensionsStatus::kBlocklistedReenabledSomeByUser,
+ Blocklisted(blocklisted),
+ ReenabledUser(reenabled_by_user),
+ ReenabledAdmin(reenabled_by_admin));
+ }
}
void SafetyCheckHandler::OnUpdateCheckResult(VersionUpdater::Status status,
@@ -30,5 +245,370 @@ void SafetyCheckHandler::OnUpdateCheckResult(VersionUpdater::Status status,
const std::string& version,
int64_t update_size,
const base::string16& message) {
- NOTIMPLEMENTED();
+ UpdateStatus update_status = ConvertToUpdateStatus(status);
+ base::DictionaryValue event;
+ event.SetIntKey(kNewState,
+ static_cast<int>(update_status != UpdateStatus::kUnknown
+ ? update_status
+ : UpdateStatus::kFailedOffline));
+ event.SetStringKey(kDisplayString, GetStringForUpdates(update_status));
+ FireWebUIListener(kUpdatesEvent, event);
+ if (update_status != UpdateStatus::kChecking) {
+ base::UmaHistogramEnumeration("Settings.SafetyCheck.UpdatesResult",
+ update_status);
+ }
+}
+
+void SafetyCheckHandler::OnSafeBrowsingCheckResult(
+ SafetyCheckHandler::SafeBrowsingStatus status) {
+ base::DictionaryValue event;
+ event.SetIntKey(kNewState, static_cast<int>(status));
+ event.SetStringKey(kDisplayString, GetStringForSafeBrowsing(status));
+ FireWebUIListener(kSafeBrowsingEvent, event);
+ if (status != SafeBrowsingStatus::kChecking) {
+ base::UmaHistogramEnumeration("Settings.SafetyCheck.SafeBrowsingResult",
+ status);
+ }
+}
+
+void SafetyCheckHandler::OnPasswordsCheckResult(PasswordsStatus status,
+ Compromised compromised,
+ Done done,
+ Total total) {
+ base::DictionaryValue event;
+ event.SetIntKey(kNewState, static_cast<int>(status));
+ if (status == PasswordsStatus::kCompromisedExist) {
+ event.SetIntKey(kPasswordsCompromised, compromised.value());
+ event.SetStringKey(
+ kButtonString,
+ l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_BUTTON, compromised.value()));
+ }
+ event.SetStringKey(kDisplayString,
+ GetStringForPasswords(status, compromised, done, total));
+ FireWebUIListener(kPasswordsEvent, event);
+ if (status != PasswordsStatus::kChecking) {
+ base::UmaHistogramEnumeration("Settings.SafetyCheck.PasswordsResult",
+ status);
+ }
+}
+
+void SafetyCheckHandler::OnExtensionsCheckResult(
+ ExtensionsStatus status,
+ Blocklisted blocklisted,
+ ReenabledUser reenabled_user,
+ ReenabledAdmin reenabled_admin) {
+ base::DictionaryValue event;
+ event.SetIntKey(kNewState, static_cast<int>(status));
+ if (status == ExtensionsStatus::kBlocklistedReenabledAllByUser ||
+ status == ExtensionsStatus::kBlocklistedReenabledSomeByUser) {
+ event.SetIntKey(kExtensionsReenabledByUser, reenabled_user.value());
+ }
+ if (status == ExtensionsStatus::kBlocklistedReenabledAllByAdmin ||
+ status == ExtensionsStatus::kBlocklistedReenabledSomeByUser) {
+ event.SetIntKey(kExtensionsReenabledByAdmin, reenabled_admin.value());
+ }
+ event.SetStringKey(kDisplayString,
+ GetStringForExtensions(status, Blocklisted(blocklisted),
+ reenabled_user, reenabled_admin));
+ FireWebUIListener(kExtensionsEvent, event);
+ if (status != ExtensionsStatus::kChecking) {
+ base::UmaHistogramEnumeration("Settings.SafetyCheck.ExtensionsResult",
+ status);
+ }
+}
+
+base::string16 SafetyCheckHandler::GetStringForUpdates(UpdateStatus status) {
+ switch (status) {
+ case UpdateStatus::kChecking:
+ return l10n_util::GetStringUTF16(IDS_SETTINGS_SAFETY_CHECK_RUNNING);
+ case UpdateStatus::kUpdated:
+#if defined(OS_CHROMEOS)
+ return ui::SubstituteChromeOSDeviceType(IDS_SETTINGS_UPGRADE_UP_TO_DATE);
+#else
+ return l10n_util::GetStringUTF16(IDS_SETTINGS_UPGRADE_UP_TO_DATE);
+#endif
+ case UpdateStatus::kUpdating:
+ return l10n_util::GetStringUTF16(IDS_SETTINGS_UPGRADE_UPDATING);
+ case UpdateStatus::kRelaunch:
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_UPGRADE_SUCCESSFUL_RELAUNCH);
+ case UpdateStatus::kDisabledByAdmin:
+ return l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_UPDATES_DISABLED_BY_ADMIN,
+ base::ASCIIToUTF16(chrome::kWhoIsMyAdministratorHelpURL));
+ case UpdateStatus::kFailedOffline:
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_UPDATES_FAILED_OFFLINE);
+ case UpdateStatus::kFailed:
+ return l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_UPDATES_FAILED,
+ base::ASCIIToUTF16(chrome::kChromeFixUpdateProblems));
+ case UpdateStatus::kUnknown:
+ return l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_ABOUT_PAGE_BROWSER_VERSION,
+ base::UTF8ToUTF16(version_info::GetVersionNumber()),
+ l10n_util::GetStringUTF16(version_info::IsOfficialBuild()
+ ? IDS_VERSION_UI_OFFICIAL
+ : IDS_VERSION_UI_UNOFFICIAL),
+ base::UTF8ToUTF16(chrome::GetChannelName()),
+ l10n_util::GetStringUTF16(sizeof(void*) == 8 ? IDS_VERSION_UI_64BIT
+ : IDS_VERSION_UI_32BIT));
+ }
+}
+
+base::string16 SafetyCheckHandler::GetStringForSafeBrowsing(
+ SafeBrowsingStatus status) {
+ switch (status) {
+ case SafeBrowsingStatus::kChecking:
+ return l10n_util::GetStringUTF16(IDS_SETTINGS_SAFETY_CHECK_RUNNING);
+ case SafeBrowsingStatus::kEnabled:
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_ENABLED);
+ case SafeBrowsingStatus::kDisabled:
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_DISABLED);
+ case SafeBrowsingStatus::kDisabledByAdmin:
+ return l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_DISABLED_BY_ADMIN,
+ base::ASCIIToUTF16(chrome::kWhoIsMyAdministratorHelpURL));
+ case SafeBrowsingStatus::kDisabledByExtension:
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_DISABLED_BY_EXTENSION);
+ }
+}
+
+base::string16 SafetyCheckHandler::GetStringForPasswords(
+ PasswordsStatus status,
+ Compromised compromised,
+ Done done,
+ Total total) {
+ const base::string16 short_product_name =
+ l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
+ switch (status) {
+ case PasswordsStatus::kChecking: {
+ // Unable to get progress for some reason.
+ if (total.value() == 0) {
+ return l10n_util::GetStringUTF16(IDS_SETTINGS_SAFETY_CHECK_RUNNING);
+ }
+ return l10n_util::GetStringFUTF16(IDS_SETTINGS_CHECK_PASSWORDS_PROGRESS,
+ base::FormatNumber(done.value()),
+ base::FormatNumber(total.value()));
+ }
+ case PasswordsStatus::kSafe:
+ return l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_COMPROMISED_PASSWORDS_COUNT, 0);
+ case PasswordsStatus::kCompromisedExist:
+ return l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_COMPROMISED_PASSWORDS_COUNT, compromised.value());
+ case PasswordsStatus::kOffline:
+ return l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CHECK_PASSWORDS_ERROR_OFFLINE, short_product_name);
+ case PasswordsStatus::kNoPasswords:
+ return l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CHECK_PASSWORDS_ERROR_NO_PASSWORDS, short_product_name);
+ case PasswordsStatus::kSignedOut:
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_SIGNED_OUT);
+ case PasswordsStatus::kQuotaLimit:
+ return l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CHECK_PASSWORDS_ERROR_QUOTA_LIMIT, short_product_name);
+ case PasswordsStatus::kError:
+ return l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CHECK_PASSWORDS_ERROR_GENERIC, short_product_name);
+ }
+}
+
+base::string16 SafetyCheckHandler::GetStringForExtensions(
+ ExtensionsStatus status,
+ Blocklisted blocklisted,
+ ReenabledUser reenabled_user,
+ ReenabledAdmin reenabled_admin) {
+ switch (status) {
+ case ExtensionsStatus::kChecking:
+ return l10n_util::GetStringUTF16(IDS_SETTINGS_SAFETY_CHECK_RUNNING);
+ case ExtensionsStatus::kError:
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_ERROR);
+ case ExtensionsStatus::kNoneBlocklisted:
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_SAFE);
+ case ExtensionsStatus::kBlocklistedAllDisabled:
+ return l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BLOCKLISTED_OFF,
+ blocklisted.value());
+ case ExtensionsStatus::kBlocklistedReenabledAllByUser:
+ return l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BLOCKLISTED_ON_USER,
+ reenabled_user.value());
+ case ExtensionsStatus::kBlocklistedReenabledSomeByUser:
+ // TODO(crbug/1060625): Make string concatenation with a period
+ // internationalized (see go/i18n-concatenation).
+ return l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BLOCKLISTED_ON_USER,
+ reenabled_user.value()) +
+ base::ASCIIToUTF16(". ") +
+ l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BLOCKLISTED_ON_ADMIN,
+ reenabled_admin.value()) +
+ base::ASCIIToUTF16(".");
+ case ExtensionsStatus::kBlocklistedReenabledAllByAdmin:
+ return l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BLOCKLISTED_ON_ADMIN,
+ reenabled_admin.value());
+ }
+}
+
+base::string16 SafetyCheckHandler::GetStringForParentRan(double timestamp_ran) {
+ return SafetyCheckHandler::GetStringForParentRan(timestamp_ran,
+ base::Time::Now());
+}
+
+base::string16 SafetyCheckHandler::GetStringForParentRan(
+ double timestamp_ran,
+ base::Time system_time) {
+ const base::Time timeRan = base::Time::FromJsTime(timestamp_ran);
+ base::Time::Exploded timeRanExploded;
+ timeRan.LocalExplode(&timeRanExploded);
+
+ base::Time::Exploded systemTimeExploded;
+ system_time.LocalExplode(&systemTimeExploded);
+
+ const base::Time timeYesterday = system_time - base::TimeDelta::FromDays(1);
+ base::Time::Exploded timeYesterdayExploded;
+ timeYesterday.LocalExplode(&timeYesterdayExploded);
+
+ const auto timeDiff = system_time - timeRan;
+ if (timeRanExploded.year == systemTimeExploded.year &&
+ timeRanExploded.month == systemTimeExploded.month &&
+ timeRanExploded.day_of_month == systemTimeExploded.day_of_month) {
+ // Safety check ran today.
+ const int timeDiffInMinutes = timeDiff.InMinutes();
+ if (timeDiffInMinutes == 0) {
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_AFTER);
+ } else if (timeDiffInMinutes < 60) {
+ return l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_AFTER_MINS,
+ timeDiffInMinutes);
+ } else {
+ return l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_AFTER_HOURS,
+ timeDiffInMinutes / 60);
+ }
+ } else if (timeRanExploded.year == timeYesterdayExploded.year &&
+ timeRanExploded.month == timeYesterdayExploded.month &&
+ timeRanExploded.day_of_month ==
+ timeYesterdayExploded.day_of_month) {
+ // Safety check ran yesterday.
+ return l10n_util::GetStringUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_AFTER_YESTERDAY);
+ } else {
+ // Safety check ran longer ago than yesterday.
+ // TODO(crbug.com/1015841): While a minor issue, this is not be the ideal
+ // way to calculate the days passed since safety check ran. For example,
+ // <48 h might still be 2 days ago.
+ const int timeDiffInDays = timeDiff.InDays();
+ return l10n_util::GetPluralStringFUTF16(
+ IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_AFTER_DAYS,
+ timeDiffInDays);
+ }
+}
+
+void SafetyCheckHandler::DetermineIfNoPasswordsOrSafe(
+ const std::vector<extensions::api::passwords_private::PasswordUiEntry>&
+ passwords) {
+ OnPasswordsCheckResult(passwords.empty() ? PasswordsStatus::kNoPasswords
+ : PasswordsStatus::kSafe,
+ Compromised(0), Done(0), Total(0));
+}
+
+void SafetyCheckHandler::OnStateChanged(
+ password_manager::BulkLeakCheckService::State state) {
+ using password_manager::BulkLeakCheckService;
+ switch (state) {
+ case BulkLeakCheckService::State::kIdle:
+ case BulkLeakCheckService::State::kCanceled: {
+ size_t num_compromised =
+ passwords_delegate_->GetCompromisedCredentials().size();
+ if (num_compromised == 0) {
+ passwords_delegate_->GetSavedPasswordsList(
+ base::BindOnce(&SafetyCheckHandler::DetermineIfNoPasswordsOrSafe,
+ base::Unretained(this)));
+ } else {
+ OnPasswordsCheckResult(PasswordsStatus::kCompromisedExist,
+ Compromised(num_compromised), Done(0), Total(0));
+ }
+ break;
+ }
+ case BulkLeakCheckService::State::kRunning:
+ OnPasswordsCheckResult(PasswordsStatus::kChecking, Compromised(0),
+ Done(0), Total(0));
+ // Non-terminal state, so nothing else needs to be done.
+ return;
+ case BulkLeakCheckService::State::kSignedOut:
+ OnPasswordsCheckResult(PasswordsStatus::kSignedOut, Compromised(0),
+ Done(0), Total(0));
+ break;
+ case BulkLeakCheckService::State::kNetworkError:
+ OnPasswordsCheckResult(PasswordsStatus::kOffline, Compromised(0), Done(0),
+ Total(0));
+ break;
+ case BulkLeakCheckService::State::kQuotaLimit:
+ OnPasswordsCheckResult(PasswordsStatus::kQuotaLimit, Compromised(0),
+ Done(0), Total(0));
+ break;
+ case BulkLeakCheckService::State::kTokenRequestFailure:
+ case BulkLeakCheckService::State::kHashingFailure:
+ case BulkLeakCheckService::State::kServiceError:
+ OnPasswordsCheckResult(PasswordsStatus::kError, Compromised(0), Done(0),
+ Total(0));
+ break;
+ }
+
+ // Stop observing the leak service in all terminal states, if it's still being
+ // observed.
+ observed_leak_check_.RemoveAll();
+}
+
+void SafetyCheckHandler::OnCredentialDone(
+ const password_manager::LeakCheckCredential& credential,
+ password_manager::IsLeaked is_leaked) {
+ extensions::api::passwords_private::PasswordCheckStatus status =
+ passwords_delegate_->GetPasswordCheckStatus();
+ // Send progress updates only if the check is still running.
+ if (status.state ==
+ extensions::api::passwords_private::PASSWORD_CHECK_STATE_RUNNING &&
+ status.already_processed && status.remaining_in_queue) {
+ Done done = Done(*(status.already_processed));
+ Total total = Total(*(status.remaining_in_queue) + done.value());
+ OnPasswordsCheckResult(PasswordsStatus::kChecking, Compromised(0), done,
+ total);
+ }
+}
+
+void SafetyCheckHandler::OnJavascriptAllowed() {}
+
+void SafetyCheckHandler::OnJavascriptDisallowed() {
+ // Remove |this| as an observer for BulkLeakCheck. This takes care of an edge
+ // case when the page is reloaded while the password check is in progress and
+ // another safety check is started. Otherwise |observed_leak_check_|
+ // automatically calls RemoveAll() on destruction.
+ observed_leak_check_.RemoveAll();
+ // Destroy the version updater to prevent getting a callback and firing a
+ // WebUI event, which would cause a crash.
+ version_updater_.reset();
+}
+
+void SafetyCheckHandler::RegisterMessages() {
+ // Usage of base::Unretained(this) is safe, because web_ui() owns `this` and
+ // won't release ownership until destruction.
+ web_ui()->RegisterMessageCallback(
+ kPerformSafetyCheck,
+ base::BindRepeating(&SafetyCheckHandler::HandlePerformSafetyCheck,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ kGetParentRanDisplayString,
+ base::BindRepeating(&SafetyCheckHandler::HandleGetParentRanDisplayString,
+ base::Unretained(this)));
}
diff --git a/chromium/chrome/browser/ui/webui/settings/safety_check_handler.h b/chromium/chrome/browser/ui/webui/settings/safety_check_handler.h
index 6268c712010..0680927e4c8 100644
--- a/chromium/chrome/browser/ui/webui/settings/safety_check_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/safety_check_handler.h
@@ -13,13 +13,75 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
+#include "base/util/type_safety/strong_alias.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
+#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/ui/webui/help/version_updater.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "components/password_manager/core/browser/bulk_leak_check_service.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
-// Settings page UI handler that checks four areas of browser safety: browser
-// updates, password leaks, malicious extensions, and unwanted software.
-class SafetyCheckHandler : public settings::SettingsPageUIHandler {
+// Settings page UI handler that checks four areas of browser safety:
+// browser updates, password leaks, malicious extensions, and unwanted
+// software.
+class SafetyCheckHandler
+ : public settings::SettingsPageUIHandler,
+ public password_manager::BulkLeakCheckService::Observer {
public:
+ // The following enums represent the state of each component of the safety
+ // check and should be kept in sync with the JS frontend
+ // (safety_check_browser_proxy.js) and |SafetyCheck*| metrics enums in
+ // enums.xml.
+ enum class UpdateStatus {
+ kChecking = 0,
+ kUpdated = 1,
+ kUpdating = 2,
+ kRelaunch = 3,
+ kDisabledByAdmin = 4,
+ kFailedOffline = 5,
+ kFailed = 6,
+ // Non-Google branded browsers cannot check for updates using
+ // VersionUpdater.
+ kUnknown = 7,
+ // New enum values must go above here.
+ kMaxValue = kUnknown,
+ };
+ enum class SafeBrowsingStatus {
+ kChecking = 0,
+ kEnabled = 1,
+ kDisabled = 2,
+ kDisabledByAdmin = 3,
+ kDisabledByExtension = 4,
+ // New enum values must go above here.
+ kMaxValue = kDisabledByExtension,
+ };
+ enum class PasswordsStatus {
+ kChecking = 0,
+ kSafe = 1,
+ kCompromisedExist = 2,
+ kOffline = 3,
+ kNoPasswords = 4,
+ kSignedOut = 5,
+ kQuotaLimit = 6,
+ kError = 7,
+ // New enum values must go above here.
+ kMaxValue = kError,
+ };
+ enum class ExtensionsStatus {
+ kChecking = 0,
+ kError = 1,
+ kNoneBlocklisted = 2,
+ kBlocklistedAllDisabled = 3,
+ kBlocklistedReenabledAllByUser = 4,
+ // In this case, at least one of the extensions was re-enabled by admin.
+ kBlocklistedReenabledSomeByUser = 5,
+ kBlocklistedReenabledAllByAdmin = 6,
+ // New enum values must go above here.
+ kMaxValue = kBlocklistedReenabledAllByAdmin,
+ };
+
SafetyCheckHandler();
~SafetyCheckHandler() override;
@@ -28,18 +90,57 @@ class SafetyCheckHandler : public settings::SettingsPageUIHandler {
// should only be called as a result of an explicit user action.
void PerformSafetyCheck();
- // Each triggers a corresponding check and calls the provided callback on
- // completion.
- void CheckUpdates(VersionUpdater* updater,
- const VersionUpdater::StatusCallback& update_callback);
+ // Constructs the 'safety check ran' display string by how long ago safety
+ // check ran.
+ base::string16 GetStringForParentRan(double timestamp_ran);
+ base::string16 GetStringForParentRan(double timestamp_ran,
+ base::Time systemTime);
+
+ protected:
+ SafetyCheckHandler(std::unique_ptr<VersionUpdater> version_updater,
+ password_manager::BulkLeakCheckService* leak_service,
+ extensions::PasswordsPrivateDelegate* passwords_delegate,
+ extensions::ExtensionPrefs* extension_prefs,
+ extensions::ExtensionServiceInterface* extension_service);
+
+ void SetVersionUpdaterForTesting(
+ std::unique_ptr<VersionUpdater> version_updater) {
+ version_updater_ = std::move(version_updater);
+ }
private:
- // SettingsPageUIHandler implementation.
- void OnJavascriptAllowed() override {}
- void OnJavascriptDisallowed() override {}
+ // These ensure integers are passed in the correct possitions in the extension
+ // check methods.
+ using Compromised = util::StrongAlias<class CompromisedTag, int>;
+ using Done = util::StrongAlias<class DoneTag, int>;
+ using Total = util::StrongAlias<class TotalTag, int>;
+ using Blocklisted = util::StrongAlias<class BlocklistedTag, int>;
+ using ReenabledUser = util::StrongAlias<class ReenabledUserTag, int>;
+ using ReenabledAdmin = util::StrongAlias<class ReenabledAdminTag, int>;
- // WebUIMessageHandler implementation.
- void RegisterMessages() override {}
+ // Handles triggering the safety check from the frontend (by user pressing a
+ // button).
+ void HandlePerformSafetyCheck(const base::ListValue* args);
+
+ // Handles updating the safety check parent display string to show how long
+ // ago the safety check last ran.
+ void HandleGetParentRanDisplayString(const base::ListValue* args);
+
+ // Triggers an update check and invokes OnUpdateCheckResult once results
+ // are available.
+ void CheckUpdates();
+
+ // Gets the status of Safe Browsing from the PrefService and invokes
+ // OnSafeBrowsingCheckResult with results.
+ void CheckSafeBrowsing();
+
+ // Triggers a bulk password leak check and invokes OnPasswordsCheckResult once
+ // results are available.
+ void CheckPasswords();
+
+ // Checks if any of the installed extensions are blocklisted, and in
+ // that case, if any of those were re-enabled.
+ void CheckExtensions();
// Callbacks that get triggered when each check completes.
void OnUpdateCheckResult(VersionUpdater::Status status,
@@ -48,10 +149,60 @@ class SafetyCheckHandler : public settings::SettingsPageUIHandler {
const std::string& version,
int64_t update_size,
const base::string16& message);
+ void OnSafeBrowsingCheckResult(SafeBrowsingStatus status);
+ void OnPasswordsCheckResult(PasswordsStatus status,
+ Compromised compromised,
+ Done done,
+ Total total);
+ void OnExtensionsCheckResult(ExtensionsStatus status,
+ Blocklisted blocklisted,
+ ReenabledUser reenabled_user,
+ ReenabledAdmin reenabled_admin);
- std::unique_ptr<VersionUpdater> version_updater_;
+ // Methods for building user-visible strings based on the safety check
+ // state.
+ base::string16 GetStringForUpdates(UpdateStatus status);
+ base::string16 GetStringForSafeBrowsing(SafeBrowsingStatus status);
+ base::string16 GetStringForPasswords(PasswordsStatus status,
+ Compromised compromised,
+ Done done,
+ Total total);
+ base::string16 GetStringForExtensions(ExtensionsStatus status,
+ Blocklisted blocklisted,
+ ReenabledUser reenabled_user,
+ ReenabledAdmin reenabled_admin);
+
+ // Since the password check API does not distinguish between the cases of
+ // having no compromised passwords and not having any passwords at all, it is
+ // necessary to use this method as a callback for
+ // |PasswordsPrivateDelegate::GetSavedPasswordsList| to distinguish the two
+ // states here.
+ void DetermineIfNoPasswordsOrSafe(
+ const std::vector<extensions::api::passwords_private::PasswordUiEntry>&
+ passwords);
- DISALLOW_COPY_AND_ASSIGN(SafetyCheckHandler);
+ // BulkLeakCheckService::Observer implementation.
+ void OnStateChanged(
+ password_manager::BulkLeakCheckService::State state) override;
+ void OnCredentialDone(const password_manager::LeakCheckCredential& credential,
+ password_manager::IsLeaked is_leaked) override;
+
+ // SettingsPageUIHandler implementation.
+ void OnJavascriptAllowed() override;
+ void OnJavascriptDisallowed() override;
+
+ // WebUIMessageHandler implementation.
+ void RegisterMessages() override;
+
+ std::unique_ptr<VersionUpdater> version_updater_;
+ password_manager::BulkLeakCheckService* leak_service_ = nullptr;
+ extensions::PasswordsPrivateDelegate* passwords_delegate_ = nullptr;
+ extensions::ExtensionPrefs* extension_prefs_ = nullptr;
+ extensions::ExtensionServiceInterface* extension_service_ = nullptr;
+ ScopedObserver<password_manager::BulkLeakCheckService,
+ password_manager::BulkLeakCheckService::Observer>
+ observed_leak_check_{this};
+ base::WeakPtrFactory<SafetyCheckHandler> weak_ptr_factory_{this};
};
#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_SAFETY_CHECK_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
index 827d2dec6bd..cefb6e359d7 100644
--- a/chromium/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
@@ -4,43 +4,1040 @@
#include "chrome/browser/ui/webui/settings/safety_check_handler.h"
+#include <string>
+#include <unordered_map>
+
#include "base/bind.h"
+#include "base/optional.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/metrics/user_action_tester.h"
+#include "base/util/type_safety/strong_alias.h"
+#include "build/build_config.h"
+#include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h"
+#include "chrome/browser/extensions/api/passwords_private/test_passwords_private_delegate.h"
+#include "chrome/browser/extensions/test_extension_service.h"
#include "chrome/browser/ui/webui/help/test_version_updater.h"
+#include "chrome/common/channel_info.h"
+#include "chrome/common/extensions/api/passwords_private.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/crx_file/id_util.h"
+#include "components/password_manager/core/browser/bulk_leak_check_service.h"
+#include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h"
+#include "components/prefs/pref_service.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "components/version_info/version_info.h"
+#include "content/public/test/test_web_ui.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_builder.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
-class SafetyCheckHandlerTest : public ::testing::Test {
+#if defined(OS_CHROMEOS)
+#include "ui/chromeos/devicetype_utils.h"
+#endif
+
+// Components for building event strings.
+constexpr char kUpdates[] = "updates";
+constexpr char kPasswords[] = "passwords";
+constexpr char kSafeBrowsing[] = "safe-browsing";
+constexpr char kExtensions[] = "extensions";
+
+namespace {
+using Enabled = util::StrongAlias<class EnabledTag, bool>;
+using UserCanDisable = util::StrongAlias<class UserCanDisableTag, bool>;
+
+class TestingSafetyCheckHandler : public SafetyCheckHandler {
public:
- void Callback(VersionUpdater::Status status,
- int progress,
- bool rollback,
- const std::string& version,
- int64_t update_size,
- const base::string16& message) {
- callback_invoked_ = true;
- result_ = status;
+ using SafetyCheckHandler::AllowJavascript;
+ using SafetyCheckHandler::DisallowJavascript;
+ using SafetyCheckHandler::set_web_ui;
+ using SafetyCheckHandler::SetVersionUpdaterForTesting;
+
+ TestingSafetyCheckHandler(
+ std::unique_ptr<VersionUpdater> version_updater,
+ password_manager::BulkLeakCheckService* leak_service,
+ extensions::PasswordsPrivateDelegate* passwords_delegate,
+ extensions::ExtensionPrefs* extension_prefs,
+ extensions::ExtensionServiceInterface* extension_service)
+ : SafetyCheckHandler(std::move(version_updater),
+ leak_service,
+ passwords_delegate,
+ extension_prefs,
+ extension_service) {}
+};
+
+class TestDestructionVersionUpdater : public TestVersionUpdater {
+ public:
+ ~TestDestructionVersionUpdater() override { destructor_invoked_ = true; }
+
+ void CheckForUpdate(const StatusCallback& callback,
+ const PromoteCallback&) override {}
+
+ static bool GetDestructorInvoked() { return destructor_invoked_; }
+
+ private:
+ static bool destructor_invoked_;
+};
+
+bool TestDestructionVersionUpdater::destructor_invoked_ = false;
+
+class TestPasswordsDelegate : public extensions::TestPasswordsPrivateDelegate {
+ public:
+ void SetBulkLeakCheckService(
+ password_manager::BulkLeakCheckService* leak_service) {
+ leak_service_ = leak_service;
+ }
+
+ void SetNumCompromisedCredentials(int compromised_password_count) {
+ compromised_password_count_ = compromised_password_count;
}
+ void SetPasswordCheckState(
+ extensions::api::passwords_private::PasswordCheckState state) {
+ state_ = state;
+ }
+
+ void SetProgress(int done, int total) {
+ done_ = done;
+ total_ = total;
+ }
+
+ std::vector<extensions::api::passwords_private::CompromisedCredential>
+ GetCompromisedCredentials() override {
+ std::vector<extensions::api::passwords_private::CompromisedCredential>
+ compromised(compromised_password_count_);
+ for (int i = 0; i < compromised_password_count_; ++i) {
+ compromised[i].username = "test" + base::NumberToString(i);
+ }
+ return compromised;
+ }
+
+ extensions::api::passwords_private::PasswordCheckStatus
+ GetPasswordCheckStatus() override {
+ extensions::api::passwords_private::PasswordCheckStatus status;
+ status.state = state_;
+ if (total_ != 0) {
+ status.already_processed = std::make_unique<int>(done_);
+ status.remaining_in_queue = std::make_unique<int>(total_ - done_);
+ }
+ return status;
+ }
+
+ private:
+ password_manager::BulkLeakCheckService* leak_service_ = nullptr;
+ int compromised_password_count_ = 0;
+ int done_ = 0;
+ int total_ = 0;
+ extensions::api::passwords_private::PasswordCheckState state_ =
+ extensions::api::passwords_private::PASSWORD_CHECK_STATE_IDLE;
+};
+
+class TestSafetyCheckExtensionService : public TestExtensionService {
+ public:
+ void AddExtensionState(const std::string& extension_id,
+ Enabled enabled,
+ UserCanDisable user_can_disable) {
+ state_map_.emplace(extension_id, ExtensionState{enabled.value(),
+ user_can_disable.value()});
+ }
+
+ bool IsExtensionEnabled(const std::string& extension_id) const override {
+ auto it = state_map_.find(extension_id);
+ if (it == state_map_.end()) {
+ return false;
+ }
+ return it->second.enabled;
+ }
+
+ bool UserCanDisableInstalledExtension(
+ const std::string& extension_id) override {
+ auto it = state_map_.find(extension_id);
+ if (it == state_map_.end()) {
+ return false;
+ }
+ return it->second.user_can_disable;
+ }
+
+ private:
+ struct ExtensionState {
+ bool enabled;
+ bool user_can_disable;
+ };
+
+ std::unordered_map<std::string, ExtensionState> state_map_;
+};
+
+} // namespace
+
+class SafetyCheckHandlerTest : public ChromeRenderViewHostTestHarness {
+ public:
+ void SetUp() override;
+
+ // Returns a |base::DictionaryValue| for safety check status update that
+ // has the specified |component| and |new_state| if it exists; nullptr
+ // otherwise.
+ const base::DictionaryValue* GetSafetyCheckStatusChangedWithDataIfExists(
+ const std::string& component,
+ int new_state);
+
+ std::string GenerateExtensionId(char char_to_repeat);
+
+ void VerifyDisplayString(const base::DictionaryValue* event,
+ const base::string16& expected);
+ void VerifyDisplayString(const base::DictionaryValue* event,
+ const std::string& expected);
+ void VerifyButtonString(const base::DictionaryValue* event,
+ const base::string16& expected);
+ void VerifyButtonString(const base::DictionaryValue* event,
+ const std::string& expected);
+
protected:
- bool callback_invoked_ = false;
- VersionUpdater::Status result_;
- TestVersionUpdater version_updater_;
- SafetyCheckHandler safety_check_;
+ TestVersionUpdater* version_updater_ = nullptr;
+ std::unique_ptr<password_manager::BulkLeakCheckService> test_leak_service_;
+ TestPasswordsDelegate test_passwords_delegate_;
+ extensions::ExtensionPrefs* test_extension_prefs_ = nullptr;
+ TestSafetyCheckExtensionService test_extension_service_;
+ content::TestWebUI test_web_ui_;
+ std::unique_ptr<TestingSafetyCheckHandler> safety_check_;
+ base::HistogramTester histogram_tester_;
+
+ private:
+ // Replaces any instances of browser name (e.g. Google Chrome, Chromium,
+ // etc) with "browser" to make sure tests work both on Chromium and
+ // Google Chrome.
+ void ReplaceBrowserName(base::string16* s);
};
-TEST_F(SafetyCheckHandlerTest, CheckUpdatesUpdated) {
- version_updater_.SetReturnedStatus(VersionUpdater::Status::UPDATED);
- safety_check_.CheckUpdates(
- &version_updater_,
- base::Bind(&SafetyCheckHandlerTest::Callback, base::Unretained(this)));
- ASSERT_TRUE(callback_invoked_);
- EXPECT_EQ(VersionUpdater::Status::UPDATED, result_);
-}
-
-TEST_F(SafetyCheckHandlerTest, CheckUpdatesNotUpdated) {
- version_updater_.SetReturnedStatus(VersionUpdater::Status::DISABLED);
- safety_check_.CheckUpdates(
- &version_updater_,
- base::Bind(&SafetyCheckHandlerTest::Callback, base::Unretained(this)));
- ASSERT_TRUE(callback_invoked_);
- EXPECT_EQ(VersionUpdater::Status::DISABLED, result_);
+void SafetyCheckHandlerTest::SetUp() {
+ ChromeRenderViewHostTestHarness::SetUp();
+
+ // The unique pointer to a TestVersionUpdater gets moved to
+ // SafetyCheckHandler, but a raw pointer is retained here to change its
+ // state.
+ auto version_updater = std::make_unique<TestVersionUpdater>();
+ test_leak_service_ = std::make_unique<password_manager::BulkLeakCheckService>(
+ nullptr, nullptr);
+ test_passwords_delegate_.SetBulkLeakCheckService(test_leak_service_.get());
+ version_updater_ = version_updater.get();
+ test_web_ui_.set_web_contents(web_contents());
+ test_extension_prefs_ = extensions::ExtensionPrefs::Get(profile());
+ safety_check_ = std::make_unique<TestingSafetyCheckHandler>(
+ std::move(version_updater), test_leak_service_.get(),
+ &test_passwords_delegate_, test_extension_prefs_,
+ &test_extension_service_);
+ test_web_ui_.ClearTrackedCalls();
+ safety_check_->set_web_ui(&test_web_ui_);
+ safety_check_->AllowJavascript();
+}
+
+const base::DictionaryValue*
+SafetyCheckHandlerTest::GetSafetyCheckStatusChangedWithDataIfExists(
+ const std::string& component,
+ int new_state) {
+ // Return the latest update if multiple, so iterate from the end.
+ const std::vector<std::unique_ptr<content::TestWebUI::CallData>>& call_data =
+ test_web_ui_.call_data();
+ for (int i = call_data.size() - 1; i >= 0; --i) {
+ const content::TestWebUI::CallData& data = *(call_data[i]);
+ if (data.function_name() != "cr.webUIListenerCallback") {
+ continue;
+ }
+ std::string event;
+ if ((!data.arg1()->GetAsString(&event)) ||
+ event != "safety-check-" + component + "-status-changed") {
+ continue;
+ }
+ const base::DictionaryValue* dictionary = nullptr;
+ if (!data.arg2()->GetAsDictionary(&dictionary)) {
+ continue;
+ }
+ int cur_new_state;
+ if (dictionary->GetInteger("newState", &cur_new_state) &&
+ cur_new_state == new_state) {
+ return dictionary;
+ }
+ }
+ return nullptr;
+}
+
+std::string SafetyCheckHandlerTest::GenerateExtensionId(char char_to_repeat) {
+ return std::string(crx_file::id_util::kIdSize * 2, char_to_repeat);
+}
+
+void SafetyCheckHandlerTest::VerifyDisplayString(
+ const base::DictionaryValue* event,
+ const base::string16& expected) {
+ base::string16 display;
+ ASSERT_TRUE(event->GetString("displayString", &display));
+ ReplaceBrowserName(&display);
+ // Need to also replace any instances of Chrome and Chromium in the
+ // expected string due to an edge case on ChromeOS, where a device name
+ // is "Chrome", which gets replaced in the display string.
+ base::string16 expected_replaced = expected;
+ ReplaceBrowserName(&expected_replaced);
+ EXPECT_EQ(expected_replaced, display);
+}
+
+void SafetyCheckHandlerTest::VerifyDisplayString(
+ const base::DictionaryValue* event,
+ const std::string& expected) {
+ VerifyDisplayString(event, base::ASCIIToUTF16(expected));
+}
+
+void SafetyCheckHandlerTest::VerifyButtonString(
+ const base::DictionaryValue* event,
+ const base::string16& expected) {
+ base::string16 button;
+ ASSERT_TRUE(event->GetString("buttonString", &button));
+ EXPECT_EQ(expected, button);
+}
+
+void SafetyCheckHandlerTest::VerifyButtonString(
+ const base::DictionaryValue* event,
+ const std::string& expected) {
+ VerifyButtonString(event, base::ASCIIToUTF16(expected));
+}
+
+void SafetyCheckHandlerTest::ReplaceBrowserName(base::string16* s) {
+ base::ReplaceSubstringsAfterOffset(s, 0, base::ASCIIToUTF16("Google Chrome"),
+ base::ASCIIToUTF16("Browser"));
+ base::ReplaceSubstringsAfterOffset(s, 0, base::ASCIIToUTF16("Chrome"),
+ base::ASCIIToUTF16("Browser"));
+ base::ReplaceSubstringsAfterOffset(s, 0, base::ASCIIToUTF16("Chromium"),
+ base::ASCIIToUTF16("Browser"));
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckUpdates_Checking) {
+ version_updater_->SetReturnedStatus(VersionUpdater::Status::CHECKING);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kUpdates,
+ static_cast<int>(SafetyCheckHandler::UpdateStatus::kChecking));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(event, base::UTF8ToUTF16("Running…"));
+ // Checking state should not get recorded.
+ histogram_tester_.ExpectTotalCount("Settings.SafetyCheck.UpdatesResult", 0);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckUpdates_Updated) {
+ version_updater_->SetReturnedStatus(VersionUpdater::Status::UPDATED);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kUpdates,
+ static_cast<int>(SafetyCheckHandler::UpdateStatus::kUpdated));
+ ASSERT_TRUE(event);
+#if defined(OS_CHROMEOS)
+ base::string16 expected = base::ASCIIToUTF16("Your ") +
+ ui::GetChromeOSDeviceName() +
+ base::ASCIIToUTF16(" is up to date");
+ VerifyDisplayString(event, expected);
+#else
+ VerifyDisplayString(event, "Browser is up to date");
+#endif
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.UpdatesResult",
+ SafetyCheckHandler::UpdateStatus::kUpdated, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckUpdates_Updating) {
+ version_updater_->SetReturnedStatus(VersionUpdater::Status::UPDATING);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kUpdates,
+ static_cast<int>(SafetyCheckHandler::UpdateStatus::kUpdating));
+ ASSERT_TRUE(event);
+#if defined(OS_CHROMEOS)
+ VerifyDisplayString(event, "Updating your device");
+#else
+ VerifyDisplayString(event, "Updating Browser");
+#endif
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.UpdatesResult",
+ SafetyCheckHandler::UpdateStatus::kUpdating, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckUpdates_Relaunch) {
+ version_updater_->SetReturnedStatus(VersionUpdater::Status::NEARLY_UPDATED);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kUpdates,
+ static_cast<int>(SafetyCheckHandler::UpdateStatus::kRelaunch));
+ ASSERT_TRUE(event);
+#if defined(OS_CHROMEOS)
+ VerifyDisplayString(
+ event, "Nearly up to date! Restart your device to finish updating.");
+#else
+ VerifyDisplayString(event,
+ "Nearly up to date! Relaunch Browser to finish "
+ "updating. Incognito windows won't reopen.");
+#endif
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.UpdatesResult",
+ SafetyCheckHandler::UpdateStatus::kRelaunch, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckUpdates_Disabled) {
+ version_updater_->SetReturnedStatus(VersionUpdater::Status::DISABLED);
+ safety_check_->PerformSafetyCheck();
+ // TODO(crbug/1072432): Since the UNKNOWN state is not present in JS in M83,
+ // use FAILED_OFFLINE, which uses the same icon.
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kUpdates,
+ static_cast<int>(SafetyCheckHandler::UpdateStatus::kFailedOffline));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(
+ event, "Version " + version_info::GetVersionNumber() + " (" +
+ (version_info::IsOfficialBuild() ? "Official Build"
+ : "Developer Build") +
+ ") " + chrome::GetChannelName() +
+ (sizeof(void*) == 8 ? " (64-bit)" : " (32-bit)"));
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.UpdatesResult",
+ SafetyCheckHandler::UpdateStatus::kUnknown, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckUpdates_DisabledByAdmin) {
+ version_updater_->SetReturnedStatus(
+ VersionUpdater::Status::DISABLED_BY_ADMIN);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kUpdates,
+ static_cast<int>(SafetyCheckHandler::UpdateStatus::kDisabledByAdmin));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(
+ event,
+ "Updates are managed by <a target=\"_blank\" "
+ "href=\"https://support.google.com/chrome?p=your_administrator\">your "
+ "administrator</a>");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.UpdatesResult",
+ SafetyCheckHandler::UpdateStatus::kDisabledByAdmin, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckUpdates_FailedOffline) {
+ version_updater_->SetReturnedStatus(VersionUpdater::Status::FAILED_OFFLINE);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kUpdates,
+ static_cast<int>(SafetyCheckHandler::UpdateStatus::kFailedOffline));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(event,
+ "Browser can't check for updates. Try checking your "
+ "internet connection.");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.UpdatesResult",
+ SafetyCheckHandler::UpdateStatus::kFailedOffline, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckUpdates_Failed) {
+ version_updater_->SetReturnedStatus(VersionUpdater::Status::FAILED);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kUpdates,
+ static_cast<int>(SafetyCheckHandler::UpdateStatus::kFailed));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(
+ event,
+ "Browser didn't update, something went wrong. <a target=\"_blank\" "
+ "href=\"https://support.google.com/chrome?p=fix_chrome_updates\">Fix "
+ "Browser update problems and failed updates.</a>");
+ histogram_tester_.ExpectBucketCount("Settings.SafetyCheck.UpdatesResult",
+ SafetyCheckHandler::UpdateStatus::kFailed,
+ 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckUpdates_DestroyedOnJavascriptDisallowed) {
+ EXPECT_FALSE(TestDestructionVersionUpdater::GetDestructorInvoked());
+ safety_check_->SetVersionUpdaterForTesting(
+ std::make_unique<TestDestructionVersionUpdater>());
+ safety_check_->PerformSafetyCheck();
+ safety_check_->DisallowJavascript();
+ EXPECT_TRUE(TestDestructionVersionUpdater::GetDestructorInvoked());
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckSafeBrowsing_Enabled) {
+ Profile::FromWebUI(&test_web_ui_)
+ ->GetPrefs()
+ ->SetBoolean(prefs::kSafeBrowsingEnabled, true);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kSafeBrowsing,
+ static_cast<int>(SafetyCheckHandler::SafeBrowsingStatus::kEnabled));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(event,
+ "Safe Browsing is on and protecting you from harmful "
+ "sites and downloads");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.SafeBrowsingResult",
+ SafetyCheckHandler::SafeBrowsingStatus::kEnabled, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckSafeBrowsing_Disabled) {
+ Profile::FromWebUI(&test_web_ui_)
+ ->GetPrefs()
+ ->SetBoolean(prefs::kSafeBrowsingEnabled, false);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kSafeBrowsing,
+ static_cast<int>(SafetyCheckHandler::SafeBrowsingStatus::kDisabled));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(
+ event, "Safe Browsing is off. Browser recommends turning it on.");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.SafeBrowsingResult",
+ SafetyCheckHandler::SafeBrowsingStatus::kDisabled, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckSafeBrowsing_DisabledByAdmin) {
+ TestingProfile::FromWebUI(&test_web_ui_)
+ ->AsTestingProfile()
+ ->GetTestingPrefService()
+ ->SetManagedPref(prefs::kSafeBrowsingEnabled,
+ std::make_unique<base::Value>(false));
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kSafeBrowsing,
+ static_cast<int>(
+ SafetyCheckHandler::SafeBrowsingStatus::kDisabledByAdmin));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(
+ event,
+ "<a target=\"_blank\" "
+ "href=\"https://support.google.com/chrome?p=your_administrator\">Your "
+ "administrator</a> has turned off Safe Browsing");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.SafeBrowsingResult",
+ SafetyCheckHandler::SafeBrowsingStatus::kDisabledByAdmin, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckSafeBrowsing_DisabledByExtension) {
+ TestingProfile::FromWebUI(&test_web_ui_)
+ ->AsTestingProfile()
+ ->GetTestingPrefService()
+ ->SetExtensionPref(prefs::kSafeBrowsingEnabled,
+ std::make_unique<base::Value>(false));
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kSafeBrowsing,
+ static_cast<int>(
+ SafetyCheckHandler::SafeBrowsingStatus::kDisabledByExtension));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(event, "An extension has turned off Safe Browsing");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.SafeBrowsingResult",
+ SafetyCheckHandler::SafeBrowsingStatus::kDisabledByExtension, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_ObserverRemovedAfterError) {
+ safety_check_->PerformSafetyCheck();
+ // First, a "running" change of state.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kRunning);
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(event, base::UTF8ToUTF16("Running…"));
+ histogram_tester_.ExpectTotalCount("Settings.SafetyCheck.PasswordsResult", 0);
+ // Second, an "offline" state.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kNetworkError);
+ const base::DictionaryValue* event2 =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kOffline));
+ ASSERT_TRUE(event2);
+ VerifyDisplayString(event2,
+ "Browser can't check your passwords. Try checking your "
+ "internet connection.");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.PasswordsResult",
+ SafetyCheckHandler::PasswordsStatus::kOffline, 1);
+ // Another error, but since the previous state is terminal, the handler
+ // should no longer be observing the BulkLeakCheckService state.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kServiceError);
+ const base::DictionaryValue* event3 =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kOffline));
+ ASSERT_TRUE(event3);
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.PasswordsResult",
+ SafetyCheckHandler::PasswordsStatus::kOffline, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_InterruptedAndRefreshed) {
+ safety_check_->PerformSafetyCheck();
+ // Password check running.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kRunning);
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(event, base::UTF8ToUTF16("Running…"));
+ // The check gets interrupted and the page is refreshed.
+ safety_check_->DisallowJavascript();
+ safety_check_->AllowJavascript();
+ // Need to set the |TestVersionUpdater| instance again to prevent
+ // |PerformSafetyCheck()| from creating a real |VersionUpdater| instance.
+ safety_check_->SetVersionUpdaterForTesting(
+ std::make_unique<TestVersionUpdater>());
+ // Another run of the safety check.
+ safety_check_->PerformSafetyCheck();
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kRunning);
+ const base::DictionaryValue* event2 =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking));
+ ASSERT_TRUE(event2);
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kSignedOut);
+ const base::DictionaryValue* event3 =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kSignedOut));
+ ASSERT_TRUE(event3);
+ VerifyDisplayString(event3,
+ "Browser can't check your passwords because you're not "
+ "signed in");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.PasswordsResult",
+ SafetyCheckHandler::PasswordsStatus::kSignedOut, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_StartedTwice) {
+ safety_check_->PerformSafetyCheck();
+ safety_check_->PerformSafetyCheck();
+ // First, a "running" change of state.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kRunning);
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking));
+ ASSERT_TRUE(event);
+ // Then, a network error.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kNetworkError);
+ const base::DictionaryValue* event2 =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kOffline));
+ EXPECT_TRUE(event2);
+ VerifyDisplayString(event2,
+ "Browser can't check your passwords. Try checking your "
+ "internet connection.");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.PasswordsResult",
+ SafetyCheckHandler::PasswordsStatus::kOffline, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_ObserverNotifiedTwice) {
+ safety_check_->PerformSafetyCheck();
+ EXPECT_TRUE(test_passwords_delegate_.StartPasswordCheckTriggered());
+ static_cast<password_manager::BulkLeakCheckService::Observer*>(
+ safety_check_.get())
+ ->OnStateChanged(
+ password_manager::BulkLeakCheckService::State::kServiceError);
+ // Another notification about the same state change.
+ static_cast<password_manager::BulkLeakCheckService::Observer*>(
+ safety_check_.get())
+ ->OnStateChanged(
+ password_manager::BulkLeakCheckService::State::kServiceError);
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kError));
+ ASSERT_TRUE(event);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_Safe) {
+ safety_check_->PerformSafetyCheck();
+ // First, a "running" change of state.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kRunning);
+ EXPECT_TRUE(GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking)));
+ // Second, a "safe" state.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kIdle);
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kSafe));
+ EXPECT_TRUE(event);
+ VerifyDisplayString(event, "No compromised passwords found");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.PasswordsResult",
+ SafetyCheckHandler::PasswordsStatus::kSafe, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_CompromisedExist) {
+ constexpr int kCompromised = 7;
+ test_passwords_delegate_.SetNumCompromisedCredentials(kCompromised);
+ safety_check_->PerformSafetyCheck();
+ // First, a "running" change of state.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kRunning);
+ EXPECT_TRUE(GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking)));
+ // Compromised passwords found state.
+ test_leak_service_->set_state_and_notify(
+ password_manager::BulkLeakCheckService::State::kIdle);
+ const base::DictionaryValue* event2 =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(
+ SafetyCheckHandler::PasswordsStatus::kCompromisedExist));
+ ASSERT_TRUE(event2);
+ VerifyDisplayString(
+ event2, base::NumberToString(kCompromised) + " compromised passwords");
+ VerifyButtonString(event2, "Change passwords");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.PasswordsResult",
+ SafetyCheckHandler::PasswordsStatus::kCompromisedExist, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_Error) {
+ safety_check_->PerformSafetyCheck();
+ EXPECT_TRUE(test_passwords_delegate_.StartPasswordCheckTriggered());
+ static_cast<password_manager::BulkLeakCheckService::Observer*>(
+ safety_check_.get())
+ ->OnStateChanged(
+ password_manager::BulkLeakCheckService::State::kServiceError);
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kError));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(event,
+ "Browser can't check your passwords. Try again "
+ "later.");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.PasswordsResult",
+ SafetyCheckHandler::PasswordsStatus::kError, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_RunningOneCompromised) {
+ test_passwords_delegate_.SetNumCompromisedCredentials(1);
+ safety_check_->PerformSafetyCheck();
+ EXPECT_TRUE(test_passwords_delegate_.StartPasswordCheckTriggered());
+ static_cast<password_manager::BulkLeakCheckService::Observer*>(
+ safety_check_.get())
+ ->OnStateChanged(password_manager::BulkLeakCheckService::State::kIdle);
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(
+ SafetyCheckHandler::PasswordsStatus::kCompromisedExist));
+ ASSERT_TRUE(event);
+ VerifyDisplayString(event, "1 compromised password");
+ VerifyButtonString(event, "Change password");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.PasswordsResult",
+ SafetyCheckHandler::PasswordsStatus::kCompromisedExist, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_NoPasswords) {
+ test_passwords_delegate_.ClearSavedPasswordsList();
+ test_passwords_delegate_.SetStartPasswordCheckState(
+ password_manager::BulkLeakCheckService::State::kIdle);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kNoPasswords));
+ EXPECT_TRUE(event);
+ VerifyDisplayString(event,
+ "No saved passwords. Chrome can check your passwords "
+ "when you save them.");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.PasswordsResult",
+ SafetyCheckHandler::PasswordsStatus::kNoPasswords, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckPasswords_Progress) {
+ auto credential = password_manager::LeakCheckCredential(
+ base::UTF8ToUTF16("test"), base::UTF8ToUTF16("test"));
+ auto is_leaked = password_manager::IsLeaked(false);
+ safety_check_->PerformSafetyCheck();
+ test_passwords_delegate_.SetPasswordCheckState(
+ extensions::api::passwords_private::PASSWORD_CHECK_STATE_RUNNING);
+ test_passwords_delegate_.SetProgress(1, 3);
+ static_cast<password_manager::BulkLeakCheckService::Observer*>(
+ safety_check_.get())
+ ->OnCredentialDone(credential, is_leaked);
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking));
+ EXPECT_TRUE(event);
+ VerifyDisplayString(event, base::UTF8ToUTF16("Checking passwords (1 of 3)…"));
+
+ test_passwords_delegate_.SetProgress(2, 3);
+ static_cast<password_manager::BulkLeakCheckService::Observer*>(
+ safety_check_.get())
+ ->OnCredentialDone(credential, is_leaked);
+ const base::DictionaryValue* event2 =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking));
+ EXPECT_TRUE(event2);
+ VerifyDisplayString(event2,
+ base::UTF8ToUTF16("Checking passwords (2 of 3)…"));
+
+ // Final update comes after status change, so no new progress message should
+ // be present.
+ test_passwords_delegate_.SetPasswordCheckState(
+ extensions::api::passwords_private::PASSWORD_CHECK_STATE_IDLE);
+ test_passwords_delegate_.SetProgress(3, 3);
+ static_cast<password_manager::BulkLeakCheckService::Observer*>(
+ safety_check_.get())
+ ->OnCredentialDone(credential, is_leaked);
+ const base::DictionaryValue* event3 =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kPasswords,
+ static_cast<int>(SafetyCheckHandler::PasswordsStatus::kChecking));
+ EXPECT_TRUE(event3);
+ // Still 2/3 event.
+ VerifyDisplayString(event3,
+ base::UTF8ToUTF16("Checking passwords (2 of 3)…"));
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckExtensions_NoExtensions) {
+ safety_check_->PerformSafetyCheck();
+ EXPECT_TRUE(GetSafetyCheckStatusChangedWithDataIfExists(
+ kExtensions,
+ static_cast<int>(
+ SafetyCheckHandler::ExtensionsStatus::kNoneBlocklisted)));
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.ExtensionsResult",
+ SafetyCheckHandler::ExtensionsStatus::kNoneBlocklisted, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckExtensions_NoneBlocklisted) {
+ std::string extension_id = GenerateExtensionId('a');
+ scoped_refptr<const extensions::Extension> extension =
+ extensions::ExtensionBuilder(extension_id).Build();
+ test_extension_prefs_->OnExtensionInstalled(
+ extension.get(), extensions::Extension::State::ENABLED,
+ syncer::StringOrdinal(), "");
+ test_extension_prefs_->SetExtensionBlacklistState(
+ extension_id, extensions::NOT_BLACKLISTED);
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kExtensions,
+ static_cast<int>(
+ SafetyCheckHandler::ExtensionsStatus::kNoneBlocklisted));
+ EXPECT_TRUE(event);
+ VerifyDisplayString(event,
+ "You're protected from potentially harmful extensions");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.ExtensionsResult",
+ SafetyCheckHandler::ExtensionsStatus::kNoneBlocklisted, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedAllDisabled) {
+ std::string extension_id = GenerateExtensionId('a');
+ scoped_refptr<const extensions::Extension> extension =
+ extensions::ExtensionBuilder("test0").SetID(extension_id).Build();
+ test_extension_prefs_->OnExtensionInstalled(
+ extension.get(), extensions::Extension::State::DISABLED,
+ syncer::StringOrdinal(), "");
+ test_extension_prefs_->SetExtensionBlacklistState(
+ extension_id, extensions::BLACKLISTED_MALWARE);
+ test_extension_service_.AddExtensionState(extension_id, Enabled(false),
+ UserCanDisable(false));
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kExtensions,
+ static_cast<int>(
+ SafetyCheckHandler::ExtensionsStatus::kBlocklistedAllDisabled));
+ EXPECT_TRUE(event);
+ VerifyDisplayString(
+ event, "1 potentially harmful extension is off. You can also remove it.");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.ExtensionsResult",
+ SafetyCheckHandler::ExtensionsStatus::kBlocklistedAllDisabled, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledAllByUser) {
+ std::string extension_id = GenerateExtensionId('a');
+ scoped_refptr<const extensions::Extension> extension =
+ extensions::ExtensionBuilder("test0").SetID(extension_id).Build();
+ test_extension_prefs_->OnExtensionInstalled(
+ extension.get(), extensions::Extension::State::ENABLED,
+ syncer::StringOrdinal(), "");
+ test_extension_prefs_->SetExtensionBlacklistState(
+ extension_id, extensions::BLACKLISTED_POTENTIALLY_UNWANTED);
+ test_extension_service_.AddExtensionState(extension_id, Enabled(true),
+ UserCanDisable(true));
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kExtensions, static_cast<int>(SafetyCheckHandler::ExtensionsStatus::
+ kBlocklistedReenabledAllByUser));
+ EXPECT_TRUE(event);
+ VerifyDisplayString(event,
+ "You turned 1 potentially harmful extension back on");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.ExtensionsResult",
+ SafetyCheckHandler::ExtensionsStatus::kBlocklistedReenabledAllByUser, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledAllByAdmin) {
+ std::string extension_id = GenerateExtensionId('a');
+ scoped_refptr<const extensions::Extension> extension =
+ extensions::ExtensionBuilder("test0").SetID(extension_id).Build();
+ test_extension_prefs_->OnExtensionInstalled(
+ extension.get(), extensions::Extension::State::ENABLED,
+ syncer::StringOrdinal(), "");
+ test_extension_prefs_->SetExtensionBlacklistState(
+ extension_id, extensions::BLACKLISTED_POTENTIALLY_UNWANTED);
+ test_extension_service_.AddExtensionState(extension_id, Enabled(true),
+ UserCanDisable(false));
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kExtensions, static_cast<int>(SafetyCheckHandler::ExtensionsStatus::
+ kBlocklistedReenabledAllByAdmin));
+ VerifyDisplayString(event,
+ "Your administrator turned 1 potentially harmful "
+ "extension back on");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.ExtensionsResult",
+ SafetyCheckHandler::ExtensionsStatus::kBlocklistedReenabledAllByAdmin, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledSomeByUser) {
+ std::string extension_id = GenerateExtensionId('a');
+ scoped_refptr<const extensions::Extension> extension =
+ extensions::ExtensionBuilder("test0").SetID(extension_id).Build();
+ test_extension_prefs_->OnExtensionInstalled(
+ extension.get(), extensions::Extension::State::ENABLED,
+ syncer::StringOrdinal(), "");
+ test_extension_prefs_->SetExtensionBlacklistState(
+ extension_id, extensions::BLACKLISTED_POTENTIALLY_UNWANTED);
+ test_extension_service_.AddExtensionState(extension_id, Enabled(true),
+ UserCanDisable(true));
+
+ std::string extension2_id = GenerateExtensionId('b');
+ scoped_refptr<const extensions::Extension> extension2 =
+ extensions::ExtensionBuilder("test1").SetID(extension2_id).Build();
+ test_extension_prefs_->OnExtensionInstalled(
+ extension2.get(), extensions::Extension::State::ENABLED,
+ syncer::StringOrdinal(), "");
+ test_extension_prefs_->SetExtensionBlacklistState(
+ extension2_id, extensions::BLACKLISTED_POTENTIALLY_UNWANTED);
+ test_extension_service_.AddExtensionState(extension2_id, Enabled(true),
+ UserCanDisable(false));
+
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kExtensions, static_cast<int>(SafetyCheckHandler::ExtensionsStatus::
+ kBlocklistedReenabledSomeByUser));
+ EXPECT_TRUE(event);
+ VerifyDisplayString(event,
+ "You turned 1 potentially harmful extension back "
+ "on. Your administrator "
+ "turned 1 potentially harmful extension back on.");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.ExtensionsResult",
+ SafetyCheckHandler::ExtensionsStatus::kBlocklistedReenabledSomeByUser, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckExtensions_Error) {
+ // One extension in the error state.
+ std::string extension_id = GenerateExtensionId('a');
+ scoped_refptr<const extensions::Extension> extension =
+ extensions::ExtensionBuilder("test0").SetID(extension_id).Build();
+ test_extension_prefs_->OnExtensionInstalled(
+ extension.get(), extensions::Extension::State::ENABLED,
+ syncer::StringOrdinal(), "");
+ test_extension_prefs_->SetExtensionBlacklistState(
+ extension_id, extensions::BLACKLISTED_UNKNOWN);
+ test_extension_service_.AddExtensionState(extension_id, Enabled(true),
+ UserCanDisable(true));
+
+ // Another extension blocklisted.
+ std::string extension2_id = GenerateExtensionId('b');
+ scoped_refptr<const extensions::Extension> extension2 =
+ extensions::ExtensionBuilder("test1").SetID(extension2_id).Build();
+ test_extension_prefs_->OnExtensionInstalled(
+ extension2.get(), extensions::Extension::State::ENABLED,
+ syncer::StringOrdinal(), "");
+ test_extension_prefs_->SetExtensionBlacklistState(
+ extension2_id, extensions::BLACKLISTED_POTENTIALLY_UNWANTED);
+ test_extension_service_.AddExtensionState(extension2_id, Enabled(true),
+ UserCanDisable(false));
+
+ safety_check_->PerformSafetyCheck();
+ const base::DictionaryValue* event =
+ GetSafetyCheckStatusChangedWithDataIfExists(
+ kExtensions,
+ static_cast<int>(SafetyCheckHandler::ExtensionsStatus::kError));
+ EXPECT_TRUE(event);
+ VerifyDisplayString(event,
+ "Browser can't check your extensions. Try again later.");
+ histogram_tester_.ExpectBucketCount(
+ "Settings.SafetyCheck.ExtensionsResult",
+ SafetyCheckHandler::ExtensionsStatus::kError, 1);
+}
+
+TEST_F(SafetyCheckHandlerTest, CheckParentRanDisplayString) {
+ // 1 second before midnight, so that -(24h-1s) is still on the same day.
+ const base::Time systemTime =
+ base::Time::Now().LocalMidnight() - base::TimeDelta::FromSeconds(1);
+ // Display strings for given time deltas in seconds.
+ std::vector<std::tuple<std::string, int>> tuples{
+ std::make_tuple("Safety check ran a moment ago", 1),
+ std::make_tuple("Safety check ran a moment ago", 59),
+ std::make_tuple("Safety check ran 1 minute ago", 60),
+ std::make_tuple("Safety check ran 2 minutes ago", 60 * 2),
+ std::make_tuple("Safety check ran 59 minutes ago", 60 * 60 - 1),
+ std::make_tuple("Safety check ran 1 hour ago", 60 * 60),
+ std::make_tuple("Safety check ran 2 hours ago", 60 * 60 * 2),
+ std::make_tuple("Safety check ran 23 hours ago", 60 * 60 * 23),
+ std::make_tuple("Safety check ran yesterday", 60 * 60 * 24),
+ std::make_tuple("Safety check ran yesterday", 60 * 60 * 24 * 2 - 1),
+ std::make_tuple("Safety check ran 2 days ago", 60 * 60 * 24 * 2),
+ std::make_tuple("Safety check ran 2 days ago", 60 * 60 * 24 * 3 - 1),
+ std::make_tuple("Safety check ran 3 days ago", 60 * 60 * 24 * 3),
+ std::make_tuple("Safety check ran 3 days ago", 60 * 60 * 24 * 4 - 1)};
+ // Test that above time deltas produce the corresponding display strings.
+ for (auto tuple : tuples) {
+ const base::Time time =
+ systemTime - base::TimeDelta::FromSeconds(std::get<1>(tuple));
+ const base::string16 displayString = safety_check_->GetStringForParentRan(
+ time.ToJsTimeIgnoringNull(), systemTime);
+ EXPECT_EQ(base::UTF8ToUTF16(std::get<0>(tuple)), displayString);
+ }
}
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
index ed1e4d58c0b..7c2416bd30a 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc
@@ -18,6 +18,7 @@
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/browsing_data/counters/browsing_data_counter_factory.h"
#include "chrome/browser/browsing_data/counters/browsing_data_counter_utils.h"
+#include "chrome/browser/engagement/important_sites_util.h"
#include "chrome/browser/history/web_history_service_factory.h"
#include "chrome/browser/signin/account_reconcilor_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
@@ -26,6 +27,7 @@
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
+#include "components/browsing_data/core/browsing_data_utils.h"
#include "components/browsing_data/core/history_notice_utils.h"
#include "components/browsing_data/core/pref_names.h"
#include "components/feature_engagement/buildflags.h"
@@ -48,6 +50,7 @@ using BrowsingDataType = browsing_data::BrowsingDataType;
namespace {
const int kMaxTimesHistoryNoticeShown = 1;
+const int kMaxInstalledAppsToWarnOf = 5;
// TODO(msramek): Get the list of deletion preferences from the JS side.
const char* kCounterPrefsAdvanced[] = {
@@ -66,14 +69,20 @@ const char* kCounterPrefsBasic[] = {
browsing_data::prefs::kDeleteCacheBasic,
};
+const char kRegisterableDomainField[] = "registerableDomain";
+const char kReasonBitfieldField[] = "reasonBitfield";
+const char kIsCheckedField[] = "isChecked";
+const char kAppName[] = "appName";
+
} // namespace
namespace settings {
// ClearBrowsingDataHandler ----------------------------------------------------
-ClearBrowsingDataHandler::ClearBrowsingDataHandler(content::WebUI* webui)
- : profile_(Profile::FromWebUI(webui)),
+ClearBrowsingDataHandler::ClearBrowsingDataHandler(content::WebUI* webui,
+ Profile* profile)
+ : profile_(profile),
sync_service_(ProfileSyncServiceFactory::GetForProfile(profile_)),
sync_service_observer_(this),
show_history_deletion_dialog_(false) {}
@@ -83,6 +92,11 @@ ClearBrowsingDataHandler::~ClearBrowsingDataHandler() {
void ClearBrowsingDataHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
+ "getInstalledApps",
+ base::BindRepeating(
+ &ClearBrowsingDataHandler::GetRecentlyLaunchedInstalledApps,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
"clearBrowsingData",
base::BindRepeating(&ClearBrowsingDataHandler::HandleClearBrowsingData,
base::Unretained(this)));
@@ -137,16 +151,99 @@ void ClearBrowsingDataHandler::HandleClearBrowsingDataForTest() {
std::make_unique<base::ListValue>();
data_types->AppendString("browser.clear_data.browsing_history");
+ std::unique_ptr<base::ListValue> installed_apps =
+ std::make_unique<base::ListValue>();
+
base::ListValue list_args;
list_args.AppendString("webui_callback_id");
list_args.Append(std::move(data_types));
list_args.AppendInteger(1u);
+ list_args.Append(std::move(installed_apps));
HandleClearBrowsingData(&list_args);
}
+void ClearBrowsingDataHandler::GetRecentlyLaunchedInstalledApps(
+ const base::ListValue* args) {
+ CHECK_EQ(2U, args->GetSize());
+ std::string webui_callback_id;
+ int period_selected;
+ CHECK(args->GetString(0, &webui_callback_id));
+
+ CHECK(args->GetInteger(1, &period_selected));
+ browsing_data::TimePeriod time_period =
+ static_cast<browsing_data::TimePeriod>(period_selected);
+
+ auto installed_apps = ImportantSitesUtil::GetInstalledRegisterableDomains(
+ time_period, profile_, kMaxInstalledAppsToWarnOf);
+
+ OnGotInstalledApps(webui_callback_id, installed_apps);
+}
+
+void ClearBrowsingDataHandler::OnGotInstalledApps(
+ const std::string& webui_callback_id,
+ const std::vector<ImportantSitesUtil::ImportantDomainInfo>&
+ installed_apps) {
+ base::ListValue installed_apps_list;
+ for (const auto& info : installed_apps) {
+ auto entry = std::make_unique<base::DictionaryValue>();
+ // Used to get favicon in ClearBrowsingDataDialog and display URL next to
+ // app name in the dialog.
+ entry->SetString(kRegisterableDomainField, info.registerable_domain);
+ // The |reason_bitfield| is only passed to Javascript to be logged
+ // from |HandleClearBrowsingData|.
+ entry->SetInteger(kReasonBitfieldField, info.reason_bitfield);
+ // Initially all sites are selected for deletion.
+ entry->SetBoolean(kIsCheckedField, true);
+ // User friendly name for the installed app.
+ DCHECK(info.app_name);
+ entry->SetString(kAppName, info.app_name.value());
+ installed_apps_list.Append(std::move(entry));
+ }
+ ResolveJavascriptCallback(base::Value(webui_callback_id),
+ installed_apps_list);
+}
+
+std::unique_ptr<content::BrowsingDataFilterBuilder>
+ClearBrowsingDataHandler::ProcessInstalledApps(
+ const base::ListValue* installed_apps) {
+ std::vector<std::string> excluded_domains;
+ std::vector<int32_t> excluded_domain_reasons;
+ std::vector<std::string> ignored_domains;
+ std::vector<int32_t> ignored_domain_reasons;
+ for (const auto& item : *installed_apps) {
+ const base::DictionaryValue* site = nullptr;
+ CHECK(item.GetAsDictionary(&site));
+ bool is_checked = false;
+ CHECK(site->GetBoolean(kIsCheckedField, &is_checked));
+ std::string domain;
+ CHECK(site->GetString(kRegisterableDomainField, &domain));
+ int domain_reason = -1;
+ CHECK(site->GetInteger(kReasonBitfieldField, &domain_reason));
+ if (is_checked) { // Selected installed apps should be deleted.
+ ignored_domains.push_back(domain);
+ ignored_domain_reasons.push_back(domain_reason);
+ } else { // Unselected sites should be kept.
+ excluded_domains.push_back(domain);
+ excluded_domain_reasons.push_back(domain_reason);
+ }
+ }
+ if (!excluded_domains.empty() || !ignored_domains.empty()) {
+ ImportantSitesUtil::RecordBlacklistedAndIgnoredImportantSites(
+ profile_->GetOriginalProfile(), excluded_domains,
+ excluded_domain_reasons, ignored_domains, ignored_domain_reasons);
+ }
+
+ std::unique_ptr<content::BrowsingDataFilterBuilder> filter_builder(
+ content::BrowsingDataFilterBuilder::Create(
+ content::BrowsingDataFilterBuilder::BLACKLIST));
+ for (const std::string& domain : excluded_domains)
+ filter_builder->AddRegisterableDomain(domain);
+ return filter_builder;
+}
+
void ClearBrowsingDataHandler::HandleClearBrowsingData(
const base::ListValue* args) {
- CHECK_EQ(3U, args->GetSize());
+ CHECK_EQ(4U, args->GetSize());
std::string webui_callback_id;
CHECK(args->GetString(0, &webui_callback_id));
@@ -261,6 +358,11 @@ void ClearBrowsingDataHandler::HandleClearBrowsingData(
int period_selected;
CHECK(args->GetInteger(2, &period_selected));
+ const base::ListValue* installed_apps = nullptr;
+ CHECK(args->GetList(3, &installed_apps));
+ std::unique_ptr<content::BrowsingDataFilterBuilder> filter_builder =
+ ProcessInstalledApps(installed_apps);
+
content::BrowsingDataRemover* remover =
content::BrowserContext::GetBrowsingDataRemover(profile_);
@@ -272,10 +374,8 @@ void ClearBrowsingDataHandler::HandleClearBrowsingData(
static_cast<browsing_data::TimePeriod>(period_selected);
browsing_data_important_sites_util::Remove(
- remove_mask, origin_mask, time_period,
- content::BrowsingDataFilterBuilder::Create(
- content::BrowsingDataFilterBuilder::BLACKLIST),
- remover, std::move(callback));
+ remove_mask, origin_mask, time_period, std::move(filter_builder), remover,
+ std::move(callback));
#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
feature_engagement::IncognitoWindowTrackerFactory::GetInstance()
@@ -360,11 +460,10 @@ void ClearBrowsingDataHandler::RefreshHistoryNotice() {
if (notice_shown_times < kMaxTimesHistoryNoticeShown) {
browsing_data::ShouldPopupDialogAboutOtherFormsOfBrowsingHistory(
- sync_service_,
- WebHistoryServiceFactory::GetForProfile(profile_),
+ sync_service_, WebHistoryServiceFactory::GetForProfile(profile_),
chrome::GetChannel(),
- base::Bind(&ClearBrowsingDataHandler::UpdateHistoryDeletionDialog,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(&ClearBrowsingDataHandler::UpdateHistoryDeletionDialog,
+ weak_ptr_factory_.GetWeakPtr()));
}
}
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h
index 9434c788871..784812552ef 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h
@@ -12,6 +12,7 @@
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/scoped_observer.h"
+#include "chrome/browser/engagement/important_sites_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
#include "components/browsing_data/core/browsing_data_utils.h"
@@ -24,6 +25,7 @@ class ListValue;
}
namespace content {
+class BrowsingDataFilterBuilder;
class WebUI;
}
@@ -33,7 +35,7 @@ namespace settings {
class ClearBrowsingDataHandler : public SettingsPageUIHandler,
public syncer::SyncServiceObserver {
public:
- explicit ClearBrowsingDataHandler(content::WebUI* webui);
+ ClearBrowsingDataHandler(content::WebUI* webui, Profile* profile);
~ClearBrowsingDataHandler() override;
// WebUIMessageHandler implementation.
@@ -44,7 +46,24 @@ class ClearBrowsingDataHandler : public SettingsPageUIHandler,
// Calls |HandleClearBrowsingData| with test data for browser test.
void HandleClearBrowsingDataForTest();
+ protected:
+ // Fetches a list of installed apps to be displayed in the clear browsing
+ // data confirmation dialog. Called by Javascript.
+ void GetRecentlyLaunchedInstalledApps(const base::ListValue* args);
+
private:
+ // Respond to the WebUI callback with the list of installed apps.
+ void OnGotInstalledApps(
+ const std::string& webui_callback_id,
+ const std::vector<ImportantSitesUtil::ImportantDomainInfo>&
+ installed_apps);
+
+ // Build a filter of sites to include and exclude from site data removal
+ // based on whether installed apps were marked for deletion by the checkbox on
+ // the installed apps warning dialog.
+ std::unique_ptr<content::BrowsingDataFilterBuilder> ProcessInstalledApps(
+ const base::ListValue* installed_apps);
+
// Clears browsing data, called by Javascript.
void HandleClearBrowsingData(const base::ListValue* value);
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc
new file mode 100644
index 00000000000..98dca3b412e
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc
@@ -0,0 +1,110 @@
+// 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 <memory>
+
+#include "chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h"
+
+#include "base/values.h"
+#include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/test_web_ui.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace {
+
+constexpr char kGetInstalledApps[] = "getInstalledApps";
+constexpr char kWebUiFunctionName[] = "webUiCallbackName";
+
+} // namespace
+
+namespace settings {
+
+class TestingClearBrowsingDataHandler : public ClearBrowsingDataHandler {
+ public:
+ TestingClearBrowsingDataHandler(content::WebUI* webui, Profile* profile)
+ : ClearBrowsingDataHandler(webui, profile) {
+ set_web_ui(webui);
+ }
+ TestingClearBrowsingDataHandler& operator=(
+ const TestingClearBrowsingDataHandler&) = delete;
+ TestingClearBrowsingDataHandler(const TestingClearBrowsingDataHandler&) =
+ delete;
+};
+
+class ClearBrowsingDataHandlerBrowserTest
+ : public web_app::WebAppControllerBrowserTest {
+ public:
+ ClearBrowsingDataHandlerBrowserTest() = default;
+ ~ClearBrowsingDataHandlerBrowserTest() = default;
+
+ void SetUpOnMainThread() override {
+ WebAppControllerBrowserTest::SetUpOnMainThread();
+
+ handler_ = std::make_unique<TestingClearBrowsingDataHandler>(
+ web_ui(), browser()->profile());
+ handler_->AllowJavascriptForTesting();
+ handler_->RegisterMessages();
+ }
+
+ void TearDownOnMainThread() override { handler_.reset(); }
+
+ protected:
+ web_app::AppId InstallAndLaunchApp(GURL& url) {
+ auto app_id = InstallPWA(url);
+
+ ui_test_utils::UrlLoadObserver url_observer(
+ url, content::NotificationService::AllSources());
+
+ auto* app_browser =
+ ClearBrowsingDataHandlerBrowserTest::LaunchWebAppBrowser(app_id);
+ url_observer.Wait();
+ DCHECK(app_browser);
+ DCHECK(app_browser != browser());
+
+ return app_id;
+ }
+
+ ClearBrowsingDataHandler* handler() { return handler_.get(); }
+ content::TestWebUI* web_ui() { return &web_ui_; }
+
+ private:
+ std::unique_ptr<ClearBrowsingDataHandler> handler_;
+ content::TestWebUI web_ui_;
+};
+
+IN_PROC_BROWSER_TEST_P(ClearBrowsingDataHandlerBrowserTest, GetInstalledApps) {
+ GURL url(https_server()->GetURL("/"));
+ InstallAndLaunchApp(url);
+ base::ListValue args;
+ args.AppendString(kWebUiFunctionName);
+ args.AppendInteger(1U);
+
+ web_ui()->HandleReceivedMessage(kGetInstalledApps, &args);
+ const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIResponse", call_data.function_name());
+ EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString());
+ ASSERT_TRUE(call_data.arg2()->GetBool());
+
+ // Get results from JS callback.
+ const base::span<const base::Value> result = call_data.arg3()->GetList();
+ ASSERT_EQ(1U, result.size());
+ auto& installed_app = result.back();
+ ASSERT_EQ(url.host(), *(installed_app.FindStringKey("registerableDomain")));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ ClearBrowsingDataHandlerBrowserTest,
+ ::testing::Values(
+ web_app::ControllerType::kHostedAppController,
+ web_app::ControllerType::kUnifiedControllerWithBookmarkApp,
+ web_app::ControllerType::kUnifiedControllerWithWebApp),
+ web_app::ControllerTypeParamToString);
+
+} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index 8dc520241ba..90189cf77f1 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -10,7 +10,6 @@
#include "base/feature_list.h"
#include "base/i18n/number_formatting.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
#include "build/branding_buildflags.h"
@@ -28,8 +27,8 @@
#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
#include "chrome/browser/ui/webui/management_ui.h"
#include "chrome/browser/ui/webui/policy_indicator_localized_strings_provider.h"
+#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
#include "chrome/browser/ui/webui/webui_util.h"
-#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
@@ -50,18 +49,20 @@
#include "components/autofill/core/common/autofill_payments_features.h"
#include "components/browsing_data/core/features.h"
#include "components/content_settings/core/common/features.h"
+#include "components/dom_distiller/core/dom_distiller_features.h"
#include "components/google/core/common/google_util.h"
#include "components/omnibox/common/omnibox_features.h"
+#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
#include "components/password_manager/core/browser/manage_passwords_referrer.h"
#include "components/password_manager/core/common/password_manager_features.h"
-#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
#include "components/signin/public/base/signin_buildflags.h"
#include "components/strings/grit/components_strings.h"
#include "components/subresource_filter/core/browser/subresource_filter_features.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/driver/sync_service_utils.h"
#include "components/sync/driver/sync_user_settings.h"
-#include "components/version_info/version_info.h"
+#include "components/zoom/page_zoom_constants.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/content_features.h"
@@ -74,42 +75,25 @@
#include "ui/accessibility/accessibility_switches.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
+#include "ui/strings/grit/ui_strings.h"
#if defined(OS_CHROMEOS)
-#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/ash_switches.h"
-#include "ash/public/mojom/assistant_state_controller.mojom.h"
#include "base/system/sys_info.h"
#include "chrome/browser/chromeos/account_manager/account_manager_util.h"
-#include "chrome/browser/chromeos/arc/arc_util.h"
#include "chrome/browser/chromeos/assistant/assistant_util.h"
-#include "chrome/browser/chromeos/crostini/crostini_features.h"
-#include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/chromeos/kerberos/kerberos_credentials_manager.h"
#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h"
#include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
-#include "chrome/browser/policy/profile_policy_connector.h"
-#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h"
-#include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h"
-#include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h"
-#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/webui_url_constants.h"
#include "chromeos/constants/chromeos_features.h"
-#include "chromeos/constants/chromeos_switches.h"
-#include "chromeos/services/assistant/public/features.h"
-#include "chromeos/services/multidevice_setup/public/cpp/url_provider.h"
-#include "chromeos/strings/grit/chromeos_strings.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/user_manager.h"
-#include "device/bluetooth/strings/grit/bluetooth_strings.h"
#include "ui/chromeos/devicetype_utils.h"
-#include "ui/chromeos/events/keyboard_layout_util.h"
-#include "ui/display/display_features.h"
-#include "ui/display/display_switches.h"
-#include "ui/display/manager/touch_device_manager.h"
#else
#include "chrome/browser/ui/webui/settings/system_handler.h"
#endif
@@ -129,7 +113,6 @@
#if defined(USE_NSS_CERTS)
#include "chrome/browser/ui/webui/certificate_manager_localized_strings_provider.h"
#endif
-
namespace settings {
namespace {
@@ -141,26 +124,6 @@ base::string16 GetHelpUrlWithBoard(const std::string& original_url) {
return base::ASCIIToUTF16(original_url +
"&b=" + base::SysInfo::GetLsbReleaseBoard());
}
-
-bool IsDeviceManaged() {
- policy::BrowserPolicyConnectorChromeOS* connector =
- g_browser_process->platform_part()->browser_policy_connector_chromeos();
- return connector->IsEnterpriseManaged();
-}
-
-bool IsProfileManaged(Profile* profile) {
- return profile->GetProfilePolicyConnector()->IsManaged();
-}
-
-bool ShouldEnableArcAdbSideloading() {
- // Only enable on supported devices per USE flag.
- if (!base::FeatureList::IsEnabled(
- chromeos::features::kArcAdbSideloadingFeature)) {
- return false;
- }
-
- return chrome::GetChannel() < version_info::Channel::BETA;
-}
#endif
void AddCommonStrings(content::WebUIDataSource* html_source, Profile* profile) {
@@ -175,11 +138,8 @@ void AddCommonStrings(content::WebUIDataSource* html_source, Profile* profile) {
{"confirm", IDS_CONFIRM},
{"continue", IDS_SETTINGS_CONTINUE},
{"controlledByExtension", IDS_SETTINGS_CONTROLLED_BY_EXTENSION},
+ {"custom", IDS_SETTINGS_CUSTOM},
{"delete", IDS_SETTINGS_DELETE},
-#if defined(OS_CHROMEOS)
- {"deviceOff", IDS_SETTINGS_DEVICE_OFF},
- {"deviceOn", IDS_SETTINGS_DEVICE_ON},
-#endif
{"disable", IDS_DISABLE},
{"done", IDS_DONE},
{"edit", IDS_SETTINGS_EDIT},
@@ -195,15 +155,24 @@ void AddCommonStrings(content::WebUIDataSource* html_source, Profile* profile) {
#endif
{"retry", IDS_SETTINGS_RETRY},
{"save", IDS_SAVE},
+ {"searchResultBubbleText", IDS_SEARCH_RESULT_BUBBLE_TEXT},
+ {"searchResultsBubbleText", IDS_SEARCH_RESULTS_BUBBLE_TEXT},
+ {"sentenceEnd", IDS_SENTENCE_END},
{"settings", IDS_SETTINGS_SETTINGS},
{"settingsAltPageTitle", IDS_SETTINGS_ALT_PAGE_TITLE},
{"subpageArrowRoleDescription", IDS_SETTINGS_SUBPAGE_BUTTON},
- {"toggleOn", IDS_SETTINGS_TOGGLE_ON},
- {"toggleOff", IDS_SETTINGS_TOGGLE_OFF},
{"notValid", IDS_SETTINGS_NOT_VALID},
{"notValidWebAddress", IDS_SETTINGS_NOT_VALID_WEB_ADDRESS},
{"notValidWebAddressForContentType",
IDS_SETTINGS_NOT_VALID_WEB_ADDRESS_FOR_CONTENT_TYPE},
+
+ // Common font related strings shown in a11y and appearance sections.
+ {"quickBrownFox", IDS_SETTINGS_QUICK_BROWN_FOX},
+ {"verySmall", IDS_SETTINGS_VERY_SMALL_FONT},
+ {"small", IDS_SETTINGS_SMALL_FONT},
+ {"medium", IDS_SETTINGS_MEDIUM_FONT},
+ {"large", IDS_SETTINGS_LARGE_FONT},
+ {"veryLarge", IDS_SETTINGS_VERY_LARGE_FONT},
};
AddLocalizedStringsBulk(html_source, kLocalizedStrings);
@@ -221,327 +190,66 @@ void AddCommonStrings(content::WebUIDataSource* html_source, Profile* profile) {
void AddA11yStrings(content::WebUIDataSource* html_source) {
static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"moreFeaturesLink", IDS_SETTINGS_MORE_FEATURES_LINK},
{"a11yPageTitle", IDS_SETTINGS_ACCESSIBILITY},
{"a11yWebStore", IDS_SETTINGS_ACCESSIBILITY_WEB_STORE},
+ {"moreFeaturesLinkDescription",
+ IDS_SETTINGS_MORE_FEATURES_LINK_DESCRIPTION},
{"accessibleImageLabelsTitle", IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_TITLE},
{"accessibleImageLabelsSubtitle",
IDS_SETTINGS_ACCESSIBLE_IMAGE_LABELS_SUBTITLE},
- {"moreFeaturesLink", IDS_SETTINGS_MORE_FEATURES_LINK},
- {"moreFeaturesLinkDescription",
- IDS_SETTINGS_MORE_FEATURES_LINK_DESCRIPTION},
- {"captionsTitle", IDS_SETTINGS_CAPTIONS},
- {"captionsSettings", IDS_SETTINGS_CAPTIONS_SETTINGS},
- {"captionsPreview", IDS_SETTINGS_CAPTIONS_PREVIEW},
- {"captionsTextSize", IDS_SETTINGS_CAPTIONS_TEXT_SIZE},
- {"captionsTextFont", IDS_SETTINGS_CAPTIONS_TEXT_FONT},
- {"captionsTextColor", IDS_SETTINGS_CAPTIONS_TEXT_COLOR},
- {"captionsTextOpacity", IDS_SETTINGS_CAPTIONS_TEXT_OPACITY},
- {"captionsBackgroundOpacity", IDS_SETTINGS_CAPTIONS_BACKGROUND_OPACITY},
- {"captionsOpacityOpaque", IDS_SETTINGS_CAPTIONS_OPACITY_OPAQUE},
- {"captionsOpacitySemiTransparent",
- IDS_SETTINGS_CAPTIONS_OPACITY_SEMI_TRANSPARENT},
- {"captionsOpacityTransparent", IDS_SETTINGS_CAPTIONS_OPACITY_TRANSPARENT},
- {"captionsTextShadow", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW},
- {"captionsTextShadowNone", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_NONE},
- {"captionsTextShadowRaised", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_RAISED},
- {"captionsTextShadowDepressed",
- IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DEPRESSED},
- {"captionsTextShadowUniform", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_UNIFORM},
- {"captionsTextShadowDropShadow",
- IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DROP_SHADOW},
- {"captionsBackgroundColor", IDS_SETTINGS_CAPTIONS_BACKGROUND_COLOR},
- {"captionsColorBlack", IDS_SETTINGS_CAPTIONS_COLOR_BLACK},
- {"captionsColorWhite", IDS_SETTINGS_CAPTIONS_COLOR_WHITE},
- {"captionsColorRed", IDS_SETTINGS_CAPTIONS_COLOR_RED},
- {"captionsColorGreen", IDS_SETTINGS_CAPTIONS_COLOR_GREEN},
- {"captionsColorBlue", IDS_SETTINGS_CAPTIONS_COLOR_BLUE},
- {"captionsColorYellow", IDS_SETTINGS_CAPTIONS_COLOR_YELLOW},
- {"captionsColorCyan", IDS_SETTINGS_CAPTIONS_COLOR_CYAN},
- {"captionsColorMagenta", IDS_SETTINGS_CAPTIONS_COLOR_MAGENTA},
- {"captionsDefaultSetting", IDS_SETTINGS_CAPTIONS_DEFAULT_SETTING},
{"settingsSliderRoleDescription",
IDS_SETTINGS_SLIDER_MIN_MAX_ARIA_ROLE_DESCRIPTION},
+ {"captionsEnableLiveCaptionTitle",
+ IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_TITLE},
+ {"captionsEnableLiveCaptionSubtitle",
+ IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_SUBTITLE},
#if defined(OS_CHROMEOS)
- {"optionsInMenuLabel", IDS_SETTINGS_OPTIONS_IN_MENU_LABEL},
- {"largeMouseCursorLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_LABEL},
- {"largeMouseCursorSizeLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_LABEL},
- {"largeMouseCursorSizeDefaultLabel",
- IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_DEFAULT_LABEL},
- {"largeMouseCursorSizeLargeLabel",
- IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_LARGE_LABEL},
- {"highContrastLabel", IDS_SETTINGS_HIGH_CONTRAST_LABEL},
- {"stickyKeysLabel", IDS_SETTINGS_STICKY_KEYS_LABEL},
- {"chromeVoxLabel", IDS_SETTINGS_CHROMEVOX_LABEL},
- {"chromeVoxOptionsLabel", IDS_SETTINGS_CHROMEVOX_OPTIONS_LABEL},
- {"screenMagnifierLabel", IDS_SETTINGS_SCREEN_MAGNIFIER_LABEL},
- {"screenMagnifierZoomLabel", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_LABEL},
- {"dockedMagnifierLabel", IDS_SETTINGS_DOCKED_MAGNIFIER_LABEL},
- {"dockedMagnifierZoomLabel", IDS_SETTINGS_DOCKED_MAGNIFIER_ZOOM_LABEL},
- {"screenMagnifierZoom2x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_2_X},
- {"screenMagnifierZoom4x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_4_X},
- {"screenMagnifierZoom6x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_6_X},
- {"screenMagnifierZoom8x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_8_X},
- {"screenMagnifierZoom10x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_10_X},
- {"screenMagnifierZoom12x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_12_X},
- {"screenMagnifierZoom14x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_14_X},
- {"screenMagnifierZoom16x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_16_X},
- {"screenMagnifierZoom18x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_18_X},
- {"screenMagnifierZoom20x", IDS_SETTINGS_SCREEN_MAGNIFIER_ZOOM_20_X},
- {"tapDraggingLabel", IDS_SETTINGS_TAP_DRAGGING_LABEL},
- {"clickOnStopLabel", IDS_SETTINGS_CLICK_ON_STOP_LABEL},
- {"delayBeforeClickLabel", IDS_SETTINGS_DELAY_BEFORE_CLICK_LABEL},
- {"delayBeforeClickExtremelyShort",
- IDS_SETTINGS_DELAY_BEFORE_CLICK_EXTREMELY_SHORT},
- {"delayBeforeClickVeryShort", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_SHORT},
- {"delayBeforeClickShort", IDS_SETTINGS_DELAY_BEFORE_CLICK_SHORT},
- {"delayBeforeClickLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_LONG},
- {"delayBeforeClickVeryLong", IDS_SETTINGS_DELAY_BEFORE_CLICK_VERY_LONG},
- {"autoclickRevertToLeftClick", IDS_SETTINGS_AUTOCLICK_REVERT_TO_LEFT_CLICK},
- {"autoclickStabilizeCursorPosition",
- IDS_SETTINGS_AUTOCLICK_STABILIZE_CURSOR_POSITION},
- {"autoclickMovementThresholdLabel",
- IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LABEL},
- {"autoclickMovementThresholdExtraSmall",
- IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_EXTRA_SMALL},
- {"autoclickMovementThresholdSmall",
- IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_SMALL},
- {"autoclickMovementThresholdDefault",
- IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_DEFAULT},
- {"autoclickMovementThresholdLarge",
- IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_LARGE},
- {"autoclickMovementThresholdExtraLarge",
- IDS_SETTINGS_AUTOCLICK_MOVEMENT_THRESHOLD_EXTRA_LARGE},
- {"dictationDescription", IDS_SETTINGS_ACCESSIBILITY_DICTATION_DESCRIPTION},
- {"dictationLabel", IDS_SETTINGS_ACCESSIBILITY_DICTATION_LABEL},
- {"onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL},
- {"monoAudioLabel", IDS_SETTINGS_MONO_AUDIO_LABEL},
- {"startupSoundLabel", IDS_SETTINGS_STARTUP_SOUND_LABEL},
- {"a11yExplanation", IDS_SETTINGS_ACCESSIBILITY_EXPLANATION},
- {"caretHighlightLabel",
- IDS_SETTINGS_ACCESSIBILITY_CARET_HIGHLIGHT_DESCRIPTION},
- {"cursorHighlightLabel",
- IDS_SETTINGS_ACCESSIBILITY_CURSOR_HIGHLIGHT_DESCRIPTION},
- {"focusHighlightLabel",
- IDS_SETTINGS_ACCESSIBILITY_FOCUS_HIGHLIGHT_DESCRIPTION},
- {"selectToSpeakTitle", IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_TITLE},
- {"selectToSpeakDisabledDescription",
- IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DISABLED_DESCRIPTION},
- {"selectToSpeakDescription",
- IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION},
- {"selectToSpeakDescriptionWithoutKeyboard",
- IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_DESCRIPTION_WITHOUT_KEYBOARD},
- {"selectToSpeakOptionsLabel",
- IDS_SETTINGS_ACCESSIBILITY_SELECT_TO_SPEAK_OPTIONS_LABEL},
- {"switchAccessLabel", IDS_SETTINGS_ACCESSIBILITY_SWITCH_ACCESS_DESCRIPTION},
- {"switchAccessOptionsLabel",
- IDS_SETTINGS_ACCESSIBILITY_SWITCH_ACCESS_OPTIONS_LABEL},
- {"manageSwitchAccessSettings", IDS_SETTINGS_MANAGE_SWITCH_ACCESS_SETTINGS},
- {"switchAssignmentHeading", IDS_SETTINGS_SWITCH_ASSIGNMENT_HEADING},
- {"switchAssignOptionNone", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_NONE},
- {"switchAssignOptionSpace", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_SPACE},
- {"switchAssignOptionEnter", IDS_SETTINGS_SWITCH_ASSIGN_OPTION_ENTER},
- {"assignSelectSwitchLabel", IDS_SETTINGS_ASSIGN_SELECT_SWITCH_LABEL},
- {"assignNextSwitchLabel", IDS_SETTINGS_ASSIGN_NEXT_SWITCH_LABEL},
- {"assignPreviousSwitchLabel", IDS_SETTINGS_ASSIGN_PREVIOUS_SWITCH_LABEL},
- {"switchAccessAutoScanHeading",
- IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_HEADING},
- {"switchAccessAutoScanLabel", IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_LABEL},
- {"switchAccessAutoScanSpeedLabel",
- IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_SPEED_LABEL},
- {"switchAccessAutoScanKeyboardSpeedLabel",
- IDS_SETTINGS_SWITCH_ACCESS_AUTO_SCAN_KEYBOARD_SPEED_LABEL},
- {"durationInSeconds", IDS_SETTINGS_DURATION_IN_SECONDS},
{"manageAccessibilityFeatures",
IDS_SETTINGS_ACCESSIBILITY_MANAGE_ACCESSIBILITY_FEATURES},
- {"textToSpeechHeading", IDS_SETTINGS_ACCESSIBILITY_TEXT_TO_SPEECH_HEADING},
- {"displayHeading", IDS_SETTINGS_ACCESSIBILITY_DISPLAY_HEADING},
- {"displaySettingsTitle", IDS_SETTINGS_ACCESSIBILITY_DISPLAY_SETTINGS_TITLE},
- {"displaySettingsDescription",
- IDS_SETTINGS_ACCESSIBILITY_DISPLAY_SETTINGS_DESCRIPTION},
- {"appearanceSettingsTitle",
- IDS_SETTINGS_ACCESSIBILITY_APPEARANCE_SETTINGS_TITLE},
- {"appearanceSettingsDescription",
- IDS_SETTINGS_ACCESSIBILITY_APPEARANCE_SETTINGS_DESCRIPTION},
- {"keyboardAndTextInputHeading",
- IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_AND_TEXT_INPUT_HEADING},
- {"keyboardSettingsTitle",
- IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_SETTINGS_TITLE},
- {"keyboardSettingsDescription",
- IDS_SETTINGS_ACCESSIBILITY_KEYBOARD_SETTINGS_DESCRIPTION},
- {"mouseAndTouchpadHeading",
- IDS_SETTINGS_ACCESSIBILITY_MOUSE_AND_TOUCHPAD_HEADING},
- {"mouseSettingsTitle", IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_TITLE},
- {"mouseSettingsDescription",
- IDS_SETTINGS_ACCESSIBILITY_MOUSE_SETTINGS_DESCRIPTION},
- {"audioAndCaptionsHeading",
- IDS_SETTINGS_ACCESSIBILITY_AUDIO_AND_CAPTIONS_HEADING},
- {"additionalFeaturesTitle",
- IDS_SETTINGS_ACCESSIBILITY_ADDITIONAL_FEATURES_TITLE},
- {"manageTtsSettings", IDS_SETTINGS_MANAGE_TTS_SETTINGS},
- {"ttsSettingsLinkDescription", IDS_SETTINGS_TTS_LINK_DESCRIPTION},
- {"textToSpeechVoices", IDS_SETTINGS_TEXT_TO_SPEECH_VOICES},
- {"textToSpeechNoVoicesMessage",
- IDS_SETTINGS_TEXT_TO_SPEECH_NO_VOICES_MESSAGE},
- {"textToSpeechMoreLanguages", IDS_SETTINGS_TEXT_TO_SPEECH_MORE_LANGUAGES},
- {"textToSpeechProperties", IDS_SETTINGS_TEXT_TO_SPEECH_PROPERTIES},
- {"textToSpeechRate", IDS_SETTINGS_TEXT_TO_SPEECH_RATE},
- {"textToSpeechRateMinimumLabel",
- IDS_SETTINGS_TEXT_TO_SPEECH_RATE_MINIMUM_LABEL},
- {"textToSpeechRateMaximumLabel",
- IDS_SETTINGS_TEXT_TO_SPEECH_RATE_MAXIMUM_LABEL},
- {"textToSpeechPitch", IDS_SETTINGS_TEXT_TO_SPEECH_PITCH},
- {"textToSpeechPitchMinimumLabel",
- IDS_SETTINGS_TEXT_TO_SPEECH_PITCH_MINIMUM_LABEL},
- {"textToSpeechPitchMaximumLabel",
- IDS_SETTINGS_TEXT_TO_SPEECH_PITCH_MAXIMUM_LABEL},
- {"textToSpeechVolume", IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME},
- {"textToSpeechVolumeMinimumLabel",
- IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME_MINIMUM_LABEL},
- {"textToSpeechVolumeMaximumLabel",
- IDS_SETTINGS_TEXT_TO_SPEECH_VOLUME_MAXIMUM_LABEL},
- {"percentage", IDS_SETTINGS_PERCENTAGE},
- {"defaultPercentage", IDS_SETTINGS_DEFAULT_PERCENTAGE},
- {"textToSpeechPreviewHeading", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_HEADING},
- {"textToSpeechPreviewInputLabel",
- IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_INPUT_LABEL},
- {"textToSpeechPreviewInput", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_INPUT},
- {"textToSpeechPreviewVoice", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_VOICE},
- {"textToSpeechPreviewPlay", IDS_SETTINGS_TEXT_TO_SPEECH_PREVIEW_PLAY},
- {"textToSpeechEngines", IDS_SETTINGS_TEXT_TO_SPEECH_ENGINES},
+ {"androidAppsManageAppLinks", IDS_SETTINGS_ANDROID_APPS_MANAGE_APP_LINKS},
#endif
};
AddLocalizedStringsBulk(html_source, kLocalizedStrings);
- html_source->AddBoolean(
- "showExperimentalA11yLabels",
- base::FeatureList::IsEnabled(features::kExperimentalAccessibilityLabels));
-
- html_source->AddBoolean(
- "enableCaptionSettings",
- base::FeatureList::IsEnabled(features::kCaptionSettings));
-
#if defined(OS_WIN)
html_source->AddBoolean("isWindows10OrNewer",
base::win::GetVersion() >= base::win::Version::WIN10);
#endif
-
-#if defined(OS_CHROMEOS)
- html_source->AddString("accountManagerLearnMoreUrl",
- chrome::kAccountManagerLearnMoreURL);
- html_source->AddString("a11yLearnMoreUrl",
- chrome::kChromeAccessibilityHelpURL);
-
- base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess();
html_source->AddBoolean(
- "showExperimentalA11yFeatures",
- cmd.HasSwitch(::switches::kEnableExperimentalAccessibilityFeatures));
+ "showExperimentalA11yLabels",
+ base::FeatureList::IsEnabled(features::kExperimentalAccessibilityLabels));
- html_source->AddBoolean(
- "showExperimentalAccessibilitySwitchAccess",
- cmd.HasSwitch(::switches::kEnableExperimentalAccessibilitySwitchAccess));
+ html_source->AddBoolean("enableLiveCaption",
+ base::FeatureList::IsEnabled(media::kLiveCaption));
- html_source->AddBoolean(
- "showExperimentalAccessibilitySwitchAccessImprovedTextInput",
- cmd.HasSwitch(
- ::switches::kEnableExperimentalAccessibilitySwitchAccessText));
-#endif
+ AddCaptionSubpageStrings(html_source);
}
-void AddAboutStrings(content::WebUIDataSource* html_source) {
+void AddAboutStrings(content::WebUIDataSource* html_source, Profile* profile) {
+ // Top level About Page strings.
static constexpr webui::LocalizedString kLocalizedStrings[] = {
{"aboutProductLogoAlt", IDS_SHORT_PRODUCT_LOGO_ALT_TEXT},
-
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
{"aboutReportAnIssue", IDS_SETTINGS_ABOUT_PAGE_REPORT_AN_ISSUE},
#endif
-
{"aboutRelaunch", IDS_SETTINGS_ABOUT_PAGE_RELAUNCH},
{"aboutUpgradeCheckStarted", IDS_SETTINGS_ABOUT_UPGRADE_CHECK_STARTED},
{"aboutUpgradeRelaunch", IDS_SETTINGS_UPGRADE_SUCCESSFUL_RELAUNCH},
{"aboutUpgradeUpdating", IDS_SETTINGS_UPGRADE_UPDATING},
{"aboutUpgradeUpdatingPercent", IDS_SETTINGS_UPGRADE_UPDATING_PERCENT},
-
+ {"aboutGetHelpUsingChrome", IDS_SETTINGS_GET_HELP_USING_CHROME},
+ {"aboutPageTitle", IDS_SETTINGS_ABOUT_PROGRAM},
+ {"aboutProductTitle", IDS_PRODUCT_NAME},
#if defined(OS_CHROMEOS)
- {"aboutBuildDetailsTitle", IDS_OS_SETTINGS_ABOUT_PAGE_BUILD_DETAILS},
- {"aboutChannelBeta", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_BETA},
- {"aboutChannelCanary", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_CANARY},
- {"aboutChannelDev", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_DEV},
- {"aboutChannelLabel", IDS_SETTINGS_ABOUT_PAGE_CHANNEL},
- {"aboutChannelStable", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL_STABLE},
- {"aboutCheckForUpdates", IDS_SETTINGS_ABOUT_PAGE_CHECK_FOR_UPDATES},
- {"aboutCurrentlyOnChannel", IDS_SETTINGS_ABOUT_PAGE_CURRENT_CHANNEL},
- {"aboutDetailedBuildInfo", IDS_SETTINGS_ABOUT_PAGE_DETAILED_BUILD_INFO},
- {"aboutEndOfLifeTitle", IDS_SETTINGS_ABOUT_PAGE_END_OF_LIFE_TITLE},
- {"aboutRelaunchAndPowerwash",
- IDS_SETTINGS_ABOUT_PAGE_RELAUNCH_AND_POWERWASH},
- {"aboutRollbackInProgress", IDS_SETTINGS_UPGRADE_ROLLBACK_IN_PROGRESS},
- {"aboutRollbackSuccess", IDS_SETTINGS_UPGRADE_ROLLBACK_SUCCESS},
{"aboutUpdateOsSettingsLink",
IDS_SETTINGS_ABOUT_SEE_OS_SETTINGS_FOR_UPDATE_MESSAGE},
- {"aboutUpgradeUpdatingChannelSwitch",
- IDS_SETTINGS_UPGRADE_UPDATING_CHANNEL_SWITCH},
- {"aboutUpgradeSuccessChannelSwitch",
- IDS_SETTINGS_UPGRADE_SUCCESSFUL_CHANNEL_SWITCH},
- {"aboutTPMFirmwareUpdateTitle",
- IDS_SETTINGS_ABOUT_TPM_FIRMWARE_UPDATE_TITLE},
- {"aboutTPMFirmwareUpdateDescription",
- IDS_SETTINGS_ABOUT_TPM_FIRMWARE_UPDATE_DESCRIPTION},
-
- // About page, channel switcher dialog.
- {"aboutChangeChannel", IDS_SETTINGS_ABOUT_PAGE_CHANGE_CHANNEL},
- {"aboutChangeChannelAndPowerwash",
- IDS_SETTINGS_ABOUT_PAGE_CHANGE_CHANNEL_AND_POWERWASH},
- {"aboutDelayedWarningMessage",
- IDS_SETTINGS_ABOUT_PAGE_DELAYED_WARNING_MESSAGE},
- {"aboutDelayedWarningTitle", IDS_SETTINGS_ABOUT_PAGE_DELAYED_WARNING_TITLE},
- {"aboutPowerwashWarningMessage",
- IDS_SETTINGS_ABOUT_PAGE_POWERWASH_WARNING_MESSAGE},
- {"aboutPowerwashWarningTitle",
- IDS_SETTINGS_ABOUT_PAGE_POWERWASH_WARNING_TITLE},
- {"aboutUnstableWarningMessage",
- IDS_SETTINGS_ABOUT_PAGE_UNSTABLE_WARNING_MESSAGE},
- {"aboutUnstableWarningTitle",
- IDS_SETTINGS_ABOUT_PAGE_UNSTABLE_WARNING_TITLE},
- {"aboutChannelDialogBeta", IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_BETA},
- {"aboutChannelDialogDev", IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_DEV},
- {"aboutChannelDialogStable", IDS_SETTINGS_ABOUT_PAGE_DIALOG_CHANNEL_STABLE},
-
- // About page, update warning dialog.
- {"aboutUpdateWarningMessage",
- IDS_SETTINGS_ABOUT_PAGE_UPDATE_WARNING_MESSAGE},
- {"aboutUpdateWarningTitle", IDS_SETTINGS_ABOUT_PAGE_UPDATE_WARNING_TITLE},
-#endif // defined(OS_CHROMEOS)
+#endif
};
AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-#if defined(OS_CHROMEOS)
- html_source->AddLocalizedString("aboutOsPageTitle", IDS_SETTINGS_ABOUT_OS);
- html_source->AddLocalizedString("aboutGetHelpUsingChromeOs",
- IDS_SETTINGS_GET_HELP_USING_CHROME_OS);
- html_source->AddLocalizedString("aboutOsProductTitle", IDS_PRODUCT_OS_NAME);
- html_source->AddLocalizedString("aboutReleaseNotesOffline",
- IDS_SETTINGS_ABOUT_PAGE_RELEASE_NOTES);
- html_source->AddLocalizedString("aboutShowReleaseNotes",
- IDS_SETTINGS_ABOUT_PAGE_SHOW_RELEASE_NOTES);
- if (base::FeatureList::IsEnabled(chromeos::features::kSplitSettings)) {
- html_source->AddLocalizedString("aboutGetHelpUsingChrome",
- IDS_SETTINGS_GET_HELP_USING_CHROME);
- html_source->AddLocalizedString("aboutPageTitle",
- IDS_SETTINGS_ABOUT_PROGRAM);
- html_source->AddLocalizedString("aboutProductTitle", IDS_PRODUCT_NAME);
- } else {
- html_source->AddLocalizedString("aboutGetHelpUsingChrome",
- IDS_SETTINGS_GET_HELP_USING_CHROME_OS);
- html_source->AddLocalizedString("aboutPageTitle", IDS_SETTINGS_ABOUT_OS);
- html_source->AddLocalizedString("aboutProductTitle", IDS_PRODUCT_OS_NAME);
- }
-#else
- html_source->AddLocalizedString("aboutGetHelpUsingChrome",
- IDS_SETTINGS_GET_HELP_USING_CHROME);
- html_source->AddLocalizedString("aboutPageTitle", IDS_SETTINGS_ABOUT_PROGRAM);
- html_source->AddLocalizedString("aboutProductTitle", IDS_PRODUCT_NAME);
-#endif
-
+ html_source->AddString("managementPage",
+ ManagementUI::GetManagementPageSubtitle(profile));
html_source->AddString(
"aboutUpgradeUpToDate",
#if defined(OS_CHROMEOS)
@@ -549,200 +257,7 @@ void AddAboutStrings(content::WebUIDataSource* html_source) {
#else
l10n_util::GetStringUTF16(IDS_SETTINGS_UPGRADE_UP_TO_DATE));
#endif
-
-#if defined(OS_CHROMEOS)
- html_source->AddString("aboutTPMFirmwareUpdateLearnMoreURL",
- chrome::kTPMFirmwareUpdateLearnMoreURL);
-#endif
-}
-
-#if defined(OS_CHROMEOS)
-void AddCrostiniStrings(content::WebUIDataSource* html_source,
- Profile* profile) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"crostiniPageTitle", IDS_SETTINGS_CROSTINI_TITLE},
- {"crostiniPageLabel", IDS_SETTINGS_CROSTINI_LABEL},
- {"crostiniEnable", IDS_SETTINGS_TURN_ON},
- {"crostiniSharedPaths", IDS_SETTINGS_CROSTINI_SHARED_PATHS},
- {"crostiniSharedPathsListHeading",
- IDS_SETTINGS_CROSTINI_SHARED_PATHS_LIST_HEADING},
- {"crostiniSharedPathsInstructionsAdd",
- IDS_SETTINGS_CROSTINI_SHARED_PATHS_INSTRUCTIONS_ADD},
- {"crostiniSharedPathsInstructionsRemove",
- IDS_SETTINGS_CROSTINI_SHARED_PATHS_INSTRUCTIONS_REMOVE},
- {"crostiniSharedPathsRemoveSharing",
- IDS_SETTINGS_CROSTINI_SHARED_PATHS_REMOVE_SHARING},
- {"crostiniExportImportTitle", IDS_SETTINGS_CROSTINI_EXPORT_IMPORT_TITLE},
- {"crostiniExport", IDS_SETTINGS_CROSTINI_EXPORT},
- {"crostiniExportLabel", IDS_SETTINGS_CROSTINI_EXPORT_LABEL},
- {"crostiniImport", IDS_SETTINGS_CROSTINI_IMPORT},
- {"crostiniImportLabel", IDS_SETTINGS_CROSTINI_IMPORT_LABEL},
- {"crostiniImportConfirmationDialogTitle",
- IDS_SETTINGS_CROSTINI_CONFIRM_IMPORT_DIALOG_WINDOW_TITLE},
- {"crostiniImportConfirmationDialogMessage",
- IDS_SETTINGS_CROSTINI_CONFIRM_IMPORT_DIALOG_WINDOW_MESSAGE},
- {"crostiniImportConfirmationDialogConfirmationButton",
- IDS_SETTINGS_CROSTINI_IMPORT},
- {"crostiniRemoveButton", IDS_SETTINGS_CROSTINI_REMOVE_BUTTON},
- {"crostiniSharedUsbDevicesLabel",
- IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_LABEL},
- {"crostiniSharedUsbDevicesDescription",
- IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_DESCRIPTION},
- {"crostiniSharedUsbDevicesExtraDescription",
- IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_EXTRA_DESCRIPTION},
- {"crostiniSharedUsbDevicesListEmptyMessage",
- IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_LIST_EMPTY_MESSAGE},
- {"crostiniArcAdbTitle", IDS_SETTINGS_CROSTINI_ARC_ADB_TITLE},
- {"crostiniArcAdbDescription", IDS_SETTINGS_CROSTINI_ARC_ADB_DESCRIPTION},
- {"crostiniArcAdbLabel", IDS_SETTINGS_CROSTINI_ARC_ADB_LABEL},
- {"crostiniArcAdbRestartButton",
- IDS_SETTINGS_CROSTINI_ARC_ADB_RESTART_BUTTON},
- {"crostiniArcAdbConfirmationTitleEnable",
- IDS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_TITLE_ENABLE},
- {"crostiniArcAdbConfirmationTitleDisable",
- IDS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_TITLE_DISABLE},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
- html_source->AddString(
- "crostiniSubtext",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_CROSTINI_SUBTEXT, ui::GetChromeOSDeviceName(),
- GetHelpUrlWithBoard(chrome::kLinuxAppsLearnMoreURL)));
- // TODO(crbug.com/893332): replace with the final URL
- html_source->AddString(
- "crostiniArcAdbPowerwashRequiredSublabel",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_CROSTINI_ARC_ADB_POWERWASH_REQUIRED_SUBLABEL,
- GetHelpUrlWithBoard(chrome::kLinuxAppsLearnMoreURL)));
- html_source->AddString("crostiniRemove", l10n_util::GetStringFUTF16(
- IDS_SETTINGS_CROSTINI_REMOVE,
- ui::GetChromeOSDeviceName()));
- html_source->AddString(
- "crostiniArcAdbConfirmationMessageEnable",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_MESSAGE_ENABLE,
- ui::GetChromeOSDeviceName()));
- html_source->AddString(
- "crostiniArcAdbConfirmationMessageDisable",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_CROSTINI_ARC_ADB_CONFIRMATION_MESSAGE_DISABLE,
- ui::GetChromeOSDeviceName()));
- html_source->AddString(
- "crostiniSharedPathsInstructionsLocate",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_CROSTINI_SHARED_PATHS_INSTRUCTIONS_LOCATE,
- base::ASCIIToUTF16(
- crostini::ContainerChromeOSBaseDirectory().value())));
- html_source->AddBoolean(
- "showCrostiniExportImport",
- crostini::CrostiniFeatures::Get()->IsExportImportUIAllowed(profile));
- html_source->AddBoolean("ArcAdbSideloadingSupported",
- ShouldEnableArcAdbSideloading());
- html_source->AddBoolean("isOwnerProfile",
- chromeos::ProfileHelper::IsOwnerProfile(profile));
- html_source->AddBoolean("isEnterpriseManaged",
- IsDeviceManaged() || IsProfileManaged(profile));
-}
-
-void AddPluginVmStrings(content::WebUIDataSource* html_source,
- Profile* profile) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"pluginVmPageTitle", IDS_SETTINGS_PLUGIN_VM_PAGE_TITLE},
- {"pluginVmPageLabel", IDS_SETTINGS_PLUGIN_VM_PAGE_LABEL},
- {"pluginVmPageSubtext", IDS_SETTINGS_PLUGIN_VM_PAGE_SUBTEXT},
- {"pluginVmPrinterAccess", IDS_SETTINGS_PLUGIN_VM_PRINTER_ACCESS},
- {"pluginVmSharedPaths", IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS},
- {"pluginVmSharedPathsListHeading",
- IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS_LIST_HEADING},
- {"pluginVmSharedPathsInstructionsAdd",
- IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS_INSTRUCTIONS_ADD},
- {"pluginVmSharedPathsInstructionsRemove",
- IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS_INSTRUCTIONS_REMOVE},
- {"pluginVmSharedPathsRemoveSharing",
- IDS_SETTINGS_PLUGIN_VM_SHARED_PATHS_REMOVE_SHARING},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-}
-
-void AddAndroidAppStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"androidAppsPageLabel", IDS_SETTINGS_ANDROID_APPS_LABEL},
- {"androidAppsEnable", IDS_SETTINGS_TURN_ON},
- {"androidAppsManageApps", IDS_SETTINGS_ANDROID_APPS_MANAGE_APPS},
- {"androidAppsRemove", IDS_SETTINGS_ANDROID_APPS_REMOVE},
- {"androidAppsRemoveButton", IDS_SETTINGS_ANDROID_APPS_REMOVE_BUTTON},
- {"androidAppsDisableDialogTitle",
- IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_TITLE},
- {"androidAppsDisableDialogMessage",
- IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_MESSAGE},
- {"androidAppsDisableDialogRemove",
- IDS_SETTINGS_ANDROID_APPS_DISABLE_DIALOG_REMOVE},
- {"androidAppsManageAppLinks", IDS_SETTINGS_ANDROID_APPS_MANAGE_APP_LINKS},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
- html_source->AddLocalizedString("androidAppsPageTitle",
- arc::IsPlayStoreAvailable()
- ? IDS_SETTINGS_ANDROID_APPS_TITLE
- : IDS_SETTINGS_ANDROID_SETTINGS_TITLE);
- html_source->AddString(
- "androidAppsSubtext",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_ANDROID_APPS_SUBTEXT, ui::GetChromeOSDeviceName(),
- GetHelpUrlWithBoard(chrome::kAndroidAppsLearnMoreURL)));
-}
-
-void AddAppsStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"appsPageTitle", IDS_SETTINGS_APPS_TITLE},
- {"appManagementTitle", IDS_SETTINGS_APPS_LINK_TEXT},
- };
-
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-}
-
-void AddAppManagementStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"appManagementAppInstalledByPolicyLabel",
- IDS_APP_MANAGEMENT_POLICY_APP_POLICY_STRING},
- {"appManagementCameraPermissionLabel", IDS_APP_MANAGEMENT_CAMERA},
- {"appManagementContactsPermissionLabel", IDS_APP_MANAGEMENT_CONTACTS},
- {"appManagementLocationPermissionLabel", IDS_APP_MANAGEMENT_LOCATION},
- {"appManagementMicrophonePermissionLabel", IDS_APP_MANAGEMENT_MICROPHONE},
- {"appManagementMoreSettingsLabel", IDS_APP_MANAGEMENT_MORE_SETTINGS},
- {"appManagementNoAppsFound", IDS_APP_MANAGEMENT_NO_APPS_FOUND},
- {"appManagementNoPermissions",
- IDS_APPLICATION_INFO_APP_NO_PERMISSIONS_TEXT},
- {"appManagementNotificationsLabel", IDS_APP_MANAGEMENT_NOTIFICATIONS},
- {"appManagementPermissionsLabel", IDS_APP_MANAGEMENT_PERMISSIONS},
- {"appManagementPinToShelfLabel", IDS_APP_MANAGEMENT_PIN_TO_SHELF},
- {"appManagementSearchPrompt", IDS_APP_MANAGEMENT_SEARCH_PROMPT},
- {"appManagementStoragePermissionLabel", IDS_APP_MANAGEMENT_STORAGE},
- {"appManagementUninstallLabel", IDS_APP_MANAGEMENT_UNINSTALL_APP},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-}
-#endif
-
-#if defined(OS_CHROMEOS)
-void AddParentalControlStrings(content::WebUIDataSource* html_source) {
- html_source->AddBoolean(
- "isChild", user_manager::UserManager::Get()->IsLoggedInAsChildUser());
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"parentalControlsPageTitle", IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_TITLE},
- {"parentalControlsPageSetUpLabel",
- IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_SET_UP_LABEL},
- {"parentalControlsPageViewSettingsLabel",
- IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_VIEW_SETTINGS_LABEL},
- {"parentalControlsPageConnectToInternetLabel",
- IDS_SETTINGS_PARENTAL_CONTROLS_PAGE_CONNECT_TO_INTERNET_LABEL},
- {"parentalControlsSetUpButtonLabel",
- IDS_SETTINGS_PARENTAL_CONTROLS_SET_UP_BUTTON_LABEL},
- {"parentalControlsSetUpButtonRole",
- IDS_SETTINGS_PARENTAL_CONTROLS_SET_UP_BUTTON_ROLE},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
}
-#endif
void AddAppearanceStrings(content::WebUIDataSource* html_source,
Profile* profile) {
@@ -752,14 +267,6 @@ void AddAppearanceStrings(content::WebUIDataSource* html_source,
{"enterCustomWebAddress", IDS_SETTINGS_ENTER_CUSTOM_WEB_ADDRESS},
{"homeButtonDisabled", IDS_SETTINGS_HOME_BUTTON_DISABLED},
{"themes", IDS_SETTINGS_THEMES},
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- {"systemTheme", IDS_SETTINGS_SYSTEM_THEME},
- {"useSystemTheme", IDS_SETTINGS_USE_SYSTEM_THEME},
- {"classicTheme", IDS_SETTINGS_CLASSIC_THEME},
- {"useClassicTheme", IDS_SETTINGS_USE_CLASSIC_THEME},
-#else
- {"resetToDefaultTheme", IDS_SETTINGS_RESET_TO_DEFAULT_THEME},
-#endif
{"chromeColors", IDS_SETTINGS_CHROME_COLORS},
{"showHomeButton", IDS_SETTINGS_SHOW_HOME_BUTTON},
{"showBookmarksBar", IDS_SETTINGS_SHOW_BOOKMARKS_BAR},
@@ -767,98 +274,39 @@ void AddAppearanceStrings(content::WebUIDataSource* html_source,
{"changeHomePage", IDS_SETTINGS_CHANGE_HOME_PAGE},
{"themesGalleryUrl", IDS_THEMES_GALLERY_URL},
{"chooseFromWebStore", IDS_SETTINGS_WEB_STORE},
-#if defined(OS_CHROMEOS)
- {"personalizationPageTitle", IDS_OS_SETTINGS_PERSONALIZATION},
- {"openWallpaperApp", IDS_OS_SETTINGS_OPEN_WALLPAPER_APP},
- {"setWallpaper", IDS_OS_SETTINGS_SET_WALLPAPER},
-#endif
+ {"pageZoom", IDS_SETTINGS_PAGE_ZOOM_LABEL},
+ {"fontSize", IDS_SETTINGS_FONT_SIZE_LABEL},
+ {"customizeFonts", IDS_SETTINGS_CUSTOMIZE_FONTS},
+ {"fonts", IDS_SETTINGS_FONTS},
+ {"standardFont", IDS_SETTINGS_STANDARD_FONT_LABEL},
+ {"serifFont", IDS_SETTINGS_SERIF_FONT_LABEL},
+ {"sansSerifFont", IDS_SETTINGS_SANS_SERIF_FONT_LABEL},
+ {"fixedWidthFont", IDS_SETTINGS_FIXED_WIDTH_FONT_LABEL},
+ {"minimumFont", IDS_SETTINGS_MINIMUM_FONT_SIZE_LABEL},
+ {"tiny", IDS_SETTINGS_TINY_FONT_SIZE},
+ {"huge", IDS_SETTINGS_HUGE_FONT_SIZE},
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ {"systemTheme", IDS_SETTINGS_SYSTEM_THEME},
+ {"useSystemTheme", IDS_SETTINGS_USE_SYSTEM_THEME},
+ {"classicTheme", IDS_SETTINGS_CLASSIC_THEME},
+ {"useClassicTheme", IDS_SETTINGS_USE_CLASSIC_THEME},
{"showWindowDecorations", IDS_SHOW_WINDOW_DECORATIONS},
+#else
+ {"resetToDefaultTheme", IDS_SETTINGS_RESET_TO_DEFAULT_THEME},
#endif
#if defined(OS_MACOSX)
{"tabsToLinks", IDS_SETTINGS_TABS_TO_LINKS_PREF},
{"warnBeforeQuitting", IDS_SETTINGS_WARN_BEFORE_QUITTING_PREF},
#endif
+ {"readerMode", IDS_SETTINGS_READER_MODE},
+ {"readerModeDescription", IDS_SETTINGS_READER_MODE_DESCRIPTION},
};
AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-#if defined(OS_CHROMEOS)
- if (base::FeatureList::IsEnabled(chromeos::features::kSplitSettings)) {
- html_source->AddLocalizedString("changePictureTitle",
- IDS_OS_SETTINGS_CHANGE_PICTURE_TITLE);
- } else {
- html_source->AddLocalizedString("changePictureTitle",
- IDS_SETTINGS_CHANGE_PICTURE_DIALOG_TITLE);
- }
-#endif
-}
-
-#if defined(OS_CHROMEOS)
-void AddBluetoothStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"bluetoothConnected", IDS_SETTINGS_BLUETOOTH_CONNECTED},
- {"bluetoothConnectedWithBattery",
- IDS_SETTINGS_BLUETOOTH_CONNECTED_WITH_BATTERY},
- {"bluetoothConnecting", IDS_SETTINGS_BLUETOOTH_CONNECTING},
- {"bluetoothDeviceListPaired", IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_PAIRED},
- {"bluetoothDeviceListUnpaired",
- IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_UNPAIRED},
- {"bluetoothConnect", IDS_SETTINGS_BLUETOOTH_CONNECT},
- {"bluetoothDisconnect", IDS_SETTINGS_BLUETOOTH_DISCONNECT},
- {"bluetoothToggleA11yLabel",
- IDS_SETTINGS_BLUETOOTH_TOGGLE_ACCESSIBILITY_LABEL},
- {"bluetoothExpandA11yLabel",
- IDS_SETTINGS_BLUETOOTH_EXPAND_ACCESSIBILITY_LABEL},
- {"bluetoothNoDevices", IDS_SETTINGS_BLUETOOTH_NO_DEVICES},
- {"bluetoothNoDevicesFound", IDS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND},
- {"bluetoothNotConnected", IDS_SETTINGS_BLUETOOTH_NOT_CONNECTED},
- {"bluetoothPageTitle", IDS_SETTINGS_BLUETOOTH},
- {"bluetoothPairDevicePageTitle",
- IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE},
- {"bluetoothRemove", IDS_SETTINGS_BLUETOOTH_REMOVE},
- {"bluetoothPrimaryUserControlled",
- IDS_SETTINGS_BLUETOOTH_PRIMARY_USER_CONTROLLED},
- {"bluetoothDeviceType_computer",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_COMPUTER},
- {"bluetoothDeviceType_phone",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_PHONE},
- {"bluetoothDeviceType_modem",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_MODEM},
- {"bluetoothDeviceType_audio",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_AUDIO},
- {"bluetoothDeviceType_carAudio",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_CAR_AUDIO},
- {"bluetoothDeviceType_video",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_VIDEO},
- {"bluetoothDeviceType_peripheral",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_PERIPHERAL},
- {"bluetoothDeviceType_joystick",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_JOYSTICK},
- {"bluetoothDeviceType_gamepad",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_GAMEPAD},
- {"bluetoothDeviceType_keyboard",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_KEYBOARD},
- {"bluetoothDeviceType_mouse",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_MOUSE},
- {"bluetoothDeviceType_tablet",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_TABLET},
- {"bluetoothDeviceType_keyboardMouseCombo",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_KEYBOARD_MOUSE_COMBO},
- {"bluetoothDeviceType_unknown",
- IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_UNKNOWN},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
- chromeos::bluetooth_dialog::AddLocalizedStrings(html_source);
-}
-#endif
-
-void AddChangePasswordStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"changePasswordPageTitle", IDS_SETTINGS_CHANGE_PASSWORD_TITLE},
- {"changePasswordPageDetails", IDS_PAGE_INFO_CHANGE_PASSWORD_DETAILS},
- {"changePasswordPageButton", IDS_SETTINGS_CHANGE_PASSWORD_BUTTON},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+ html_source->AddString("presetZoomFactors",
+ zoom::GetPresetZoomFactorsAsJSON());
+ html_source->AddBoolean("showReaderModeOption",
+ dom_distiller::OfferReaderModeInSettings());
}
void AddClearBrowsingDataStrings(content::WebUIDataSource* html_source,
@@ -895,6 +343,8 @@ void AddClearBrowsingDataStrings(content::WebUIDataSource* html_source,
{"historyDeletionDialogTitle",
IDS_CLEAR_BROWSING_DATA_HISTORY_NOTICE_TITLE},
{"historyDeletionDialogOK", IDS_CLEAR_BROWSING_DATA_HISTORY_NOTICE_OK},
+ {"installedAppsConfirm", IDS_SETTINGS_CLEAR_INSTALLED_APPS_DATA_CONFIRM},
+ {"installedAppsTitle", IDS_SETTINGS_CLEAR_INSTALLED_APPS_DATA_TITLE},
{"notificationWarning", IDS_SETTINGS_NOTIFICATION_WARNING},
};
@@ -933,288 +383,12 @@ void AddDefaultBrowserStrings(content::WebUIDataSource* html_source) {
}
#endif
-#if defined(OS_CHROMEOS)
-void AddDeviceStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kDeviceStrings[] = {
- {"devicePageTitle", IDS_SETTINGS_DEVICE_TITLE},
- {"scrollLabel", IDS_SETTINGS_SCROLL_LABEL},
- {"traditionalScrollLabel", IDS_SETTINGS_TRADITIONAL_SCROLL_LABEL},
- {"naturalScrollLabel", IDS_SETTINGS_NATURAL_SCROLL_LABEL},
- {"naturalScrollLearnMore", IDS_LEARN_MORE},
- };
- AddLocalizedStringsBulk(html_source, kDeviceStrings);
-
- static constexpr webui::LocalizedString kPointersStrings[] = {
- {"mouseTitle", IDS_SETTINGS_MOUSE_TITLE},
- {"touchpadTitle", IDS_SETTINGS_TOUCHPAD_TITLE},
- {"mouseAndTouchpadTitle", IDS_SETTINGS_MOUSE_AND_TOUCHPAD_TITLE},
- {"touchpadTapToClickEnabledLabel",
- IDS_SETTINGS_TOUCHPAD_TAP_TO_CLICK_ENABLED_LABEL},
- {"touchpadSpeed", IDS_SETTINGS_TOUCHPAD_SPEED_LABEL},
- {"pointerSlow", IDS_SETTINGS_POINTER_SPEED_SLOW_LABEL},
- {"pointerFast", IDS_SETTINGS_POINTER_SPEED_FAST_LABEL},
- {"mouseSpeed", IDS_SETTINGS_MOUSE_SPEED_LABEL},
- {"mouseSwapButtons", IDS_SETTINGS_MOUSE_SWAP_BUTTONS_LABEL},
- {"mouseReverseScroll", IDS_SETTINGS_MOUSE_REVERSE_SCROLL_LABEL},
- {"mouseAccelerationLabel", IDS_SETTINGS_MOUSE_ACCELERATION_LABEL},
- {"touchpadAccelerationLabel", IDS_SETTINGS_TOUCHPAD_ACCELERATION_LABEL},
- };
- AddLocalizedStringsBulk(html_source, kPointersStrings);
-
- static constexpr webui::LocalizedString keyboard_strings[] = {
- {"keyboardTitle", IDS_SETTINGS_KEYBOARD_TITLE},
- {"keyboardKeyCtrl", IDS_SETTINGS_KEYBOARD_KEY_LEFT_CTRL},
- {"keyboardKeyAlt", IDS_SETTINGS_KEYBOARD_KEY_LEFT_ALT},
- {"keyboardKeyCapsLock", IDS_SETTINGS_KEYBOARD_KEY_CAPS_LOCK},
- {"keyboardKeyCommand", IDS_SETTINGS_KEYBOARD_KEY_COMMAND},
- {"keyboardKeyDiamond", IDS_SETTINGS_KEYBOARD_KEY_DIAMOND},
- {"keyboardKeyEscape", IDS_SETTINGS_KEYBOARD_KEY_ESCAPE},
- {"keyboardKeyBackspace", IDS_SETTINGS_KEYBOARD_KEY_BACKSPACE},
- {"keyboardKeyAssistant", IDS_SETTINGS_KEYBOARD_KEY_ASSISTANT},
- {"keyboardKeyDisabled", IDS_SETTINGS_KEYBOARD_KEY_DISABLED},
- {"keyboardKeyExternalCommand",
- IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_COMMAND},
- {"keyboardKeyExternalMeta", IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_META},
- {"keyboardKeyMeta", IDS_SETTINGS_KEYBOARD_KEY_META},
- {"keyboardSendFunctionKeys", IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS},
- {"keyboardEnableAutoRepeat", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_ENABLE},
- {"keyRepeatDelay", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY},
- {"keyRepeatDelayLong", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_LONG},
- {"keyRepeatDelayShort", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_DELAY_SHORT},
- {"keyRepeatRate", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE},
- {"keyRepeatRateSlow", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_RATE_SLOW},
- {"keyRepeatRateFast", IDS_SETTINGS_KEYBOARD_AUTO_REPEAT_FAST},
- {"showKeyboardShortcutViewer",
- IDS_SETTINGS_KEYBOARD_SHOW_SHORTCUT_VIEWER},
- {"keyboardShowLanguageAndInput",
- IDS_SETTINGS_KEYBOARD_SHOW_LANGUAGE_AND_INPUT},
- };
- AddLocalizedStringsBulk(html_source, keyboard_strings);
- html_source->AddLocalizedString("keyboardKeySearch",
- ui::DeviceUsesKeyboardLayout2()
- ? IDS_SETTINGS_KEYBOARD_KEY_LAUNCHER
- : IDS_SETTINGS_KEYBOARD_KEY_SEARCH);
- html_source->AddLocalizedString(
- "keyboardSendFunctionKeysDescription",
- ui::DeviceUsesKeyboardLayout2()
- ? IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_LAYOUT2_DESCRIPTION
- : IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS_DESCRIPTION);
-
- static constexpr webui::LocalizedString kStylusStrings[] = {
- {"stylusTitle", IDS_SETTINGS_STYLUS_TITLE},
- {"stylusEnableStylusTools", IDS_SETTINGS_STYLUS_ENABLE_STYLUS_TOOLS},
- {"stylusAutoOpenStylusTools", IDS_SETTINGS_STYLUS_AUTO_OPEN_STYLUS_TOOLS},
- {"stylusFindMoreAppsPrimary", IDS_SETTINGS_STYLUS_FIND_MORE_APPS_PRIMARY},
- {"stylusFindMoreAppsSecondary",
- IDS_SETTINGS_STYLUS_FIND_MORE_APPS_SECONDARY},
- {"stylusNoteTakingApp", IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_LABEL},
- {"stylusNoteTakingAppEnabledOnLockScreen",
- IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_LOCK_SCREEN_CHECKBOX},
- {"stylusNoteTakingAppKeepsLastNoteOnLockScreen",
- IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_KEEP_LATEST_NOTE},
- {"stylusNoteTakingAppLockScreenSettingsHeader",
- IDS_SETTINGS_STYLUS_LOCK_SCREEN_NOTES_TITLE},
- {"stylusNoteTakingAppNoneAvailable",
- IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_NONE_AVAILABLE},
- {"stylusNoteTakingAppWaitingForAndroid",
- IDS_SETTINGS_STYLUS_NOTE_TAKING_APP_WAITING_FOR_ANDROID}};
- AddLocalizedStringsBulk(html_source, kStylusStrings);
-
- static constexpr webui::LocalizedString kDisplayStrings[] = {
- {"displayTitle", IDS_SETTINGS_DISPLAY_TITLE},
- {"displayArrangementText", IDS_SETTINGS_DISPLAY_ARRANGEMENT_TEXT},
- {"displayArrangementTitle", IDS_SETTINGS_DISPLAY_ARRANGEMENT_TITLE},
- {"displayMirror", IDS_SETTINGS_DISPLAY_MIRROR},
- {"displayMirrorDisplayName", IDS_SETTINGS_DISPLAY_MIRROR_DISPLAY_NAME},
- {"displayAmbientColorTitle", IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_TITLE},
- {"displayAmbientColorSubtitle",
- IDS_SETTINGS_DISPLAY_AMBIENT_COLOR_SUBTITLE},
- {"displayNightLightLabel", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_LABEL},
- {"displayNightLightOnAtSunset",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_ON_AT_SUNSET},
- {"displayNightLightOffAtSunrise",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_OFF_AT_SUNRISE},
- {"displayNightLightScheduleCustom",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_CUSTOM},
- {"displayNightLightScheduleLabel",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_LABEL},
- {"displayNightLightScheduleNever",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_NEVER},
- {"displayNightLightScheduleSunsetToSunRise",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_SCHEDULE_SUNSET_TO_SUNRISE},
- {"displayNightLightStartTime",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_START_TIME},
- {"displayNightLightStopTime", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_STOP_TIME},
- {"displayNightLightText", IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEXT},
- {"displayNightLightTemperatureLabel",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMPERATURE_LABEL},
- {"displayNightLightTempSliderMaxLabel",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MAX_LABEL},
- {"displayNightLightTempSliderMinLabel",
- IDS_SETTINGS_DISPLAY_NIGHT_LIGHT_TEMP_SLIDER_MIN_LABEL},
- {"displayUnifiedDesktop", IDS_SETTINGS_DISPLAY_UNIFIED_DESKTOP},
- {"displayResolutionTitle", IDS_SETTINGS_DISPLAY_RESOLUTION_TITLE},
- {"displayResolutionText", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT},
- {"displayResolutionTextBest", IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_BEST},
- {"displayResolutionTextNative",
- IDS_SETTINGS_DISPLAY_RESOLUTION_TEXT_NATIVE},
- {"displayResolutionSublabel", IDS_SETTINGS_DISPLAY_RESOLUTION_SUBLABEL},
- {"displayResolutionMenuItem", IDS_SETTINGS_DISPLAY_RESOLUTION_MENU_ITEM},
- {"displayResolutionInterlacedMenuItem",
- IDS_SETTINGS_DISPLAY_RESOLUTION_INTERLACED_MENU_ITEM},
- {"displayZoomTitle", IDS_SETTINGS_DISPLAY_ZOOM_TITLE},
- {"displayZoomSublabel", IDS_SETTINGS_DISPLAY_ZOOM_SUBLABEL},
- {"displayZoomValue", IDS_SETTINGS_DISPLAY_ZOOM_VALUE},
- {"displayZoomLogicalResolutionText",
- IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_TEXT},
- {"displayZoomNativeLogicalResolutionNativeText",
- IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_NATIVE_TEXT},
- {"displayZoomLogicalResolutionDefaultText",
- IDS_SETTINGS_DISPLAY_ZOOM_LOGICAL_RESOLUTION_DEFAULT_TEXT},
- {"displaySizeSliderMinLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MINIMUM},
- {"displaySizeSliderMaxLabel", IDS_SETTINGS_DISPLAY_ZOOM_SLIDER_MAXIMUM},
- {"displayScreenTitle", IDS_SETTINGS_DISPLAY_SCREEN},
- {"displayScreenExtended", IDS_SETTINGS_DISPLAY_SCREEN_EXTENDED},
- {"displayScreenPrimary", IDS_SETTINGS_DISPLAY_SCREEN_PRIMARY},
- {"displayOrientation", IDS_SETTINGS_DISPLAY_ORIENTATION},
- {"displayOrientationStandard", IDS_SETTINGS_DISPLAY_ORIENTATION_STANDARD},
- {"displayOrientationAutoRotate",
- IDS_SETTINGS_DISPLAY_ORIENTATION_AUTO_ROTATE},
- {"displayOverscanPageText", IDS_SETTINGS_DISPLAY_OVERSCAN_TEXT},
- {"displayOverscanPageTitle", IDS_SETTINGS_DISPLAY_OVERSCAN_TITLE},
- {"displayOverscanSubtitle", IDS_SETTINGS_DISPLAY_OVERSCAN_SUBTITLE},
- {"displayOverscanInstructions",
- IDS_SETTINGS_DISPLAY_OVERSCAN_INSTRUCTIONS},
- {"displayOverscanResize", IDS_SETTINGS_DISPLAY_OVERSCAN_RESIZE},
- {"displayOverscanPosition", IDS_SETTINGS_DISPLAY_OVERSCAN_POSITION},
- {"displayOverscanReset", IDS_SETTINGS_DISPLAY_OVERSCAN_RESET},
- {"displayTouchCalibrationTitle",
- IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TITLE},
- {"displayTouchCalibrationText",
- IDS_SETTINGS_DISPLAY_TOUCH_CALIBRATION_TEXT}};
- AddLocalizedStringsBulk(html_source, kDisplayStrings);
- base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess();
- html_source->AddBoolean("unifiedDesktopAvailable",
- cmd.HasSwitch(::switches::kEnableUnifiedDesktop));
-
- html_source->AddBoolean("listAllDisplayModes",
- display::features::IsListAllDisplayModesEnabled());
-
- html_source->AddBoolean("deviceSupportsAmbientColor",
- ash::features::IsAllowAmbientEQEnabled());
-
- html_source->AddBoolean(
- "enableTouchCalibrationSetting",
- cmd.HasSwitch(chromeos::switches::kEnableTouchCalibrationSetting));
-
- html_source->AddBoolean("hasExternalTouchDevice",
- display::HasExternalTouchscreenDevice());
-
- html_source->AddBoolean(
- "allowDisableMouseAcceleration",
- base::FeatureList::IsEnabled(features::kAllowDisableMouseAcceleration));
-
- static constexpr webui::LocalizedString kStorageStrings[] = {
- {"storageTitle", IDS_SETTINGS_STORAGE_TITLE},
- {"storageItemInUse", IDS_SETTINGS_STORAGE_ITEM_IN_USE},
- {"storageItemAvailable", IDS_SETTINGS_STORAGE_ITEM_AVAILABLE},
- {"storageItemDownloads", IDS_SETTINGS_STORAGE_ITEM_DOWNLOADS},
- {"storageItemBrowsingData", IDS_SETTINGS_STORAGE_ITEM_BROWSING_DATA},
- {"storageItemAndroid", IDS_SETTINGS_STORAGE_ITEM_ANDROID},
- {"storageItemCrostini", IDS_SETTINGS_STORAGE_ITEM_CROSTINI},
- {"storageItemOtherUsers", IDS_SETTINGS_STORAGE_ITEM_OTHER_USERS},
- {"storageSizeComputing", IDS_SETTINGS_STORAGE_SIZE_CALCULATING},
- {"storageSizeUnknown", IDS_SETTINGS_STORAGE_SIZE_UNKNOWN},
- {"storageSpaceLowMessageTitle",
- IDS_SETTINGS_STORAGE_SPACE_LOW_MESSAGE_TITLE},
- {"storageSpaceLowMessageLine1",
- IDS_SETTINGS_STORAGE_SPACE_LOW_MESSAGE_LINE_1},
- {"storageSpaceLowMessageLine2",
- IDS_SETTINGS_STORAGE_SPACE_LOW_MESSAGE_LINE_2},
- {"storageSpaceCriticallyLowMessageTitle",
- IDS_SETTINGS_STORAGE_SPACE_CRITICALLY_LOW_MESSAGE_TITLE},
- {"storageSpaceCriticallyLowMessageLine1",
- IDS_SETTINGS_STORAGE_SPACE_CRITICALLY_LOW_MESSAGE_LINE_1},
- {"storageSpaceCriticallyLowMessageLine2",
- IDS_SETTINGS_STORAGE_SPACE_CRITICALLY_LOW_MESSAGE_LINE_2},
- {"storageExternal", IDS_SETTINGS_STORAGE_EXTERNAL},
- {"storageExternalStorageEmptyListHeader",
- IDS_SETTINGS_STORAGE_EXTERNAL_STORAGE_EMPTY_LIST_HEADER},
- {"storageExternalStorageListHeader",
- IDS_SETTINGS_STORAGE_EXTERNAL_STORAGE_LIST_HEADER},
- {"storageOverviewAriaLabel", IDS_SETTINGS_STORAGE_OVERVIEW_ARIA_LABEL}};
-
- AddLocalizedStringsBulk(html_source, kStorageStrings);
-
- html_source->AddString(
- "storageAndroidAppsExternalDrivesNote",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_STORAGE_ANDROID_APPS_ACCESS_EXTERNAL_DRIVES_NOTE,
- base::ASCIIToUTF16(chrome::kArcExternalStorageLearnMoreURL)));
-
- static constexpr webui::LocalizedString kPowerStrings[] = {
- {"powerTitle", IDS_SETTINGS_POWER_TITLE},
- {"powerSourceLabel", IDS_SETTINGS_POWER_SOURCE_LABEL},
- {"powerSourceBattery", IDS_SETTINGS_POWER_SOURCE_BATTERY},
- {"powerSourceAcAdapter", IDS_SETTINGS_POWER_SOURCE_AC_ADAPTER},
- {"powerSourceLowPowerCharger",
- IDS_SETTINGS_POWER_SOURCE_LOW_POWER_CHARGER},
- {"calculatingPower", IDS_SETTINGS_POWER_SOURCE_CALCULATING},
- {"powerIdleLabel", IDS_SETTINGS_POWER_IDLE_LABEL},
- {"powerIdleDisplayOffSleep", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF_SLEEP},
- {"powerIdleDisplayOff", IDS_SETTINGS_POWER_IDLE_DISPLAY_OFF},
- {"powerIdleDisplayOn", IDS_SETTINGS_POWER_IDLE_DISPLAY_ON},
- {"powerIdleOther", IDS_SETTINGS_POWER_IDLE_OTHER},
- {"powerLidSleepLabel", IDS_SETTINGS_POWER_LID_CLOSED_SLEEP_LABEL},
- {"powerLidSignOutLabel", IDS_SETTINGS_POWER_LID_CLOSED_SIGN_OUT_LABEL},
- {"powerLidShutDownLabel", IDS_SETTINGS_POWER_LID_CLOSED_SHUT_DOWN_LABEL},
- };
- AddLocalizedStringsBulk(html_source, kPowerStrings);
-
- html_source->AddString("naturalScrollLearnMoreLink",
- GetHelpUrlWithBoard(chrome::kNaturalScrollHelpURL));
-}
-
-void AddFilesStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"filesPageTitle", IDS_OS_SETTINGS_FILES},
- {"smbSharesTitle", IDS_SETTINGS_DOWNLOADS_SMB_SHARES},
- {"smbSharesLearnMoreLabel",
- IDS_SETTINGS_DOWNLOADS_SMB_SHARES_LEARN_MORE_LABEL},
- {"addSmbShare", IDS_SETTINGS_DOWNLOADS_SMB_SHARES_ADD_SHARE},
- {"smbShareAddedSuccessfulMessage",
- IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_SUCCESS_MESSAGE},
- {"smbShareAddedErrorMessage",
- IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_ERROR_MESSAGE},
- {"smbShareAddedAuthFailedMessage",
- IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_AUTH_FAILED_MESSAGE},
- {"smbShareAddedNotFoundMessage",
- IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_NOT_FOUND_MESSAGE},
- {"smbShareAddedUnsupportedDeviceMessage",
- IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_UNSUPPORTED_DEVICE_MESSAGE},
- {"smbShareAddedMountExistsMessage",
- IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE},
- {"smbShareAddedInvalidURLMessage",
- IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE},
- {"smbShareAddedInvalidSSOURLMessage",
- IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_SSO_URL_MESSAGE},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-
- chromeos::smb_dialog::AddLocalizedStrings(html_source);
-
- html_source->AddString("smbSharesLearnMoreURL",
- GetHelpUrlWithBoard(chrome::kSmbSharesLearnMoreURL));
-}
-#endif // defined(OS_CHROMEOS)
-
void AddDownloadsStrings(content::WebUIDataSource* html_source) {
static constexpr webui::LocalizedString kLocalizedStrings[] = {
{"downloadsPageTitle", IDS_SETTINGS_DOWNLOADS},
{"downloadLocation", IDS_SETTINGS_DOWNLOAD_LOCATION},
{"changeDownloadLocation", IDS_SETTINGS_CHANGE_DOWNLOAD_LOCATION},
{"promptForDownload", IDS_SETTINGS_PROMPT_FOR_DOWNLOAD},
- {"disconnectGoogleDriveAccount", IDS_SETTINGS_DISCONNECT_GOOGLE_DRIVE},
{"openFileTypesAutomatically",
IDS_SETTINGS_OPEN_FILE_TYPES_AUTOMATICALLY},
};
@@ -1364,15 +538,7 @@ void AddResetStrings(content::WebUIDataSource* html_source) {
{"triggeredResetPageTitle", IDS_TRIGGERED_RESET_PROFILE_SETTINGS_TITLE},
{"resetDialogCommit", IDS_SETTINGS_RESET},
{"resetPageFeedback", IDS_SETTINGS_RESET_PROFILE_FEEDBACK},
-#if defined(OS_CHROMEOS)
- {"powerwashTitle", IDS_SETTINGS_FACTORY_RESET},
- {"powerwashDialogTitle", IDS_SETTINGS_FACTORY_RESET_HEADING},
- {"powerwashDialogExplanation", IDS_SETTINGS_FACTORY_RESET_WARNING},
- {"powerwashDialogButton", IDS_SETTINGS_RESTART},
- {"powerwashLearnMoreUrl", IDS_FACTORY_RESET_HELP_URL},
- {"powerwashButton", IDS_SETTINGS_FACTORY_RESET_BUTTON_LABEL},
- {"powerwashButtonRoleDescription", IDS_SETTINGS_FACTORY_RESET_BUTTON_ROLE},
-#endif
+
// Automatic reset banner (now a dialog).
{"resetAutomatedDialogTitle", IDS_SETTINGS_RESET_AUTOMATED_DIALOG_TITLE},
{"resetProfileBannerButton", IDS_SETTINGS_RESET_BANNER_RESET_BUTTON_TEXT},
@@ -1388,12 +554,6 @@ void AddResetStrings(content::WebUIDataSource* html_source) {
chrome::kResetProfileSettingsLearnMoreURL);
html_source->AddString("resetProfileBannerLearnMoreUrl",
chrome::kAutomaticSettingsResetLearnMoreURL);
-#if defined(OS_CHROMEOS)
- html_source->AddString(
- "powerwashDescription",
- l10n_util::GetStringFUTF16(IDS_SETTINGS_FACTORY_RESET_DESCRIPTION,
- l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)));
-#endif
}
#if !defined(OS_CHROMEOS)
@@ -1418,242 +578,20 @@ void AddImportDataStrings(content::WebUIDataSource* html_source) {
}
#endif
-#if defined(OS_CHROMEOS)
-void AddDateTimeStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"dateTimePageTitle", IDS_SETTINGS_DATE_TIME},
- {"timeZone", IDS_SETTINGS_TIME_ZONE},
- {"selectTimeZoneResolveMethod",
- IDS_SETTINGS_SELECT_TIME_ZONE_RESOLVE_METHOD},
- {"timeZoneGeolocation", IDS_SETTINGS_TIME_ZONE_GEOLOCATION},
- {"timeZoneButton", IDS_SETTINGS_TIME_ZONE_BUTTON},
- {"timeZoneSubpageTitle", IDS_SETTINGS_TIME_ZONE_SUBPAGE_TITLE},
- {"setTimeZoneAutomaticallyDisabled",
- IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_DISABLED},
- {"setTimeZoneAutomaticallyOn",
- IDS_SETTINGS_TIME_ZONE_DETECTION_SET_AUTOMATICALLY},
- {"setTimeZoneAutomaticallyOff",
- IDS_SETTINGS_TIME_ZONE_DETECTION_CHOOSE_FROM_LIST},
- {"setTimeZoneAutomaticallyIpOnlyDefault",
- IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_IP_ONLY_DEFAULT},
- {"setTimeZoneAutomaticallyWithWiFiAccessPointsData",
- IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_WIFI_AP},
- {"setTimeZoneAutomaticallyWithAllLocationInfo",
- IDS_SETTINGS_TIME_ZONE_DETECTION_MODE_SEND_ALL_INFO},
- {"use24HourClock", IDS_SETTINGS_USE_24_HOUR_CLOCK},
- {"setDateTime", IDS_SETTINGS_SET_DATE_TIME},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
- html_source->AddString(
- "timeZoneSettingsLearnMoreURL",
- base::ASCIIToUTF16(base::StringPrintf(
- chrome::kTimeZoneSettingsLearnMoreURL,
- g_browser_process->GetApplicationLocale().c_str())));
-}
-
-void AddEasyUnlockStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"easyUnlockSectionTitle", IDS_SETTINGS_EASY_UNLOCK_SECTION_TITLE},
- {"easyUnlockUnlockDeviceOnly",
- IDS_SETTINGS_EASY_UNLOCK_UNLOCK_DEVICE_ONLY},
- {"easyUnlockUnlockDeviceAndAllowSignin",
- IDS_SETTINGS_EASY_UNLOCK_UNLOCK_DEVICE_AND_ALLOW_SIGNIN},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-}
-
-void AddFingerprintStrings(content::WebUIDataSource* html_source) {
- int instruction_id, aria_label_id;
- using FingerprintLocation = chromeos::quick_unlock::FingerprintLocation;
- switch (chromeos::quick_unlock::GetFingerprintLocation()) {
- case FingerprintLocation::TABLET_POWER_BUTTON:
- instruction_id =
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_POWER_BUTTON;
- aria_label_id =
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_POWER_BUTTON_ARIA_LABEL;
- break;
- case FingerprintLocation::KEYBOARD_TOP_RIGHT:
- instruction_id =
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD;
- aria_label_id =
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD_TOP_RIGHT_ARIA_LABEL;
- break;
- case FingerprintLocation::KEYBOARD_BOTTOM_RIGHT:
- instruction_id =
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD;
- aria_label_id =
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD_BOTTOM_RIGHT_ARIA_LABEL;
- break;
- }
- html_source->AddLocalizedString(
- "configureFingerprintInstructionLocateScannerStep", instruction_id);
- html_source->AddLocalizedString("configureFingerprintScannerStepAriaLabel",
- aria_label_id);
-}
-
-void AddInternetStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"internetAddConnection", IDS_SETTINGS_INTERNET_ADD_CONNECTION},
- {"internetAddConnectionExpandA11yLabel",
- IDS_SETTINGS_INTERNET_ADD_CONNECTION_EXPAND_ACCESSIBILITY_LABEL},
- {"internetAddConnectionNotAllowed",
- IDS_SETTINGS_INTERNET_ADD_CONNECTION_NOT_ALLOWED},
- {"internetAddThirdPartyVPN", IDS_SETTINGS_INTERNET_ADD_THIRD_PARTY_VPN},
- {"internetAddVPN", IDS_SETTINGS_INTERNET_ADD_VPN},
- {"internetAddWiFi", IDS_SETTINGS_INTERNET_ADD_WIFI},
- {"internetConfigName", IDS_SETTINGS_INTERNET_CONFIG_NAME},
- {"internetDetailPageTitle", IDS_SETTINGS_INTERNET_DETAIL},
- {"internetDeviceEnabling", IDS_SETTINGS_INTERNET_DEVICE_ENABLING},
- {"internetDeviceInitializing", IDS_SETTINGS_INTERNET_DEVICE_INITIALIZING},
- {"internetJoinType", IDS_SETTINGS_INTERNET_JOIN_TYPE},
- {"internetKnownNetworksPageTitle", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS},
- {"internetMobileSearching", IDS_SETTINGS_INTERNET_MOBILE_SEARCH},
- {"internetNoNetworks", IDS_SETTINGS_INTERNET_NO_NETWORKS},
- {"internetPageTitle", IDS_SETTINGS_INTERNET},
- {"internetSummaryButtonA11yLabel",
- IDS_SETTINGS_INTERNET_SUMMARY_BUTTON_ACCESSIBILITY_LABEL},
- {"internetToggleMobileA11yLabel",
- IDS_SETTINGS_INTERNET_TOGGLE_MOBILE_ACCESSIBILITY_LABEL},
- {"internetToggleTetherLabel", IDS_SETTINGS_INTERNET_TOGGLE_TETHER_LABEL},
- {"internetToggleTetherSubtext",
- IDS_SETTINGS_INTERNET_TOGGLE_TETHER_SUBTEXT},
- {"internetToggleWiFiA11yLabel",
- IDS_SETTINGS_INTERNET_TOGGLE_WIFI_ACCESSIBILITY_LABEL},
- {"knownNetworksAll", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_ALL},
- {"knownNetworksButton", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_BUTTON},
- {"knownNetworksMessage", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MESSAGE},
- {"knownNetworksPreferred",
- IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_PREFFERED},
- {"knownNetworksMenuAddPreferred",
- IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MENU_ADD_PREFERRED},
- {"knownNetworksMenuRemovePreferred",
- IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MENU_REMOVE_PREFERRED},
- {"knownNetworksMenuForget",
- IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MENU_FORGET},
- {"networkAllowDataRoaming",
- IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING},
- {"networkAllowDataRoamingEnabledHome",
- IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_ENABLED_HOME},
- {"networkAllowDataRoamingEnabledRoaming",
- IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_ENABLED_ROAMING},
- {"networkAllowDataRoamingDisabled",
- IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING_DISABLED},
- {"networkAlwaysOnVpn", IDS_SETTINGS_INTERNET_NETWORK_ALWAYS_ON_VPN},
- {"networkAutoConnect", IDS_SETTINGS_INTERNET_NETWORK_AUTO_CONNECT},
- {"networkAutoConnectCellular",
- IDS_SETTINGS_INTERNET_NETWORK_AUTO_CONNECT_CELLULAR},
- {"networkButtonActivate", IDS_SETTINGS_INTERNET_BUTTON_ACTIVATE},
- {"networkButtonConfigure", IDS_SETTINGS_INTERNET_BUTTON_CONFIGURE},
- {"networkButtonConnect", IDS_SETTINGS_INTERNET_BUTTON_CONNECT},
- {"networkButtonDisconnect", IDS_SETTINGS_INTERNET_BUTTON_DISCONNECT},
- {"networkButtonForget", IDS_SETTINGS_INTERNET_BUTTON_FORGET},
- {"networkButtonViewAccount", IDS_SETTINGS_INTERNET_BUTTON_VIEW_ACCOUNT},
- {"networkConnectNotAllowed", IDS_SETTINGS_INTERNET_CONNECT_NOT_ALLOWED},
- {"networkIPAddress", IDS_SETTINGS_INTERNET_NETWORK_IP_ADDRESS},
- {"networkIPConfigAuto", IDS_SETTINGS_INTERNET_NETWORK_IP_CONFIG_AUTO},
- {"networkNameserversLearnMore", IDS_LEARN_MORE},
- {"networkPrefer", IDS_SETTINGS_INTERNET_NETWORK_PREFER},
- {"networkPrimaryUserControlled",
- IDS_SETTINGS_INTERNET_NETWORK_PRIMARY_USER_CONTROLLED},
- {"networkScanningLabel", IDS_NETWORK_SCANNING_MESSAGE},
- {"networkSectionAdvanced",
- IDS_SETTINGS_INTERNET_NETWORK_SECTION_ADVANCED},
- {"networkSectionAdvancedA11yLabel",
- IDS_SETTINGS_INTERNET_NETWORK_SECTION_ADVANCED_ACCESSIBILITY_LABEL},
- {"networkSectionNetwork", IDS_SETTINGS_INTERNET_NETWORK_SECTION_NETWORK},
- {"networkSectionNetworkExpandA11yLabel",
- IDS_SETTINGS_INTERNET_NETWORK_SECTION_NETWORK_ACCESSIBILITY_LABEL},
- {"networkSectionProxy", IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY},
- {"networkSectionProxyExpandA11yLabel",
- IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY_ACCESSIBILITY_LABEL},
- {"networkShared", IDS_SETTINGS_INTERNET_NETWORK_SHARED},
- {"networkVpnBuiltin", IDS_NETWORK_TYPE_VPN_BUILTIN},
- {"networkOutOfRange", IDS_SETTINGS_INTERNET_WIFI_NETWORK_OUT_OF_RANGE},
- {"cellularContactSpecificCarrier",
- IDS_SETTINGS_INTERNET_CELLULAR_CONTACT_SPECIFIC_CARRIER},
- {"cellularContactDefaultCarrier",
- IDS_SETTINGS_INTERNET_CELLULAR_CONTACT_DEFAULT_CARRIER},
- {"tetherPhoneOutOfRange",
- IDS_SETTINGS_INTERNET_TETHER_PHONE_OUT_OF_RANGE},
- {"gmscoreNotificationsTitle",
- IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_TITLE},
- {"gmscoreNotificationsOneDeviceSubtitle",
- IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_ONE_DEVICE_SUBTITLE},
- {"gmscoreNotificationsTwoDevicesSubtitle",
- IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_TWO_DEVICES_SUBTITLE},
- {"gmscoreNotificationsManyDevicesSubtitle",
- IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_MANY_DEVICES_SUBTITLE},
- {"gmscoreNotificationsFirstStep",
- IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_FIRST_STEP},
- {"gmscoreNotificationsSecondStep",
- IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_SECOND_STEP},
- {"gmscoreNotificationsThirdStep",
- IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_THIRD_STEP},
- {"gmscoreNotificationsFourthStep",
- IDS_SETTINGS_INTERNET_GMSCORE_NOTIFICATIONS_FOURTH_STEP},
- {"tetherConnectionDialogTitle",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DIALOG_TITLE},
- {"tetherConnectionAvailableDeviceTitle",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_AVAILABLE_DEVICE_TITLE},
- {"tetherConnectionBatteryPercentage",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_BATTERY_PERCENTAGE},
- {"tetherConnectionExplanation",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_EXPLANATION},
- {"tetherConnectionCarrierWarning",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_CARRIER_WARNING},
- {"tetherConnectionDescriptionTitle",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DESCRIPTION_TITLE},
- {"tetherConnectionDescriptionMobileData",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DESCRIPTION_MOBILE_DATA},
- {"tetherConnectionDescriptionBattery",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DESCRIPTION_BATTERY},
- {"tetherConnectionDescriptionWiFi",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_DESCRIPTION_WIFI},
- {"tetherConnectionNotNowButton",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_NOT_NOW_BUTTON},
- {"tetherConnectionConnectButton",
- IDS_SETTINGS_INTERNET_TETHER_CONNECTION_CONNECT_BUTTON},
- {"tetherEnableBluetooth", IDS_ENABLE_BLUETOOTH},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-
- html_source->AddString("networkGoogleNameserversLearnMoreUrl",
- chrome::kGoogleNameserversLearnMoreURL);
- html_source->AddString(
- "internetNoNetworksMobileData",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_INTERNET_LOOKING_FOR_MOBILE_NETWORK,
- GetHelpUrlWithBoard(chrome::kInstantTetheringLearnMoreURL)));
-}
-#endif
-
-void AddLanguagesStrings(content::WebUIDataSource* html_source) {
+void AddLanguagesStrings(content::WebUIDataSource* html_source,
+ Profile* profile) {
static constexpr webui::LocalizedString kLocalizedStrings[] = {
{"languagesListTitle", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_TITLE},
{"searchLanguages", IDS_SETTINGS_LANGUAGE_SEARCH},
{"languagesExpandA11yLabel",
IDS_SETTINGS_LANGUAGES_EXPAND_ACCESSIBILITY_LABEL},
- {"orderLanguagesInstructions",
- IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_ORDERING_INSTRUCTIONS},
+ {"orderBrowserLanguagesInstructions",
+ IDS_SETTINGS_LANGUAGES_BROWSER_LANGUAGES_LIST_ORDERING_INSTRUCTIONS},
{"moveToTop", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_MOVE_TO_TOP},
{"moveUp", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_MOVE_UP},
{"moveDown", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_MOVE_DOWN},
{"removeLanguage", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_REMOVE},
{"addLanguages", IDS_SETTINGS_LANGUAGES_LANGUAGES_ADD},
-#if defined(OS_CHROMEOS)
- {"osLanguagesPageTitle", IDS_OS_SETTINGS_LANGUAGES_AND_INPUT_PAGE_TITLE},
- {"osLanguagesListTitle", IDS_OS_SETTINGS_LANGUAGES_LIST_TITLE},
- {"inputMethodsListTitle", IDS_SETTINGS_LANGUAGES_INPUT_METHODS_LIST_TITLE},
- {"inputMethodEnabled", IDS_SETTINGS_LANGUAGES_INPUT_METHOD_ENABLED},
- {"inputMethodsExpandA11yLabel",
- IDS_SETTINGS_LANGUAGES_INPUT_METHODS_EXPAND_ACCESSIBILITY_LABEL},
- {"inputMethodsManagedbyPolicy",
- IDS_SETTINGS_LANGUAGES_INPUT_METHODS_MANAGED_BY_POLICY},
- {"manageInputMethods", IDS_SETTINGS_LANGUAGES_INPUT_METHODS_MANAGE},
- {"manageInputMethodsPageTitle",
- IDS_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_TITLE},
- {"showImeMenu", IDS_SETTINGS_LANGUAGES_SHOW_IME_MENU},
-#endif
{"addLanguagesDialogTitle", IDS_SETTINGS_LANGUAGES_MANAGE_LANGUAGES_TITLE},
{"allLanguages", IDS_SETTINGS_LANGUAGES_ALL_LANGUAGES},
{"enabledLanguages", IDS_SETTINGS_LANGUAGES_ENABLED_LANGUAGES},
@@ -1704,18 +642,23 @@ void AddLanguagesStrings(content::WebUIDataSource* html_source) {
html_source->AddString(
"languagesLearnMoreURL",
base::ASCIIToUTF16(chrome::kLanguageSettingsLearnMoreUrl));
- // TODO(hsuregan): Remove once OS Browser split settings is complete.
html_source->AddString(
"languagesPageTitle",
- l10n_util::GetStringUTF16(
- base::FeatureList::IsEnabled(chromeos::features::kSplitSettings)
- ? IDS_SETTINGS_LANGUAGES_PAGE_TITLE
- : IDS_OS_SETTINGS_LANGUAGES_AND_INPUT_PAGE_TITLE));
+ l10n_util::GetStringUTF16(IDS_SETTINGS_LANGUAGES_PAGE_TITLE));
#else
html_source->AddString(
"languagesPageTitle",
l10n_util::GetStringUTF16(IDS_SETTINGS_LANGUAGES_PAGE_TITLE));
#endif
+#if defined(OS_CHROMEOS)
+ user_manager::UserManager* user_manager = user_manager::UserManager::Get();
+ const user_manager::User* user =
+ chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
+ const user_manager::User* primary_user = user_manager->GetPrimaryUser();
+ html_source->AddBoolean(
+ "isSecondaryUser",
+ user && user->GetAccountId() != primary_user->GetAccountId());
+#endif // defined(OS_CHROMEOS)
}
#if defined(OS_CHROMEOS)
@@ -1723,34 +666,13 @@ void AddChromeOSUserStrings(content::WebUIDataSource* html_source,
Profile* profile) {
user_manager::UserManager* user_manager = user_manager::UserManager::Get();
- const user_manager::User* user =
- chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
const user_manager::User* primary_user = user_manager->GetPrimaryUser();
std::string primary_user_email = primary_user->GetAccountId().GetUserEmail();
- html_source->AddString("primaryUserEmail", primary_user_email);
- html_source->AddBoolean(
- "isSecondaryUser",
- user && user->GetAccountId() != primary_user->GetAccountId());
- html_source->AddString(
- "secondaryUserBannerText",
- l10n_util::GetStringFUTF16(IDS_SETTINGS_SECONDARY_USER_BANNER,
- base::ASCIIToUTF16(primary_user_email)));
- html_source->AddString("browserSettingsBannerText",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_BROWSER_SETTINGS_BANNER,
- base::ASCIIToUTF16(chrome::kChromeUISettingsURL)));
html_source->AddString(
"osSettingsBannerText",
l10n_util::GetStringFUTF16(
IDS_SETTINGS_OS_SETTINGS_BANNER,
base::ASCIIToUTF16(chrome::kChromeUIOSSettingsURL)));
- html_source->AddBoolean("isActiveDirectoryUser",
- user && user->IsActiveDirectoryUser());
-
- if (!IsDeviceManaged() && !user_manager->IsCurrentUserOwner()) {
- html_source->AddString("ownerEmail",
- user_manager->GetOwnerAccountId().GetUserEmail());
- }
}
#endif
@@ -1809,8 +731,42 @@ void AddAutofillStrings(content::WebUIDataSource* html_source,
static constexpr webui::LocalizedString kLocalizedStrings[] = {
{"autofillPageTitle", IDS_SETTINGS_AUTOFILL},
{"passwords", IDS_SETTINGS_PASSWORDS},
+ {"checkPasswords", IDS_SETTINGS_CHECK_PASSWORDS},
+ {"checkPasswordsCanceled", IDS_SETTINGS_CHECK_PASSWORDS_CANCELED},
+ {"checkedPasswords", IDS_SETTINGS_CHECKED_PASSWORDS},
+ {"checkPasswordsDescription", IDS_SETTINGS_CHECK_PASSWORDS_DESCRIPTION},
+ {"checkPasswordsAgain", IDS_SETTINGS_CHECK_PASSWORDS_AGAIN},
+ {"checkPasswordsAgainAfterError",
+ IDS_SETTINGS_CHECK_PASSWORDS_AGAIN_AFTER_ERROR},
+ {"checkPasswordsProgress", IDS_SETTINGS_CHECK_PASSWORDS_PROGRESS},
+ {"checkPasswordsStop", IDS_SETTINGS_CHECK_PASSWORDS_STOP},
+ {"compromisedPasswords", IDS_SETTINGS_COMPROMISED_PASSWORDS},
+ {"compromisedPasswordsDescription",
+ IDS_SETTINGS_COMPROMISED_PASSWORDS_ADVICE},
+ {"changePasswordButton", IDS_SETTINGS_CHANGE_PASSWORD_BUTTON},
+ {"changePasswordInApp", IDS_SETTINGS_CHANGE_PASSWORD_IN_APP_LABEL},
+ {"leakedPassword", IDS_SETTINGS_COMPROMISED_PASSWORD_REASON_LEAKED},
+ {"phishedPassword", IDS_SETTINGS_COMPROMISED_PASSWORD_REASON_PHISHED},
+ {"phishedAndLeakedPassword",
+ IDS_SETTINGS_COMPROMISED_PASSWORD_REASON_PHISHED_AND_LEAKED},
+ {"showCompromisedPassword", IDS_SETTINGS_COMPROMISED_PASSWORD_SHOW},
+ {"hideCompromisedPassword", IDS_SETTINGS_COMPROMISED_PASSWORD_HIDE},
+ {"editCompromisedPassword", IDS_SETTINGS_COMPROMISED_PASSWORD_EDIT},
+ {"removeCompromisedPassword", IDS_SETTINGS_COMPROMISED_PASSWORD_REMOVE},
+ {"removeCompromisedPasswordConfirmationTitle",
+ IDS_SETTINGS_REMOVE_COMPROMISED_PASSWORD_CONFIRMATION_TITLE},
+ {"removeCompromisedPasswordConfirmationDescription",
+ IDS_SETTINGS_REMOVE_COMPROMISED_PASSWORD_CONFIRMATION_DESCRIPTION},
+ {"editCompromisedPasswordTitle",
+ IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_TITLE},
+ {"editCompromisedPasswordFootnote",
+ IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_FOOTNOTE},
+ {"editCompromisedPasswordSite",
+ IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_SITE},
+ {"editCompromisedPasswordApp",
+ IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_APP},
{"creditCards", IDS_AUTOFILL_PAYMENT_METHODS},
- {"noCreditCardsFound", IDS_SETTINGS_PAYMENT_METHODS_NONE},
+ {"noPaymentMethodsFound", IDS_SETTINGS_PAYMENT_METHODS_NONE},
{"googlePayments", IDS_SETTINGS_GOOGLE_PAYMENTS},
{"googlePaymentsCached", IDS_SETTINGS_GOOGLE_PAYMENTS_CACHED},
{"enableProfilesLabel", IDS_AUTOFILL_ENABLE_PROFILES_TOGGLE_LABEL},
@@ -1844,6 +800,8 @@ void AddAutofillStrings(content::WebUIDataSource* html_source,
{"migratableCardsInfoSingle", IDS_SETTINGS_SINGLE_MIGRATABLE_CARD_INFO},
{"migratableCardsInfoMultiple",
IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_INFO},
+ {"upiIdLabel", IDS_SETTINGS_UPI_ID_LABEL},
+ {"upiIdExpirationNever", IDS_SETTINGS_UPI_ID_EXPIRATION_NEVER},
{"canMakePaymentToggleLabel", IDS_SETTINGS_CAN_MAKE_PAYMENT_TOGGLE_LABEL},
{"autofillDetail", IDS_SETTINGS_AUTOFILL_DETAIL},
{"passwordsSavePasswordsLabel",
@@ -1854,6 +812,8 @@ void AddAutofillStrings(content::WebUIDataSource* html_source,
IDS_SETTINGS_PASSWORDS_AUTOSIGNIN_CHECKBOX_DESC},
{"passwordsLeakDetectionLabel",
IDS_SETTINGS_PASSWORDS_LEAK_DETECTION_LABEL},
+ {"passwordsLeakDetectionGeneralDescription",
+ IDS_PASSWORD_MANAGER_LEAK_HELP_MESSAGE},
{"passwordsLeakDetectionSignedOutEnabledDescription",
IDS_SETTINGS_PASSWORDS_LEAK_DETECTION_SIGNED_OUT_ENABLED_DESC},
{"savedPasswordsHeading", IDS_SETTINGS_PASSWORDS_SAVED_HEADING},
@@ -1865,6 +825,7 @@ void AddAutofillStrings(content::WebUIDataSource* html_source,
{"hidePassword", IDS_SETTINGS_PASSWORD_HIDE},
{"passwordDetailsTitle", IDS_SETTINGS_PASSWORDS_VIEW_DETAILS_TITLE},
{"passwordViewDetails", IDS_SETTINGS_PASSWORD_DETAILS},
+ {"copyPassword", IDS_SETTINGS_PASSWORD_COPY},
{"editPasswordWebsiteLabel", IDS_SETTINGS_PASSWORDS_WEBSITE},
{"editPasswordUsernameLabel", IDS_SETTINGS_PASSWORDS_USERNAME},
{"editPasswordPasswordLabel", IDS_SETTINGS_PASSWORDS_PASSWORD},
@@ -1873,6 +834,10 @@ void AddAutofillStrings(content::WebUIDataSource* html_source,
{"noExceptionsFound", IDS_SETTINGS_PASSWORDS_EXCEPTIONS_NONE},
{"import", IDS_PASSWORD_MANAGER_IMPORT_BUTTON},
{"exportMenuItem", IDS_SETTINGS_PASSWORDS_EXPORT_MENU_ITEM},
+ {"optInAccountStorageLabel",
+ IDS_SETTINGS_PASSWORDS_OPT_IN_ACCOUNT_STORAGE_LABEL},
+ {"optOutAccountStorageLabel",
+ IDS_SETTINGS_PASSWORDS_OPT_OUT_ACCOUNT_STORAGE_LABEL},
{"undoRemovePassword", IDS_SETTINGS_PASSWORD_UNDO},
{"passwordDeleted", IDS_SETTINGS_PASSWORD_DELETED_PASSWORD},
{"passwordRowMoreActionsButton", IDS_SETTINGS_PASSWORD_ROW_MORE_ACTIONS},
@@ -1894,6 +859,33 @@ void AddAutofillStrings(content::WebUIDataSource* html_source,
{"savedToThisDeviceOnly",
IDS_SETTINGS_PAYMENTS_SAVED_TO_THIS_DEVICE_ONLY}};
+ const base::string16 short_product_name =
+ l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
+ html_source->AddString(
+ "checkPasswordsErrorOffline",
+ l10n_util::GetStringFUTF16(IDS_SETTINGS_CHECK_PASSWORDS_ERROR_OFFLINE,
+ short_product_name));
+ html_source->AddString(
+ "checkPasswordsErrorSignedOut",
+ l10n_util::GetStringFUTF16(IDS_SETTINGS_CHECK_PASSWORDS_ERROR_SIGNED_OUT,
+ short_product_name));
+ html_source->AddString(
+ "checkPasswordsErrorNoPasswords",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CHECK_PASSWORDS_ERROR_NO_PASSWORDS, short_product_name));
+ html_source->AddString(
+ "checkPasswordsErrorQuota",
+ l10n_util::GetStringFUTF16(IDS_SETTINGS_CHECK_PASSWORDS_ERROR_QUOTA_LIMIT,
+ short_product_name));
+ html_source->AddString(
+ "checkPasswordsErrorGeneric",
+ l10n_util::GetStringFUTF16(IDS_SETTINGS_CHECK_PASSWORDS_ERROR_GENERIC,
+ short_product_name));
+ html_source->AddString(
+ "noCompromisedCredentials",
+ l10n_util::GetStringFUTF16(IDS_SETTINGS_NO_COMPROMISED_CREDENTIALS_LABEL,
+ short_product_name));
+
GURL google_password_manager_url = GetGooglePasswordManagerURL(
password_manager::ManagePasswordsReferrer::kChromeSettings);
@@ -1902,8 +894,19 @@ void AddAutofillStrings(content::WebUIDataSource* html_source,
l10n_util::GetStringFUTF16(
IDS_SETTINGS_PASSWORDS_MANAGE_PASSWORDS,
base::UTF8ToUTF16(google_password_manager_url.spec())));
+ html_source->AddString(
+ "checkPasswordsErrorQuotaGoogleAccount",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_CHECK_PASSWORDS_ERROR_QUOTA_LIMIT_GOOGLE_ACCOUNT,
+ short_product_name,
+ base::UTF8ToUTF16(
+ password_manager::GetPasswordCheckupURL(
+ password_manager::PasswordCheckupReferrer::kPasswordCheck)
+ .spec())));
html_source->AddString("googlePasswordManagerUrl",
google_password_manager_url.spec());
+ html_source->AddString("passwordCheckLearnMoreURL",
+ chrome::kPasswordCheckLearnMoreURL);
html_source->AddString("passwordManagerLearnMoreURL",
chrome::kPasswordManagerLearnMoreURL);
html_source->AddString("manageAddressesUrl",
@@ -1937,397 +940,119 @@ void AddAutofillStrings(content::WebUIDataSource* html_source,
"fidoAuthenticationAvailableForAutofill",
IsFidoAuthenticationAvailable(personal_data, web_contents));
- html_source->AddBoolean(
- "passwordsLeakDetectionEnabled",
- base::FeatureList::IsEnabled(password_manager::features::kLeakDetection));
-
ui::Accelerator undo_accelerator(ui::VKEY_Z, ui::EF_PLATFORM_ACCELERATOR);
html_source->AddString(
"undoDescription",
l10n_util::GetStringFUTF16(IDS_UNDO_DESCRIPTION,
undo_accelerator.GetShortcutText()));
+ html_source->AddBoolean("showUpiIdSettings",
+ base::FeatureList::IsEnabled(
+ autofill::features::kAutofillSaveAndFillVPA));
+
AddLocalizedStringsBulk(html_source, kLocalizedStrings);
}
-void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"peoplePageTitle", IDS_SETTINGS_PEOPLE},
- {"manageOtherPeople", IDS_SETTINGS_PEOPLE_MANAGE_OTHER_PEOPLE},
+void AddSignOutDialogStrings(content::WebUIDataSource* html_source,
+ Profile* profile) {
#if defined(OS_CHROMEOS)
- {"accountManagerDescription", IDS_SETTINGS_ACCOUNT_MANAGER_DESCRIPTION},
- {"accountManagerPageTitle", IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE},
- {"accountManagerSubMenuLabel", IDS_SETTINGS_ACCOUNT_MANAGER_SUBMENU_LABEL},
- {"accountListHeader", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER},
- {"addAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_ADD_ACCOUNT_LABEL},
- {"removeAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_REMOVE_ACCOUNT_LABEL},
- {"accountManagerPrimaryAccountTooltip",
- IDS_SETTINGS_ACCOUNT_MANAGER_PRIMARY_ACCOUNT_TOOLTIP},
- {"accountManagerSecondaryAccountsDisabledText",
- IDS_SETTINGS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_TEXT},
- {"accountManagerSecondaryAccountsDisabledChildText",
- IDS_SETTINGS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_CHILD_TEXT},
- {"accountManagerSignedOutAccountName",
- IDS_SETTINGS_ACCOUNT_MANAGER_SIGNED_OUT_ACCOUNT_PLACEHOLDER},
- {"accountManagerUnmigratedAccountName",
- IDS_SETTINGS_ACCOUNT_MANAGER_UNMIGRATED_ACCOUNT_PLACEHOLDER},
- {"accountManagerMigrationLabel",
- IDS_SETTINGS_ACCOUNT_MANAGER_MIGRATION_LABEL},
- {"accountManagerReauthenticationLabel",
- IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_LABEL},
- {"accountManagerMigrationTooltip",
- IDS_SETTINGS_ACCOUNT_MANAGER_MIGRATION_TOOLTIP},
- {"accountManagerReauthenticationTooltip",
- IDS_SETTINGS_ACCOUNT_MANAGER_REAUTHENTICATION_TOOLTIP},
- {"accountManagerMoreActionsTooltip",
- IDS_SETTINGS_ACCOUNT_MANAGER_MORE_ACTIONS_TOOLTIP},
- {"accountManagerManagedLabel",
- IDS_SETTINGS_ACCOUNT_MANAGER_MANAGEMENT_STATUS_MANAGED_ACCOUNT},
- {"accountManagerUnmanagedLabel",
- IDS_SETTINGS_ACCOUNT_MANAGER_MANAGEMENT_STATUS_UNMANAGED_ACCOUNT},
- {"configureFingerprintTitle", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TITLE},
- {"configureFingerprintInstructionReadyStep",
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_READY},
- {"configureFingerprintLiftFinger",
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_LIFT_FINGER},
- {"configureFingerprintTryAgain",
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TRY_AGAIN},
- {"configureFingerprintImmobile",
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_FINGER_IMMOBILE},
- {"configureFingerprintAddAnotherButton",
- IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_ADD_ANOTHER_BUTTON},
- {"configurePinChoosePinTitle",
- IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CHOOSE_PIN_TITLE},
- {"configurePinConfirmPinTitle",
- IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_CONFIRM_PIN_TITLE},
- {"configurePinMismatched", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_MISMATCHED},
- {"configurePinTooShort", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT},
- {"configurePinTooLong", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_LONG},
- {"configurePinWeakPin", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_WEAK_PIN},
- {"enableScreenlock", IDS_SETTINGS_PEOPLE_ENABLE_SCREENLOCK},
- {"kerberosAccountsSubMenuLabel",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_SUBMENU_LABEL},
- {"kerberosAccountsPageTitle", IDS_SETTINGS_KERBEROS_ACCOUNTS_PAGE_TITLE},
- {"kerberosAccountsListHeader", IDS_SETTINGS_KERBEROS_ACCOUNTS_LIST_HEADER},
- {"kerberosAccountsAddAccountLabel",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_ADD_ACCOUNT_LABEL},
- {"kerberosAccountsRefreshNowLabel",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_REFRESH_NOW_LABEL},
- {"kerberosAccountsSetAsActiveAccountLabel",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_SET_AS_ACTIVE_ACCOUNT_LABEL},
- {"kerberosAccountsRemoveAccountLabel",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_REMOVE_ACCOUNT_LABEL},
- {"kerberosAccountsAccountRemovedTip",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_ACCOUNT_REMOVED_TIP},
- {"kerberosAccountsAccountRefreshedTip",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_ACCOUNT_REFRESHED_TIP},
- {"kerberosAccountsSignedIn", IDS_SETTINGS_KERBEROS_ACCOUNTS_SIGNED_IN},
- {"kerberosAccountsSignedOut", IDS_SETTINGS_KERBEROS_ACCOUNTS_SIGNED_OUT},
- {"kerberosAccountsReauthenticationLabel",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_REAUTHENTICATION_LABEL},
- {"kerberosAccountsTicketActive",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_TICKET_ACTIVE},
- {"addKerberosAccount", IDS_SETTINGS_ADD_KERBEROS_ACCOUNT},
- {"refreshKerberosAccount", IDS_SETTINGS_REFRESH_KERBEROS_ACCOUNT},
- {"addKerberosAccountDescription",
- IDS_SETTINGS_ADD_KERBEROS_ACCOUNT_DESCRIPTION},
- {"addKerberosAccountRememberPassword",
- IDS_SETTINGS_ADD_KERBEROS_ACCOUNT_REMEMBER_PASSWORD},
- {"addKerberosAccountRefreshButtonLabel",
- IDS_SETTINGS_ADD_KERBEROS_ACCOUNT_REFRESH_BUTTON_LABEL},
- {"kerberosUsername", IDS_SETTINGS_KERBEROS_USERNAME},
- {"kerberosPassword", IDS_SETTINGS_KERBEROS_PASSWORD},
- {"kerberosAccountsAdvancedConfigLabel",
- IDS_SETTINGS_KERBEROS_ACCOUNTS_ADVANCED_CONFIG_LABEL},
- {"kerberosAdvancedConfigTitle",
- IDS_SETTINGS_KERBEROS_ADVANCED_CONFIG_TITLE},
- {"kerberosAdvancedConfigDesc", IDS_SETTINGS_KERBEROS_ADVANCED_CONFIG_DESC},
- {"kerberosErrorNetworkProblem",
- IDS_SETTINGS_KERBEROS_ERROR_NETWORK_PROBLEM},
- {"kerberosErrorUsernameInvalid",
- IDS_SETTINGS_KERBEROS_ERROR_USERNAME_INVALID},
- {"kerberosErrorUsernameUnknown",
- IDS_SETTINGS_KERBEROS_ERROR_USERNAME_UNKNOWN},
- {"kerberosErrorDuplicatePrincipalName",
- IDS_SETTINGS_KERBEROS_ERROR_DUPLICATE_PRINCIPAL_NAME},
- {"kerberosErrorContactingServer",
- IDS_SETTINGS_KERBEROS_ERROR_CONTACTING_SERVER},
- {"kerberosErrorPasswordInvalid",
- IDS_SETTINGS_KERBEROS_ERROR_PASSWORD_INVALID},
- {"kerberosErrorPasswordExpired",
- IDS_SETTINGS_KERBEROS_ERROR_PASSWORD_EXPIRED},
- {"kerberosErrorKdcEncType", IDS_SETTINGS_KERBEROS_ERROR_KDC_ENC_TYPE},
- {"kerberosErrorGeneral", IDS_SETTINGS_KERBEROS_ERROR_GENERAL},
- {"kerberosConfigErrorSectionNestedInGroup",
- IDS_SETTINGS_KERBEROS_CONFIG_ERROR_SECTION_NESTED_IN_GROUP},
- {"kerberosConfigErrorSectionSyntax",
- IDS_SETTINGS_KERBEROS_CONFIG_ERROR_SECTION_SYNTAX},
- {"kerberosConfigErrorExpectedOpeningCurlyBrace",
- IDS_SETTINGS_KERBEROS_CONFIG_ERROR_EXPECTED_OPENING_CURLY_BRACE},
- {"kerberosConfigErrorExtraCurlyBrace",
- IDS_SETTINGS_KERBEROS_CONFIG_ERROR_EXTRA_CURLY_BRACE},
- {"kerberosConfigErrorRelationSyntax",
- IDS_SETTINGS_KERBEROS_CONFIG_ERROR_RELATION_SYNTAX_ERROR},
- {"kerberosConfigErrorKeyNotSupported",
- IDS_SETTINGS_KERBEROS_CONFIG_ERROR_KEY_NOT_SUPPORTED},
- {"kerberosConfigErrorSectionNotSupported",
- IDS_SETTINGS_KERBEROS_CONFIG_ERROR_SECTION_NOT_SUPPORTED},
- {"kerberosConfigErrorKrb5FailedToParse",
- IDS_SETTINGS_KERBEROS_CONFIG_ERROR_KRB5_FAILED_TO_PARSE},
- {"lockScreenAddFingerprint",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_ADD_FINGERPRINT_BUTTON},
- {"lockScreenChangePinButton",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_CHANGE_PIN_BUTTON},
- {"lockScreenEditFingerprints",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS},
- {"lockScreenEditFingerprintsDescription",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_EDIT_FINGERPRINTS_DESCRIPTION},
- {"lockScreenSetupFingerprintButton",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SETUP_BUTTON},
- {"lockScreenNumberFingerprints",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NUM_FINGERPRINTS},
- {"lockScreenNone", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NONE},
- {"lockScreenFingerprintNewName",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME},
- {"lockScreenFingerprintTitle",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SUBPAGE_TITLE},
- {"lockScreenFingerprintWarning",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_LESS_SECURE},
- {"lockScreenDeleteFingerprintLabel",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_DELETE_FINGERPRINT_ARIA_LABEL},
- {"lockScreenNotificationHide",
- IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE},
- {"lockScreenNotificationHideSensitive",
- IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE_SENSITIVE},
- {"lockScreenNotificationShow",
- IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_SHOW},
- {"lockScreenNotificationTitle",
- IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_TITLE},
- {"lockScreenOptionsLock", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOCK},
- {"lockScreenOptionsLoginLock",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOGIN_LOCK},
- {"lockScreenPasswordOnly", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PASSWORD_ONLY},
- {"lockScreenPinOrPassword",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_PIN_OR_PASSWORD},
- {"lockScreenRegisteredFingerprints",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_REGISTERED_FINGERPRINTS_LABEL},
- {"lockScreenSetupPinButton",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_SETUP_PIN_BUTTON},
- {"lockScreenTitleLock", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOCK},
- {"lockScreenTitleLoginLock",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOGIN_LOCK},
- {"passwordPromptEnterPasswordLock",
- IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOCK},
- {"passwordPromptEnterPasswordLoginLock",
- IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_ENTER_PASSWORD_LOGIN_LOCK},
- {"passwordPromptInvalidPassword",
- IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_INVALID_PASSWORD},
- {"passwordPromptPasswordLabel",
- IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_PASSWORD_LABEL},
- {"passwordPromptTitle", IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_TITLE},
- {"pinKeyboardPlaceholderPin", IDS_PIN_KEYBOARD_HINT_TEXT_PIN},
- {"pinKeyboardPlaceholderPinPassword",
- IDS_PIN_KEYBOARD_HINT_TEXT_PIN_PASSWORD},
- {"pinKeyboardDeleteAccessibleName",
- IDS_PIN_KEYBOARD_DELETE_ACCESSIBLE_NAME},
- {"changePicturePageDescription", IDS_SETTINGS_CHANGE_PICTURE_DIALOG_TEXT},
- {"takePhoto", IDS_SETTINGS_CHANGE_PICTURE_TAKE_PHOTO},
- {"captureVideo", IDS_SETTINGS_CHANGE_PICTURE_CAPTURE_VIDEO},
- {"discardPhoto", IDS_SETTINGS_CHANGE_PICTURE_DISCARD_PHOTO},
- {"switchModeToCamera", IDS_SETTINGS_CHANGE_PICTURE_SWITCH_MODE_TO_CAMERA},
- {"switchModeToVideo", IDS_SETTINGS_CHANGE_PICTURE_SWITCH_MODE_TO_VIDEO},
- {"chooseFile", IDS_SETTINGS_CHANGE_PICTURE_CHOOSE_FILE},
- {"profilePhoto", IDS_SETTINGS_CHANGE_PICTURE_PROFILE_PHOTO},
- {"oldPhoto", IDS_SETTINGS_CHANGE_PICTURE_OLD_PHOTO},
- {"oldVideo", IDS_SETTINGS_CHANGE_PICTURE_OLD_VIDEO},
- {"previewAltText", IDS_SETTINGS_CHANGE_PICTURE_PREVIEW_ALT},
- {"authorCreditText", IDS_SETTINGS_CHANGE_PICTURE_AUTHOR_CREDIT_TEXT},
- {"photoCaptureAccessibleText", IDS_SETTINGS_PHOTO_CAPTURE_ACCESSIBLE_TEXT},
- {"photoDiscardAccessibleText", IDS_SETTINGS_PHOTO_DISCARD_ACCESSIBLE_TEXT},
- {"photoModeAccessibleText", IDS_SETTINGS_PHOTO_MODE_ACCESSIBLE_TEXT},
- {"syncOsAppsCheckboxLabel", IDS_OS_SETTINGS_SYNC_OS_APPS_CHECKBOX_LABEL},
- {"syncOsSettingsCheckboxLabel",
- IDS_OS_SETTINGS_SYNC_OS_SETTINGS_CHECKBOX_LABEL},
- {"syncPrintersCheckboxLabel", IDS_OS_SETTINGS_SYNC_PRINTERS_CHECKBOX_LABEL},
- {"videoModeAccessibleText", IDS_SETTINGS_VIDEO_MODE_ACCESSIBLE_TEXT},
- {"wifiConfigurationsCheckboxLabel",
- IDS_SETTINGS_WIFI_CONFIGURATIONS_CHECKBOX_LABEL},
-#else // !defined(OS_CHROMEOS)
- {"domainManagedProfile", IDS_SETTINGS_PEOPLE_DOMAIN_MANAGED_PROFILE},
- {"editPerson", IDS_SETTINGS_EDIT_PERSON},
- {"profileNameAndPicture", IDS_SETTINGS_PROFILE_NAME_AND_PICTURE},
- {"showShortcutLabel", IDS_SETTINGS_PROFILE_SHORTCUT_TOGGLE_LABEL},
- {"syncWillStart", IDS_SETTINGS_SYNC_WILL_START},
- {"syncSettingsSavedToast", IDS_SETTINGS_SYNC_SETTINGS_SAVED_TOAST_LABEL},
- {"cancelSync", IDS_SETTINGS_SYNC_SETTINGS_CANCEL_SYNC},
- {"syncSetupCancelDialogTitle", IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_TITLE},
- {"syncSetupCancelDialogBody", IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_BODY},
-#endif // defined(OS_CHROMEOS)
-#if BUILDFLAG(ENABLE_DICE_SUPPORT)
- {"peopleSignIn", IDS_PROFILES_DICE_SIGNIN_BUTTON},
- {"peopleSignOut", IDS_SETTINGS_PEOPLE_SIGN_OUT},
- {"peopleSignInPrompt", IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT},
- {"peopleSignInPromptSecondaryWithNoAccount",
- IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT},
- {"peopleSignInPromptSecondaryWithAccount",
- IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT},
- {"useAnotherAccount", IDS_SETTINGS_PEOPLE_SYNC_ANOTHER_ACCOUNT},
- {"syncingTo", IDS_SETTINGS_PEOPLE_SYNCING_TO_ACCOUNT},
- {"turnOffSync", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF},
- {"signInAgain", IDS_SYNC_ERROR_USER_MENU_SIGNIN_AGAIN_BUTTON},
- {"syncNotWorking", IDS_SETTINGS_PEOPLE_SYNC_NOT_WORKING},
- {"syncPasswordsNotWorking", IDS_SETTINGS_PEOPLE_SYNC_PASSWORDS_NOT_WORKING},
- {"syncPaused", IDS_SETTINGS_PEOPLE_SYNC_PAUSED},
- {"syncSignInPromptWithAccount",
- IDS_SETTINGS_SYNC_SIGN_IN_PROMPT_WITH_ACCOUNT},
- {"syncSignInPromptWithNoAccount",
- IDS_SETTINGS_SYNC_SIGN_IN_PROMPT_WITH_NO_ACCOUNT},
+ bool is_dice_enabled = false;
+ bool is_split_sync_consent_enabled =
+ chromeos::features::IsSplitSyncConsentEnabled();
+#else
+ bool is_dice_enabled =
+ AccountConsistencyModeManager::IsDiceEnabledForProfile(profile);
+ bool is_split_sync_consent_enabled = false;
#endif
- {"syncOverview", IDS_SETTINGS_SYNC_OVERVIEW},
- {"syncDisabled", IDS_PROFILES_DICE_SYNC_DISABLED_TITLE},
- {"syncDisabledByAdministrator", IDS_SIGNED_IN_WITH_SYNC_DISABLED_BY_POLICY},
- {"syncSignin", IDS_SETTINGS_SYNC_SIGNIN},
- {"syncDisconnect", IDS_SETTINGS_PEOPLE_SIGN_OUT},
- {"syncDisconnectTitle", IDS_SETTINGS_SYNC_DISCONNECT_TITLE},
- {"syncDisconnectDeleteProfile",
- IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE},
- {"deleteProfileWarningExpandA11yLabel",
- IDS_SETTINGS_SYNC_DISCONNECT_EXPAND_ACCESSIBILITY_LABEL},
- {"deleteProfileWarningWithCountsSingular",
- IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE_WARNING_WITH_COUNTS_SINGULAR},
- {"deleteProfileWarningWithCountsPlural",
- IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE_WARNING_WITH_COUNTS_PLURAL},
- {"deleteProfileWarningWithoutCounts",
- IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE_WARNING_WITHOUT_COUNTS},
- {"syncDisconnectConfirm", IDS_SETTINGS_SYNC_DISCONNECT_CONFIRM},
- {"sync", IDS_SETTINGS_SYNC},
- {"nonPersonalizedServicesSectionLabel",
- IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_LABEL},
- {"syncAndNonPersonalizedServices",
- IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES},
- {"syncPageTitle", IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES},
- {"syncAdvancedPageTitle", IDS_SETTINGS_SYNC_ADVANCED_PAGE_TITLE},
- {"syncLoading", IDS_SETTINGS_SYNC_LOADING},
- {"syncTimeout", IDS_SETTINGS_SYNC_TIMEOUT},
- {"syncEverythingCheckboxLabel",
- IDS_SETTINGS_SYNC_EVERYTHING_CHECKBOX_LABEL},
- {"manageGoogleAccount", IDS_SETTINGS_MANAGE_GOOGLE_ACCOUNT},
- {"appCheckboxLabel", IDS_SETTINGS_APPS_CHECKBOX_LABEL},
- {"extensionsCheckboxLabel", IDS_SETTINGS_EXTENSIONS_CHECKBOX_LABEL},
- {"settingsCheckboxLabel", IDS_SETTINGS_SETTINGS_CHECKBOX_LABEL},
- {"autofillCheckboxLabel", IDS_SETTINGS_AUTOFILL_CHECKBOX_LABEL},
- {"historyCheckboxLabel", IDS_SETTINGS_HISTORY_CHECKBOX_LABEL},
- {"themesAndWallpapersCheckboxLabel",
- IDS_SETTINGS_THEMES_AND_WALLPAPERS_CHECKBOX_LABEL},
- {"bookmarksCheckboxLabel", IDS_SETTINGS_BOOKMARKS_CHECKBOX_LABEL},
- {"passwordsCheckboxLabel", IDS_SETTINGS_PASSWORDS_CHECKBOX_LABEL},
- {"openTabsCheckboxLabel", IDS_SETTINGS_OPEN_TABS_CHECKBOX_LABEL},
- {"driveSuggestPref", IDS_DRIVE_SUGGEST_PREF},
- {"driveSuggestPrefDesc", IDS_DRIVE_SUGGEST_PREF_DESC},
- {"manageSyncedDataTitle",
- IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE_UNIFIED_CONSENT},
- {"encryptionOptionsTitle", IDS_SETTINGS_ENCRYPTION_OPTIONS},
- {"syncDataEncryptedText", IDS_SETTINGS_SYNC_DATA_ENCRYPTED_TEXT},
- {"encryptWithGoogleCredentialsLabel",
- IDS_SETTINGS_ENCRYPT_WITH_GOOGLE_CREDENTIALS_LABEL},
- {"useDefaultSettingsButton", IDS_SETTINGS_USE_DEFAULT_SETTINGS},
- {"emptyPassphraseError", IDS_SETTINGS_EMPTY_PASSPHRASE_ERROR},
- {"mismatchedPassphraseError", IDS_SETTINGS_MISMATCHED_PASSPHRASE_ERROR},
- {"incorrectPassphraseError", IDS_SETTINGS_INCORRECT_PASSPHRASE_ERROR},
- {"passphrasePlaceholder", IDS_SETTINGS_PASSPHRASE_PLACEHOLDER},
- {"passphraseConfirmationPlaceholder",
- IDS_SETTINGS_PASSPHRASE_CONFIRMATION_PLACEHOLDER},
- {"submitPassphraseButton", IDS_SETTINGS_SUBMIT_PASSPHRASE},
- {"personalizeGoogleServicesTitle",
- IDS_SETTINGS_PERSONALIZE_GOOGLE_SERVICES_TITLE},
- {"existingPassphraseTitle", IDS_SETTINGS_EXISTING_PASSPHRASE_TITLE},
- {"enablePaymentsIntegrationCheckboxLabel",
- IDS_AUTOFILL_ENABLE_PAYMENTS_INTEGRATION_CHECKBOX_LABEL},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-#if defined(OS_CHROMEOS)
- // TODO(crbug.com/1013466): String for this row label.
- html_source->AddString("peopleOsSyncRowLabel", "SYNC PLACEHOLDER LABEL");
- AddFingerprintStrings(html_source);
-#endif // OS_CHROMEOS
- html_source->AddString("managementPage",
- ManagementUI::GetManagementPageSubtitle(profile));
- // Format numbers to be used on the pin keyboard.
- for (int j = 0; j <= 9; j++) {
- html_source->AddString("pinKeyboard" + base::NumberToString(j),
- base::FormatNumber(int64_t{j}));
+ if (is_split_sync_consent_enabled || is_dice_enabled) {
+ static constexpr webui::LocalizedString kTurnOffStrings[] = {
+ {"syncDisconnect", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF},
+ {"syncDisconnectTitle",
+ IDS_SETTINGS_TURN_OFF_SYNC_AND_SIGN_OUT_DIALOG_TITLE},
+ };
+ AddLocalizedStringsBulk(html_source, kTurnOffStrings);
+ } else {
+ static constexpr webui::LocalizedString kSignOutStrings[] = {
+ {"syncDisconnect", IDS_SETTINGS_PEOPLE_SIGN_OUT},
+ {"syncDisconnectTitle", IDS_SETTINGS_SYNC_DISCONNECT_TITLE},
+ };
+ AddLocalizedStringsBulk(html_source, kSignOutStrings);
}
- html_source->AddString("syncLearnMoreUrl", chrome::kSyncLearnMoreURL);
- html_source->AddString("supervisedUsersUrl",
- chrome::kLegacySupervisedUserManagementURL);
-
- html_source->AddString(
- "encryptWithSyncPassphraseLabel",
- l10n_util::GetStringFUTF8(
- IDS_SETTINGS_ENCRYPT_WITH_SYNC_PASSPHRASE_LABEL,
-#if defined(OS_CHROMEOS)
- GetHelpUrlWithBoard(chrome::kSyncEncryptionHelpURL)));
-#else
- base::ASCIIToUTF16(chrome::kSyncEncryptionHelpURL)));
-#endif
-
std::string sync_dashboard_url =
google_util::AppendGoogleLocaleParam(
GURL(chrome::kSyncGoogleDashboardURL),
g_browser_process->GetApplicationLocale())
.spec();
- html_source->AddString("syncDashboardUrl", sync_dashboard_url);
-
- html_source->AddString(
- "passphraseExplanationText",
- l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_EXPLANATION_TEXT,
- base::ASCIIToUTF16(sync_dashboard_url)));
- html_source->AddString(
- "passphraseResetHintEncryption",
- l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_RESET_HINT_ENCRYPTION,
- base::ASCIIToUTF16(sync_dashboard_url)));
- html_source->AddString(
- "passphraseResetHintToggle",
- l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_RESET_HINT_TOGGLE,
- base::ASCIIToUTF16(sync_dashboard_url)));
- html_source->AddString(
- "passphraseRecover",
- l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_RECOVER,
- base::ASCIIToUTF16(sync_dashboard_url)));
- html_source->AddString(
- "syncDisconnectExplanation",
- l10n_util::GetStringFUTF8(IDS_SETTINGS_SYNC_DISCONNECT_EXPLANATION,
- base::ASCIIToUTF16(sync_dashboard_url)));
-#if !defined(OS_CHROMEOS)
- html_source->AddString(
- "syncDisconnectManagedProfileExplanation",
- l10n_util::GetStringFUTF8(
- IDS_SETTINGS_SYNC_DISCONNECT_MANAGED_PROFILE_EXPLANATION,
- base::ASCIIToUTF16("$1"), base::ASCIIToUTF16(sync_dashboard_url)));
- // The syncDisconnect text differs depending on Dice-enabledness.
- if (AccountConsistencyModeManager::IsDiceEnabledForProfile(profile)) {
+ if (is_dice_enabled) {
static constexpr webui::LocalizedString kSyncDisconnectStrings[] = {
- {"syncDisconnect", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF},
- {"syncDisconnectTitle",
- IDS_SETTINGS_TURN_OFF_SYNC_AND_SIGN_OUT_DIALOG_TITLE},
{"syncDisconnectDeleteProfile",
IDS_SETTINGS_TURN_OFF_SYNC_DIALOG_CHECKBOX},
{"syncDisconnectConfirm",
IDS_SETTINGS_TURN_OFF_SYNC_DIALOG_MANAGED_CONFIRM},
+ {"syncDisconnectExplanation",
+ IDS_SETTINGS_SYNC_DISCONNECT_AND_SIGN_OUT_EXPLANATION},
+ };
+ AddLocalizedStringsBulk(html_source, kSyncDisconnectStrings);
+ } else {
+ static constexpr webui::LocalizedString kSyncDisconnectStrings[] = {
+ {"syncDisconnectDeleteProfile",
+ IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE},
+ {"syncDisconnectConfirm", IDS_SETTINGS_SYNC_DISCONNECT_CONFIRM},
};
AddLocalizedStringsBulk(html_source, kSyncDisconnectStrings);
- html_source->AddLocalizedString(
+ html_source->AddString(
"syncDisconnectExplanation",
- IDS_SETTINGS_SYNC_DISCONNECT_AND_SIGN_OUT_EXPLANATION);
+ l10n_util::GetStringFUTF8(IDS_SETTINGS_SYNC_DISCONNECT_EXPLANATION,
+ base::ASCIIToUTF16(sync_dashboard_url)));
}
+
+#if !defined(OS_CHROMEOS)
+ html_source->AddString(
+ "syncDisconnectManagedProfileExplanation",
+ l10n_util::GetStringFUTF8(
+ IDS_SETTINGS_SYNC_DISCONNECT_MANAGED_PROFILE_EXPLANATION,
+ base::ASCIIToUTF16("$1"), base::ASCIIToUTF16(sync_dashboard_url)));
#endif
+}
- html_source->AddString("activityControlsUrl",
- chrome::kGoogleAccountActivityControlsURL);
+void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ // Top level people strings:
+ {"peopleSignInPromptSecondaryWithAccount",
+ IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT},
+ {"peopleSignInPromptSecondaryWithNoAccount",
+ IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT},
+ {"peoplePageTitle", IDS_SETTINGS_PEOPLE},
+ {"syncSettingsSavedToast", IDS_SETTINGS_SYNC_SETTINGS_SAVED_TOAST_LABEL},
+ {"peopleSignInPrompt", IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT},
+ {"manageGoogleAccount", IDS_SETTINGS_MANAGE_GOOGLE_ACCOUNT},
+ {"syncAndNonPersonalizedServices",
+ IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES},
+#if defined(OS_CHROMEOS)
+ {"accountManagerSubMenuLabel", IDS_SETTINGS_ACCOUNT_MANAGER_SUBMENU_LABEL},
+#else
+ {"editPerson", IDS_SETTINGS_EDIT_PERSON},
+ {"profileNameAndPicture", IDS_SETTINGS_PROFILE_NAME_AND_PICTURE},
+#endif
+
+ // Manage profile strings:
+#if !defined(OS_CHROMEOS)
+ {"showShortcutLabel", IDS_SETTINGS_PROFILE_SHORTCUT_TOGGLE_LABEL},
+#endif
+ {"deleteProfileWarningExpandA11yLabel",
+ IDS_SETTINGS_SYNC_DISCONNECT_EXPAND_ACCESSIBILITY_LABEL},
+ {"deleteProfileWarningWithCountsSingular",
+ IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE_WARNING_WITH_COUNTS_SINGULAR},
+ {"deleteProfileWarningWithCountsPlural",
+ IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE_WARNING_WITH_COUNTS_PLURAL},
+ {"deleteProfileWarningWithoutCounts",
+ IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE_WARNING_WITHOUT_COUNTS},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
// Add Google Account URL and include UTM parameter to signal the source of
// the navigation.
@@ -2336,52 +1061,21 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) {
net::AppendQueryParameter(GURL(chrome::kGoogleAccountURL), "utm_source",
"chrome-settings")
.spec());
-
html_source->AddBoolean("profileShortcutsEnabled",
ProfileShortcutManager::IsFeatureEnabled());
-
- html_source->AddBoolean(
- "changePictureVideoModeEnabled",
- base::FeatureList::IsEnabled(features::kChangePictureVideoMode));
-
- html_source->AddBoolean(
- "driveSuggestAvailable",
- base::FeatureList::IsEnabled(omnibox::kDocumentProvider));
-
#if defined(OS_CHROMEOS)
// Toggles the Chrome OS Account Manager submenu in the People section.
html_source->AddBoolean("isAccountManagerEnabled",
chromeos::IsAccountManagerAvailable(profile));
+#endif
- PrefService* local_state = g_browser_process->local_state();
-
- // Toggles the Chrome OS Kerberos Accounts submenu in the People section.
- // Note that the handler is also dependent on this pref.
- html_source->AddBoolean("isKerberosEnabled",
- local_state->GetBoolean(prefs::kKerberosEnabled));
-
- // Whether the 'Remember password' checkbox is enabled.
- html_source->AddBoolean(
- "kerberosRememberPasswordEnabled",
- local_state->GetBoolean(prefs::kKerberosRememberPasswordEnabled));
-
- // Whether new Kerberos accounts may be added.
- html_source->AddBoolean(
- "kerberosAddAccountsAllowed",
- local_state->GetBoolean(prefs::kKerberosAddAccountsAllowed));
-
- // Kerberos default configuration.
- html_source->AddString(
- "defaultKerberosConfig",
- chromeos::KerberosCredentialsManager::GetDefaultKerberosConfig());
-
- // Kerberos accounts page with "Learn more" link.
- html_source->AddString(
- "kerberosAccountsDescription",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_KERBEROS_ACCOUNTS_DESCRIPTION,
- GetHelpUrlWithBoard(chrome::kKerberosAccountsLearnMoreURL)));
+ AddSignOutDialogStrings(html_source, profile);
+ AddSyncControlsStrings(html_source);
+ AddSyncAccountControlStrings(html_source);
+#if defined(OS_CHROMEOS)
+ AddPasswordPromptDialogStrings(html_source);
#endif
+ AddSyncPageStrings(html_source);
}
void AddPrintingStrings(content::WebUIDataSource* html_source) {
@@ -2393,126 +1087,7 @@ void AddPrintingStrings(content::WebUIDataSource* html_source) {
{"printingManageCloudPrintDevices",
IDS_SETTINGS_PRINTING_MANAGE_CLOUD_PRINT_DEVICES},
{"cloudPrintersTitle", IDS_SETTINGS_PRINTING_CLOUD_PRINTERS},
-#if defined(OS_CHROMEOS)
- {"cupsPrintersTitle", IDS_SETTINGS_PRINTING_CUPS_PRINTERS},
- {"cupsPrintersLearnMoreLabel",
- IDS_SETTINGS_PRINTING_CUPS_PRINTERS_LEARN_MORE_LABEL},
- {"addCupsPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_ADD_PRINTER},
- {"editPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_EDIT},
- {"removePrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_REMOVE},
- {"setupPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SETUP_BUTTON},
- {"setupPrinterAria", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SETUP_BUTTON_ARIA},
- {"savePrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SAVE_BUTTON},
- {"savePrinterAria", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SAVE_BUTTON_ARIA},
- {"searchLabel", IDS_SETTINGS_PRINTING_CUPS_SEARCH_LABEL},
- {"noSearchResults", IDS_SEARCH_NO_RESULTS},
- {"printerDetailsTitle", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_TITLE},
- {"printerName", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_NAME},
- {"printerModel", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_MODEL},
- {"printerQueue", IDS_SETTINGS_PRINTING_CUPS_PRINTER_DETAILS_QUEUE},
- {"savedPrintersTitle", IDS_SETTINGS_PRINTING_CUPS_SAVED_PRINTERS_TITLE},
- {"savedPrintersCountMany",
- IDS_SETTINGS_PRINTING_CUPS_PRINTERS_SAVED_PRINTERS_COUNT_MANY},
- {"savedPrintersCountOne",
- IDS_SETTINGS_PRINTING_CUPS_PRINTERS_SAVED_PRINTERS_COUNT_ONE},
- {"savedPrintersCountNone",
- IDS_SETTINGS_PRINTING_CUPS_PRINTERS_SAVED_PRINTERS_COUNT_NONE},
- {"showMorePrinters", IDS_SETTINGS_PRINTING_CUPS_SHOW_MORE},
- {"addPrintersNearbyTitle",
- IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTERS_NEARBY_TITLE},
- {"addPrintersManuallyTitle",
- IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTERS_MANUALLY_TITLE},
- {"manufacturerAndModelDialogTitle",
- IDS_SETTINGS_PRINTING_CUPS_SELECT_MANUFACTURER_AND_MODEL_TITLE},
- {"nearbyPrintersListTitle",
- IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTERS},
- {"nearbyPrintersCountMany",
- IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTERS_COUNT_MANY},
- {"nearbyPrintersCountOne",
- IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTER_COUNT_ONE},
- {"nearbyPrintersCountNone",
- IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTER_COUNT_NONE},
- {"nearbyPrintersListDescription",
- IDS_SETTINGS_PRINTING_CUPS_PRINTERS_ADD_DETECTED_OR_NEW_PRINTER},
- {"manufacturerAndModelAdditionalInformation",
- IDS_SETTINGS_PRINTING_CUPS_MANUFACTURER_MODEL_ADDITIONAL_INFORMATION},
- {"addPrinterButtonText", IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTER_BUTTON_ADD},
- {"printerDetailsAdvanced", IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED},
- {"printerDetailsA11yLabel",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED_ACCESSIBILITY_LABEL},
- {"printerAddress", IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED_ADDRESS},
- {"printerProtocol", IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED_PROTOCOL},
- {"printerURI", IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED_URI},
- {"manuallyAddPrinterButtonText",
- IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTER_BUTTON_MANUAL_ADD},
- {"discoverPrintersButtonText",
- IDS_SETTINGS_PRINTING_CUPS_ADD_PRINTER_BUTTON_DISCOVER_PRINTERS},
- {"printerProtocolIpp", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_IPP},
- {"printerProtocolIpps", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_IPPS},
- {"printerProtocolHttp", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_HTTP},
- {"printerProtocolHttps", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_HTTPS},
- {"printerProtocolAppSocket",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_APP_SOCKET},
- {"printerProtocolLpd", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_LPD},
- {"printerProtocolUsb", IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_USB},
- {"printerProtocolIppUsb",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_PROTOCOL_IPPUSB},
- {"printerConfiguringMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_CONFIGURING_MESSAGE},
- {"printerManufacturer", IDS_SETTINGS_PRINTING_CUPS_PRINTER_MANUFACTURER},
- {"selectDriver", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SELECT_DRIVER},
- {"selectDriverButtonText",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_BUTTON_SELECT_DRIVER},
- {"selectDriverButtonAriaLabel",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_BUTTON_SELECT_DRIVER_ARIA_LABEL},
- {"selectDriverErrorMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_INVALID_DRIVER},
- {"printerAddedSuccessfulMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_DONE_MESSAGE},
- {"printerEditedSuccessfulMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_EDITED_PRINTER_DONE_MESSAGE},
- {"printerUnavailableMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_UNAVAILABLE_MESSAGE},
- {"noPrinterNearbyMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_NO_PRINTER_NEARBY},
- {"searchingNearbyPrinters",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_SEARCHING_NEARBY_PRINTER},
- {"printerAddedFailedMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_ERROR_MESSAGE},
- {"printerAddedFatalErrorMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_FATAL_ERROR_MESSAGE},
- {"printerAddedUnreachableMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_PRINTER_UNREACHABLE_MESSAGE},
- {"printerAddedPpdTooLargeMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_PPD_TOO_LARGE_MESSAGE},
- {"printerAddedInvalidPpdMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_INVALID_PPD_MESSAGE},
- {"printerAddedPpdNotFoundMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_PPD_NOT_FOUND},
- {"printerAddedPpdUnretrievableMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_PRINTER_PPD_UNRETRIEVABLE},
- {"printerAddedNativePrintersNotAllowedMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADDED_NATIVE_PRINTERS_NOT_ALLOWED_MESSAGE},
- {"editPrinterInvalidPrinterUpdate",
- IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_INVALID_PRINTER_UPDATE},
- {"requireNetworkMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_REQUIRE_INTERNET_MESSAGE},
- {"checkNetworkMessage",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_CHECK_CONNECTION_MESSAGE},
- {"noInternetConnection",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_NO_INTERNET_CONNECTION},
- {"checkNetworkAndTryAgain",
- IDS_SETTINGS_PRINTING_CUPS_PRINTER_CONNECT_TO_NETWORK_SUBTEXT},
- {"editPrinterDialogTitle",
- IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_DIALOG_TITLE},
- {"editPrinterButtonText", IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_BUTTON},
- {"currentPpdMessage",
- IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_CURRENT_PPD_MESSAGE},
- {"printerEulaNotice", IDS_SETTINGS_PRINTING_CUPS_EULA_NOTICE},
- {"ippPrinterUnreachable", IDS_SETTINGS_PRINTING_CUPS_IPP_URI_UNREACHABLE},
- {"generalPrinterDialogError",
- IDS_SETTINGS_PRINTING_CUPS_DIALOG_GENERAL_ERROR},
-#else
+#if !defined(OS_CHROMEOS)
{"localPrintersTitle", IDS_SETTINGS_PRINTING_LOCAL_PRINTERS_TITLE},
#endif
};
@@ -2521,18 +1096,6 @@ void AddPrintingStrings(content::WebUIDataSource* html_source) {
html_source->AddString("devicesUrl", chrome::kChromeUIDevicesURL);
html_source->AddString("printingCloudPrintLearnMoreUrl",
chrome::kCloudPrintLearnMoreURL);
-
-#if defined(OS_CHROMEOS)
- html_source->AddString("printingCUPSPrintLearnMoreUrl",
- GetHelpUrlWithBoard(chrome::kCupsPrintLearnMoreURL));
- html_source->AddString(
- "printingCUPSPrintPpdLearnMoreUrl",
- GetHelpUrlWithBoard(chrome::kCupsPrintPPDLearnMoreURL));
-
- html_source->AddBoolean(
- "updatedCupsPrintersUiEnabled",
- base::FeatureList::IsEnabled(features::kCupsPrintersUiOverhaul));
-#endif
}
void AddPrivacyStrings(content::WebUIDataSource* html_source,
@@ -2540,16 +1103,46 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source,
static constexpr webui::LocalizedString kLocalizedStrings[] = {
{"privacyPageTitle", IDS_SETTINGS_PRIVACY},
{"privacyPageMore", IDS_SETTINGS_PRIVACY_MORE},
- {"signinAllowedTitle", IDS_SETTINGS_SIGNIN_ALLOWED},
- {"signinAllowedDescription", IDS_SETTINGS_SIGNIN_ALLOWED_DESC},
{"doNotTrack", IDS_SETTINGS_ENABLE_DO_NOT_TRACK},
{"doNotTrackDialogTitle", IDS_SETTINGS_ENABLE_DO_NOT_TRACK_DIALOG_TITLE},
- {"enableContentProtectionAttestation",
- IDS_SETTINGS_ENABLE_CONTENT_PROTECTION_ATTESTATION},
- {"wakeOnWifi", IDS_SETTINGS_WAKE_ON_WIFI_DESCRIPTION},
+ // TODO(crbug.com/1062607): This string is no longer used. Remove.
+ {"permissionsPageTitle", IDS_SETTINGS_PERMISSIONS},
+ {"permissionsPageDescription", IDS_SETTINGS_PERMISSIONS_DESCRIPTION},
+ {"securityPageTitle", IDS_SETTINGS_SECURITY},
+ {"securityPageDescription", IDS_SETTINGS_SECURITY_DESCRIPTION},
+ {"securityPageAdvancedSectionLabel",
+ IDS_SETTINGS_SECURITY_ADVANCED_SECTION_LABEL},
+ {"advancedProtectionProgramTitle",
+ IDS_SETTINGS_ADVANCED_PROTECTION_PROGRAM},
+ {"advancedProtectionProgramDesc",
+ IDS_SETTINGS_ADVANCED_PROTECTION_PROGRAM_DESC},
{"manageCertificates", IDS_SETTINGS_MANAGE_CERTIFICATES},
{"manageCertificatesDescription",
IDS_SETTINGS_MANAGE_CERTIFICATES_DESCRIPTION},
+ {"secureDns", IDS_SETTINGS_SECURE_DNS},
+ {"secureDnsDescription", IDS_SETTINGS_SECURE_DNS_DESCRIPTION},
+ {"secureDnsDisabledForManagedEnvironment",
+ IDS_SETTINGS_SECURE_DNS_DISABLED_FOR_MANAGED_ENVIRONMENT},
+ {"secureDnsDisabledForParentalControl",
+ IDS_SETTINGS_SECURE_DNS_DISABLED_FOR_PARENTAL_CONTROL},
+ {"secureDnsAutomaticModeDescription",
+ IDS_SETTINGS_AUTOMATIC_MODE_DESCRIPTION},
+ {"secureDnsAutomaticModeDescriptionSecondary",
+ IDS_SETTINGS_AUTOMATIC_MODE_DESCRIPTION_SECONDARY},
+ {"secureDnsSecureModeA11yLabel",
+ IDS_SETTINGS_SECURE_MODE_DESCRIPTION_ACCESSIBILITY_LABEL},
+ {"secureDnsDropdownA11yLabel",
+ IDS_SETTINGS_SECURE_DNS_DROPDOWN_ACCESSIBILITY_LABEL},
+ {"secureDnsSecureDropdownModeDescription",
+ IDS_SETTINGS_SECURE_DROPDOWN_MODE_DESCRIPTION},
+ {"secureDnsSecureDropdownModePrivacyPolicy",
+ IDS_SETTINGS_SECURE_DROPDOWN_MODE_PRIVACY_POLICY},
+ {"secureDnsCustomPlaceholder",
+ IDS_SETTINGS_SECURE_DNS_CUSTOM_PLACEHOLDER},
+ {"secureDnsCustomFormatError",
+ IDS_SETTINGS_SECURE_DNS_CUSTOM_FORMAT_ERROR},
+ {"secureDnsCustomConnectionError",
+ IDS_SETTINGS_SECURE_DNS_CUSTOM_CONNECTION_ERROR},
{"contentSettings", IDS_SETTINGS_CONTENT_SETTINGS},
{"siteSettings", IDS_SETTINGS_SITE_SETTINGS},
{"siteSettingsDescription", IDS_SETTINGS_SITE_SETTINGS_DESCRIPTION},
@@ -2561,37 +1154,125 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source,
IDS_SETTINGS_SAFEBROWSING_ENABLE_REPORTING},
{"safeBrowsingEnableExtendedReportingDesc",
IDS_SETTINGS_SAFEBROWSING_ENABLE_REPORTING_DESC},
+ {"safeBrowsingEnhanced", IDS_SETTINGS_SAFEBROWSING_ENHANCED},
+ {"safeBrowsingEnhancedDesc", IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC},
+ {"safeBrowsingEnhancedBulOne",
+ IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_ONE},
+ {"safeBrowsingEnhancedBulTwo",
+ IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_TWO},
+ {"safeBrowsingEnhancedBulThree",
+ IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_THREE},
+ {"safeBrowsingEnhancedBulFour",
+ IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_FOUR},
+ {"safeBrowsingEnhancedBulFive",
+ IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_FIVE},
+ {"safeBrowsingStandard", IDS_SETTINGS_SAFEBROWSING_STANDARD},
+ {"safeBrowsingStandardDesc", IDS_SETTINGS_SAFEBROWSING_STANDARD_DESC},
+ {"safeBrowsingStandardBulOne",
+ IDS_SETTINGS_SAFEBROWSING_STANDARD_BULLET_ONE},
+ {"safeBrowsingStandardBulTwo",
+ IDS_SETTINGS_SAFEBROWSING_STANDARD_BULLET_TWO},
+ {"safeBrowsingStandardReportingLabel",
+ IDS_SETTINGS_SAFEBROWSING_STANDARD_HELP_IMPROVE},
+ {"safeBrowsingNone", IDS_SETTINGS_SAFEBROWSING_NONE},
+ {"safeBrowsingNoneDesc", IDS_SETTINGS_SAFEBROWSING_NONE_DESC},
+ {"safeBrowsingDisableDialog",
+ IDS_SETTINGS_SAFEBROWSING_DISABLE_DIALOG_TITLE},
+ {"safeBrowsingDisableDialogDesc",
+ IDS_SETTINGS_SAFEBROWSING_DISABLE_DIALOG_DESC},
+ {"safeBrowsingDisableDialogConfrim",
+ IDS_SETTINGS_SAFEBROWSING_DISABLE_DIALOG_CONFIRM},
{"safeBrowsingEnableProtection",
IDS_SETTINGS_SAFEBROWSING_ENABLEPROTECTION},
{"safeBrowsingEnableProtectionDesc",
IDS_SETTINGS_SAFEBROWSING_ENABLEPROTECTION_DESC},
+ {"safeBrowsingSectionLabel", IDS_SETTINGS_SAFEBROWSING_SECTION_LABEL},
{"syncAndGoogleServicesPrivacyDescription",
IDS_SETTINGS_SYNC_AND_GOOGLE_SERVICES_PRIVACY_DESC_UNIFIED_CONSENT},
{"urlKeyedAnonymizedDataCollection",
IDS_SETTINGS_ENABLE_URL_KEYED_ANONYMIZED_DATA_COLLECTION},
{"urlKeyedAnonymizedDataCollectionDesc",
IDS_SETTINGS_ENABLE_URL_KEYED_ANONYMIZED_DATA_COLLECTION_DESC},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-
- static constexpr webui::LocalizedString kConditionalLocalizedStrings[] = {
- {"searchSuggestPref", IDS_SETTINGS_SUGGEST_PREF},
- {"searchSuggestPrefDesc", IDS_SETTINGS_SUGGEST_PREF_DESC},
+ {"noRecentPermissions", IDS_SETTINGS_RECENT_PERMISSIONS_NO_CHANGES},
+ {"recentPermissionChangeAutoblockedSentenceStart",
+ IDS_SETTINGS_RECENT_PERMISSIONS_CHANGE_AUTOBLOCKED_SENTENCE_START},
+ {"recentPermissionChangeBlockedSentenceStart",
+ IDS_SETTINGS_RECENT_PERMISSIONS_CHANGE_BLOCKED_SENTENCE_START},
+ {"recentPermissionChangeAllowedSentenceStart",
+ IDS_SETTINGS_RECENT_PERMISSIONS_CHANGE_ALLOWED_SENTENCE_START},
+ {"recentPermissionChangeAutoblocked",
+ IDS_SETTINGS_RECENT_PERMISSIONS_CHANGE_AUTOBLOCKED},
+ {"recentPermissionChangeBlocked",
+ IDS_SETTINGS_RECENT_PERMISSIONS_CHANGE_BLOCKED},
+ {"recentPermissionChangeAllowed",
+ IDS_SETTINGS_RECENT_PERMISSIONS_CHANGE_ALLOWED},
+ {"recentPermissionsTwoItems", IDS_SETTINGS_RECENT_PERMISSIONS_TWO_ITEMS},
+ {"recentPermissionsThreeItems",
+ IDS_SETTINGS_RECENT_PERMISSIONS_THREE_ITEMS},
+ {"recentPermissionsOverThreeItems",
+ IDS_SETTINGS_RECENT_PERMISSIONS_OVER_THREE_ITEMS},
+ {"recentPermissionsOneItemIncognito",
+ IDS_SETTINGS_RECENT_PERMISSIONS_ONE_ITEM_INCOGNITO},
+ {"recentPermissionsTwoItemsIncognito",
+ IDS_SETTINGS_RECENT_PERMISSIONS_TWO_ITEMS_INCOGNITO},
+ {"recentPermissionsThreeItemsIncognito",
+ IDS_SETTINGS_RECENT_PERMISSIONS_THREE_ITEMS_INCOGNITO},
+ {"recentPermissionsOverThreeItemsIncognito",
+ IDS_SETTINGS_RECENT_PERMISSIONS_OVER_THREE_ITEMS_INCOGNITO},
{"networkPredictionEnabled",
IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_LABEL},
{"networkPredictionEnabledDesc",
IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_DESC},
- {"linkDoctorPref", IDS_SETTINGS_LINKDOCTOR_PREF},
- {"linkDoctorPrefDesc", IDS_SETTINGS_LINKDOCTOR_PREF_DESC},
- {"spellingPref", IDS_SETTINGS_SPELLING_PREF},
- {"spellingDescription", IDS_SETTINGS_SPELLING_PREF_DESC},
- {"enableLogging", IDS_SETTINGS_ENABLE_LOGGING_PREF},
- {"enableLoggingDesc", IDS_SETTINGS_ENABLE_LOGGING_PREF_DESC},
+ {"networkPredictionEnabledDescCookiesPage",
+ IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_DESC_COOKIES_PAGE},
+ {"safetyCheckSectionTitle", IDS_SETTINGS_SAFETY_CHECK_SECTION_TITLE},
+ {"safetyCheckParentPrimaryLabelBefore",
+ IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_BEFORE},
+ {"safetyCheckRunning", IDS_SETTINGS_SAFETY_CHECK_RUNNING},
+ {"safetyCheckParentPrimaryLabelAfter",
+ IDS_SETTINGS_SAFETY_CHECK_PARENT_PRIMARY_LABEL_AFTER},
+ {"safetyCheckAriaLiveRunning",
+ IDS_SETTINGS_SAFETY_CHECK_ARIA_LIVE_RUNNING},
+ {"safetyCheckAriaLiveAfter", IDS_SETTINGS_SAFETY_CHECK_ARIA_LIVE_AFTER},
+ {"safetyCheckParentButton", IDS_SETTINGS_SAFETY_CHECK_PARENT_BUTTON},
+ {"safetyCheckParentButtonAriaLabel",
+ IDS_SETTINGS_SAFETY_CHECK_PARENT_BUTTON_ARIA_LABEL},
+ {"safetyCheckIconRunningAriaLabel",
+ IDS_SETTINGS_SAFETY_CHECK_ICON_RUNNING_ARIA_LABEL},
+ {"safetyCheckIconSafeAriaLabel",
+ IDS_SETTINGS_SAFETY_CHECK_ICON_SAFE_ARIA_LABEL},
+ {"safetyCheckIconInfoAriaLabel",
+ IDS_SETTINGS_SAFETY_CHECK_ICON_INFO_ARIA_LABEL},
+ {"safetyCheckIconWarningAriaLabel",
+ IDS_SETTINGS_SAFETY_CHECK_ICON_WARNING_ARIA_LABEL},
+ {"safetyCheckUpdatesPrimaryLabel",
+ IDS_SETTINGS_SAFETY_CHECK_UPDATES_PRIMARY_LABEL},
+ {"safetyCheckUpdatesButtonAriaLabel",
+ IDS_UPDATE_RECOMMENDED_DIALOG_TITLE},
+ {"safetyCheckPasswordsButton",
+ IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_BUTTON},
+ {"safetyCheckSafeBrowsingButton",
+ IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_BUTTON},
+ {"safetyCheckSafeBrowsingButtonAriaLabel",
+ IDS_SETTINGS_SAFETY_CHECK_SAFE_BROWSING_BUTTON_ARIA_LABEL},
+ {"safetyCheckExtensionsPrimaryLabel",
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_PRIMARY_LABEL},
+ {"safetyCheckExtensionsButton",
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BUTTON},
+ {"safetyCheckExtensionsButtonAriaLabel",
+ IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BUTTON_ARIA_LABEL},
};
- AddLocalizedStringsBulk(html_source, kConditionalLocalizedStrings);
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ html_source->AddString("cookiesSettingsHelpCenterURL",
+ chrome::kCookiesSettingsHelpCenterURL);
+
+ html_source->AddString("safeBrowsingHelpCenterURL",
+ chrome::kSafeBrowsingHelpCenterURL);
html_source->AddString("syncAndGoogleServicesLearnMoreURL",
chrome::kSyncAndGoogleServicesLearnMoreURL);
+
html_source->AddString(
"doNotTrackDialogMessage",
l10n_util::GetStringFUTF16(
@@ -2604,6 +1285,29 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source,
html_source->AddString(
"exceptionsLearnMoreURL",
base::ASCIIToUTF16(chrome::kContentSettingsExceptionsLearnMoreURL));
+ html_source->AddBoolean(
+ "installedAppsInCbd",
+ base::FeatureList::IsEnabled(features::kStoragePressureUI));
+ html_source->AddBoolean(
+ "driveSuggestAvailable",
+ base::FeatureList::IsEnabled(omnibox::kDocumentProvider));
+ html_source->AddBoolean("showSecureDnsSetting",
+ features::kDnsOverHttpsShowUiParam.Get());
+
+ // The link to the Advanced Protection Program landing page, with a referrer
+ // from Chrome settings.
+ GURL advanced_protection_url(
+ "https://landing.google.com/advancedprotection/");
+ advanced_protection_url = net::AppendQueryParameter(advanced_protection_url,
+ "utm_source", "Chrome");
+ advanced_protection_url = net::AppendQueryParameter(
+ advanced_protection_url, "utm_medium", "ChromeSecuritySettings");
+ advanced_protection_url = net::AppendQueryParameter(
+ advanced_protection_url, "utm_campaign", "ChromeSettings");
+ html_source->AddString("advancedProtectionURL",
+ advanced_protection_url.spec());
+
+ AddPersonalizationOptionsStrings(html_source);
}
void AddSearchInSettingsStrings(content::WebUIDataSource* html_source) {
@@ -2623,52 +1327,18 @@ void AddSearchInSettingsStrings(content::WebUIDataSource* html_source) {
html_source->AddString("searchNoResultsHelp", help_text);
}
-void AddSearchStrings(content::WebUIDataSource* html_source, Profile* profile) {
-#if defined(OS_CHROMEOS)
- // NOTE: This will be false when the flag is disabled.
- const bool is_assistant_allowed =
- assistant::IsAssistantAllowedForProfile(profile) ==
- ash::mojom::AssistantAllowedState::ALLOWED;
- // SplitSettings moves Assistant to the OS settings window.
- const bool assistant_in_browser_settings =
- is_assistant_allowed && !chromeos::features::IsSplitSettingsEnabled();
-#endif
-
+void AddSearchStrings(content::WebUIDataSource* html_source) {
static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"searchEnginesManage", IDS_SETTINGS_SEARCH_MANAGE_SEARCH_ENGINES},
-#if defined(OS_CHROMEOS)
- {"osSearchEngineLabel", IDS_OS_SETTINGS_SEARCH_ENGINE_LABEL},
- {"searchGoogleAssistant", IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT},
- {"searchGoogleAssistantEnabled",
- IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_ENABLED},
- {"searchGoogleAssistantDisabled",
- IDS_SETTINGS_SEARCH_GOOGLE_ASSISTANT_DISABLED},
-#endif
+ {"searchEnginesManage", IDS_SETTINGS_SEARCH_MANAGE_SEARCH_ENGINES},
+ {"searchPageTitle", IDS_SETTINGS_SEARCH},
+
};
AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-#if defined(OS_CHROMEOS)
- html_source->AddLocalizedString("searchPageTitle",
- assistant_in_browser_settings
- ? IDS_SETTINGS_SEARCH_AND_ASSISTANT
- : IDS_SETTINGS_SEARCH);
- html_source->AddLocalizedString("osSearchPageTitle",
- is_assistant_allowed
- ? IDS_SETTINGS_SEARCH_AND_ASSISTANT
- : IDS_SETTINGS_SEARCH);
-#else
- html_source->AddLocalizedString("searchPageTitle", IDS_SETTINGS_SEARCH);
-#endif
- base::string16 search_explanation_text = l10n_util::GetStringFUTF16(
- IDS_SETTINGS_SEARCH_EXPLANATION,
- base::ASCIIToUTF16(chrome::kOmniboxLearnMoreURL));
- html_source->AddString("searchExplanation", search_explanation_text);
-#if defined(OS_CHROMEOS)
- html_source->AddString(
- "osSearchEngineTooltip",
- ui::SubstituteChromeOSDeviceType(IDS_OS_SETTINGS_SEARCH_ENGINE_TOOLTIP));
- html_source->AddBoolean("isAssistantAllowed", is_assistant_allowed);
-#endif
+ html_source->AddString("searchExplanation",
+ l10n_util::GetStringFUTF16(
+ IDS_SETTINGS_SEARCH_EXPLANATION,
+ base::ASCIIToUTF16(chrome::kOmniboxLearnMoreURL)));
}
void AddSearchEnginesStrings(content::WebUIDataSource* html_source) {
@@ -2699,52 +1369,6 @@ void AddSearchEnginesStrings(content::WebUIDataSource* html_source) {
AddLocalizedStringsBulk(html_source, kLocalizedStrings);
}
-#if defined(OS_CHROMEOS)
-void AddGoogleAssistantStrings(content::WebUIDataSource* html_source,
- Profile* profile) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"googleAssistantPageTitle", IDS_SETTINGS_GOOGLE_ASSISTANT},
- {"googleAssistantEnableContext", IDS_ASSISTANT_SCREEN_CONTEXT_TITLE},
- {"googleAssistantEnableContextDescription",
- IDS_ASSISTANT_SCREEN_CONTEXT_DESC},
- {"googleAssistantEnableHotword",
- IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD},
- {"googleAssistantEnableHotwordDescription",
- IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_DESCRIPTION},
- {"googleAssistantVoiceSettings",
- IDS_SETTINGS_GOOGLE_ASSISTANT_VOICE_SETTINGS},
- {"googleAssistantVoiceSettingsDescription",
- IDS_ASSISTANT_VOICE_MATCH_RECORDING},
- {"googleAssistantVoiceSettingsRetrainButton",
- IDS_SETTINGS_GOOGLE_ASSISTANT_VOICE_SETTINGS_RETRAIN},
- {"googleAssistantEnableHotwordWithoutDspDescription",
- IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_WITHOUT_DSP_DESCRIPTION},
- {"googleAssistantEnableHotwordWithoutDspRecommended",
- IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_WITHOUT_DSP_RECOMMENDED},
- {"googleAssistantEnableHotwordWithoutDspAlwaysOn",
- IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_WITHOUT_DSP_ALWAYS_ON},
- {"googleAssistantEnableHotwordWithoutDspOff",
- IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_WITHOUT_DSP_OFF},
- {"googleAssistantEnableNotification",
- IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION},
- {"googleAssistantEnableNotificationDescription",
- IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION_DESCRIPTION},
- {"googleAssistantLaunchWithMicOpen",
- IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN},
- {"googleAssistantLaunchWithMicOpenDescription",
- IDS_SETTINGS_GOOGLE_ASSISTANT_LAUNCH_WITH_MIC_OPEN_DESCRIPTION},
- {"googleAssistantSettings", IDS_SETTINGS_GOOGLE_ASSISTANT_SETTINGS},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-
- html_source->AddBoolean("hotwordDspAvailable",
- chromeos::IsHotwordDspAvailable());
- html_source->AddBoolean(
- "voiceMatchDisabled",
- chromeos::assistant::features::IsVoiceMatchDisabled());
-}
-#endif
-
void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
Profile* profile) {
static constexpr webui::LocalizedString kLocalizedStrings[] = {
@@ -2800,6 +1424,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
{"mediaLicenseSize", IDS_SETTINGS_COOKIES_LOCAL_STORAGE_SIZE_ON_DISK_LABEL},
{"mediaLicenseLastModified",
IDS_SETTINGS_COOKIES_LOCAL_STORAGE_LAST_MODIFIED_LABEL},
+ {"noBluetoothDevicesFound", IDS_SETTINGS_NO_BLUETOOTH_DEVICES_FOUND},
+ {"noHidDevicesFound", IDS_SETTINGS_NO_HID_DEVICES_FOUND},
{"noSerialPortsFound", IDS_SETTINGS_NO_SERIAL_PORTS_FOUND},
{"noUsbDevicesFound", IDS_SETTINGS_NO_USB_DEVICES_FOUND},
{"serviceWorkerOrigin", IDS_SETTINGS_COOKIES_LOCAL_STORAGE_ORIGIN_LABEL},
@@ -2808,8 +1434,37 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
{"sharedWorkerWorker", IDS_SETTINGS_COOKIES_SHARED_WORKER_WORKER_LABEL},
{"sharedWorkerName", IDS_SETTINGS_COOKIES_COOKIE_NAME_LABEL},
{"siteSettingsCategoryPageTitle", IDS_SETTINGS_SITE_SETTINGS_CATEGORY},
+ {"siteSettingsRecentPermissionsSectionLabel",
+ IDS_SETTINGS_SITE_SETTINGS_RECENT_ACTIVITY},
{"siteSettingsCategoryCamera", IDS_SETTINGS_SITE_SETTINGS_CAMERA},
{"siteSettingsCameraLabel", IDS_SETTINGS_SITE_SETTINGS_CAMERA_LABEL},
+ {"cookiePageTitle", IDS_SETTINGS_COOKIES_PAGE},
+ {"cookiePageGeneralControls", IDS_SETTINGS_COOKIES_CONTROLS},
+ {"cookiePageAllowAll", IDS_SETTINGS_COOKIES_ALLOW_ALL},
+ {"cookiePageAllowAllBulOne", IDS_SETTINGS_COOKIES_ALLOW_ALL_BULLET_ONE},
+ {"cookiePageAllowAllBulTwo", IDS_SETTINGS_COOKIES_ALLOW_ALL_BULLET_TWO},
+ {"cookiePageBlockThirdIncognito",
+ IDS_SETTINGS_COOKIES_BLOCK_THIRD_PARTY_INCOGNITO},
+ {"cookiePageBlockThirdIncognitoBulOne",
+ IDS_SETTINGS_COOKIES_BLOCK_THIRD_PARTY_INCOGNITO_BULLET_ONE},
+ {"cookiePageBlockThirdIncognitoBulTwo",
+ IDS_SETTINGS_COOKIES_BLOCK_THIRD_PARTY_INCOGNITO_BULLET_TWO},
+ {"cookiePageBlockThird", IDS_SETTINGS_COOKIES_BLOCK_THIRD_PARTY},
+ {"cookiePageBlockThirdBulOne",
+ IDS_SETTINGS_COOKIES_BLOCK_THIRD_PARTY_BULLET_ONE},
+ {"cookiePageBlockThirdBulTwo",
+ IDS_SETTINGS_COOKIES_BLOCK_THIRD_PARTY_BULLET_TWO},
+ {"cookiePageBlockAll", IDS_SETTINGS_COOKIES_BLOCK_ALL},
+ {"cookiePageBlockAllBulOne", IDS_SETTINGS_COOKIES_BLOCK_ALL_BULLET_ONE},
+ {"cookiePageBlockAllBulTwo", IDS_SETTINGS_COOKIES_BLOCK_ALL_BULLET_TWO},
+ {"cookiePageBlockAllBulThree", IDS_SETTINGS_COOKIES_BLOCK_ALL_BULLET_THREE},
+ {"cookiePageClearOnExit", IDS_SETTINGS_COOKIES_CLEAR_ON_EXIT},
+ {"cookiePageAllowExceptions", IDS_SETTINGS_COOKIES_ALLOW_EXCEPTIONS},
+ {"cookiePageBlockExceptions", IDS_SETTINGS_COOKIES_BLOCK_EXCEPTIONS},
+ {"cookiePageSessionOnlyExceptions",
+ IDS_SETTINGS_COOKIES_SESSION_ONLY_EXCEPTIONS},
+ {"cookiesManageSiteSpecificExceptions",
+ IDS_SETTINGS_COOKIES_SITE_SPECIFIC_EXCEPTIONS},
{"siteSettingsCategoryCookies", IDS_SETTINGS_SITE_SETTINGS_COOKIES},
{"siteSettingsCategoryHandlers", IDS_SETTINGS_SITE_SETTINGS_HANDLERS},
{"siteSettingsCategoryImages", IDS_SETTINGS_SITE_SETTINGS_IMAGES},
@@ -2892,6 +1547,12 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
{"siteSettingsPopups", IDS_SETTINGS_SITE_SETTINGS_POPUPS},
{"siteSettingsUnsandboxedPlugins",
IDS_SETTINGS_SITE_SETTINGS_UNSANDBOXED_PLUGINS},
+ {"siteSettingsHidDevices", IDS_SETTINGS_SITE_SETTINGS_HID_DEVICES},
+ {"siteSettingsHidDevicesAsk", IDS_SETTINGS_SITE_SETTINGS_HID_DEVICES_ASK},
+ {"siteSettingsHidDevicesAskRecommended",
+ IDS_SETTINGS_SITE_SETTINGS_HID_DEVICES_ASK_RECOMMENDED},
+ {"siteSettingsHidDevicesBlock",
+ IDS_SETTINGS_SITE_SETTINGS_HID_DEVICES_BLOCK},
{"siteSettingsMidiDevices", IDS_SETTINGS_SITE_SETTINGS_MIDI_DEVICES},
{"siteSettingsMidiDevicesAsk", IDS_SETTINGS_SITE_SETTINGS_MIDI_DEVICES_ASK},
{"siteSettingsMidiDevicesAskRecommended",
@@ -2910,6 +1571,14 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
IDS_SETTINGS_SITE_SETTINGS_USB_DEVICES_ASK_RECOMMENDED},
{"siteSettingsUsbDevicesBlock",
IDS_SETTINGS_SITE_SETTINGS_USB_DEVICES_BLOCK},
+ {"siteSettingsBluetoothDevices",
+ IDS_SETTINGS_SITE_SETTINGS_BLUETOOTH_DEVICES},
+ {"siteSettingsBluetoothDevicesAsk",
+ IDS_SETTINGS_SITE_SETTINGS_BLUETOOTH_DEVICES_ASK},
+ {"siteSettingsBluetoothDevicesAskRecommended",
+ IDS_SETTINGS_SITE_SETTINGS_BLUETOOTH_DEVICES_ASK_RECOMMENDED},
+ {"siteSettingsBluetoothDevicesBlock",
+ IDS_SETTINGS_SITE_SETTINGS_BLUETOOTH_DEVICES_BLOCK},
{"siteSettingsNativeFileSystemWrite",
IDS_SETTINGS_SITE_SETTINGS_NATIVE_FILE_SYSTEM_WRITE},
{"siteSettingsNativeFileSystemWriteAsk",
@@ -2996,6 +1665,10 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
{"siteSettingsUsage", IDS_SETTINGS_SITE_SETTINGS_USAGE},
{"siteSettingsUsageNone", IDS_SETTINGS_SITE_SETTINGS_USAGE_NONE},
{"siteSettingsPermissions", IDS_SETTINGS_SITE_SETTINGS_PERMISSIONS},
+ {"siteSettingsPermissionsMore",
+ IDS_SETTINGS_SITE_SETTINGS_PERMISSIONS_MORE},
+ {"siteSettingsContent", IDS_SETTINGS_SITE_SETTINGS_CONTENT},
+ {"siteSettingsContentMore", IDS_SETTINGS_SITE_SETTINGS_CONTENT_MORE},
{"siteSettingsSourceExtensionAllow",
IDS_PAGE_INFO_PERMISSION_ALLOWED_BY_EXTENSION},
{"siteSettingsSourceExtensionBlock",
@@ -3048,6 +1721,24 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
{"siteSettingsCookieSearch", IDS_SETTINGS_SITE_SETTINGS_COOKIE_SEARCH},
{"siteSettingsCookieSubpage", IDS_SETTINGS_SITE_SETTINGS_COOKIE_SUBPAGE},
{"siteSettingsDelete", IDS_SETTINGS_SITE_SETTINGS_DELETE},
+ {"siteSettingsClearAllStorageDialogTitle",
+ IDS_SETTINGS_SITE_SETTINGS_CLEAR_ALL_STORAGE_DIALOG_TITLE},
+ {"siteSettingsClearAllStorageDescription",
+ IDS_SETTINGS_SITE_SETTINGS_CLEAR_ALL_STORAGE_DESCRIPTION},
+ {"siteSettingsClearAllStorageLabel",
+ IDS_SETTINGS_SITE_SETTINGS_CLEAR_ALL_STORAGE_LABEL},
+ {"siteSettingsClearAllStorageConfirmation",
+ IDS_SETTINGS_SITE_SETTINGS_CLEAR_ALL_STORAGE_CONFIRMATION},
+ {"siteSettingsClearAllStorageConfirmationInstalled",
+ IDS_SETTINGS_SITE_SETTINGS_CLEAR_ALL_STORAGE_CONFIRMATION_INSTALLED},
+ {"siteSettingsClearAllStorageSignOut",
+ IDS_SETTINGS_SITE_SETTINGS_CLEAR_ALL_STORAGE_SIGN_OUT},
+ {"siteSettingsOriginDeleteConfirmation",
+ IDS_SETTINGS_SITE_SETTINGS_ORIGIN_DELETE_CONFIRMATION},
+ {"siteSettingsOriginDeleteConfirmationInstalled",
+ IDS_SETTINGS_SITE_SETTINGS_ORIGIN_DELETE_CONFIRMATION_INSTALLED},
+ {"siteSettingsSiteGroupDeleteConfirmationInstalledPlural",
+ IDS_SETTINGS_SITE_SETTINGS_SITE_GROUP_DELETE_CONFIRMATION_INSTALLED_PLURAL},
{"siteSettingsSiteClearStorage",
IDS_SETTINGS_SITE_SETTINGS_SITE_CLEAR_STORAGE},
{"siteSettingsSiteClearStorageConfirmation",
@@ -3069,6 +1760,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
IDS_SETTINGS_SITE_SETTINGS_SITE_GROUP_DELETE_CONFIRMATION},
{"siteSettingsSiteGroupDeleteConfirmationNew",
IDS_SETTINGS_SITE_SETTINGS_SITE_GROUP_DELETE_CONFIRMATION_NEW},
+ {"siteSettingsSiteGroupDeleteConfirmationInstalled",
+ IDS_SETTINGS_SITE_SETTINGS_SITE_GROUP_DELETE_CONFIRMATION_INSTALLED},
{"siteSettingsSiteGroupDeleteSignOut",
IDS_SETTINGS_SITE_SETTINGS_SITE_GROUP_DELETE_SIGN_OUT},
{"siteSettingsSiteGroupDeleteOfflineData",
@@ -3083,18 +1776,17 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
{"siteSettingsSiteResetAll", IDS_SETTINGS_SITE_SETTINGS_SITE_RESET_ALL},
{"siteSettingsSiteResetConfirmation",
IDS_SETTINGS_SITE_SETTINGS_SITE_RESET_CONFIRMATION},
- {"thirdPartyCookie", IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE},
- {"thirdPartyCookieSublabel",
- IDS_SETTINGS_SITE_SETTINGS_THIRD_PARTY_COOKIE_SUBLABEL},
+ {"thirdPartyCookie", IDS_NEW_TAB_OTR_THIRD_PARTY_COOKIE},
+ {"thirdPartyCookieSublabel", IDS_NEW_TAB_OTR_THIRD_PARTY_COOKIE_SUBLABEL},
{"deleteDataPostSession",
IDS_SETTINGS_SITE_SETTINGS_DELETE_DATA_POST_SESSION},
{"handlerIsDefault", IDS_SETTINGS_SITE_SETTINGS_HANDLER_IS_DEFAULT},
{"handlerSetDefault", IDS_SETTINGS_SITE_SETTINGS_HANDLER_SET_DEFAULT},
{"handlerRemove", IDS_SETTINGS_SITE_SETTINGS_REMOVE},
{"adobeFlashStorage", IDS_SETTINGS_SITE_SETTINGS_ADOBE_FLASH_SETTINGS},
- {"incognitoSite", IDS_SETTINGS_SITE_SETTINGS_INCOGNITO},
{"incognitoSiteOnly", IDS_SETTINGS_SITE_SETTINGS_INCOGNITO_ONLY},
- {"embeddedIncognitoSite", IDS_SETTINGS_SITE_SETTINGS_INCOGNITO_EMBEDDED},
+ {"incognitoSiteExceptionDesc",
+ IDS_SETTINGS_SITE_SETTINGS_INCOGNITO_SITE_EXCEPTION_DESC},
{"noSitesAdded", IDS_SETTINGS_SITE_NO_SITES_ADDED},
{"siteSettingsAds", IDS_SETTINGS_SITE_SETTINGS_ADS},
{"siteSettingsAdsBlock", IDS_SETTINGS_SITE_SETTINGS_ADS_BLOCK},
@@ -3119,6 +1811,16 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
IDS_SETTINGS_SITE_SETTINGS_BLUETOOTH_SCANNING_ASK_RECOMMENDED},
{"siteSettingsBluetoothScanningBlock",
IDS_SETTINGS_SITE_SETTINGS_BLUETOOTH_SCANNING_BLOCK},
+ {"siteSettingsAr", IDS_SETTINGS_SITE_SETTINGS_AR},
+ {"siteSettingsArAsk", IDS_SETTINGS_SITE_SETTINGS_AR_ASK},
+ {"siteSettingsArAskRecommended",
+ IDS_SETTINGS_SITE_SETTINGS_AR_ASK_RECOMMENDED},
+ {"siteSettingsArBlock", IDS_SETTINGS_SITE_SETTINGS_AR_BLOCK},
+ {"siteSettingsVr", IDS_SETTINGS_SITE_SETTINGS_VR},
+ {"siteSettingsVrAsk", IDS_SETTINGS_SITE_SETTINGS_VR_ASK},
+ {"siteSettingsVrAskRecommended",
+ IDS_SETTINGS_SITE_SETTINGS_VR_ASK_RECOMMENDED},
+ {"siteSettingsVrBlock", IDS_SETTINGS_SITE_SETTINGS_VR_BLOCK},
};
AddLocalizedStringsBulk(html_source, kLocalizedStrings);
@@ -3187,25 +1889,15 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source,
html_source->AddBoolean(
"enableQuietNotificationPromptsSetting",
base::FeatureList::IsEnabled(features::kQuietNotificationPrompts));
-}
-#if defined(OS_CHROMEOS)
-void AddUsersStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"usersModifiedByOwnerLabel", IDS_SETTINGS_USERS_MODIFIED_BY_OWNER_LABEL},
- {"guestBrowsingLabel", IDS_SETTINGS_USERS_GUEST_BROWSING_LABEL},
- {"settingsManagedLabel", IDS_SETTINGS_USERS_MANAGED_LABEL},
- {"showOnSigninLabel", IDS_SETTINGS_USERS_SHOW_ON_SIGNIN_LABEL},
- {"restrictSigninLabel", IDS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL},
- {"deviceOwnerLabel", IDS_SETTINGS_USERS_DEVICE_OWNER_LABEL},
- {"removeUserTooltip", IDS_SETTINGS_USERS_REMOVE_USER_TOOLTIP},
- {"addUsers", IDS_SETTINGS_USERS_ADD_USERS},
- {"addUsersEmail", IDS_SETTINGS_USERS_ADD_USERS_EMAIL},
- {"userExistsError", IDS_SETTINGS_USER_EXISTS_ERROR},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+ html_source->AddBoolean("enableWebBluetoothNewPermissionsBackend",
+ base::FeatureList::IsEnabled(
+ features::kWebBluetoothNewPermissionsBackend));
+
+ html_source->AddBoolean(
+ "enableWebXrContentSetting",
+ base::FeatureList::IsEnabled(features::kWebXrPermissionsApi));
}
-#endif
#if !defined(OS_CHROMEOS)
void AddSystemStrings(content::WebUIDataSource* html_source) {
@@ -3237,110 +1929,6 @@ void AddSystemStrings(content::WebUIDataSource* html_source) {
}
#endif
-void AddWebContentStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"webContent", IDS_SETTINGS_WEB_CONTENT},
- {"pageZoom", IDS_SETTINGS_PAGE_ZOOM_LABEL},
- {"fontSize", IDS_SETTINGS_FONT_SIZE_LABEL},
- {"verySmall", IDS_SETTINGS_VERY_SMALL_FONT},
- {"small", IDS_SETTINGS_SMALL_FONT},
- {"medium", IDS_SETTINGS_MEDIUM_FONT},
- {"large", IDS_SETTINGS_LARGE_FONT},
- {"veryLarge", IDS_SETTINGS_VERY_LARGE_FONT},
- {"custom", IDS_SETTINGS_CUSTOM},
- {"customizeFonts", IDS_SETTINGS_CUSTOMIZE_FONTS},
- {"fonts", IDS_SETTINGS_FONTS},
- {"standardFont", IDS_SETTINGS_STANDARD_FONT_LABEL},
- {"serifFont", IDS_SETTINGS_SERIF_FONT_LABEL},
- {"sansSerifFont", IDS_SETTINGS_SANS_SERIF_FONT_LABEL},
- {"fixedWidthFont", IDS_SETTINGS_FIXED_WIDTH_FONT_LABEL},
- {"minimumFont", IDS_SETTINGS_MINIMUM_FONT_SIZE_LABEL},
- {"tiny", IDS_SETTINGS_TINY_FONT_SIZE},
- {"huge", IDS_SETTINGS_HUGE_FONT_SIZE},
- {"loremIpsum", IDS_SETTINGS_LOREM_IPSUM},
- {"loading", IDS_SETTINGS_LOADING},
- {"advancedFontSettings", IDS_SETTINGS_ADVANCED_FONT_SETTINGS},
- {"openAdvancedFontSettings", IDS_SETTINGS_OPEN_ADVANCED_FONT_SETTINGS},
- {"requiresWebStoreExtension", IDS_SETTINGS_REQUIRES_WEB_STORE_EXTENSION},
- {"quickBrownFox", IDS_SETTINGS_QUICK_BROWN_FOX},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-}
-
-#if defined(OS_CHROMEOS)
-void AddMultideviceStrings(content::WebUIDataSource* html_source) {
- static constexpr webui::LocalizedString kLocalizedStrings[] = {
- {"multidevicePageTitle", IDS_SETTINGS_MULTIDEVICE},
- {"multideviceSetupButton", IDS_SETTINGS_MULTIDEVICE_SETUP_BUTTON},
- {"multideviceVerifyButton", IDS_SETTINGS_MULTIDEVICE_VERIFY_BUTTON},
- {"multideviceSetupItemHeading",
- IDS_SETTINGS_MULTIDEVICE_SETUP_ITEM_HEADING},
- {"multideviceEnabled", IDS_SETTINGS_MULTIDEVICE_ENABLED},
- {"multideviceDisabled", IDS_SETTINGS_MULTIDEVICE_DISABLED},
- {"multideviceSmartLockItemTitle", IDS_SETTINGS_EASY_UNLOCK_SECTION_TITLE},
- {"multideviceInstantTetheringItemTitle",
- IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING},
- {"multideviceInstantTetheringItemSummary",
- IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING_SUMMARY},
- {"multideviceAndroidMessagesItemTitle",
- IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES},
- {"multideviceForgetDevice", IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE},
- {"multideviceSmartLockOptions",
- IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOCK},
- {"multideviceForgetDeviceDisconnect",
- IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_DISCONNECT},
- };
- AddLocalizedStringsBulk(html_source, kLocalizedStrings);
-
- html_source->AddString(
- "multideviceForgetDeviceSummary",
- ui::SubstituteChromeOSDeviceType(
- IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_EXPLANATION));
- html_source->AddString(
- "multideviceForgetDeviceDialogMessage",
- ui::SubstituteChromeOSDeviceType(
- IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_MESSAGE));
- html_source->AddString(
- "multideviceVerificationText",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_MULTIDEVICE_VERIFICATION_TEXT,
- base::UTF8ToUTF16(
- chromeos::multidevice_setup::
- GetBoardSpecificBetterTogetherSuiteLearnMoreUrl()
- .spec())));
- html_source->AddString(
- "multideviceSetupSummary",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_MULTIDEVICE_SETUP_SUMMARY, ui::GetChromeOSDeviceName(),
- base::UTF8ToUTF16(
- chromeos::multidevice_setup::
- GetBoardSpecificBetterTogetherSuiteLearnMoreUrl()
- .spec())));
- html_source->AddString(
- "multideviceNoHostText",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_MULTIDEVICE_NO_ELIGIBLE_HOSTS,
- base::UTF8ToUTF16(
- chromeos::multidevice_setup::
- GetBoardSpecificBetterTogetherSuiteLearnMoreUrl()
- .spec())));
- html_source->AddString(
- "multideviceAndroidMessagesItemSummary",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES_SUMMARY,
- ui::GetChromeOSDeviceName(),
- base::UTF8ToUTF16(chromeos::multidevice_setup::
- GetBoardSpecificMessagesLearnMoreUrl()
- .spec())));
- html_source->AddString(
- "multideviceSmartLockItemSummary",
- l10n_util::GetStringFUTF16(
- IDS_SETTINGS_MULTIDEVICE_SMART_LOCK_SUMMARY,
- ui::GetChromeOSDeviceName(),
- GetHelpUrlWithBoard(chrome::kEasyUnlockLearnMoreUrl)));
-}
-#endif
-
void AddExtensionsStrings(content::WebUIDataSource* html_source) {
html_source->AddLocalizedString("extensionsPageTitle",
IDS_SETTINGS_EXTENSIONS_CHECKBOX_LABEL);
@@ -3358,6 +1946,10 @@ void AddSecurityKeysStrings(content::WebUIDataSource* html_source) {
IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_COMPLETE_LABEL},
{"securityKeysBioEnrollmentEnrollingLabel",
IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_LABEL},
+ {"securityKeysBioEnrollmentEnrollingFailedLabel",
+ IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_FAILED_LABEL},
+ {"securityKeysBioEnrollmentTryAgainLabel",
+ IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_TRY_AGAIN_LABEL},
{"securityKeysBioEnrollmentEnrollmentsLabel",
IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLMENTS_LABEL},
{"securityKeysBioEnrollmentNoEnrollmentsLabel",
@@ -3453,11 +2045,11 @@ void AddSecurityKeysStrings(content::WebUIDataSource* html_source) {
} // namespace
-void AddLocalizedStrings(content::WebUIDataSource* html_source,
- Profile* profile,
- content::WebContents* web_contents) {
+void AddBrowserLocalizedStrings(content::WebUIDataSource* html_source,
+ Profile* profile,
+ content::WebContents* web_contents) {
AddA11yStrings(html_source);
- AddAboutStrings(html_source);
+ AddAboutStrings(html_source, profile);
AddAutofillStrings(html_source, profile, web_contents);
AddAppearanceStrings(html_source, profile);
@@ -3466,41 +2058,22 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source,
AddIncompatibleApplicationsStrings(html_source);
#endif // defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
- AddChangePasswordStrings(html_source);
AddClearBrowsingDataStrings(html_source, profile);
AddCommonStrings(html_source, profile);
AddDownloadsStrings(html_source);
- AddLanguagesStrings(html_source);
+ AddLanguagesStrings(html_source, profile);
AddOnStartupStrings(html_source);
AddPeopleStrings(html_source, profile);
AddPrintingStrings(html_source);
AddPrivacyStrings(html_source, profile);
AddResetStrings(html_source);
AddSearchEnginesStrings(html_source);
-#if defined(OS_CHROMEOS)
- AddGoogleAssistantStrings(html_source, profile);
-#endif
AddSearchInSettingsStrings(html_source);
- AddSearchStrings(html_source, profile);
+ AddSearchStrings(html_source);
AddSiteSettingsStrings(html_source, profile);
- AddWebContentStrings(html_source);
#if defined(OS_CHROMEOS)
- AddAndroidAppStrings(html_source);
- AddAppManagementStrings(html_source);
- AddAppsStrings(html_source);
- AddBluetoothStrings(html_source);
AddChromeOSUserStrings(html_source, profile);
- AddCrostiniStrings(html_source, profile);
- AddDateTimeStrings(html_source);
- AddDeviceStrings(html_source);
- AddEasyUnlockStrings(html_source);
- AddFilesStrings(html_source);
- AddInternetStrings(html_source);
- AddMultideviceStrings(html_source);
- AddParentalControlStrings(html_source);
- AddPluginVmStrings(html_source, profile);
- AddUsersStrings(html_source);
#else
AddDefaultBrowserStrings(html_source);
AddImportDataStrings(html_source);
@@ -3512,13 +2085,6 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source,
certificate_manager::AddLocalizedStrings(html_source);
#endif
-#if defined(OS_CHROMEOS)
- chromeos::network_element::AddLocalizedStrings(html_source);
- chromeos::network_element::AddOncLocalizedStrings(html_source);
- chromeos::network_element::AddDetailsLocalizedStrings(html_source);
- chromeos::network_element::AddConfigLocalizedStrings(html_source);
- chromeos::network_element::AddErrorLocalizedStrings(html_source);
-#endif
policy_indicator::AddLocalizedStrings(html_source);
AddSecurityKeysStrings(html_source);
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h b/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h
index a72290f479f..0940dc5a24e 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h
+++ b/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h
@@ -14,12 +14,14 @@ class WebContents;
namespace settings {
-// Adds the strings needed by the settings page to |html_source|. This function
-// causes |html_source| to expose a strings.js file from its source which
-// contains a mapping from string's name to its translated value.
-void AddLocalizedStrings(content::WebUIDataSource* html_source,
- Profile* profile,
- content::WebContents* web_contents);
+// Adds the strings needed by the browser settings page to |html_source|
+// This function causes |html_source| to expose a strings.js file from its
+// source which contains a mapping from string's name to its translated value.
+// TODO(crbug/967888): This still contains OS Settings strings. Strings specific
+// to OS settings should be moved to os_settings_localized_strings_provider.cc.
+void AddBrowserLocalizedStrings(content::WebUIDataSource* html_source,
+ Profile* profile,
+ content::WebContents* web_contents);
} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc
new file mode 100644
index 00000000000..0ba238f7959
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc
@@ -0,0 +1,314 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/settings_secure_dns_handler.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/rand_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/net/dns_util.h"
+#include "chrome/browser/net/stub_resolver_config_reader.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/country_codes/country_codes.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "net/dns/public/dns_over_https_server_config.h"
+#include "net/dns/public/doh_provider_list.h"
+#include "net/dns/public/util.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace settings {
+
+namespace {
+
+const char kProbeHostname[] = "google.com";
+
+std::unique_ptr<base::DictionaryValue> CreateSecureDnsSettingDict() {
+ // Fetch the current host resolver configuration. It is not sufficient to read
+ // the secure DNS prefs directly since the host resolver configuration takes
+ // other factors into account such as whether a managed environment or
+ // parental controls have been detected.
+ bool insecure_stub_resolver_enabled = false;
+ net::DnsConfig::SecureDnsMode secure_dns_mode;
+ std::vector<net::DnsOverHttpsServerConfig> dns_over_https_servers;
+ chrome_browser_net::SecureDnsUiManagementMode management_mode;
+ SystemNetworkContextManager::GetStubResolverConfigReader()->GetConfiguration(
+ true /* force_check_parental_controls_for_automatic_mode */,
+ &insecure_stub_resolver_enabled, &secure_dns_mode,
+ &dns_over_https_servers, &management_mode);
+
+ std::string secure_dns_mode_str;
+ switch (secure_dns_mode) {
+ case net::DnsConfig::SecureDnsMode::SECURE:
+ secure_dns_mode_str = chrome_browser_net::kDnsOverHttpsModeSecure;
+ break;
+ case net::DnsConfig::SecureDnsMode::AUTOMATIC:
+ secure_dns_mode_str = chrome_browser_net::kDnsOverHttpsModeAutomatic;
+ break;
+ case net::DnsConfig::SecureDnsMode::OFF:
+ secure_dns_mode_str = chrome_browser_net::kDnsOverHttpsModeOff;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ auto secure_dns_templates = std::make_unique<base::ListValue>();
+ for (const auto& doh_server : dns_over_https_servers) {
+ secure_dns_templates->Append(doh_server.server_template);
+ }
+
+ auto dict = std::make_unique<base::DictionaryValue>();
+ dict->SetString("mode", secure_dns_mode_str);
+ dict->SetList("templates", std::move(secure_dns_templates));
+ dict->SetInteger("managementMode", static_cast<int>(management_mode));
+ return dict;
+}
+
+} // namespace
+
+SecureDnsHandler::SecureDnsHandler() = default;
+
+SecureDnsHandler::~SecureDnsHandler() = default;
+
+void SecureDnsHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "getSecureDnsResolverList",
+ base::BindRepeating(&SecureDnsHandler::HandleGetSecureDnsResolverList,
+ base::Unretained(this)));
+
+ web_ui()->RegisterMessageCallback(
+ "getSecureDnsSetting",
+ base::BindRepeating(&SecureDnsHandler::HandleGetSecureDnsSetting,
+ base::Unretained(this)));
+
+ web_ui()->RegisterMessageCallback(
+ "validateCustomDnsEntry",
+ base::BindRepeating(&SecureDnsHandler::HandleValidateCustomDnsEntry,
+ base::Unretained(this)));
+
+ web_ui()->RegisterMessageCallback(
+ "probeCustomDnsTemplate",
+ base::BindRepeating(&SecureDnsHandler::HandleProbeCustomDnsTemplate,
+ base::Unretained(this)));
+
+ web_ui()->RegisterMessageCallback(
+ "recordUserDropdownInteraction",
+ base::BindRepeating(
+ &SecureDnsHandler::HandleRecordUserDropdownInteraction,
+ base::Unretained(this)));
+}
+
+void SecureDnsHandler::OnJavascriptAllowed() {
+ // Register for updates to the underlying secure DNS prefs so that the
+ // secure DNS setting can be updated to reflect the current host resolver
+ // configuration.
+ pref_registrar_.Init(g_browser_process->local_state());
+ pref_registrar_.Add(
+ prefs::kDnsOverHttpsMode,
+ base::Bind(&SecureDnsHandler::SendSecureDnsSettingUpdatesToJavascript,
+ base::Unretained(this)));
+ pref_registrar_.Add(
+ prefs::kDnsOverHttpsTemplates,
+ base::Bind(&SecureDnsHandler::SendSecureDnsSettingUpdatesToJavascript,
+ base::Unretained(this)));
+}
+
+void SecureDnsHandler::OnJavascriptDisallowed() {
+ pref_registrar_.RemoveAll();
+}
+
+base::Value SecureDnsHandler::GetSecureDnsResolverListForCountry(
+ int country_id,
+ const std::vector<net::DohProviderEntry>& providers) {
+ std::vector<std::string> disabled_providers =
+ SplitString(features::kDnsOverHttpsDisabledProvidersParam.Get(), ",",
+ base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ base::Value resolvers(base::Value::Type::LIST);
+ resolver_histogram_map_.clear();
+ // Add all non-disabled resolvers that should be displayed in |country_id|.
+ for (const auto& entry : providers) {
+ if (base::Contains(disabled_providers, entry.provider))
+ continue;
+
+ if (entry.display_globally ||
+ std::find_if(
+ entry.display_countries.begin(), entry.display_countries.end(),
+ [&country_id](const std::string& country_code) {
+ return country_codes::CountryCharsToCountryID(
+ country_code[0], country_code[1]) == country_id;
+ }) != entry.display_countries.end()) {
+ DCHECK(!entry.ui_name.empty());
+ DCHECK(!entry.privacy_policy.empty());
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetKey("name", base::Value(entry.ui_name));
+ dict.SetKey("value", base::Value(entry.dns_over_https_template));
+ dict.SetKey("policy", base::Value(entry.privacy_policy));
+ resolvers.Append(std::move(dict));
+ DCHECK(entry.provider_id_for_histogram.has_value());
+ resolver_histogram_map_.insert({entry.dns_over_https_template,
+ entry.provider_id_for_histogram.value()});
+ }
+ }
+
+ // Randomize the order of the resolvers.
+ base::RandomShuffle(resolvers.GetList().begin(), resolvers.GetList().end());
+
+ // Add a custom option to the front of the list
+ base::Value custom(base::Value::Type::DICTIONARY);
+ custom.SetKey("name",
+ base::Value(l10n_util::GetStringUTF8(IDS_SETTINGS_CUSTOM)));
+ custom.SetKey("value", base::Value("custom"));
+ custom.SetKey("policy", base::Value(std::string()));
+ resolvers.Insert(resolvers.GetList().begin(), std::move(custom));
+ resolver_histogram_map_.insert(
+ {"custom", net::DohProviderIdForHistogram::kCustom});
+
+ return resolvers;
+}
+
+void SecureDnsHandler::SetNetworkContextForTesting(
+ network::mojom::NetworkContext* network_context) {
+ network_context_for_testing_ = network_context;
+}
+
+void SecureDnsHandler::HandleGetSecureDnsResolverList(
+ const base::ListValue* args) {
+ AllowJavascript();
+ std::string callback_id = args->GetList()[0].GetString();
+
+ ResolveJavascriptCallback(
+ base::Value(callback_id),
+ GetSecureDnsResolverListForCountry(country_codes::GetCurrentCountryID(),
+ net::GetDohProviderList()));
+}
+
+void SecureDnsHandler::HandleGetSecureDnsSetting(const base::ListValue* args) {
+ AllowJavascript();
+ CHECK_EQ(1u, args->GetList().size());
+ const base::Value& callback_id = args->GetList()[0];
+ ResolveJavascriptCallback(callback_id, *CreateSecureDnsSettingDict());
+}
+
+void SecureDnsHandler::HandleValidateCustomDnsEntry(
+ const base::ListValue* args) {
+ AllowJavascript();
+ const base::Value* callback_id;
+ std::string custom_entry;
+ CHECK(args->Get(0, &callback_id));
+ CHECK(args->GetString(1, &custom_entry));
+
+ // Return the first template, or none if the entry is invalid.
+ std::string first_template;
+ bool valid = !custom_entry.empty() &&
+ chrome_browser_net::IsValidDohTemplateGroup(custom_entry);
+ if (valid) {
+ first_template =
+ std::string(chrome_browser_net::SplitDohTemplateGroup(custom_entry)[0]);
+ }
+ UMA_HISTOGRAM_BOOLEAN("Net.DNS.UI.ValidationAttemptSuccess", valid);
+ ResolveJavascriptCallback(*callback_id, base::Value(first_template));
+}
+
+void SecureDnsHandler::HandleProbeCustomDnsTemplate(
+ const base::ListValue* args) {
+ AllowJavascript();
+ receiver_.reset();
+ host_resolver_.reset();
+
+ std::string server_template;
+ CHECK(args->GetString(0, &probe_callback_id_));
+ CHECK(args->GetString(1, &server_template));
+
+ net::DnsConfigOverrides overrides;
+ overrides.search = std::vector<std::string>();
+ overrides.attempts = 1;
+ overrides.randomize_ports = false;
+ overrides.secure_dns_mode = net::DnsConfig::SecureDnsMode::SECURE;
+ std::string server_method;
+ // We only send probe queries to templates that have already passed a format
+ // validation check.
+ CHECK(net::dns_util::IsValidDohTemplate(server_template, &server_method));
+ overrides.dns_over_https_servers.emplace({net::DnsOverHttpsServerConfig(
+ server_template, server_method == "POST")});
+ auto* network_context =
+ network_context_for_testing_
+ ? network_context_for_testing_
+ : content::BrowserContext::GetDefaultStoragePartition(
+ web_ui()->GetWebContents()->GetBrowserContext())
+ ->GetNetworkContext();
+ network_context->CreateHostResolver(
+ overrides, host_resolver_.BindNewPipeAndPassReceiver());
+
+ network::mojom::ResolveHostParametersPtr parameters =
+ network::mojom::ResolveHostParameters::New();
+ parameters->dns_query_type = net::DnsQueryType::A;
+ parameters->source = net::HostResolverSource::DNS;
+ parameters->cache_usage =
+ network::mojom::ResolveHostParameters::CacheUsage::DISALLOWED;
+ host_resolver_->ResolveHost(net::HostPortPair(kProbeHostname, 80),
+ net::NetworkIsolationKey::CreateTransient(),
+ std::move(parameters),
+ receiver_.BindNewPipeAndPassRemote());
+ receiver_.set_disconnect_handler(base::BindOnce(
+ &SecureDnsHandler::OnMojoConnectionError, base::Unretained(this)));
+}
+
+void SecureDnsHandler::HandleRecordUserDropdownInteraction(
+ const base::ListValue* args) {
+ CHECK_EQ(2U, args->GetSize());
+ std::string old_provider;
+ std::string new_provider;
+ CHECK(args->GetString(0, &old_provider));
+ CHECK(args->GetString(1, &new_provider));
+ DCHECK(resolver_histogram_map_.find(old_provider) !=
+ resolver_histogram_map_.end());
+ DCHECK(resolver_histogram_map_.find(new_provider) !=
+ resolver_histogram_map_.end());
+ for (auto& pair : resolver_histogram_map_) {
+ if (pair.first == old_provider) {
+ UMA_HISTOGRAM_ENUMERATION("Net.DNS.UI.DropdownSelectionEvent.Unselected",
+ pair.second);
+ } else if (pair.first == new_provider) {
+ UMA_HISTOGRAM_ENUMERATION("Net.DNS.UI.DropdownSelectionEvent.Selected",
+ pair.second);
+ } else {
+ UMA_HISTOGRAM_ENUMERATION("Net.DNS.UI.DropdownSelectionEvent.Ignored",
+ pair.second);
+ }
+ }
+}
+
+// network::ResolveHostClientBase impl:
+void SecureDnsHandler::OnComplete(
+ int result,
+ const net::ResolveErrorInfo& resolve_error_info,
+ const base::Optional<net::AddressList>& resolved_addresses) {
+ receiver_.reset();
+ host_resolver_.reset();
+ UMA_HISTOGRAM_BOOLEAN("Net.DNS.UI.ProbeAttemptSuccess", (result == 0));
+ ResolveJavascriptCallback(base::Value(probe_callback_id_),
+ base::Value(result == 0));
+}
+
+void SecureDnsHandler::OnMojoConnectionError() {
+ OnComplete(net::ERR_NAME_NOT_RESOLVED, net::ResolveErrorInfo(net::ERR_FAILED),
+ base::nullopt);
+}
+
+void SecureDnsHandler::SendSecureDnsSettingUpdatesToJavascript() {
+ FireWebUIListener("secure-dns-setting-changed",
+ *CreateSecureDnsSettingDict());
+}
+
+} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h
new file mode 100644
index 00000000000..ed68ee5b664
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h
@@ -0,0 +1,89 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_SECURE_DNS_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_SECURE_DNS_HANDLER_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/values.h"
+#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "components/prefs/pref_change_registrar.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "net/dns/public/doh_provider_list.h"
+#include "services/network/public/cpp/resolve_host_client_base.h"
+#include "services/network/public/mojom/host_resolver.mojom.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+
+namespace settings {
+
+// Handler for the Secure DNS setting.
+class SecureDnsHandler : public SettingsPageUIHandler,
+ network::ResolveHostClientBase {
+ public:
+ SecureDnsHandler();
+ ~SecureDnsHandler() override;
+
+ // SettingsPageUIHandler:
+ void RegisterMessages() override;
+ void OnJavascriptAllowed() override;
+ void OnJavascriptDisallowed() override;
+
+ // Get the list of dropdown resolver options. Each option is represented
+ // as a dictionary with the following keys: "name" (the text to display in the
+ // UI), "value" (the DoH template for this provider), and "policy" (the URL of
+ // the provider's privacy policy).
+ base::Value GetSecureDnsResolverListForCountry(
+ int country_id,
+ const std::vector<net::DohProviderEntry>& providers);
+
+ void SetNetworkContextForTesting(
+ network::mojom::NetworkContext* network_context);
+
+ protected:
+ // Retrieves all pre-approved secure resolvers and returns them to WebUI.
+ void HandleGetSecureDnsResolverList(const base::ListValue* args);
+
+ // Intended to be called once upon creation of the secure DNS setting.
+ void HandleGetSecureDnsSetting(const base::ListValue* args);
+
+ // Returns the first template if a custom entry is valid.
+ void HandleValidateCustomDnsEntry(const base::ListValue* args);
+
+ // Returns whether or not a test query to the resolver succeeds.
+ void HandleProbeCustomDnsTemplate(const base::ListValue* args);
+
+ // Records metrics on the user-initiated dropdown selection event.
+ void HandleRecordUserDropdownInteraction(const base::ListValue* args);
+
+ // Retrieves the current host resolver configuration, computes the
+ // corresponding UI representation, and sends it to javascript.
+ void SendSecureDnsSettingUpdatesToJavascript();
+
+ private:
+ // network::ResolveHostClientBase impl:
+ void OnComplete(
+ int result,
+ const net::ResolveErrorInfo& resolve_error_info,
+ const base::Optional<net::AddressList>& resolved_addresses) override;
+
+ void OnMojoConnectionError();
+
+ std::map<std::string, net::DohProviderIdForHistogram> resolver_histogram_map_;
+ network::mojom::NetworkContext* network_context_for_testing_ = nullptr;
+ mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
+ mojo::Remote<network::mojom::HostResolver> host_resolver_;
+ std::string probe_callback_id_;
+ PrefChangeRegistrar pref_registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(SecureDnsHandler);
+};
+
+} // namespace settings
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_SETTINGS_SECURE_DNS_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc
new file mode 100644
index 00000000000..c57dde40d12
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc
@@ -0,0 +1,609 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/settings_secure_dns_handler.h"
+
+#include "base/test/metrics/histogram_tester.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/net/dns_probe_test_util.h"
+#include "chrome/browser/net/dns_util.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "components/country_codes/country_codes.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "components/policy/policy_constants.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/test/test_web_ui.h"
+#include "net/dns/public/resolve_error_info.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#endif
+
+using net::DohProviderEntry;
+using testing::_;
+using testing::Return;
+
+namespace settings {
+
+namespace {
+
+constexpr char kGetSecureDnsResolverList[] = "getSecureDnsResolverList";
+constexpr char kValidateCustomDnsEntry[] = "validateCustomDnsEntry";
+constexpr char kProbeCustomDnsTemplate[] = "probeCustomDnsTemplate";
+constexpr char kRecordUserDropdownInteraction[] =
+ "recordUserDropdownInteraction";
+constexpr char kWebUiFunctionName[] = "webUiCallbackName";
+
+const std::vector<DohProviderEntry>& GetDohProviderListForTesting() {
+ static const base::NoDestructor<std::vector<DohProviderEntry>> test_providers{
+ {
+ DohProviderEntry(
+ "Provider_Global1", net::DohProviderIdForHistogram(-1),
+ {} /*ip_strs */, {} /* dot_hostnames */,
+ "https://global1.provider/dns-query{?dns}",
+ "Global Provider 1" /* ui_name */,
+ "https://global1.provider/privacy_policy/" /* privacy_policy */,
+ true /* display_globally */, {} /* display_countries */),
+ DohProviderEntry(
+ "Provider_NoDisplay", net::DohProviderIdForHistogram(-2),
+ {} /*ip_strs */, {} /* dot_hostnames */,
+ "https://nodisplay.provider/dns-query{?dns}",
+ "No Display Provider" /* ui_name */,
+ "https://nodisplay.provider/privacy_policy/" /* privacy_policy */,
+ false /* display_globally */, {} /* display_countries */),
+ DohProviderEntry(
+ "Provider_EE_FR", net::DohProviderIdForHistogram(-3),
+ {} /*ip_strs */, {} /* dot_hostnames */,
+ "https://ee.fr.provider/dns-query{?dns}",
+ "EE/FR Provider" /* ui_name */,
+ "https://ee.fr.provider/privacy_policy/" /* privacy_policy */,
+ false /* display_globally */,
+ {"EE", "FR"} /* display_countries */),
+ DohProviderEntry(
+ "Provider_FR", net::DohProviderIdForHistogram(-4),
+ {} /*ip_strs */, {} /* dot_hostnames */,
+ "https://fr.provider/dns-query{?dns}",
+ "FR Provider" /* ui_name */,
+ "https://fr.provider/privacy_policy/" /* privacy_policy */,
+ false /* display_globally */, {"FR"} /* display_countries */),
+ DohProviderEntry(
+ "Provider_Global2", net::DohProviderIdForHistogram(-5),
+ {} /*ip_strs */, {} /* dot_hostnames */,
+ "https://global2.provider/dns-query{?dns}",
+ "Global Provider 2" /* ui_name */,
+ "https://global2.provider/privacy_policy/" /* privacy_policy */,
+ true /* display_globally */, {} /* display_countries */),
+ }};
+ return *test_providers;
+}
+
+bool FindDropdownItem(const base::Value& resolvers,
+ const std::string& name,
+ const std::string& value,
+ const std::string& policy) {
+ base::Value dict(base::Value::Type::DICTIONARY);
+ dict.SetKey("name", base::Value(name));
+ dict.SetKey("value", base::Value(value));
+ dict.SetKey("policy", base::Value(policy));
+
+ return std::find(resolvers.GetList().begin(), resolvers.GetList().end(),
+ dict) != resolvers.GetList().end();
+}
+
+} // namespace
+
+class TestSecureDnsHandler : public SecureDnsHandler {
+ public:
+ // Pull WebUIMessageHandler::set_web_ui() into public so tests can call it.
+ using SecureDnsHandler::set_web_ui;
+};
+
+class SecureDnsHandlerTest : public InProcessBrowserTest {
+ protected:
+#if defined(OS_WIN)
+ SecureDnsHandlerTest()
+ // Mark as not enterprise managed to prevent the secure DNS mode from
+ // being downgraded to off.
+ : scoped_domain_(false) {}
+#else
+ SecureDnsHandlerTest() = default;
+#endif
+ ~SecureDnsHandlerTest() override = default;
+
+ // InProcessBrowserTest:
+ void SetUpInProcessBrowserTestFixture() override {
+ // Initialize user policy.
+ ON_CALL(provider_, IsInitializationComplete(_)).WillByDefault(Return(true));
+ policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
+ }
+
+ void SetUpOnMainThread() override {
+ handler_ = std::make_unique<TestSecureDnsHandler>();
+ handler_->set_web_ui(&web_ui_);
+ handler_->RegisterMessages();
+ handler_->AllowJavascriptForTesting();
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void TearDownOnMainThread() override { handler_.reset(); }
+
+ // Updates out-params from the last message sent to WebUI about a secure DNS
+ // change. Returns false if the message was invalid or not found.
+ bool GetLastSettingsChangedMessage(
+ std::string* secure_dns_mode,
+ std::vector<std::string>* secure_dns_templates,
+ int* management_mode) {
+ for (auto it = web_ui_.call_data().rbegin();
+ it != web_ui_.call_data().rend(); ++it) {
+ const content::TestWebUI::CallData* data = it->get();
+ if (data->function_name() != "cr.webUIListenerCallback" ||
+ !data->arg1()->is_string() ||
+ data->arg1()->GetString() != "secure-dns-setting-changed") {
+ continue;
+ }
+
+ const base::DictionaryValue* dict = nullptr;
+ if (!data->arg2()->GetAsDictionary(&dict))
+ return false;
+
+ // Get the secure DNS mode.
+ if (!dict->FindStringPath("mode"))
+ return false;
+ *secure_dns_mode = *dict->FindStringPath("mode");
+
+ // Get the secure DNS templates.
+ if (!dict->FindListPath("templates"))
+ return false;
+ secure_dns_templates->clear();
+ for (const auto& template_str :
+ dict->FindListPath("templates")->GetList()) {
+ if (!template_str.is_string())
+ return false;
+ secure_dns_templates->push_back(template_str.GetString());
+ }
+
+ // Get the forced management description.
+ if (!dict->FindIntPath("managementMode"))
+ return false;
+ *management_mode = *dict->FindIntPath("managementMode");
+
+ return true;
+ }
+ return false;
+ }
+
+ // Sets a policy update which will cause power pref managed change.
+ void SetPolicyForPolicyKey(policy::PolicyMap* policy_map,
+ const std::string& policy_key,
+ std::unique_ptr<base::Value> value) {
+ policy_map->Set(policy_key, policy::POLICY_LEVEL_MANDATORY,
+ policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
+ std::move(value), nullptr);
+ provider_.UpdateChromePolicy(*policy_map);
+ base::RunLoop().RunUntilIdle();
+ }
+
+ std::unique_ptr<TestSecureDnsHandler> handler_;
+ content::TestWebUI web_ui_;
+ policy::MockConfigurationPolicyProvider provider_;
+
+ private:
+#if defined(OS_WIN)
+ base::win::ScopedDomainStateForTesting scoped_domain_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(SecureDnsHandlerTest);
+};
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsModes) {
+ PrefService* local_state = g_browser_process->local_state();
+ std::string secure_dns_mode;
+ std::vector<std::string> secure_dns_templates;
+ int management_mode;
+
+ local_state->SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeOff);
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeOff, secure_dns_mode);
+
+ local_state->SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeAutomatic);
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeAutomatic, secure_dns_mode);
+
+ local_state->SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeSecure);
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeSecure, secure_dns_mode);
+
+ local_state->SetString(prefs::kDnsOverHttpsMode, "unknown");
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeOff, secure_dns_mode);
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsPolicy) {
+ policy::PolicyMap policy_map;
+ SetPolicyForPolicyKey(&policy_map, policy::key::kDnsOverHttpsMode,
+ std::make_unique<base::Value>(
+ chrome_browser_net::kDnsOverHttpsModeAutomatic));
+
+ PrefService* local_state = g_browser_process->local_state();
+ local_state->SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeSecure);
+
+ std::string secure_dns_mode;
+ std::vector<std::string> secure_dns_templates;
+ int management_mode;
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeAutomatic, secure_dns_mode);
+ EXPECT_EQ(static_cast<int>(
+ chrome_browser_net::SecureDnsUiManagementMode::kNoOverride),
+ management_mode);
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsPolicyChange) {
+ policy::PolicyMap policy_map;
+ SetPolicyForPolicyKey(&policy_map, policy::key::kDnsOverHttpsMode,
+ std::make_unique<base::Value>(
+ chrome_browser_net::kDnsOverHttpsModeAutomatic));
+
+ std::string secure_dns_mode;
+ std::vector<std::string> secure_dns_templates;
+ int management_mode;
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeAutomatic, secure_dns_mode);
+ EXPECT_EQ(static_cast<int>(
+ chrome_browser_net::SecureDnsUiManagementMode::kNoOverride),
+ management_mode);
+
+ SetPolicyForPolicyKey(
+ &policy_map, policy::key::kDnsOverHttpsMode,
+ std::make_unique<base::Value>(chrome_browser_net::kDnsOverHttpsModeOff));
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeOff, secure_dns_mode);
+ EXPECT_EQ(static_cast<int>(
+ chrome_browser_net::SecureDnsUiManagementMode::kNoOverride),
+ management_mode);
+}
+
+// On platforms where enterprise policies do not have default values, test
+// that DoH is disabled when non-DoH policies are set.
+#if !defined(OS_CHROMEOS)
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, OtherPoliciesSet) {
+ policy::PolicyMap policy_map;
+ SetPolicyForPolicyKey(&policy_map, policy::key::kIncognitoModeAvailability,
+ std::make_unique<base::Value>(1));
+
+ PrefService* local_state = g_browser_process->local_state();
+ local_state->SetString(prefs::kDnsOverHttpsMode,
+ chrome_browser_net::kDnsOverHttpsModeSecure);
+
+ std::string secure_dns_mode;
+ std::vector<std::string> secure_dns_templates;
+ int management_mode;
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(chrome_browser_net::kDnsOverHttpsModeOff, secure_dns_mode);
+ EXPECT_EQ(
+ static_cast<int>(
+ chrome_browser_net::SecureDnsUiManagementMode::kDisabledManaged),
+ management_mode);
+}
+#endif
+
+// This test makes no assumptions about the country or underlying resolver list.
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownList) {
+ base::ListValue args;
+ args.AppendString(kWebUiFunctionName);
+
+ web_ui_.HandleReceivedMessage(kGetSecureDnsResolverList, &args);
+ const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
+ EXPECT_EQ("cr.webUIResponse", call_data.function_name());
+ EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString());
+ ASSERT_TRUE(call_data.arg2()->GetBool());
+
+ // Check results.
+ base::Value::ConstListView resolver_list = call_data.arg3()->GetList();
+ ASSERT_GE(resolver_list.size(), 1U);
+ EXPECT_EQ("custom", resolver_list[0].FindKey("value")->GetString());
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownListForCountry) {
+ // The 'EE' list should start with the custom entry, followed by the two
+ // global providers and the 'EE' provider in some random order.
+ base::Value resolver_list = handler_->GetSecureDnsResolverListForCountry(
+ country_codes::CountryCharsToCountryID('E', 'E'),
+ GetDohProviderListForTesting());
+ EXPECT_EQ(4u, resolver_list.GetList().size());
+ EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString());
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1",
+ "https://global1.provider/dns-query{?dns}",
+ "https://global1.provider/privacy_policy/"));
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 2",
+ "https://global2.provider/dns-query{?dns}",
+ "https://global2.provider/privacy_policy/"));
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "EE/FR Provider",
+ "https://ee.fr.provider/dns-query{?dns}",
+ "https://ee.fr.provider/privacy_policy/"));
+
+ // The 'FR' list should start with the custom entry, followed by the two
+ // global providers and the two 'FR' providers in some random order.
+ resolver_list = handler_->GetSecureDnsResolverListForCountry(
+ country_codes::CountryCharsToCountryID('F', 'R'),
+ GetDohProviderListForTesting());
+ EXPECT_EQ(5u, resolver_list.GetList().size());
+ EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString());
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1",
+ "https://global1.provider/dns-query{?dns}",
+ "https://global1.provider/privacy_policy/"));
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 2",
+ "https://global2.provider/dns-query{?dns}",
+ "https://global2.provider/privacy_policy/"));
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "EE/FR Provider",
+ "https://ee.fr.provider/dns-query{?dns}",
+ "https://ee.fr.provider/privacy_policy/"));
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "FR Provider",
+ "https://fr.provider/dns-query{?dns}",
+ "https://fr.provider/privacy_policy/"));
+
+ // The 'CA' list should start with the custom entry, followed by the two
+ // global providers.
+ resolver_list = handler_->GetSecureDnsResolverListForCountry(
+ country_codes::CountryCharsToCountryID('C', 'A'),
+ GetDohProviderListForTesting());
+ EXPECT_EQ(3u, resolver_list.GetList().size());
+ EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString());
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1",
+ "https://global1.provider/dns-query{?dns}",
+ "https://global1.provider/privacy_policy/"));
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 2",
+ "https://global2.provider/dns-query{?dns}",
+ "https://global2.provider/privacy_policy/"));
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownListChange) {
+ // Populate the map for recording dropdown change metrics.
+ base::Value resolver_list = handler_->GetSecureDnsResolverListForCountry(
+ country_codes::CountryCharsToCountryID('E', 'E'),
+ GetDohProviderListForTesting());
+ EXPECT_EQ(4u, resolver_list.GetList().size());
+
+ base::HistogramTester histograms;
+ base::ListValue args;
+ args.AppendString("custom" /* old_provider */);
+ args.AppendString(
+ "https://global1.provider/dns-query{?dns}" /* new_provider */);
+ web_ui_.HandleReceivedMessage(kRecordUserDropdownInteraction, &args);
+
+ const std::string uma_base("Net.DNS.UI.DropdownSelectionEvent");
+ histograms.ExpectTotalCount(uma_base + ".Ignored", 2u);
+ histograms.ExpectTotalCount(uma_base + ".Selected", 1u);
+ histograms.ExpectTotalCount(uma_base + ".Unselected", 1u);
+}
+
+class SecureDnsHandlerTestWithDisabledProviders : public SecureDnsHandlerTest {
+ protected:
+ SecureDnsHandlerTestWithDisabledProviders() {
+ scoped_features_.InitAndEnableFeatureWithParameters(
+ features::kDnsOverHttps,
+ {{"DisabledProviders",
+ "Provider_Global2, , Provider_EE_FR,Unexpected"}});
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_features_;
+
+ DISALLOW_COPY_AND_ASSIGN(SecureDnsHandlerTestWithDisabledProviders);
+};
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTestWithDisabledProviders,
+ DropdownListDisabledProviders) {
+ // The 'FR' list should start with the custom entry, followed by the two
+ // global providers and the two 'FR' providers in some random order.
+ base::Value resolver_list = handler_->GetSecureDnsResolverListForCountry(
+ country_codes::CountryCharsToCountryID('F', 'R'),
+ GetDohProviderListForTesting());
+ EXPECT_EQ(3u, resolver_list.GetList().size());
+ EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString());
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1",
+ "https://global1.provider/dns-query{?dns}",
+ "https://global1.provider/privacy_policy/"));
+ EXPECT_TRUE(FindDropdownItem(resolver_list, "FR Provider",
+ "https://fr.provider/dns-query{?dns}",
+ "https://fr.provider/privacy_policy/"));
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTestWithDisabledProviders,
+ SecureDnsTemplates) {
+ std::string good_post_template = "https://foo.test/";
+ std::string good_get_template = "https://bar.test/dns-query{?dns}";
+ std::string bad_template = "dns-query{?dns}";
+
+ std::string secure_dns_mode;
+ std::vector<std::string> secure_dns_templates;
+ int management_mode;
+ PrefService* local_state = g_browser_process->local_state();
+ local_state->SetString(prefs::kDnsOverHttpsTemplates, good_post_template);
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(1u, secure_dns_templates.size());
+ EXPECT_EQ(good_post_template, secure_dns_templates[0]);
+
+ local_state->SetString(prefs::kDnsOverHttpsTemplates,
+ good_post_template + " " + good_get_template);
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(2u, secure_dns_templates.size());
+ EXPECT_EQ(good_post_template, secure_dns_templates[0]);
+ EXPECT_EQ(good_get_template, secure_dns_templates[1]);
+
+ local_state->SetString(prefs::kDnsOverHttpsTemplates, bad_template);
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(0u, secure_dns_templates.size());
+
+ local_state->SetString(prefs::kDnsOverHttpsTemplates,
+ bad_template + " " + good_post_template);
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(1u, secure_dns_templates.size());
+ EXPECT_EQ(good_post_template, secure_dns_templates[0]);
+
+ // Should still return a provider that was disabled.
+ local_state->SetString(prefs::kDnsOverHttpsTemplates,
+ "https://global2.provider/dns-query{?dns}");
+ EXPECT_TRUE(GetLastSettingsChangedMessage(
+ &secure_dns_mode, &secure_dns_templates, &management_mode));
+ EXPECT_EQ(1u, secure_dns_templates.size());
+ EXPECT_EQ("https://global2.provider/dns-query{?dns}",
+ secure_dns_templates[0]);
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateValid) {
+ base::ListValue args;
+ args.AppendString(kWebUiFunctionName);
+ args.AppendString("https://example.template/dns-query");
+
+ base::HistogramTester histograms;
+ web_ui_.HandleReceivedMessage(kValidateCustomDnsEntry, &args);
+ const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
+ EXPECT_EQ("cr.webUIResponse", call_data.function_name());
+ EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString());
+ // The request should be successful.
+ ASSERT_TRUE(call_data.arg2()->GetBool());
+ // The template should be valid.
+ ASSERT_EQ("https://example.template/dns-query",
+ call_data.arg3()->GetString());
+ histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", false, 0);
+ histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", true, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateInvalid) {
+ base::ListValue args;
+ args.AppendString(kWebUiFunctionName);
+ args.AppendString("invalid_template");
+
+ base::HistogramTester histograms;
+ web_ui_.HandleReceivedMessage(kValidateCustomDnsEntry, &args);
+ const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back();
+ EXPECT_EQ("cr.webUIResponse", call_data.function_name());
+ EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString());
+ // The request should be successful.
+ ASSERT_TRUE(call_data.arg2()->GetBool());
+ // The template should be invalid.
+ ASSERT_EQ(std::string(), call_data.arg3()->GetString());
+ histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", false, 1);
+ histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", true, 0);
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, MultipleTemplates) {
+ base::HistogramTester histograms;
+ base::ListValue args_valid;
+ args_valid.AppendString(kWebUiFunctionName);
+ args_valid.AppendString(
+ "https://example1.template/dns https://example2.template/dns-query");
+ web_ui_.HandleReceivedMessage(kValidateCustomDnsEntry, &args_valid);
+ const content::TestWebUI::CallData& call_data_valid =
+ *web_ui_.call_data().back();
+ EXPECT_EQ("cr.webUIResponse", call_data_valid.function_name());
+ EXPECT_EQ(kWebUiFunctionName, call_data_valid.arg1()->GetString());
+ // The request should be successful.
+ ASSERT_TRUE(call_data_valid.arg2()->GetBool());
+ // Both templates are valid, so validate returns the first.
+ ASSERT_EQ("https://example1.template/dns",
+ call_data_valid.arg3()->GetString());
+ histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", false, 0);
+ histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", true, 1);
+
+ base::ListValue args_invalid;
+ args_invalid.AppendString(kWebUiFunctionName);
+ args_invalid.AppendString("invalid_template https://example.template/dns");
+ web_ui_.HandleReceivedMessage(kValidateCustomDnsEntry, &args_invalid);
+ const content::TestWebUI::CallData& call_data_invalid =
+ *web_ui_.call_data().back();
+ EXPECT_EQ("cr.webUIResponse", call_data_invalid.function_name());
+ EXPECT_EQ(kWebUiFunctionName, call_data_invalid.arg1()->GetString());
+ // The request should be successful.
+ ASSERT_TRUE(call_data_invalid.arg2()->GetBool());
+ // The entry should be invalid.
+ ASSERT_EQ(std::string(), call_data_invalid.arg3()->GetString());
+ histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", false, 1);
+ histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", true, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeSuccess) {
+ auto network_context_ =
+ std::make_unique<chrome_browser_net::FakeHostResolverNetworkContext>(
+ std::vector<chrome_browser_net::FakeHostResolver::SingleResult>(
+ {chrome_browser_net::FakeHostResolver::SingleResult(
+ net::OK, net::ResolveErrorInfo(net::OK),
+ chrome_browser_net::FakeHostResolver::
+ kOneAddressResponse)}) /* current_config_result_list */,
+ std::vector<chrome_browser_net::FakeHostResolver::
+ SingleResult>() /* google_config_result_list */);
+ handler_->SetNetworkContextForTesting(network_context_.get());
+ base::HistogramTester histograms;
+ base::ListValue args_valid;
+ args_valid.AppendString(kWebUiFunctionName);
+ args_valid.AppendString("https://example.template/dns-query");
+ web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid);
+ base::RunLoop().RunUntilIdle();
+
+ const content::TestWebUI::CallData& call_data_valid =
+ *web_ui_.call_data().back();
+ EXPECT_EQ("cr.webUIResponse", call_data_valid.function_name());
+ EXPECT_EQ(kWebUiFunctionName, call_data_valid.arg1()->GetString());
+ // The request should be successful.
+ ASSERT_TRUE(call_data_valid.arg2()->GetBool());
+ // The probe query should have succeeded.
+ ASSERT_TRUE(call_data_valid.arg3()->GetBool());
+ histograms.ExpectBucketCount("Net.DNS.UI.ProbeAttemptSuccess", false, 0);
+ histograms.ExpectBucketCount("Net.DNS.UI.ProbeAttemptSuccess", true, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeFailure) {
+ auto network_context_ =
+ std::make_unique<chrome_browser_net::FakeHostResolverNetworkContext>(
+ std::vector<chrome_browser_net::FakeHostResolver::SingleResult>(
+ {chrome_browser_net::FakeHostResolver::SingleResult(
+ net::ERR_NAME_NOT_RESOLVED,
+ net::ResolveErrorInfo(net::ERR_DNS_MALFORMED_RESPONSE),
+ chrome_browser_net::FakeHostResolver::
+ kNoResponse)}) /* current_config_result_list */,
+ std::vector<chrome_browser_net::FakeHostResolver::
+ SingleResult>() /* google_config_result_list */);
+ handler_->SetNetworkContextForTesting(network_context_.get());
+ base::HistogramTester histograms;
+ base::ListValue args_valid;
+ args_valid.AppendString(kWebUiFunctionName);
+ args_valid.AppendString("https://example.template/dns-query");
+ web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid);
+ base::RunLoop().RunUntilIdle();
+
+ const content::TestWebUI::CallData& call_data_valid =
+ *web_ui_.call_data().back();
+ EXPECT_EQ("cr.webUIResponse", call_data_valid.function_name());
+ EXPECT_EQ(kWebUiFunctionName, call_data_valid.arg1()->GetString());
+ // The request should be successful.
+ ASSERT_TRUE(call_data_valid.arg2()->GetBool());
+ // The probe query should have failed.
+ ASSERT_FALSE(call_data_valid.arg3()->GetBool());
+ histograms.ExpectBucketCount("Net.DNS.UI.ProbeAttemptSuccess", false, 1);
+ histograms.ExpectBucketCount("Net.DNS.UI.ProbeAttemptSuccess", true, 0);
+}
+
+} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_security_key_handler.cc b/chromium/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
index b949500f09a..112a3e1dc4b 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/settings_security_key_handler.cc
@@ -15,7 +15,6 @@
#include "chrome/browser/ui/webui/settings/settings_security_key_handler.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/system_connector.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/service_manager_connection.h"
#include "device/fido/bio/enrollment_handler.h"
@@ -103,7 +102,7 @@ void SecurityKeysPINHandler::HandleStartSetPIN(const base::ListValue* args) {
callback_id_ = args->GetList()[0].GetString();
state_ = State::kStartSetPIN;
set_pin_ = std::make_unique<device::SetPINRequestHandler>(
- content::GetSystemConnector(), supported_transports(),
+ supported_transports(),
base::BindOnce(&SecurityKeysPINHandler::OnGatherPIN,
weak_factory_.GetWeakPtr()),
base::BindRepeating(&SecurityKeysPINHandler::OnSetPINComplete,
@@ -203,7 +202,7 @@ void SecurityKeysResetHandler::HandleReset(const base::ListValue* args) {
state_ = State::kStartReset;
reset_ = std::make_unique<device::ResetRequestHandler>(
- content::GetSystemConnector(), supported_transports(),
+ supported_transports(),
base::BindOnce(&SecurityKeysResetHandler::OnResetSent,
weak_factory_.GetWeakPtr()),
base::BindOnce(&SecurityKeysResetHandler::OnResetFinished,
@@ -334,7 +333,6 @@ void SecurityKeysCredentialHandler::HandleStart(const base::ListValue* args) {
discovery_factory_ = std::make_unique<device::FidoDiscoveryFactory>();
credential_management_ =
std::make_unique<device::CredentialManagementHandler>(
- content::ServiceManagerConnection::GetForProcess()->GetConnector(),
discovery_factory_.get(), supported_transports(),
base::BindOnce(
&SecurityKeysCredentialHandler::OnCredentialManagementReady,
@@ -589,7 +587,6 @@ void SecurityKeysBioEnrollmentHandler::HandleStart(
callback_id_ = args->GetList()[0].GetString();
discovery_factory_ = std::make_unique<device::FidoDiscoveryFactory>();
bio_ = std::make_unique<device::BioEnrollmentHandler>(
- content::ServiceManagerConnection::GetForProcess()->GetConnector(),
supported_transports(),
base::BindOnce(&SecurityKeysBioEnrollmentHandler::OnReady,
weak_factory_.GetWeakPtr()),
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_ui.cc b/chromium/chrome/browser/ui/webui/settings/settings_ui.cc
index 1f4acc97c4d..84d467e2229 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chromium/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -19,10 +19,14 @@
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/ui/hats/hats_service.h"
+#include "chrome/browser/ui/hats/hats_service_factory.h"
#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
+#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/webui/favicon_source.h"
#include "chrome/browser/ui/webui/managed_ui_handler.h"
#include "chrome/browser/ui/webui/metrics_handler.h"
+#include "chrome/browser/ui/webui/plural_string_handler.h"
#include "chrome/browser/ui/webui/settings/about_handler.h"
#include "chrome/browser/ui/webui/settings/accessibility_main_handler.h"
#include "chrome/browser/ui/webui/settings/appearance_handler.h"
@@ -31,22 +35,28 @@
#include "chrome/browser/ui/webui/settings/downloads_handler.h"
#include "chrome/browser/ui/webui/settings/extension_control_handler.h"
#include "chrome/browser/ui/webui/settings/font_handler.h"
+#include "chrome/browser/ui/webui/settings/hats_handler.h"
+#include "chrome/browser/ui/webui/settings/import_data_handler.h"
#include "chrome/browser/ui/webui/settings/metrics_reporting_handler.h"
#include "chrome/browser/ui/webui/settings/on_startup_handler.h"
#include "chrome/browser/ui/webui/settings/people_handler.h"
#include "chrome/browser/ui/webui/settings/profile_info_handler.h"
#include "chrome/browser/ui/webui/settings/protocol_handlers_handler.h"
#include "chrome/browser/ui/webui/settings/reset_settings_handler.h"
+#include "chrome/browser/ui/webui/settings/safe_browsing_handler.h"
+#include "chrome/browser/ui/webui/settings/safety_check_handler.h"
#include "chrome/browser/ui/webui/settings/search_engines_handler.h"
#include "chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h"
#include "chrome/browser/ui/webui/settings/settings_cookies_view_handler.h"
-#include "chrome/browser/ui/webui/settings/settings_import_data_handler.h"
#include "chrome/browser/ui/webui/settings/settings_localized_strings_provider.h"
#include "chrome/browser/ui/webui/settings/settings_media_devices_selection_handler.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
+#include "chrome/browser/ui/webui/settings/settings_secure_dns_handler.h"
#include "chrome/browser/ui/webui/settings/settings_security_key_handler.h"
#include "chrome/browser/ui/webui/settings/settings_startup_pages_handler.h"
+#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
#include "chrome/browser/ui/webui/settings/site_settings_handler.h"
+#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/browser/web_applications/components/app_registrar.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
@@ -56,14 +66,19 @@
#include "chrome/grit/generated_resources.h"
#include "chrome/grit/settings_resources.h"
#include "chrome/grit/settings_resources_map.h"
+#include "components/content_settings/core/common/features.h"
#include "components/favicon_base/favicon_url_parser.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
+#include "components/safe_browsing/core/features.h"
+#include "components/signin/public/base/signin_pref_names.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
#include "printing/buildflags/buildflags.h"
+#include "ui/resources/grit/webui_resources.h"
#if defined(OS_WIN)
#include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h"
@@ -78,64 +93,28 @@
#if defined(OS_WIN) || defined(OS_CHROMEOS)
#include "chrome/browser/ui/webui/settings/languages_handler.h"
-#include "chrome/browser/ui/webui/settings/tts_handler.h"
#endif // defined(OS_WIN) || defined(OS_CHROMEOS)
#if defined(OS_CHROMEOS)
-#include "ash/public/cpp/network_config_service.h"
-#include "ash/public/cpp/resources/grit/ash_public_unscaled_resources.h"
-#include "ash/public/cpp/stylus_utils.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/chromeos/account_manager/account_manager_util.h"
#include "chrome/browser/chromeos/android_sms/android_sms_app_manager.h"
#include "chrome/browser/chromeos/android_sms/android_sms_service_factory.h"
-#include "chrome/browser/chromeos/arc/arc_util.h"
-#include "chrome/browser/chromeos/crostini/crostini_features.h"
-#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
-#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
#include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h"
-#include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
-#include "chrome/browser/ui/webui/chromeos/smb_shares/smb_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h"
#include "chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h"
#include "chrome/browser/ui/webui/settings/chromeos/android_apps_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/crostini_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/date_time_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/device_pointer_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/device_stylus_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/internet_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h"
#include "chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h"
-#include "chrome/browser/ui/webui/settings/chromeos/wallpaper_handler.h"
-#include "chrome/browser/web_applications/system_web_app_manager.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/grit/browser_resources.h"
#include "chromeos/components/account_manager/account_manager.h"
#include "chromeos/components/account_manager/account_manager_factory.h"
#include "chromeos/constants/chromeos_features.h"
-#include "chromeos/constants/chromeos_pref_names.h"
#include "chromeos/login/auth/password_visibility_utils.h"
-#include "chromeos/services/multidevice_setup/public/cpp/prefs.h"
-#include "chromeos/services/network_config/public/mojom/constants.mojom.h" // nogncheck
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" // nogncheck
#include "components/arc/arc_util.h"
-#include "components/prefs/pref_service.h"
#include "components/user_manager/user.h"
#include "ui/base/ui_base_features.h"
-#include "ui/chromeos/resources/grit/ui_chromeos_resources.h"
-#include "ui/resources/grit/webui_resources.h"
#else // !defined(OS_CHROMEOS)
#include "chrome/browser/signin/account_consistency_mode_manager.h"
#include "chrome/browser/ui/webui/settings/settings_default_browser_handler.h"
@@ -154,6 +133,12 @@
#endif
namespace settings {
+
+#if !BUILDFLAG(OPTIMIZE_WEBUI)
+constexpr char kGeneratedPath[] =
+ "@out_folder@/gen/chrome/browser/resources/settings/";
+#endif
+
// static
void SettingsUI::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
@@ -169,11 +154,7 @@ web_app::AppRegistrar& GetRegistrarForProfile(Profile* profile) {
}
SettingsUI::SettingsUI(content::WebUI* web_ui)
-#if defined(OS_CHROMEOS)
- : ui::MojoWebUIController(web_ui, /*enable_chrome_send =*/true),
-#else
: content::WebUIController(web_ui),
-#endif
webui_load_timer_(web_ui->GetWebContents(),
"Settings.LoadDocumentTime.MD",
"Settings.LoadCompletedTime.MD") {
@@ -181,6 +162,18 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
content::WebUIDataSource* html_source =
content::WebUIDataSource::Create(chrome::kChromeUISettingsHost);
+ // TODO(dpapad): Replace the following calls with
+ // SetupBundledWebUIDataSource() when Settings is migrated to Polymer3.
+ // Currently only used for testing the Polymer 3 version of
+ // certificate-manager.
+#if BUILDFLAG(OPTIMIZE_WEBUI)
+ html_source->EnableReplaceI18nInJS();
+ html_source->OverrideContentSecurityPolicyScriptSrc(
+ "script-src chrome://resources chrome://test 'self';");
+ html_source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER);
+ html_source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER);
+#endif
+
AddSettingsPageUIHandler(std::make_unique<AppearanceHandler>(web_ui));
#if defined(USE_NSS_CERTS)
@@ -192,12 +185,15 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
AddSettingsPageUIHandler(std::make_unique<AccessibilityMainHandler>());
AddSettingsPageUIHandler(std::make_unique<BrowserLifetimeHandler>());
- AddSettingsPageUIHandler(std::make_unique<ClearBrowsingDataHandler>(web_ui));
+ AddSettingsPageUIHandler(
+ std::make_unique<ClearBrowsingDataHandler>(web_ui, profile));
+ AddSettingsPageUIHandler(std::make_unique<SafetyCheckHandler>());
AddSettingsPageUIHandler(std::make_unique<CookiesViewHandler>());
AddSettingsPageUIHandler(std::make_unique<DownloadsHandler>(profile));
AddSettingsPageUIHandler(std::make_unique<ExtensionControlHandler>());
AddSettingsPageUIHandler(std::make_unique<FontHandler>(web_ui));
AddSettingsPageUIHandler(std::make_unique<ImportDataHandler>());
+ AddSettingsPageUIHandler(std::make_unique<HatsHandler>());
#if defined(OS_WIN) || defined(OS_CHROMEOS)
AddSettingsPageUIHandler(std::make_unique<LanguagesHandler>(web_ui));
@@ -212,7 +208,9 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
AddSettingsPageUIHandler(std::make_unique<PeopleHandler>(profile));
AddSettingsPageUIHandler(std::make_unique<ProfileInfoHandler>(profile));
AddSettingsPageUIHandler(std::make_unique<ProtocolHandlersHandler>());
+ AddSettingsPageUIHandler(std::make_unique<SafeBrowsingHandler>(profile));
AddSettingsPageUIHandler(std::make_unique<SearchEnginesHandler>(profile));
+ AddSettingsPageUIHandler(std::make_unique<SecureDnsHandler>());
AddSettingsPageUIHandler(std::make_unique<SiteSettingsHandler>(
profile, GetRegistrarForProfile(profile)));
AddSettingsPageUIHandler(std::make_unique<StartupPagesHandler>(web_ui));
@@ -227,9 +225,7 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
#endif
#if defined(OS_CHROMEOS)
- // TODO(950007): Remove this when SplitSettings is the default and there are
- // no Chrome OS settings in the browser settings page.
- InitOSWebUIHandlers(profile, web_ui, html_source);
+ InitBrowserSettingsWebUIHandlers();
#else
AddSettingsPageUIHandler(std::make_unique<DefaultBrowserHandler>());
AddSettingsPageUIHandler(std::make_unique<ManageProfileHandler>(profile));
@@ -256,60 +252,77 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
std::make_unique<IncompatibleApplicationsHandler>());
#endif // OS_WIN && BUILDFLAG(GOOGLE_CHROME_BRANDING)
-#if !defined(OS_CHROMEOS)
+ html_source->AddBoolean("signinAllowed", !profile->IsGuestSession() &&
+ profile->GetPrefs()->GetBoolean(
+ prefs::kSigninAllowed));
html_source->AddBoolean(
- "diceEnabled",
- AccountConsistencyModeManager::IsDiceEnabledForProfile(profile));
-#endif // !defined(OS_CHROMEOS)
+ "improvedCookieControlsEnabled",
+ base::FeatureList::IsEnabled(content_settings::kImprovedCookieControls));
html_source->AddBoolean(
"privacySettingsRedesignEnabled",
base::FeatureList::IsEnabled(features::kPrivacySettingsRedesign));
html_source->AddBoolean(
+ "safeBrowsingEnhancedEnabled",
+ base::FeatureList::IsEnabled(safe_browsing::kEnhancedProtection));
+
+ html_source->AddBoolean(
"navigateToGooglePasswordManager",
ShouldManagePasswordsinGooglePasswordManager(profile));
+ html_source->AddBoolean(
+ "enablePasswordCheck",
+ base::FeatureList::IsEnabled(password_manager::features::kPasswordCheck));
+
html_source->AddBoolean("showImportPasswords",
base::FeatureList::IsEnabled(
password_manager::features::kPasswordImport));
+ html_source->AddBoolean(
+ "enableAccountStorage",
+ base::FeatureList::IsEnabled(
+ password_manager::features::kEnablePasswordsAccountStorage));
+
+ html_source->AddBoolean(
+ "syncSetupFriendlySettings",
+ base::FeatureList::IsEnabled(features::kSyncSetupFriendlySettings));
+
#if defined(OS_CHROMEOS)
+ html_source->AddBoolean("splitSettingsSyncEnabled",
+ chromeos::features::IsSplitSettingsSyncEnabled());
+ html_source->AddBoolean("splitSyncConsent",
+ chromeos::features::IsSplitSyncConsentEnabled());
+
html_source->AddBoolean(
- "showParentalControls",
- chromeos::settings::ShouldShowParentalControls(profile));
+ "userCannotManuallyEnterPassword",
+ !chromeos::password_visibility::AccountHasUserFacingPassword(
+ chromeos::ProfileHelper::Get()
+ ->GetUserByProfile(profile)
+ ->GetAccountId()));
#endif
#if defined(OS_CHROMEOS)
// This is the browser settings page.
html_source->AddBoolean("isOSSettings", false);
- // If false, hides OS-specific settings (like networks) in browser settings.
- html_source->AddBoolean(
- "showOSSettings",
- !base::FeatureList::IsEnabled(chromeos::features::kSplitSettings));
-#else
- html_source->AddBoolean("showOSSettings", false);
#endif
+ // TODO(crbug.com/1026455): Delete this as part of the SplitSettings cleanup.
+ html_source->AddBoolean("showOSSettings", false);
AddSettingsPageUIHandler(
base::WrapUnique(AboutHandler::Create(html_source, profile)));
AddSettingsPageUIHandler(
base::WrapUnique(ResetSettingsHandler::Create(html_source, profile)));
+ // Add a handler to provide pluralized strings.
+ auto plural_string_handler = std::make_unique<PluralStringHandler>();
+ plural_string_handler->AddLocalizedString(
+ "compromisedPasswords", IDS_SETTINGS_COMPROMISED_PASSWORDS_COUNT);
+ web_ui->AddMessageHandler(std::move(plural_string_handler));
+
// Add the metrics handler to write uma stats.
web_ui->AddMessageHandler(std::make_unique<MetricsHandler>());
-#if defined(OS_CHROMEOS)
- // Add the System Web App resources for Settings.
- // TODO(jamescook|calamity): Migrate to chromeos::settings::OSSettingsUI.
- if (web_app::SystemWebAppManager::IsEnabled()) {
- html_source->AddResourcePath("icon-192.png", IDR_SETTINGS_LOGO_192);
- html_source->AddResourcePath("pwa.html", IDR_PWA_HTML);
- web_app::SetManifestRequestFilter(html_source, IDR_SETTINGS_MANIFEST,
- IDS_SETTINGS_SETTINGS);
- }
-#endif // defined (OS_CHROMEOS)
-
#if BUILDFLAG(OPTIMIZE_WEBUI)
html_source->AddResourcePath("crisper.js", IDR_SETTINGS_CRISPER_JS);
html_source->AddResourcePath("lazy_load.crisper.js",
@@ -317,16 +330,52 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
html_source->AddResourcePath("lazy_load.html",
IDR_SETTINGS_LAZY_LOAD_VULCANIZED_HTML);
html_source->SetDefaultResource(IDR_SETTINGS_VULCANIZED_HTML);
+
+ // Register SVG images that are purposefully not inlined in the HTML bundle
+ // above.
+ html_source->AddResourcePath("images/cookies_banner.svg",
+ IDR_SETTINGS_IMAGES_COOKIES_BANNER_SVG);
+ html_source->AddResourcePath("images/cookies_banner_dark.svg",
+ IDR_SETTINGS_IMAGES_COOKIES_BANNER_DARK_SVG);
+ html_source->AddResourcePath("images/permissions_banner.svg",
+ IDR_SETTINGS_IMAGES_PERMISSIONS_BANNER_SVG);
+ html_source->AddResourcePath("images/permissions_banner_dark.svg",
+ IDR_SETTINGS_IMAGES_PERMISSIONS_BANNER_DARK_SVG);
+ html_source->AddResourcePath("images/safe_browsing_banner.svg",
+ IDR_SETTINGS_IMAGES_SAFE_BROWSING_BANNER_SVG);
+ html_source->AddResourcePath(
+ "images/safe_browsing_banner_dark.svg",
+ IDR_SETTINGS_IMAGES_SAFE_BROWSING_BANNER_DARK_SVG);
+ html_source->AddResourcePath("images/sync_banner.svg",
+ IDR_SETTINGS_IMAGES_SYNC_BANNER_SVG);
+ html_source->AddResourcePath("images/sync_banner_dark.svg",
+ IDR_SETTINGS_IMAGES_SYNC_BANNER_DARK_SVG);
+ html_source->AddResourcePath("images/password_check_neutral.svg",
+ IDR_SETTINGS_IMAGES_PASSWORD_CHECK_NEUTRAL_SVG);
+ html_source->AddResourcePath(
+ "images/password_check_neutral_dark.svg",
+ IDR_SETTINGS_IMAGES_PASSWORD_CHECK_NEUTRAL_DARK_SVG);
+ html_source->AddResourcePath("images/password_check_positive.svg",
+ IDR_SETTINGS_IMAGES_PASSWORD_CHECK_POSITIVE_SVG);
+ html_source->AddResourcePath(
+ "images/password_check_positive_dark.svg",
+ IDR_SETTINGS_IMAGES_PASSWORD_CHECK_POSITIVE_DARK_SVG);
+
+ // Only used in Polymer 3, see https://crbug.com/1026426.
+ html_source->AddResourcePath("settings.js", IDR_SETTINGS_SETTINGS_ROLLUP_JS);
+ html_source->AddResourcePath("shared.rollup.js",
+ IDR_SETTINGS_SHARED_ROLLUP_JS);
+ html_source->AddResourcePath("lazy_load.js",
+ IDR_SETTINGS_LAZY_LOAD_ROLLUP_JS);
+ html_source->AddResourcePath("settings_v3.html",
+ IDR_SETTINGS_SETTINGS_V3_HTML);
#else
- // Add all settings resources.
- for (size_t i = 0; i < kSettingsResourcesSize; ++i) {
- html_source->AddResourcePath(kSettingsResources[i].name,
- kSettingsResources[i].value);
- }
- html_source->SetDefaultResource(IDR_SETTINGS_SETTINGS_HTML);
+ webui::SetupWebUIDataSource(
+ html_source, base::make_span(kSettingsResources, kSettingsResourcesSize),
+ kGeneratedPath, IDR_SETTINGS_SETTINGS_HTML);
#endif
- AddLocalizedStrings(html_source, profile, web_ui->GetWebContents());
+ AddBrowserLocalizedStrings(html_source, profile, web_ui->GetWebContents());
ManagedUIHandler::Initialize(web_ui, html_source);
@@ -337,19 +386,15 @@ SettingsUI::SettingsUI(content::WebUI* web_ui)
profile, std::make_unique<FaviconSource>(
profile, chrome::FaviconUrlFormat::kFavicon2));
-#if defined(OS_CHROMEOS)
- AddHandlerToRegistry(base::BindRepeating(&SettingsUI::BindCrosNetworkConfig,
- base::Unretained(this)));
-#endif // defined (OS_CHROMEOS)
+ TryShowHatsSurveyWithTimeout();
}
SettingsUI::~SettingsUI() = default;
#if defined(OS_CHROMEOS)
-// static
-void SettingsUI::InitOSWebUIHandlers(Profile* profile,
- content::WebUI* web_ui,
- content::WebUIDataSource* html_source) {
+void SettingsUI::InitBrowserSettingsWebUIHandlers() {
+ Profile* profile = Profile::FromWebUI(web_ui());
+
// TODO(jamescook): Sort out how account management is split between Chrome OS
// and browser settings.
if (chromeos::IsAccountManagerAvailable(profile)) {
@@ -359,75 +404,19 @@ void SettingsUI::InitOSWebUIHandlers(Profile* profile,
factory->GetAccountManager(profile->GetPath().value());
DCHECK(account_manager);
- web_ui->AddMessageHandler(
+ web_ui()->AddMessageHandler(
std::make_unique<chromeos::settings::AccountManagerUIHandler>(
account_manager, IdentityManagerFactory::GetForProfile(profile)));
- html_source->AddBoolean(
- "secondaryGoogleAccountSigninAllowed",
- profile->GetPrefs()->GetBoolean(
- chromeos::prefs::kSecondaryGoogleAccountSigninAllowed));
- }
-
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::ChangePictureHandler>());
-
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::AccessibilityHandler>(web_ui));
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::AndroidAppsHandler>(profile));
- if (crostini::CrostiniFeatures::Get()->IsUIAllowed(profile,
- /*check_policy=*/false)) {
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::CrostiniHandler>(profile));
- }
- web_ui->AddMessageHandler(
- chromeos::settings::CupsPrintersHandler::Create(web_ui));
- web_ui->AddMessageHandler(base::WrapUnique(
- chromeos::settings::DateTimeHandler::Create(html_source)));
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::FingerprintHandler>(profile));
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::GoogleAssistantHandler>(profile));
-
- std::unique_ptr<chromeos::settings::KerberosAccountsHandler>
- kerberos_accounts_handler =
- chromeos::settings::KerberosAccountsHandler::CreateIfKerberosEnabled(
- profile);
- if (kerberos_accounts_handler) {
- // Note that the UI is enabled only if Kerberos is enabled.
- web_ui->AddMessageHandler(std::move(kerberos_accounts_handler));
}
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::KeyboardHandler>());
-
- // TODO(crbug/950007): Remove adding WallpaperHandler when
- // SplitSettings complete.
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::WallpaperHandler>(web_ui));
-
- if (plugin_vm::IsPluginVmEnabled(profile)) {
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::PluginVmHandler>(profile));
- }
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::PointerHandler>());
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::StorageHandler>(profile,
- html_source));
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::StylusHandler>());
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::InternetHandler>(profile));
- web_ui->AddMessageHandler(std::make_unique<TtsHandler>());
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::smb_dialog::SmbHandler>(profile));
-
+ // MultideviceHandler is required in browser settings to show a special note
+ // under the notification permission that is auto-granted for Android Messages
+ // integration in ChromeOS.
if (!profile->IsGuestSession()) {
chromeos::android_sms::AndroidSmsService* android_sms_service =
chromeos::android_sms::AndroidSmsServiceFactory::GetForBrowserContext(
profile);
- web_ui->AddMessageHandler(
+ web_ui()->AddMessageHandler(
std::make_unique<chromeos::settings::MultideviceHandler>(
profile->GetPrefs(),
chromeos::multidevice_setup::MultiDeviceSetupClientFactory::
@@ -437,93 +426,10 @@ void SettingsUI::InitOSWebUIHandlers(Profile* profile,
: nullptr,
android_sms_service ? android_sms_service->android_sms_app_manager()
: nullptr));
- if (chromeos::settings::ShouldShowParentalControls(profile)) {
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::ParentalControlsHandler>(
- profile));
- }
- }
-
- html_source->AddBoolean(
- "privacySettingsRedesignEnabled",
- base::FeatureList::IsEnabled(::features::kPrivacySettingsRedesign));
-
- html_source->AddBoolean(
- "multideviceAllowedByPolicy",
- chromeos::multidevice_setup::AreAnyMultiDeviceFeaturesAllowed(
- profile->GetPrefs()));
- html_source->AddBoolean(
- "quickUnlockEnabled",
- chromeos::quick_unlock::IsPinEnabled(profile->GetPrefs()));
- html_source->AddBoolean(
- "quickUnlockDisabledByPolicy",
- chromeos::quick_unlock::IsPinDisabledByPolicy(profile->GetPrefs()));
- html_source->AddBoolean(
- "userCannotManuallyEnterPassword",
- !chromeos::password_visibility::AccountHasUserFacingPassword(
- chromeos::ProfileHelper::Get()
- ->GetUserByProfile(profile)
- ->GetAccountId()));
- const bool fingerprint_unlock_enabled =
- chromeos::quick_unlock::IsFingerprintEnabled(profile);
- html_source->AddBoolean("fingerprintUnlockEnabled",
- fingerprint_unlock_enabled);
- if (fingerprint_unlock_enabled) {
- html_source->AddInteger(
- "fingerprintReaderLocation",
- static_cast<int32_t>(chromeos::quick_unlock::GetFingerprintLocation()));
-
- // To use lottie, the worker-src CSP needs to be updated for the web ui that
- // is using it. Since as of now there are only a couple of webuis using
- // lottie animations, this update has to be performed manually. As the usage
- // increases, set this as the default so manual override is no longer
- // required.
- html_source->OverrideContentSecurityPolicyWorkerSrc(
- "worker-src blob: 'self';");
- html_source->AddResourcePath("finger_print.json",
- IDR_LOGIN_FINGER_PRINT_TABLET_ANIMATION);
}
- html_source->AddBoolean("lockScreenNotificationsEnabled",
- ash::features::IsLockScreenNotificationsEnabled());
- html_source->AddBoolean(
- "lockScreenHideSensitiveNotificationsSupported",
- ash::features::IsLockScreenHideSensitiveNotificationsSupported());
- html_source->AddBoolean("showTechnologyBadge",
- !ash::features::IsSeparateNetworkIconsEnabled());
- html_source->AddBoolean("hasInternalStylus",
- ash::stylus_utils::HasInternalStylus());
-
- html_source->AddBoolean("showCrostini",
- crostini::CrostiniFeatures::Get()->IsUIAllowed(
- profile, /*check_policy=*/false));
-
- html_source->AddBoolean(
- "allowCrostini", crostini::CrostiniFeatures::Get()->IsUIAllowed(profile));
- html_source->AddBoolean("showPluginVm",
- plugin_vm::IsPluginVmEnabled(profile));
-
- html_source->AddBoolean("isDemoSession",
- chromeos::DemoSession::IsDeviceInDemoMode());
-
- // We have 2 variants of Android apps settings. Default case, when the Play
- // Store app exists we show expandable section that allows as to
- // enable/disable the Play Store and link to Android settings which is
- // available once settings app is registered in the system.
- // For AOSP images we don't have the Play Store app. In last case we Android
- // apps settings consists only from root link to Android settings and only
- // visible once settings app is registered.
- html_source->AddBoolean("androidAppsVisible",
- arc::IsArcAllowedForProfile(profile));
- html_source->AddBoolean("havePlayStoreApp", arc::IsPlayStoreAvailable());
-
- html_source->AddBoolean("enablePowerSettings", true);
- web_ui->AddMessageHandler(
- std::make_unique<chromeos::settings::PowerHandler>(profile->GetPrefs()));
-
- html_source->AddBoolean(
- "showParentalControlsSettings",
- chromeos::settings::ShouldShowParentalControls(profile));
+ web_ui()->AddMessageHandler(
+ std::make_unique<chromeos::settings::AndroidAppsHandler>(profile));
}
#endif // defined(OS_CHROMEOS)
@@ -533,12 +439,14 @@ void SettingsUI::AddSettingsPageUIHandler(
web_ui()->AddMessageHandler(std::move(handler));
}
-#if defined(OS_CHROMEOS)
-void SettingsUI::BindCrosNetworkConfig(
- mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
- receiver) {
- ash::GetNetworkConfigService(std::move(receiver));
+void SettingsUI::TryShowHatsSurveyWithTimeout() {
+ HatsService* hats_service =
+ HatsServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()),
+ /* create_if_necessary = */ true);
+ if (hats_service) {
+ hats_service->LaunchDelayedSurveyForWebContents(
+ kHatsSurveyTriggerSettings, web_ui()->GetWebContents(), 20000);
+ }
}
-#endif // defined(OS_CHROMEOS)
} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_ui.h b/chromium/chrome/browser/ui/webui/settings/settings_ui.h
index 0353806fc15..ff4a05c608e 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_ui.h
+++ b/chromium/chrome/browser/ui/webui/settings/settings_ui.h
@@ -8,19 +8,9 @@
#include "base/macros.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/webui_load_timer.h"
-
-#if defined(OS_CHROMEOS)
-#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h" // nogncheck
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "ui/webui/mojo_web_ui_controller.h"
-#else
#include "content/public/browser/web_ui_controller.h"
-#endif
-
-class Profile;
namespace content {
-class WebUIDataSource;
class WebUIMessageHandler;
} // namespace content
@@ -31,13 +21,7 @@ class PrefRegistrySyncable;
namespace settings {
// The WebUI handler for chrome://settings.
-class SettingsUI
-#if defined(OS_CHROMEOS)
- : public ui::MojoWebUIController
-#else
- : public content::WebUIController
-#endif
-{
+class SettingsUI : public content::WebUIController {
public:
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
@@ -45,20 +29,17 @@ class SettingsUI
~SettingsUI() override;
#if defined(OS_CHROMEOS)
- // Initializes the WebUI message handlers for OS-specific settings.
- static void InitOSWebUIHandlers(Profile* profile,
- content::WebUI* web_ui,
- content::WebUIDataSource* html_source);
+ // Initializes the WebUI message handlers for CrOS-specific settings that are
+ // still shown in the browser settings UI.
+ void InitBrowserSettingsWebUIHandlers();
#endif // defined(OS_CHROMEOS)
private:
void AddSettingsPageUIHandler(
std::unique_ptr<content::WebUIMessageHandler> handler);
-#if defined(OS_CHROMEOS)
- void BindCrosNetworkConfig(
- mojo::PendingReceiver<chromeos::network_config::mojom::CrosNetworkConfig>
- receiver);
-#endif
+
+ // Makes a request to show a HaTS survey.
+ void TryShowHatsSurveyWithTimeout();
WebuiLoadTimer webui_load_timer_;
diff --git a/chromium/chrome/browser/ui/webui/settings/settings_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/settings_ui_browsertest.cc
index 459f2165900..c19638cf1bc 100644
--- a/chromium/chrome/browser/ui/webui/settings/settings_ui_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/settings/settings_ui_browsertest.cc
@@ -5,7 +5,10 @@
#include <string>
#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/hats/hats_service_factory.h"
+#include "chrome/browser/ui/hats/mock_hats_service.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/settings/settings_ui.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
@@ -17,6 +20,7 @@
typedef InProcessBrowserTest SettingsUITest;
+using ::testing::_;
using ui_test_utils::NavigateToURL;
IN_PROC_BROWSER_TEST_F(SettingsUITest, ViewSourceDoesntCrash) {
@@ -43,3 +47,13 @@ IN_PROC_BROWSER_TEST_F(SettingsUITest, ToggleJavaScript) {
handler->AllowJavascriptForTesting();
}
}
+
+IN_PROC_BROWSER_TEST_F(SettingsUITest, TriggerHappinessTrackingSurveys) {
+ MockHatsService* mock_hats_service_ = static_cast<MockHatsService*>(
+ HatsServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+ browser()->profile(), base::BindRepeating(&BuildMockHatsService)));
+ EXPECT_CALL(*mock_hats_service_, LaunchDelayedSurveyForWebContents(
+ kHatsSurveyTriggerSettings, _, _));
+ NavigateToURL(browser(), GURL(chrome::kChromeUISettingsURL));
+ base::RunLoop().RunUntilIdle();
+}
diff --git a/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc
new file mode 100644
index 00000000000..9a461686fd3
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc
@@ -0,0 +1,243 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h"
+
+#include "base/feature_list.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/system/sys_info.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/browser_process_platform_part.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/webui/webui_util.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "chromeos/constants/chromeos_features.h"
+#include "components/google/core/common/google_util.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/user_manager/user_manager.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/content_features.h"
+#include "media/base/media_switches.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
+
+#if defined(OS_CHROMEOS)
+#include "ui/base/l10n/l10n_util.h"
+#endif
+
+namespace settings {
+#if defined(OS_CHROMEOS)
+namespace {
+
+// Generates a Google Help URL which includes a "board type" parameter. Some
+// help pages need to be adjusted depending on the type of CrOS device that is
+// accessing the page.
+base::string16 GetHelpUrlWithBoard(const std::string& original_url) {
+ return base::ASCIIToUTF16(original_url +
+ "&b=" + base::SysInfo::GetLsbReleaseBoard());
+}
+
+} // namespace
+#endif
+
+void AddCaptionSubpageStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"captionsTitle", IDS_SETTINGS_CAPTIONS},
+ {"captionsSettings", IDS_SETTINGS_CAPTIONS_SETTINGS},
+ {"captionsPreview", IDS_SETTINGS_CAPTIONS_PREVIEW},
+ {"captionsTextSize", IDS_SETTINGS_CAPTIONS_TEXT_SIZE},
+ {"captionsTextFont", IDS_SETTINGS_CAPTIONS_TEXT_FONT},
+ {"captionsTextColor", IDS_SETTINGS_CAPTIONS_TEXT_COLOR},
+ {"captionsTextOpacity", IDS_SETTINGS_CAPTIONS_TEXT_OPACITY},
+ {"captionsBackgroundOpacity", IDS_SETTINGS_CAPTIONS_BACKGROUND_OPACITY},
+ {"captionsOpacityOpaque", IDS_SETTINGS_CAPTIONS_OPACITY_OPAQUE},
+ {"captionsOpacitySemiTransparent",
+ IDS_SETTINGS_CAPTIONS_OPACITY_SEMI_TRANSPARENT},
+ {"captionsOpacityTransparent", IDS_SETTINGS_CAPTIONS_OPACITY_TRANSPARENT},
+ {"captionsTextShadow", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW},
+ {"captionsTextShadowNone", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_NONE},
+ {"captionsTextShadowRaised", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_RAISED},
+ {"captionsTextShadowDepressed",
+ IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DEPRESSED},
+ {"captionsTextShadowUniform", IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_UNIFORM},
+ {"captionsTextShadowDropShadow",
+ IDS_SETTINGS_CAPTIONS_TEXT_SHADOW_DROP_SHADOW},
+ {"captionsBackgroundColor", IDS_SETTINGS_CAPTIONS_BACKGROUND_COLOR},
+ {"captionsColorBlack", IDS_SETTINGS_CAPTIONS_COLOR_BLACK},
+ {"captionsColorWhite", IDS_SETTINGS_CAPTIONS_COLOR_WHITE},
+ {"captionsColorRed", IDS_SETTINGS_CAPTIONS_COLOR_RED},
+ {"captionsColorGreen", IDS_SETTINGS_CAPTIONS_COLOR_GREEN},
+ {"captionsColorBlue", IDS_SETTINGS_CAPTIONS_COLOR_BLUE},
+ {"captionsColorYellow", IDS_SETTINGS_CAPTIONS_COLOR_YELLOW},
+ {"captionsColorCyan", IDS_SETTINGS_CAPTIONS_COLOR_CYAN},
+ {"captionsColorMagenta", IDS_SETTINGS_CAPTIONS_COLOR_MAGENTA},
+ {"captionsDefaultSetting", IDS_SETTINGS_CAPTIONS_DEFAULT_SETTING},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddPersonalizationOptionsStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"urlKeyedAnonymizedDataCollection",
+ IDS_SETTINGS_ENABLE_URL_KEYED_ANONYMIZED_DATA_COLLECTION},
+ {"urlKeyedAnonymizedDataCollectionDesc",
+ IDS_SETTINGS_ENABLE_URL_KEYED_ANONYMIZED_DATA_COLLECTION_DESC},
+ {"spellingPref", IDS_SETTINGS_SPELLING_PREF},
+#if !defined(OS_CHROMEOS)
+ {"signinAllowedTitle", IDS_SETTINGS_SIGNIN_ALLOWED},
+ {"signinAllowedDescription", IDS_SETTINGS_SIGNIN_ALLOWED_DESC},
+#endif
+ {"searchSuggestPref", IDS_SETTINGS_SUGGEST_PREF},
+ {"enablePersonalizationLogging", IDS_SETTINGS_ENABLE_LOGGING_PREF},
+ {"enablePersonalizationLoggingDesc", IDS_SETTINGS_ENABLE_LOGGING_PREF_DESC},
+ {"spellingDescription", IDS_SETTINGS_SPELLING_PREF_DESC},
+ {"searchSuggestPrefDesc", IDS_SETTINGS_SUGGEST_PREF_DESC},
+ {"linkDoctorPref", IDS_SETTINGS_LINKDOCTOR_PREF},
+ {"linkDoctorPrefDesc", IDS_SETTINGS_LINKDOCTOR_PREF_DESC},
+ {"driveSuggestPref", IDS_DRIVE_SUGGEST_PREF},
+ {"driveSuggestPrefDesc", IDS_DRIVE_SUGGEST_PREF_DESC},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddSyncControlsStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"autofillCheckboxLabel", IDS_SETTINGS_AUTOFILL_CHECKBOX_LABEL},
+ {"historyCheckboxLabel", IDS_SETTINGS_HISTORY_CHECKBOX_LABEL},
+ {"extensionsCheckboxLabel", IDS_SETTINGS_EXTENSIONS_CHECKBOX_LABEL},
+ {"openTabsCheckboxLabel", IDS_SETTINGS_OPEN_TABS_CHECKBOX_LABEL},
+ {"syncEverythingCheckboxLabel",
+ IDS_SETTINGS_SYNC_EVERYTHING_CHECKBOX_LABEL},
+ {"appCheckboxLabel", IDS_SETTINGS_APPS_CHECKBOX_LABEL},
+ {"enablePaymentsIntegrationCheckboxLabel",
+ IDS_AUTOFILL_ENABLE_PAYMENTS_INTEGRATION_CHECKBOX_LABEL},
+ {"nonPersonalizedServicesSectionLabel",
+ IDS_SETTINGS_NON_PERSONALIZED_SERVICES_SECTION_LABEL},
+ {"customizeSyncLabel", IDS_SETTINGS_CUSTOMIZE_SYNC},
+ {"syncData", IDS_SETTINGS_SYNC_DATA},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+
+void AddSyncAccountControlStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"syncingTo", IDS_SETTINGS_PEOPLE_SYNCING_TO_ACCOUNT},
+ {"peopleSignIn", IDS_PROFILES_DICE_SIGNIN_BUTTON},
+ {"syncPaused", IDS_SETTINGS_PEOPLE_SYNC_PAUSED},
+ {"turnOffSync", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF},
+ {"settingsCheckboxLabel", IDS_SETTINGS_SETTINGS_CHECKBOX_LABEL},
+ {"syncNotWorking", IDS_SETTINGS_PEOPLE_SYNC_NOT_WORKING},
+ {"syncDisabled", IDS_PROFILES_DICE_SYNC_DISABLED_TITLE},
+ {"syncPasswordsNotWorking",
+ IDS_SETTINGS_PEOPLE_SYNC_PASSWORDS_NOT_WORKING},
+ {"peopleSignOut", IDS_SETTINGS_PEOPLE_SIGN_OUT},
+ {"useAnotherAccount", IDS_SETTINGS_PEOPLE_SYNC_ANOTHER_ACCOUNT},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+ if (base::FeatureList::IsEnabled(features::kSyncSetupFriendlySettings)) {
+ html_source->AddLocalizedString("syncAdvancedPageTitle",
+ IDS_SETTINGS_NEW_SYNC_ADVANCED_PAGE_TITLE);
+
+ } else {
+ html_source->AddLocalizedString("syncAdvancedPageTitle",
+ IDS_SETTINGS_SYNC_ADVANCED_PAGE_TITLE);
+ }
+}
+
+#if defined(OS_CHROMEOS)
+void AddPasswordPromptDialogStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"passwordPromptTitle", IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_TITLE},
+ {"passwordPromptInvalidPassword",
+ IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_INVALID_PASSWORD},
+ {"passwordPromptPasswordLabel",
+ IDS_SETTINGS_PEOPLE_PASSWORD_PROMPT_PASSWORD_LABEL},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+}
+#endif
+
+void AddSyncPageStrings(content::WebUIDataSource* html_source) {
+ static constexpr webui::LocalizedString kLocalizedStrings[] = {
+ {"syncDisabledByAdministrator",
+ IDS_SIGNED_IN_WITH_SYNC_DISABLED_BY_POLICY},
+ {"passwordsCheckboxLabel", IDS_SETTINGS_PASSWORDS_CHECKBOX_LABEL},
+ {"passphrasePlaceholder", IDS_SETTINGS_PASSPHRASE_PLACEHOLDER},
+ {"peopleSignInSyncPagePromptSecondaryWithAccount",
+ IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT},
+ {"peopleSignInSyncPagePromptSecondaryWithNoAccount",
+ IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT},
+ {"existingPassphraseTitle", IDS_SETTINGS_EXISTING_PASSPHRASE_TITLE},
+ {"submitPassphraseButton", IDS_SETTINGS_SUBMIT_PASSPHRASE},
+ {"encryptWithGoogleCredentialsLabel",
+ IDS_SETTINGS_ENCRYPT_WITH_GOOGLE_CREDENTIALS_LABEL},
+ {"bookmarksCheckboxLabel", IDS_SETTINGS_BOOKMARKS_CHECKBOX_LABEL},
+ {"encryptionOptionsTitle", IDS_SETTINGS_ENCRYPTION_OPTIONS},
+ {"mismatchedPassphraseError", IDS_SETTINGS_MISMATCHED_PASSPHRASE_ERROR},
+ {"emptyPassphraseError", IDS_SETTINGS_EMPTY_PASSPHRASE_ERROR},
+ {"incorrectPassphraseError", IDS_SETTINGS_INCORRECT_PASSPHRASE_ERROR},
+ {"syncPageTitle", IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES},
+ {"passphraseConfirmationPlaceholder",
+ IDS_SETTINGS_PASSPHRASE_CONFIRMATION_PLACEHOLDER},
+ {"syncLoading", IDS_SETTINGS_SYNC_LOADING},
+ {"themesAndWallpapersCheckboxLabel",
+ IDS_SETTINGS_THEMES_AND_WALLPAPERS_CHECKBOX_LABEL},
+ {"syncDataEncryptedText", IDS_SETTINGS_SYNC_DATA_ENCRYPTED_TEXT},
+ {"sync", IDS_SETTINGS_SYNC},
+ {"cancelSync", IDS_SETTINGS_SYNC_SETTINGS_CANCEL_SYNC},
+ {"syncSetupCancelDialogTitle",
+ IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_TITLE},
+ {"syncSetupCancelDialogBody", IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_BODY},
+ {"personalizeGoogleServicesTitle",
+ IDS_SETTINGS_PERSONALIZE_GOOGLE_SERVICES_TITLE},
+ };
+ AddLocalizedStringsBulk(html_source, kLocalizedStrings);
+
+ std::string sync_dashboard_url =
+ google_util::AppendGoogleLocaleParam(
+ GURL(chrome::kSyncGoogleDashboardURL),
+ g_browser_process->GetApplicationLocale())
+ .spec();
+
+ html_source->AddString(
+ "passphraseResetHintEncryption",
+ l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_RESET_HINT_ENCRYPTION,
+ base::ASCIIToUTF16(sync_dashboard_url)));
+ html_source->AddString(
+ "passphraseRecover",
+ l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_RECOVER,
+ base::ASCIIToUTF16(sync_dashboard_url)));
+ html_source->AddString("activityControlsUrl",
+ chrome::kGoogleAccountActivityControlsURL);
+ html_source->AddString("syncDashboardUrl", sync_dashboard_url);
+ html_source->AddString(
+ "passphraseExplanationText",
+ l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_EXPLANATION_TEXT,
+ base::ASCIIToUTF16(sync_dashboard_url)));
+ html_source->AddString(
+ "encryptWithSyncPassphraseLabel",
+ l10n_util::GetStringFUTF8(
+ IDS_SETTINGS_ENCRYPT_WITH_SYNC_PASSPHRASE_LABEL,
+#if defined(OS_CHROMEOS)
+ GetHelpUrlWithBoard(chrome::kSyncEncryptionHelpURL)));
+#else
+ base::ASCIIToUTF16(chrome::kSyncEncryptionHelpURL)));
+#endif
+ if (base::FeatureList::IsEnabled(features::kSyncSetupFriendlySettings)) {
+ html_source->AddLocalizedString(
+ "manageSyncedDataTitle",
+ IDS_SETTINGS_NEW_MANAGE_SYNCED_DATA_TITLE_UNIFIED_CONSENT);
+ } else {
+ html_source->AddLocalizedString(
+ "manageSyncedDataTitle",
+ IDS_SETTINGS_MANAGE_SYNCED_DATA_TITLE_UNIFIED_CONSENT);
+ }
+}
+
+} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h b/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h
new file mode 100644
index 00000000000..33dc5c453d4
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h
@@ -0,0 +1,36 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_SHARED_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
+#define CHROME_BROWSER_UI_WEBUI_SETTINGS_SHARED_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
+
+namespace content {
+class WebUIDataSource;
+} // namespace content
+
+namespace settings {
+
+// Adds strings used by the <settings-captions> element.
+void AddCaptionSubpageStrings(content::WebUIDataSource* html_source);
+
+// Adds strings used by the <settings-personalization-options> element.
+void AddPersonalizationOptionsStrings(content::WebUIDataSource* html_source);
+
+// Adds strings used by the <settings-sync-controls> element.
+void AddSyncControlsStrings(content::WebUIDataSource* html_source);
+
+// Adds strings used by the <settings-sync-account-control> element.
+void AddSyncAccountControlStrings(content::WebUIDataSource* html_source);
+
+#if defined(OS_CHROMEOS)
+// Adds strings used by the <settings-password-prompt-dialog> element.
+void AddPasswordPromptDialogStrings(content::WebUIDataSource* html_source);
+#endif
+
+// Adds strings used by the <settings-sync-page> element.
+void AddSyncPageStrings(content::WebUIDataSource* html_source);
+
+} // namespace settings
+
+#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_SHARED_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_
diff --git a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc
index 95ccbe20024..b53e4f98315 100644
--- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc
+++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc
@@ -5,11 +5,13 @@
#include "chrome/browser/ui/webui/settings/site_settings_handler.h"
#include <algorithm>
+#include <set>
#include <utility>
#include <vector>
#include "base/barrier_closure.h"
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/i18n/number_formatting.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
@@ -17,22 +19,22 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/browser/bluetooth/bluetooth_chooser_context.h"
+#include "chrome/browser/bluetooth/bluetooth_chooser_context_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/content_settings/web_site_settings_uma_util.h"
#include "chrome/browser/engagement/site_engagement_service.h"
+#include "chrome/browser/hid/hid_chooser_context.h"
+#include "chrome/browser/hid/hid_chooser_context_factory.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/media/unified_autoplay_config.h"
-#include "chrome/browser/permissions/chooser_context_base.h"
-#include "chrome/browser/permissions/permission_decision_auto_blocker.h"
-#include "chrome/browser/permissions/permission_manager.h"
-#include "chrome/browser/permissions/permission_uma_util.h"
-#include "chrome/browser/permissions/permission_util.h"
+#include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
#include "chrome/browser/serial/serial_chooser_context.h"
#include "chrome/browser/serial/serial_chooser_context_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/page_info/page_info_infobar_delegate.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/recent_site_settings_helper.h"
#include "chrome/browser/ui/webui/site_settings_helper.h"
#include "chrome/browser/usb/usb_chooser_context.h"
#include "chrome/browser/usb/usb_chooser_context_factory.h"
@@ -41,15 +43,24 @@
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/content_settings/core/browser/uma_util.h"
#include "components/content_settings/core/browser/website_settings_registry.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/content_settings/core/common/content_settings_utils.h"
+#include "components/content_settings/core/common/features.h"
+#include "components/content_settings/core/common/pref_names.h"
#include "components/crx_file/id_util.h"
+#include "components/permissions/chooser_context_base.h"
+#include "components/permissions/permission_decision_auto_blocker.h"
+#include "components/permissions/permission_uma_util.h"
+#include "components/permissions/permission_util.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/extension_registry.h"
@@ -92,6 +103,17 @@ enum class AllSitesAction {
kMaxValue = kEnterSiteDetails,
};
+enum class AllSitesAction2 {
+ kLoadPage = 0,
+ kResetSiteGroupPermissions = 1,
+ kResetOriginPermissions = 2,
+ kClearAllData = 3,
+ kClearSiteGroupData = 4,
+ kClearOriginData = 5,
+ kEnterSiteDetails = 6,
+ kMaxValue = kEnterSiteDetails,
+};
+
// Return an appropriate API Permission ID for the given string name.
extensions::APIPermission::APIPermission::ID APIPermissionFromGroupName(
std::string type) {
@@ -142,32 +164,13 @@ void AddExceptionsGrantedByHostedApps(
}
}
-base::flat_set<web_app::AppId> GetInstalledApps(
+base::flat_set<std::string> GetInstalledAppOrigins(
Profile* profile,
- web_app::AppRegistrar& registrar) {
- auto apps = registrar.GetAppIds();
- base::flat_set<std::string> installed;
- for (auto app : apps) {
- base::Optional<GURL> scope = registrar.GetAppScope(app);
- if (scope.has_value())
- installed.insert(scope.value().GetOrigin().spec());
- }
- return installed;
-}
-
-// Whether |pattern| applies to a single origin.
-bool PatternAppliesToSingleOrigin(const ContentSettingPatternSource& pattern) {
- const GURL url(pattern.primary_pattern.ToString());
- // Default settings and other patterns apply to multiple origins.
- if (url::Origin::Create(url).opaque())
- return false;
- // Embedded content settings only when |url| is embedded in another origin, so
- // ignore non-wildcard secondary patterns that are different to the primary.
- if (pattern.primary_pattern != pattern.secondary_pattern &&
- pattern.secondary_pattern != ContentSettingsPattern::Wildcard()) {
- return false;
- }
- return true;
+ const web_app::AppRegistrar& registrar) {
+ base::flat_set<std::string> origins;
+ for (const web_app::AppId& app : registrar.GetAppIds())
+ origins.insert(registrar.GetAppScope(app).GetOrigin().spec());
+ return origins;
}
// Groups |url| into sets of eTLD+1s in |site_group_map|, assuming |url| is an
@@ -236,11 +239,11 @@ void ConvertSiteGroupMapToListValue(
const std::set<std::string>& origin_permission_set,
base::Value* list_value,
Profile* profile,
- web_app::AppRegistrar& registrar) {
+ const web_app::AppRegistrar& registrar) {
DCHECK_EQ(base::Value::Type::LIST, list_value->type());
DCHECK(profile);
- base::flat_set<web_app::AppId> installed_apps =
- GetInstalledApps(profile, registrar);
+ base::flat_set<std::string> installed_origins =
+ GetInstalledAppOrigins(profile, registrar);
SiteEngagementService* engagement_service =
SiteEngagementService::Get(profile);
for (const auto& entry : site_group_map) {
@@ -267,7 +270,7 @@ void ConvertSiteGroupMapToListValue(
origin_object.SetKey("usage", base::Value(0));
origin_object.SetKey(kNumCookies, base::Value(0));
- bool is_installed = installed_apps.contains(origin);
+ bool is_installed = installed_origins.contains(origin);
if (is_installed)
has_installed_pwa = true;
origin_object.SetKey(kIsInstalled, base::Value(is_installed));
@@ -327,8 +330,58 @@ void UpdateDataFromCookiesTree(
CreateOrAppendSiteGroupEntry(all_sites_map, origin);
}
-void LogAllSitesAction(AllSitesAction action) {
- UMA_HISTOGRAM_ENUMERATION("WebsiteSettings.AllSitesAction", action);
+void LogAllSitesAction(AllSitesAction2 action) {
+ UMA_HISTOGRAM_ENUMERATION("WebsiteSettings.AllSitesAction2", action);
+}
+
+int GetNumCookieExceptionsOfTypes(HostContentSettingsMap* map,
+ const std::set<ContentSetting> types) {
+ ContentSettingsForOneType output;
+ map->GetSettingsForOneType(ContentSettingsType::COOKIES, std::string(),
+ &output);
+ return std::count_if(
+ output.begin(), output.end(),
+ [types](const ContentSettingPatternSource setting) {
+ return types.count(
+ content_settings::ValueToContentSetting(&setting.setting_value));
+ });
+}
+
+std::string GetCookieSettingDescription(Profile* profile) {
+ HostContentSettingsMap* map =
+ HostContentSettingsMapFactory::GetForProfile(profile);
+ auto content_setting =
+ map->GetDefaultContentSetting(ContentSettingsType::COOKIES, nullptr);
+
+ bool block_third_party =
+ profile->GetPrefs()->GetBoolean(prefs::kBlockThirdPartyCookies);
+ auto control_mode = static_cast<content_settings::CookieControlsMode>(
+ profile->GetPrefs()->GetInteger(prefs::kCookieControlsMode));
+
+ // Determine what the effective cookie setting is. These conditions are not
+ // mutually exclusive and rely on ordering.
+ if (content_setting == ContentSetting::CONTENT_SETTING_BLOCK) {
+ return l10n_util::GetPluralStringFUTF8(
+ IDS_SETTINGS_SITE_SETTINGS_COOKIES_BLOCK,
+ GetNumCookieExceptionsOfTypes(
+ map, {ContentSetting::CONTENT_SETTING_ALLOW,
+ ContentSetting::CONTENT_SETTING_SESSION_ONLY}));
+ } else if (block_third_party) {
+ return l10n_util::GetStringUTF8(
+ IDS_SETTINGS_SITE_SETTINGS_COOKIES_BLOCK_THIRD_PARTY);
+ } else if (base::FeatureList::IsEnabled(
+ content_settings::kImprovedCookieControls) &&
+ control_mode ==
+ content_settings::CookieControlsMode::kIncognitoOnly) {
+ return l10n_util::GetStringUTF8(
+ IDS_SETTINGS_SITE_SETTINGS_COOKIES_BLOCK_THIRD_PARTY_INCOGNITO);
+ } else {
+ // We do not make a distinction between allow and clear on exit.
+ return l10n_util::GetPluralStringFUTF8(
+ IDS_SETTINGS_SITE_SETTINGS_COOKIES_ALLOW,
+ GetNumCookieExceptionsOfTypes(map,
+ {ContentSetting::CONTENT_SETTING_BLOCK}));
+ }
}
} // namespace
@@ -365,6 +418,20 @@ void SiteSettingsHandler::RegisterMessages() {
base::BindRepeating(&SiteSettingsHandler::HandleGetAllSites,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
+ "getCookieControlsManagedState",
+ base::BindRepeating(
+ &SiteSettingsHandler::HandleGetCookieControlsManagedState,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "getCookieSettingDescription",
+ base::BindRepeating(
+ &SiteSettingsHandler::HandleGetCookieSettingDescription,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "getRecentSitePermissions",
+ base::BindRepeating(&SiteSettingsHandler::HandleGetRecentSitePermissions,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
"getFormattedBytes",
base::BindRepeating(&SiteSettingsHandler::HandleGetFormattedBytes,
base::Unretained(this)));
@@ -454,8 +521,8 @@ void SiteSettingsHandler::OnJavascriptAllowed() {
host_zoom_map_subscription_ =
content::HostZoomMap::GetDefaultForBrowserContext(profile_)
->AddZoomLevelChangedCallback(
- base::Bind(&SiteSettingsHandler::OnZoomLevelChanged,
- base::Unretained(this)));
+ base::BindRepeating(&SiteSettingsHandler::OnZoomLevelChanged,
+ base::Unretained(this)));
pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
pref_change_registrar_->Init(profile_->GetPrefs());
@@ -466,6 +533,16 @@ void SiteSettingsHandler::OnJavascriptAllowed() {
base::Bind(&SiteSettingsHandler::SendBlockAutoplayStatus,
base::Unretained(this)));
+ // Listen for prefs that impact the effective cookie setting
+ pref_change_registrar_->Add(
+ prefs::kBlockThirdPartyCookies,
+ base::Bind(&SiteSettingsHandler::SendCookieSettingDescription,
+ base::Unretained(this)));
+ pref_change_registrar_->Add(
+ prefs::kCookieControlsMode,
+ base::Bind(&SiteSettingsHandler::SendCookieSettingDescription,
+ base::Unretained(this)));
+
#if defined(OS_CHROMEOS)
pref_change_registrar_->Add(
prefs::kEnableDRM,
@@ -479,6 +556,8 @@ void SiteSettingsHandler::OnJavascriptDisallowed() {
chooser_observer_.RemoveAll();
host_zoom_map_subscription_.reset();
pref_change_registrar_->Remove(prefs::kBlockAutoplayEnabled);
+ pref_change_registrar_->Remove(prefs::kBlockThirdPartyCookies);
+ pref_change_registrar_->Remove(prefs::kCookieControlsMode);
#if defined(OS_CHROMEOS)
pref_change_registrar_->Remove(prefs::kEnableDRM);
#endif
@@ -505,9 +584,8 @@ void SiteSettingsHandler::OnGetUsageInfo() {
}
break;
}
- CallJavascriptFunction("settings.WebsiteUsagePrivateApi.returnUsageTotal",
- base::Value(usage_host_), base::Value(usage_string),
- base::Value(cookie_string));
+ FireWebUIListener("usage-total-changed", base::Value(usage_host_),
+ base::Value(usage_string), base::Value(cookie_string));
}
#if defined(OS_CHROMEOS)
@@ -546,6 +624,12 @@ void SiteSettingsHandler::OnContentSettingChanged(
content_type == ContentSettingsType::SOUND) {
SendBlockAutoplayStatus();
}
+
+ // If the default cookie setting changed we should update the effective
+ // setting description.
+ if (content_type == ContentSettingsType::COOKIES) {
+ SendCookieSettingDescription();
+ }
}
void SiteSettingsHandler::OnOffTheRecordProfileCreated(
@@ -671,22 +755,14 @@ void SiteSettingsHandler::HandleGetDefaultValueForContentType(
void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) {
AllowJavascript();
- CHECK_EQ(2U, args->GetSize());
- const base::Value* callback_id;
- CHECK(args->Get(0, &callback_id));
- const base::ListValue* types;
- CHECK(args->GetList(1, &types));
+ CHECK_EQ(2U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+ auto types = args->GetList()[1].GetList();
all_sites_map_.clear();
origin_permission_set_.clear();
- // Convert |types| to a list of ContentSettingsTypes.
- std::vector<ContentSettingsType> content_types;
- for (size_t i = 0; i < types->GetSize(); ++i) {
- std::string type;
- types->GetString(i, &type);
- content_types.push_back(
- site_settings::ContentSettingsTypeFromGroupName(type));
- }
+
+ auto content_types = site_settings::ContentSettingsTypesFromGroupNames(types);
// Incognito contains incognito content settings plus non-incognito content
// settings. Thus if it exists, just get exceptions for the incognito profile.
@@ -701,38 +777,22 @@ void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) {
// Retrieve a list of embargoed settings to check separately. This ensures
// that only settings included in |content_types| will be listed in all sites.
- ContentSettingsForOneType embargo_settings;
- map->GetSettingsForOneType(ContentSettingsType::PERMISSION_AUTOBLOCKER_DATA,
- std::string(), &embargo_settings);
- PermissionManager* permission_manager = PermissionManager::Get(profile);
- for (const ContentSettingPatternSource& e : embargo_settings) {
- for (ContentSettingsType content_type : content_types) {
- if (PermissionUtil::IsPermission(content_type)) {
- const GURL url(e.primary_pattern.ToString());
- // Add |url| to the set if there are any embargo settings.
- PermissionResult result =
- permission_manager->GetPermissionStatus(content_type, url, url);
- if (result.source == PermissionStatusSource::MULTIPLE_DISMISSALS ||
- result.source == PermissionStatusSource::MULTIPLE_IGNORES) {
- CreateOrAppendSiteGroupEntry(&all_sites_map_, url);
- origin_permission_set_.insert(url.spec());
- break;
- }
- }
- }
+ auto* autoblocker =
+ PermissionDecisionAutoBlockerFactory::GetForProfile(profile_);
+ for (auto& url : autoblocker->GetEmbargoedOrigins(content_types)) {
+ // Add |url| to the set if there are any embargo settings.
+ CreateOrAppendSiteGroupEntry(&all_sites_map_, url);
+ origin_permission_set_.insert(url.spec());
}
- // Convert |types| to a list of ContentSettingsTypes.
- for (ContentSettingsType content_type : content_types) {
- ContentSettingsForOneType entries;
- map->GetSettingsForOneType(content_type, std::string(), &entries);
- for (const ContentSettingPatternSource& e : entries) {
- if (PatternAppliesToSingleOrigin(e)) {
- CreateOrAppendSiteGroupEntry(&all_sites_map_,
- GURL(e.primary_pattern.ToString()));
- origin_permission_set_.insert(
- GURL(e.primary_pattern.ToString()).spec());
- }
+ // Get permission exceptions which apply to a single site
+ for (auto content_type : content_types) {
+ auto exceptions =
+ site_settings::GetSiteExceptionsForContentType(map, content_type);
+ for (const auto& e : exceptions) {
+ GURL url = GURL(e.primary_pattern.ToString());
+ CreateOrAppendSiteGroupEntry(&all_sites_map_, url);
+ origin_permission_set_.insert(url.spec());
}
}
@@ -750,11 +810,95 @@ void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) {
ConvertSiteGroupMapToListValue(all_sites_map_, origin_permission_set_,
&result, profile, app_registrar_);
- LogAllSitesAction(AllSitesAction::kLoadPage);
+ LogAllSitesAction(AllSitesAction2::kLoadPage);
send_sites_list_ = true;
- ResolveJavascriptCallback(*callback_id, result);
+ ResolveJavascriptCallback(base::Value(callback_id), result);
+}
+
+void SiteSettingsHandler::HandleGetCookieControlsManagedState(
+ const base::ListValue* args) {
+ AllowJavascript();
+ CHECK_EQ(1U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+
+ auto managed_states = site_settings::GetCookieControlsManagedState(profile_);
+
+ base::Value result(base::Value::Type::DICTIONARY);
+ result.SetKey(
+ site_settings::kAllowAll,
+ site_settings::GetValueForManagedState(managed_states.allow_all));
+ result.SetKey(site_settings::kBlockThirdPartyIncognito,
+ site_settings::GetValueForManagedState(
+ managed_states.block_third_party_incognito));
+ result.SetKey(
+ site_settings::kBlockThirdParty,
+ site_settings::GetValueForManagedState(managed_states.block_third_party));
+ result.SetKey(
+ site_settings::kBlockAll,
+ site_settings::GetValueForManagedState(managed_states.block_all));
+ result.SetKey(
+ site_settings::kSessionOnly,
+ site_settings::GetValueForManagedState(managed_states.session_only));
+
+ ResolveJavascriptCallback(base::Value(callback_id), result);
+}
+
+void SiteSettingsHandler::HandleGetCookieSettingDescription(
+ const base::ListValue* args) {
+ AllowJavascript();
+ CHECK_EQ(1U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+ ResolveJavascriptCallback(base::Value(callback_id),
+ base::Value(GetCookieSettingDescription(profile_)));
+}
+
+void SiteSettingsHandler::HandleGetRecentSitePermissions(
+ const base::ListValue* args) {
+ AllowJavascript();
+
+ CHECK_EQ(3U, args->GetList().size());
+ std::string callback_id = args->GetList()[0].GetString();
+ auto types = args->GetList()[1].GetList();
+ size_t max_sources = base::checked_cast<size_t>(args->GetList()[2].GetInt());
+
+ auto content_types = site_settings::ContentSettingsTypesFromGroupNames(types);
+ auto recent_site_permissions = site_settings::GetRecentSitePermissions(
+ profile_, content_types, max_sources);
+
+ // Convert groups of TimestampedPermissions for consumption by JS
+ base::Value result(base::Value::Type::LIST);
+ for (const auto& site_permissions : recent_site_permissions) {
+ DCHECK(!site_permissions.settings.empty());
+ base::Value recent_site(base::Value::Type::DICTIONARY);
+ recent_site.SetKey(site_settings::kOrigin,
+ base::Value(site_permissions.origin.spec()));
+ recent_site.SetKey(site_settings::kIncognito,
+ base::Value(site_permissions.incognito));
+
+ base::Value permissions_list(base::Value::Type::LIST);
+ for (const auto& p : site_permissions.settings) {
+ base::Value recent_permission(base::Value::Type::DICTIONARY);
+ recent_permission.SetKey(
+ site_settings::kType,
+ base::Value(
+ site_settings::ContentSettingsTypeToGroupName(p.content_type)));
+ recent_permission.SetKey(
+ site_settings::kSetting,
+ base::Value(
+ content_settings::ContentSettingToString(p.content_setting)));
+ recent_permission.SetKey(
+ site_settings::kSource,
+ base::Value(
+ site_settings::SiteSettingSourceToString(p.setting_source)));
+ permissions_list.Append(std::move(recent_permission));
+ }
+ recent_site.SetKey(site_settings::kRecentPermissions,
+ std::move(permissions_list));
+ result.Append(std::move(recent_site));
+ }
+ ResolveJavascriptCallback(base::Value(callback_id), result);
}
base::Value SiteSettingsHandler::PopulateCookiesAndUsageData(Profile* profile) {
@@ -783,14 +927,16 @@ base::Value SiteSettingsHandler::PopulateCookiesAndUsageData(Profile* profile) {
const std::string& origin = origin_info.FindKey("origin")->GetString();
const auto& size_info_it = origin_size_map.find(origin);
if (size_info_it != origin_size_map.end())
- origin_info.SetKey("usage", base::Value(double(size_info_it->second)));
+ origin_info.SetKey(
+ "usage", base::Value(static_cast<double>(size_info_it->second)));
+ GURL origin_url(origin);
const auto& origin_cookie_num_it =
- origin_cookie_map.find(GURL(origin).host());
+ origin_cookie_map.find(origin_url.host());
if (origin_cookie_num_it != origin_cookie_map.end()) {
origin_info.SetKey(kNumCookies,
base::Value(origin_cookie_num_it->second));
// Add cookies numbers for origins that isn't an eTLD+1.
- if (GURL(origin).host() != etld_plus1)
+ if (origin_url.host() != etld_plus1)
cookie_num += origin_cookie_num_it->second;
}
}
@@ -946,13 +1092,14 @@ void SiteSettingsHandler::HandleSetOriginPermissions(
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(profile_);
- PermissionUtil::ScopedRevocationReporter scoped_revocation_reporter(
- profile_, origin, origin, content_type,
- PermissionSourceUI::SITE_SETTINGS);
+ permissions::PermissionUmaUtil::ScopedRevocationReporter
+ scoped_revocation_reporter(
+ profile_, origin, origin, content_type,
+ permissions::PermissionSourceUI::SITE_SETTINGS);
// Clear any existing embargo status if the new setting isn't block.
if (setting != CONTENT_SETTING_BLOCK) {
- PermissionDecisionAutoBlocker::GetForProfile(profile_)
+ PermissionDecisionAutoBlockerFactory::GetForProfile(profile_)
->RemoveEmbargoByUrl(origin, content_type);
}
map->SetContentSettingDefaultScope(origin, origin, content_type,
@@ -971,7 +1118,7 @@ void SiteSettingsHandler::HandleSetOriginPermissions(
"SoundContentSetting.UnmuteBy.SiteSettings"));
}
}
- WebSiteSettingsUmaUtil::LogPermissionChange(content_type, setting);
+ content_settings::LogWebSiteSettingsPermissionChange(content_type, setting);
}
// Show an infobar reminding the user to reload tabs where their site
@@ -1036,9 +1183,10 @@ void SiteSettingsHandler::HandleResetCategoryPermissionForPattern(
secondary_pattern_string.empty()
? ContentSettingsPattern::Wildcard()
: ContentSettingsPattern::FromString(secondary_pattern_string);
- PermissionUtil::ScopedRevocationReporter scoped_revocation_reporter(
- profile, primary_pattern, secondary_pattern, content_type,
- PermissionSourceUI::SITE_SETTINGS);
+ permissions::PermissionUmaUtil::ScopedRevocationReporter
+ scoped_revocation_reporter(
+ profile, primary_pattern, secondary_pattern, content_type,
+ permissions::PermissionSourceUI::SITE_SETTINGS);
map->SetContentSettingCustomScope(primary_pattern, secondary_pattern,
content_type, "", CONTENT_SETTING_DEFAULT);
@@ -1054,7 +1202,7 @@ void SiteSettingsHandler::HandleResetCategoryPermissionForPattern(
"SoundContentSetting.UnmuteBy.PatternException"));
}
}
- WebSiteSettingsUmaUtil::LogPermissionChange(
+ content_settings::LogWebSiteSettingsPermissionChange(
content_type, ContentSetting::CONTENT_SETTING_DEFAULT);
}
@@ -1096,9 +1244,10 @@ void SiteSettingsHandler::HandleSetCategoryPermissionForPattern(
? ContentSettingsPattern::Wildcard()
: ContentSettingsPattern::FromString(secondary_pattern_string);
- PermissionUtil::ScopedRevocationReporter scoped_revocation_reporter(
- profile, primary_pattern, secondary_pattern, content_type,
- PermissionSourceUI::SITE_SETTINGS);
+ permissions::PermissionUmaUtil::ScopedRevocationReporter
+ scoped_revocation_reporter(
+ profile, primary_pattern, secondary_pattern, content_type,
+ permissions::PermissionSourceUI::SITE_SETTINGS);
map->SetContentSettingCustomScope(primary_pattern, secondary_pattern,
content_type, "", setting);
@@ -1117,7 +1266,7 @@ void SiteSettingsHandler::HandleSetCategoryPermissionForPattern(
"SoundContentSetting.UnmuteBy.PatternException"));
}
}
- WebSiteSettingsUmaUtil::LogPermissionChange(content_type, setting);
+ content_settings::LogWebSiteSettingsPermissionChange(content_type, setting);
}
void SiteSettingsHandler::HandleResetChooserExceptionForSite(
@@ -1140,7 +1289,8 @@ void SiteSettingsHandler::HandleResetChooserExceptionForSite(
GURL embedding_origin(embedding_origin_str);
CHECK(embedding_origin.is_valid());
- ChooserContextBase* chooser_context = chooser_type->get_context(profile_);
+ permissions::ChooserContextBase* chooser_context =
+ chooser_type->get_context(profile_);
chooser_context->RevokeObjectPermission(
url::Origin::Create(requesting_origin),
url::Origin::Create(embedding_origin), args->GetList()[3]);
@@ -1352,6 +1502,18 @@ void SiteSettingsHandler::ObserveSourcesForProfile(Profile* profile) {
if (!chooser_observer_.IsObserving(serial_context))
chooser_observer_.Add(serial_context);
+ auto* hid_context = HidChooserContextFactory::GetForProfile(profile);
+ if (!chooser_observer_.IsObserving(hid_context))
+ chooser_observer_.Add(hid_context);
+
+ if (base::FeatureList::IsEnabled(
+ features::kWebBluetoothNewPermissionsBackend)) {
+ auto* bluetooth_context =
+ BluetoothChooserContextFactory::GetForProfile(profile);
+ if (!chooser_observer_.IsObserving(bluetooth_context))
+ chooser_observer_.Add(bluetooth_context);
+ }
+
observed_profiles_.Add(profile);
}
@@ -1368,6 +1530,18 @@ void SiteSettingsHandler::StopObservingSourcesForProfile(Profile* profile) {
if (chooser_observer_.IsObserving(serial_context))
chooser_observer_.Remove(serial_context);
+ auto* hid_context = HidChooserContextFactory::GetForProfile(profile);
+ if (chooser_observer_.IsObserving(hid_context))
+ chooser_observer_.Remove(hid_context);
+
+ if (base::FeatureList::IsEnabled(
+ features::kWebBluetoothNewPermissionsBackend)) {
+ auto* bluetooth_context =
+ BluetoothChooserContextFactory::GetForProfile(profile);
+ if (chooser_observer_.IsObserving(bluetooth_context))
+ chooser_observer_.Remove(bluetooth_context);
+ }
+
observed_profiles_.Remove(profile);
}
@@ -1444,18 +1618,16 @@ void SiteSettingsHandler::HandleClearEtldPlus1DataAndCookies(
}
for (auto* node : nodes_to_delete)
cookies_tree_model_->DeleteCookieNode(node);
-
- LogAllSitesAction(AllSitesAction::kClearData);
}
void SiteSettingsHandler::HandleRecordAction(const base::ListValue* args) {
CHECK_EQ(1U, args->GetSize());
int action;
CHECK(args->GetInteger(0, &action));
- DCHECK_LE(action, static_cast<int>(AllSitesAction::kMaxValue));
- DCHECK_GE(action, static_cast<int>(AllSitesAction::kLoadPage));
+ DCHECK_LE(action, static_cast<int>(AllSitesAction2::kMaxValue));
+ DCHECK_GE(action, static_cast<int>(AllSitesAction2::kLoadPage));
- LogAllSitesAction(static_cast<AllSitesAction>(action));
+ LogAllSitesAction(static_cast<AllSitesAction2>(action));
}
void SiteSettingsHandler::SetCookiesTreeModelForTesting(
@@ -1466,4 +1638,10 @@ void SiteSettingsHandler::SetCookiesTreeModelForTesting(
void SiteSettingsHandler::ClearAllSitesMapForTesting() {
all_sites_map_.clear();
}
+
+void SiteSettingsHandler::SendCookieSettingDescription() {
+ FireWebUIListener("cookieSettingDescriptionChanged",
+ base::Value(GetCookieSettingDescription(profile_)));
+}
+
} // namespace settings
diff --git a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h
index b60de36fcc2..575661dc87e 100644
--- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h
+++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h
@@ -13,7 +13,6 @@
#include "base/containers/flat_set.h"
#include "base/scoped_observer.h"
#include "chrome/browser/browsing_data/cookies_tree_model.h"
-#include "chrome/browser/permissions/chooser_context_base.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_observer.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
@@ -21,6 +20,8 @@
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "components/content_settings/core/browser/content_settings_observer.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/permissions/chooser_context_base.h"
+#include "components/prefs/pref_store.h"
#include "content/public/browser/host_zoom_map.h"
#include "ppapi/buildflags/buildflags.h"
@@ -33,11 +34,12 @@ class ListValue;
namespace settings {
// Chrome "ContentSettings" settings page UI handler.
-class SiteSettingsHandler : public SettingsPageUIHandler,
- public content_settings::Observer,
- public ProfileObserver,
- public ChooserContextBase::PermissionObserver,
- public CookiesTreeModel::Observer {
+class SiteSettingsHandler
+ : public SettingsPageUIHandler,
+ public content_settings::Observer,
+ public ProfileObserver,
+ public permissions::ChooserContextBase::PermissionObserver,
+ public CookiesTreeModel::Observer {
public:
explicit SiteSettingsHandler(Profile* profile,
web_app::AppRegistrar& web_app_registrar);
@@ -110,6 +112,7 @@ class SiteSettingsHandler : public SettingsPageUIHandler,
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ExceptionHelpers);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ExtensionDisplayName);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAllSites);
+ FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetRecentSitePermissions);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, OnStorageFetched);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAndSetDefault);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAndSetForInvalidURLs);
@@ -122,6 +125,8 @@ class SiteSettingsHandler : public SettingsPageUIHandler,
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ZoomLevels);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest,
HandleClearEtldPlus1DataAndCookies);
+ FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, CookieControlsManagedState);
+ FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, CookieSettingDescription);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, HandleGetFormattedBytes);
FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest,
NotificationPermissionRevokeUkm);
@@ -163,6 +168,20 @@ class SiteSettingsHandler : public SettingsPageUIHandler,
// the front end when fetching finished.
void HandleGetAllSites(const base::ListValue* args);
+ // Returns whether each of the cookie controls is managed and if so what
+ // the source of that management is.
+ void HandleGetCookieControlsManagedState(const base::ListValue* args);
+
+ // Returns a string for display describing the current cookie settings.
+ void HandleGetCookieSettingDescription(const base::ListValue* args);
+
+ // Returns a list containing the most recent permission changes for the
+ // provided content types grouped by origin/profile (incognito, regular)
+ // combinations, limited to N origin/profile pairings. This includes
+ // permission changes made by embargo, but does not include permissions
+ // enforced via policy.
+ void HandleGetRecentSitePermissions(const base::ListValue* args);
+
// Called when the list of origins using storage has been fetched, and sends
// this list back to the front end.
void OnStorageFetched();
@@ -240,6 +259,10 @@ class SiteSettingsHandler : public SettingsPageUIHandler,
void ClearAllSitesMapForTesting();
+ // Notifies the JS side the effective cookies setting has changed and
+ // provides the updated description label for display.
+ void SendCookieSettingDescription();
+
Profile* profile_;
web_app::AppRegistrar& app_registrar_;
@@ -260,7 +283,8 @@ class SiteSettingsHandler : public SettingsPageUIHandler,
this};
// Change observer for chooser permissions.
- ScopedObserver<ChooserContextBase, ChooserContextBase::PermissionObserver>
+ ScopedObserver<permissions::ChooserContextBase,
+ permissions::ChooserContextBase::PermissionObserver>
chooser_observer_{this};
// Change observer for prefs.
diff --git a/chromium/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
index 42c7a310795..0fd6541604d 100644
--- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -15,6 +15,7 @@
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_clock.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -26,10 +27,7 @@
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/permissions/chooser_context_base.h"
-#include "chrome/browser/permissions/chooser_context_base_mock_permission_observer.h"
-#include "chrome/browser/permissions/permission_decision_auto_blocker.h"
-#include "chrome/browser/permissions/permission_uma_util.h"
+#include "chrome/browser/permissions/permission_decision_auto_blocker_factory.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/site_settings_helper.h"
@@ -38,14 +36,23 @@
#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/browser/web_applications/test/test_app_registrar.h"
#include "chrome/common/pref_names.h"
+#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/browser_with_test_window_test.h"
#include "chrome/test/base/testing_profile.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/content_settings/core/common/features.h"
#include "components/content_settings/core/common/pref_names.h"
+#include "components/content_settings/core/test/content_settings_mock_provider.h"
+#include "components/content_settings/core/test/content_settings_test_utils.h"
#include "components/history/core/browser/history_service.h"
#include "components/infobars/core/infobar.h"
+#include "components/permissions/chooser_context_base.h"
+#include "components/permissions/permission_decision_auto_blocker.h"
+#include "components/permissions/permission_uma_util.h"
+#include "components/permissions/test/chooser_context_base_mock_permission_observer.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/navigation_controller.h"
@@ -58,6 +65,7 @@
#include "ppapi/buildflags/buildflags.h"
#include "services/device/public/cpp/test/fake_usb_device_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
#include "ui/base/text/bytes_formatting.h"
#if defined(OS_CHROMEOS)
@@ -190,6 +198,8 @@ class SiteSettingsHandlerTest : public testing::Test {
TestingProfile::Builder profile_builder;
profile_builder.SetPath(profile_dir_.GetPath());
profile_ = profile_builder.Build();
+ feature_list_.InitAndEnableFeature(
+ content_settings::kImprovedCookieControls);
}
void SetUp() override {
@@ -399,6 +409,16 @@ class SiteSettingsHandlerTest : public testing::Test {
}
}
+ void ValidateCookieSettingUpdate(const std::string expected_string,
+ const int expected_call_index) {
+ const content::TestWebUI::CallData& data =
+ *web_ui()->call_data()[expected_call_index];
+
+ ASSERT_EQ("cr.webUIListenerCallback", data.function_name());
+ ASSERT_EQ("cookieSettingDescriptionChanged", data.arg1()->GetString());
+ ASSERT_EQ(expected_string, data.arg2()->GetString());
+ }
+
void CreateIncognitoProfile() {
incognito_profile_ = TestingProfile::Builder().BuildIncognito(profile());
}
@@ -479,6 +499,10 @@ class SiteSettingsHandlerTest : public testing::Test {
const std::string kCookies;
const std::string kFlash;
+ // The number of listeners that are expected to fire when any content setting
+ // is changed.
+ const size_t kNumberContentSettingListeners = 2;
+
private:
// A profile directory that outlives |task_environment_| is needed because
// TestingProfile::CreateHistoryService uses the directory to host a
@@ -490,6 +514,7 @@ class SiteSettingsHandlerTest : public testing::Test {
web_app::TestAppRegistrar app_registrar_;
content::TestWebUI web_ui_;
std::unique_ptr<SiteSettingsHandler> handler_;
+ base::test::ScopedFeatureList feature_list_;
#if defined(OS_CHROMEOS)
std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_;
#endif
@@ -611,8 +636,8 @@ TEST_F(SiteSettingsHandlerTest, MAYBE_GetAllSites) {
}
// Test embargoed settings also appear.
- PermissionDecisionAutoBlocker* auto_blocker =
- PermissionDecisionAutoBlocker::GetForProfile(profile());
+ permissions::PermissionDecisionAutoBlocker* auto_blocker =
+ PermissionDecisionAutoBlockerFactory::GetForProfile(profile());
base::SimpleTestClock clock;
clock.SetNow(base::Time::Now());
auto_blocker->SetClockForTesting(&clock);
@@ -712,12 +737,137 @@ TEST_F(SiteSettingsHandlerTest, MAYBE_GetAllSites) {
}
// Each call to HandleGetAllSites() above added a callback to the profile's
- // BrowsingDataLocalStorageHelper, so make sure these aren't stuck waiting to
- // run at the end of the test.
+ // browsing_data::LocalStorageHelper, so make sure these aren't stuck waiting
+ // to run at the end of the test.
base::RunLoop run_loop;
run_loop.RunUntilIdle();
}
+TEST_F(SiteSettingsHandlerTest, GetRecentSitePermissions) {
+ // Constants used only in this test.
+ std::string kAllowed = content_settings::ContentSettingToString(
+ ContentSetting::CONTENT_SETTING_ALLOW);
+ std::string kBlocked = content_settings::ContentSettingToString(
+ ContentSetting::CONTENT_SETTING_BLOCK);
+ std::string kEmbargo =
+ SiteSettingSourceToString(site_settings::SiteSettingSource::kEmbargo);
+ std::string kPreference =
+ SiteSettingSourceToString(site_settings::SiteSettingSource::kPreference);
+
+ base::ListValue get_recent_permissions_args;
+ get_recent_permissions_args.AppendString(kCallbackId);
+ base::Value category_list(base::Value::Type::LIST);
+ category_list.Append(kNotifications);
+ category_list.Append(kFlash);
+ get_recent_permissions_args.Append(std::move(category_list));
+ get_recent_permissions_args.Append(3);
+
+ // Configure prefs and auto blocker with a controllable clock.
+ base::SimpleTestClock clock;
+ clock.SetNow(base::Time::Now());
+ HostContentSettingsMap* map =
+ HostContentSettingsMapFactory::GetForProfile(profile());
+ map->SetClockForTesting(&clock);
+ permissions::PermissionDecisionAutoBlocker* auto_blocker =
+ PermissionDecisionAutoBlockerFactory::GetForProfile(profile());
+ auto_blocker->SetClockForTesting(&clock);
+ clock.Advance(base::TimeDelta::FromHours(1));
+
+ // Test recent permissions is empty when there are no preferences.
+ handler()->HandleGetRecentSitePermissions(&get_recent_permissions_args);
+ EXPECT_EQ(1U, web_ui()->call_data().size());
+
+ {
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIResponse", data.function_name());
+ EXPECT_EQ(kCallbackId, data.arg1()->GetString());
+ ASSERT_TRUE(data.arg2()->GetBool());
+
+ base::Value::ConstListView recent_permissions = data.arg3()->GetList();
+ EXPECT_EQ(0UL, recent_permissions.size());
+ }
+
+ // Add numerous permissions from different sources and confirm that the recent
+ // permissions are correctly transformed for usage by JS.
+ const GURL url1("https://example.com");
+ const GURL url2("http://example.com");
+ for (int i = 0; i < 3; ++i)
+ auto_blocker->RecordDismissAndEmbargo(
+ url1, ContentSettingsType::NOTIFICATIONS, false);
+
+ clock.Advance(base::TimeDelta::FromHours(2));
+ map->SetContentSettingDefaultScope(url2, url2, ContentSettingsType::PLUGINS,
+ std::string(), CONTENT_SETTING_ALLOW);
+ clock.Advance(base::TimeDelta::FromHours(1));
+ CreateIncognitoProfile();
+ HostContentSettingsMap* incognito_map =
+ HostContentSettingsMapFactory::GetForProfile(incognito_profile());
+ incognito_map->SetClockForTesting(&clock);
+ incognito_map->SetContentSettingDefaultScope(
+ url1, url1, ContentSettingsType::PLUGINS, std::string(),
+ CONTENT_SETTING_ALLOW);
+
+ clock.Advance(base::TimeDelta::FromHours(1));
+ permissions::PermissionDecisionAutoBlocker* incognito_auto_blocker =
+ PermissionDecisionAutoBlockerFactory::GetForProfile(incognito_profile());
+ incognito_auto_blocker->SetClockForTesting(&clock);
+ for (int i = 0; i < 3; ++i)
+ incognito_auto_blocker->RecordDismissAndEmbargo(
+ url1, ContentSettingsType::NOTIFICATIONS, false);
+
+ handler()->HandleGetRecentSitePermissions(&get_recent_permissions_args);
+ {
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIResponse", data.function_name());
+ EXPECT_EQ(kCallbackId, data.arg1()->GetString());
+ ASSERT_TRUE(data.arg2()->GetBool());
+
+ base::Value::ConstListView recent_permissions = data.arg3()->GetList();
+ EXPECT_EQ(3UL, recent_permissions.size());
+ EXPECT_EQ(url1.spec(),
+ recent_permissions[2].FindKey("origin")->GetString());
+ EXPECT_EQ(url2.spec(),
+ recent_permissions[1].FindKey("origin")->GetString());
+ EXPECT_EQ(url1.spec(),
+ recent_permissions[0].FindKey("origin")->GetString());
+
+ EXPECT_TRUE(recent_permissions[0].FindKey("incognito")->GetBool());
+ EXPECT_FALSE(recent_permissions[1].FindKey("incognito")->GetBool());
+ EXPECT_FALSE(recent_permissions[2].FindKey("incognito")->GetBool());
+
+ base::Value::ConstListView incognito_url1_permissions =
+ recent_permissions[0].FindKey("recentPermissions")->GetList();
+ base::Value::ConstListView url1_permissions =
+ recent_permissions[2].FindKey("recentPermissions")->GetList();
+ base::Value::ConstListView url2_permissions =
+ recent_permissions[1].FindKey("recentPermissions")->GetList();
+
+ EXPECT_EQ(2UL, incognito_url1_permissions.size());
+
+ EXPECT_EQ(kNotifications,
+ incognito_url1_permissions[0].FindKey("type")->GetString());
+ EXPECT_EQ(kBlocked,
+ incognito_url1_permissions[0].FindKey("setting")->GetString());
+ EXPECT_EQ(kEmbargo,
+ incognito_url1_permissions[0].FindKey("source")->GetString());
+
+ EXPECT_EQ(kFlash,
+ incognito_url1_permissions[1].FindKey("type")->GetString());
+ EXPECT_EQ(kAllowed,
+ incognito_url1_permissions[1].FindKey("setting")->GetString());
+ EXPECT_EQ(kPreference,
+ incognito_url1_permissions[1].FindKey("source")->GetString());
+
+ EXPECT_EQ(kNotifications, url1_permissions[0].FindKey("type")->GetString());
+ EXPECT_EQ(kBlocked, url1_permissions[0].FindKey("setting")->GetString());
+ EXPECT_EQ(kEmbargo, url1_permissions[0].FindKey("source")->GetString());
+
+ EXPECT_EQ(kFlash, url2_permissions[0].FindKey("type")->GetString());
+ EXPECT_EQ(kAllowed, url2_permissions[0].FindKey("setting")->GetString());
+ EXPECT_EQ(kPreference, url2_permissions[0].FindKey("source")->GetString());
+ }
+}
+
TEST_F(SiteSettingsHandlerTest, OnStorageFetched) {
SetUpCookiesTreeModel();
@@ -942,12 +1092,13 @@ TEST_F(SiteSettingsHandlerTest, NotificationPermissionRevokeUkm) {
auto* entry = entries.front();
ukm_recorder.ExpectEntrySourceHasUrl(entry, GURL(google));
- EXPECT_EQ(*ukm_recorder.GetEntryMetric(entry, "Source"),
- static_cast<int64_t>(PermissionSourceUI::SITE_SETTINGS));
+ EXPECT_EQ(
+ *ukm_recorder.GetEntryMetric(entry, "Source"),
+ static_cast<int64_t>(permissions::PermissionSourceUI::SITE_SETTINGS));
EXPECT_EQ(*ukm_recorder.GetEntryMetric(entry, "PermissionType"),
static_cast<int64_t>(ContentSettingsType::NOTIFICATIONS));
EXPECT_EQ(*ukm_recorder.GetEntryMetric(entry, "Action"),
- static_cast<int64_t>(PermissionAction::REVOKED));
+ static_cast<int64_t>(permissions::PermissionAction::REVOKED));
}
TEST_F(SiteSettingsHandlerTest, DefaultSettingSource) {
@@ -956,6 +1107,8 @@ TEST_F(SiteSettingsHandlerTest, DefaultSettingSource) {
// Use a non-default port to verify the display name does not strip this off.
const std::string google("https://www.google.com:183");
+ const std::string expected_display_name("www.google.com:183");
+
ContentSettingSourceSetter source_setter(profile(),
ContentSettingsType::NOTIFICATIONS);
@@ -968,7 +1121,7 @@ TEST_F(SiteSettingsHandlerTest, DefaultSettingSource) {
// Test Chrome built-in defaults are marked as default.
handler()->HandleGetOriginPermissions(&get_origin_permissions_args);
- ValidateOrigin(google, google, google, CONTENT_SETTING_ASK,
+ ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_ASK,
site_settings::SiteSettingSource::kDefault, 1U);
base::ListValue default_value_args;
@@ -978,7 +1131,7 @@ TEST_F(SiteSettingsHandlerTest, DefaultSettingSource) {
handler()->HandleSetDefaultValueForContentType(&default_value_args);
// A user-set global default should also show up as default.
handler()->HandleGetOriginPermissions(&get_origin_permissions_args);
- ValidateOrigin(google, google, google, CONTENT_SETTING_BLOCK,
+ ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_BLOCK,
site_settings::SiteSettingSource::kDefault, 3U);
base::ListValue set_notification_pattern_args;
@@ -992,7 +1145,7 @@ TEST_F(SiteSettingsHandlerTest, DefaultSettingSource) {
&set_notification_pattern_args);
// A user-set pattern should not show up as default.
handler()->HandleGetOriginPermissions(&get_origin_permissions_args);
- ValidateOrigin(google, google, google, CONTENT_SETTING_ALLOW,
+ ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_ALLOW,
site_settings::SiteSettingSource::kPreference, 5U);
base::ListValue set_notification_origin_args;
@@ -1006,20 +1159,20 @@ TEST_F(SiteSettingsHandlerTest, DefaultSettingSource) {
&set_notification_origin_args);
// A user-set per-origin permission should not show up as default.
handler()->HandleGetOriginPermissions(&get_origin_permissions_args);
- ValidateOrigin(google, google, google, CONTENT_SETTING_BLOCK,
+ ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_BLOCK,
site_settings::SiteSettingSource::kPreference, 7U);
// Enterprise-policy set defaults should not show up as default.
source_setter.SetPolicyDefault(CONTENT_SETTING_ALLOW);
handler()->HandleGetOriginPermissions(&get_origin_permissions_args);
- ValidateOrigin(google, google, google, CONTENT_SETTING_ALLOW,
+ ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_ALLOW,
site_settings::SiteSettingSource::kPolicy, 8U);
}
TEST_F(SiteSettingsHandlerTest, GetAndSetOriginPermissions) {
const std::string origin_with_port("https://www.example.com:443");
// The display name won't show the port if it's default for that scheme.
- const std::string origin("https://www.example.com");
+ const std::string origin("www.example.com");
base::ListValue get_args;
get_args.AppendString(kCallbackId);
get_args.AppendString(origin_with_port);
@@ -1511,7 +1664,8 @@ TEST_F(SiteSettingsHandlerTest, SessionOnlyException) {
set_args.AppendBoolean(false); // Incognito.
base::HistogramTester histograms;
handler()->HandleSetCategoryPermissionForPattern(&set_args);
- EXPECT_EQ(1U, web_ui()->call_data().size());
+
+ EXPECT_EQ(kNumberContentSettingListeners, web_ui()->call_data().size());
histograms.ExpectTotalCount(uma_base, 1);
histograms.ExpectTotalCount(uma_base + ".SessionOnly", 1);
}
@@ -1564,10 +1718,6 @@ TEST_F(SiteSettingsHandlerTest, BlockAutoplay_Update) {
namespace {
-const GURL kAndroidUrl("https://android.com");
-const GURL kChromiumUrl("https://chromium.org");
-const GURL kGoogleUrl("https://google.com");
-
constexpr char kUsbPolicySetting[] = R"(
[
{
@@ -1585,6 +1735,18 @@ constexpr char kUsbPolicySetting[] = R"(
}
])";
+// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
+// function.
+GURL AndroidUrl() {
+ return GURL("https://android.com");
+}
+GURL ChromiumUrl() {
+ return GURL("https://chromium.org");
+}
+GURL GoogleUrl() {
+ return GURL("https://google.com");
+}
+
} // namespace
class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest {
@@ -1601,7 +1763,8 @@ class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest {
void TearDown() override {
auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile());
- chooser_context->ChooserContextBase::RemoveObserver(&observer_);
+ chooser_context->permissions::ChooserContextBase::RemoveObserver(
+ &observer_);
}
// Sets up the UsbChooserContext with two devices and permissions for these
@@ -1627,9 +1790,9 @@ class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest {
base::DoNothing::Once<std::vector<device::mojom::UsbDeviceInfoPtr>>());
base::RunLoop().RunUntilIdle();
- const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl);
- const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl);
- const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl);
+ const auto kAndroidOrigin = url::Origin::Create(AndroidUrl());
+ const auto kChromiumOrigin = url::Origin::Create(ChromiumUrl());
+ const auto kGoogleOrigin = url::Origin::Create(GoogleUrl());
// Add the user granted permissions for testing.
// These two persistent device permissions should be lumped together with
@@ -1652,7 +1815,7 @@ class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest {
*policy_value);
// Add the observer for permission changes.
- chooser_context->ChooserContextBase::AddObserver(&observer_);
+ chooser_context->permissions::ChooserContextBase::AddObserver(&observer_);
}
void SetUpOffTheRecordUsbChooserContext() {
@@ -1670,19 +1833,20 @@ class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest {
base::DoNothing::Once<std::vector<device::mojom::UsbDeviceInfoPtr>>());
base::RunLoop().RunUntilIdle();
- const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl);
- const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl);
+ const auto kAndroidOrigin = url::Origin::Create(AndroidUrl());
+ const auto kChromiumOrigin = url::Origin::Create(ChromiumUrl());
chooser_context->GrantDevicePermission(kChromiumOrigin, kAndroidOrigin,
*off_the_record_device_);
// Add the observer for permission changes.
- chooser_context->ChooserContextBase::AddObserver(&observer_);
+ chooser_context->permissions::ChooserContextBase::AddObserver(&observer_);
}
void DestroyIncognitoProfile() override {
auto* chooser_context =
UsbChooserContextFactory::GetForProfile(incognito_profile());
- chooser_context->ChooserContextBase::RemoveObserver(&observer_);
+ chooser_context->permissions::ChooserContextBase::RemoveObserver(
+ &observer_);
SiteSettingsHandlerTest::DestroyIncognitoProfile();
}
@@ -1778,7 +1942,7 @@ class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest {
device::mojom::UsbDeviceInfoPtr persistent_device_info_;
device::mojom::UsbDeviceInfoPtr user_granted_device_info_;
- MockPermissionObserver observer_;
+ permissions::MockPermissionObserver observer_;
private:
device::FakeUsbDeviceManager device_manager_;
@@ -1836,10 +2000,10 @@ TEST_F(SiteSettingsHandlerChooserExceptionTest,
const std::string kUsbChooserGroupName =
site_settings::ContentSettingsTypeToGroupName(
ContentSettingsType::USB_CHOOSER_DATA);
- const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl);
- const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl);
- const std::string kAndroidOriginStr = kAndroidUrl.GetOrigin().spec();
- const std::string kChromiumOriginStr = kChromiumUrl.GetOrigin().spec();
+ const auto kAndroidOrigin = url::Origin::Create(AndroidUrl());
+ const auto kChromiumOrigin = url::Origin::Create(ChromiumUrl());
+ const std::string kAndroidOriginStr = AndroidUrl().GetOrigin().spec();
+ const std::string kChromiumOriginStr = ChromiumUrl().GetOrigin().spec();
{
const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData(
@@ -2013,6 +2177,158 @@ TEST_F(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies) {
EXPECT_EQ(0U, storage_and_cookie_list->GetSize());
}
+TEST_F(SiteSettingsHandlerTest, CookieControlsManagedState) {
+ // Test that the handler correctly wraps the helper result. Helper with
+ // extensive logic is tested in site_settings_helper_unittest.cc.
+ const std::string kNone = "none";
+ const std::string kDevicePolicy = "devicePolicy";
+ const std::vector<std::string> kControlNames = {
+ "allowAll", "blockAll", "blockThirdParty", "blockThirdPartyIncognito",
+ "sessionOnly"};
+
+ // Check that the default cookie control state is handled correctly.
+ base::ListValue get_args;
+ get_args.AppendString(kCallbackId);
+ handler()->HandleGetCookieControlsManagedState(&get_args);
+ {
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIResponse", data.function_name());
+ EXPECT_EQ(kCallbackId, data.arg1()->GetString());
+ ASSERT_TRUE(data.arg2()->GetBool());
+ for (const auto& control_name : kControlNames) {
+ auto* control_state = data.arg3()->FindPath(control_name);
+ ASSERT_FALSE(control_state->FindKey("disabled")->GetBool());
+ ASSERT_EQ(kNone, control_state->FindKey("indicator")->GetString());
+ }
+ }
+
+ // Check that a fully managed cookie state is handled correctly.
+ HostContentSettingsMap* map =
+ HostContentSettingsMapFactory::GetForProfile(profile());
+ auto provider = std::make_unique<content_settings::MockProvider>();
+ provider->SetWebsiteSetting(
+ ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
+ ContentSettingsType::COOKIES, std::string(),
+ std::make_unique<base::Value>(CONTENT_SETTING_ALLOW));
+ content_settings::TestUtils::OverrideProvider(
+ map, std::move(provider), HostContentSettingsMap::POLICY_PROVIDER);
+ sync_preferences::TestingPrefServiceSyncable* pref_service =
+ profile()->GetTestingPrefService();
+ pref_service->SetManagedPref(prefs::kBlockThirdPartyCookies,
+ std::make_unique<base::Value>(true));
+
+ handler()->HandleGetCookieControlsManagedState(&get_args);
+ {
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIResponse", data.function_name());
+ EXPECT_EQ(kCallbackId, data.arg1()->GetString());
+ ASSERT_TRUE(data.arg2()->GetBool());
+ for (const auto& control_name : kControlNames) {
+ auto* control_state = data.arg3()->FindPath(control_name);
+ ASSERT_TRUE(control_state->FindKey("disabled")->GetBool());
+ ASSERT_EQ(kDevicePolicy,
+ control_state->FindKey("indicator")->GetString());
+ }
+ }
+}
+
+TEST_F(SiteSettingsHandlerTest, CookieSettingDescription) {
+ const auto kBlocked = [](int num) {
+ return l10n_util::GetPluralStringFUTF8(
+ IDS_SETTINGS_SITE_SETTINGS_COOKIES_BLOCK, num);
+ };
+ const auto kAllowed = [](int num) {
+ return l10n_util::GetPluralStringFUTF8(
+ IDS_SETTINGS_SITE_SETTINGS_COOKIES_ALLOW, num);
+ };
+ const std::string kBlockThirdParty = l10n_util::GetStringUTF8(
+ IDS_SETTINGS_SITE_SETTINGS_COOKIES_BLOCK_THIRD_PARTY);
+ const std::string kBlockThirdPartyIncognito = l10n_util::GetStringUTF8(
+ IDS_SETTINGS_SITE_SETTINGS_COOKIES_BLOCK_THIRD_PARTY_INCOGNITO);
+
+ // Enforce expected default profile setting.
+ profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, false);
+ profile()->GetPrefs()->SetInteger(
+ prefs::kCookieControlsMode,
+ static_cast<int>(content_settings::CookieControlsMode::kIncognitoOnly));
+ auto* content_settings =
+ HostContentSettingsMapFactory::GetForProfile(profile());
+ content_settings->SetDefaultContentSetting(
+ ContentSettingsType::COOKIES, ContentSetting::CONTENT_SETTING_ALLOW);
+ web_ui()->ClearTrackedCalls();
+
+ // Validate get method works.
+ base::ListValue get_args;
+ get_args.AppendString(kCallbackId);
+ handler()->HandleGetCookieSettingDescription(&get_args);
+ const content::TestWebUI::CallData& data = *web_ui()->call_data().back();
+
+ EXPECT_EQ("cr.webUIResponse", data.function_name());
+ EXPECT_EQ(kCallbackId, data.arg1()->GetString());
+ ASSERT_TRUE(data.arg2()->GetBool());
+ EXPECT_EQ(kBlockThirdPartyIncognito, data.arg3()->GetString());
+
+ // Multiple listeners will be called when prefs and content settings are
+ // changed in this test. Increment our expected call_data index accordingly.
+ int expected_call_index = 0;
+ const int kPrefListenerIndex = 1;
+ const int kContentSettingListenerIndex = 2;
+
+ // Check updates are working,
+ profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, true);
+ expected_call_index += kPrefListenerIndex;
+ ValidateCookieSettingUpdate(kBlockThirdParty, expected_call_index);
+
+ content_settings->SetDefaultContentSetting(
+ ContentSettingsType::COOKIES, ContentSetting::CONTENT_SETTING_BLOCK);
+ expected_call_index += kContentSettingListenerIndex;
+ ValidateCookieSettingUpdate(kBlocked(0), expected_call_index);
+
+ // Check changes which do not affect the effective cookie setting.
+ profile()->GetPrefs()->SetBoolean(prefs::kBlockThirdPartyCookies, false);
+ expected_call_index += kPrefListenerIndex;
+ ValidateCookieSettingUpdate(kBlocked(0), expected_call_index);
+
+ profile()->GetPrefs()->SetInteger(
+ prefs::kCookieControlsMode,
+ static_cast<int>(content_settings::CookieControlsMode::kOff));
+ expected_call_index += kPrefListenerIndex;
+ ValidateCookieSettingUpdate(kBlocked(0), expected_call_index);
+
+ // Set to allow and check previous changes are respected.
+ content_settings->SetDefaultContentSetting(
+ ContentSettingsType::COOKIES, ContentSetting::CONTENT_SETTING_ALLOW);
+ expected_call_index += kContentSettingListenerIndex;
+ ValidateCookieSettingUpdate(kAllowed(0), expected_call_index);
+
+ // Confirm exceptions are counted correctly.
+ GURL url1("https://example.com");
+ GURL url2("http://example.com");
+ GURL url3("http://another.example.com");
+ content_settings->SetContentSettingDefaultScope(
+ url1, url1, ContentSettingsType::COOKIES, std::string(),
+ ContentSetting::CONTENT_SETTING_BLOCK);
+ expected_call_index += kContentSettingListenerIndex;
+ ValidateCookieSettingUpdate(kAllowed(1), expected_call_index);
+
+ content_settings->SetContentSettingDefaultScope(
+ url2, url2, ContentSettingsType::COOKIES, std::string(),
+ ContentSetting::CONTENT_SETTING_ALLOW);
+ expected_call_index += kContentSettingListenerIndex;
+ ValidateCookieSettingUpdate(kAllowed(1), expected_call_index);
+
+ content_settings->SetContentSettingDefaultScope(
+ url3, url3, ContentSettingsType::COOKIES, std::string(),
+ ContentSetting::CONTENT_SETTING_SESSION_ONLY);
+ expected_call_index += kContentSettingListenerIndex;
+ ValidateCookieSettingUpdate(kAllowed(1), expected_call_index);
+
+ content_settings->SetDefaultContentSetting(
+ ContentSettingsType::COOKIES, ContentSetting::CONTENT_SETTING_BLOCK);
+ expected_call_index += kContentSettingListenerIndex;
+ ValidateCookieSettingUpdate(kBlocked(2), expected_call_index);
+}
+
TEST_F(SiteSettingsHandlerTest, HandleGetFormattedBytes) {
const double size = 120000000000;
base::ListValue get_args;
diff --git a/chromium/chrome/browser/ui/webui/settings_utils_linux.cc b/chromium/chrome/browser/ui/webui/settings_utils_linux.cc
index 19f554e3951..d56f9f30684 100644
--- a/chromium/chrome/browser/ui/webui/settings_utils_linux.cc
+++ b/chromium/chrome/browser/ui/webui/settings_utils_linux.cc
@@ -12,6 +12,7 @@
#include "base/nix/xdg_util.h"
#include "base/process/launch.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "build/build_config.h"
#include "chrome/browser/tab_contents/tab_util.h"
@@ -143,9 +144,8 @@ void DetectAndStartProxyConfigUtil(int render_process_id,
namespace settings_utils {
void ShowNetworkProxySettings(content::WebContents* web_contents) {
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
base::BindOnce(&DetectAndStartProxyConfigUtil,
web_contents->GetRenderViewHost()->GetProcess()->GetID(),
web_contents->GetRenderViewHost()->GetRoutingID()));
diff --git a/chromium/chrome/browser/ui/webui/settings_utils_win.cc b/chromium/chrome/browser/ui/webui/settings_utils_win.cc
index c5d1717a99a..d0c2084850f 100644
--- a/chromium/chrome/browser/ui/webui/settings_utils_win.cc
+++ b/chromium/chrome/browser/ui/webui/settings_utils_win.cc
@@ -14,6 +14,7 @@
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/windows_version.h"
@@ -109,10 +110,9 @@ void ShowNetworkProxySettings(content::WebContents* web_contents) {
Profile::FromBrowserContext(web_contents->GetBrowserContext()),
GURL("ms-settings:network-proxy"));
} else {
- base::PostTask(FROM_HERE,
- {base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
- base::MayBlock()},
- base::BindOnce(&OpenConnectionDialogCallback));
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+ base::BindOnce(&OpenConnectionDialogCallback));
}
}
diff --git a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
index 7f36b096ba3..5db2926d98f 100644
--- a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
+++ b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc
@@ -18,9 +18,9 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/policy/chrome_policy_conversions_client.h"
#include "chrome/browser/policy/cloud/user_policy_signin_service.h"
#include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h"
-#include "chrome/browser/policy/policy_conversions.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile_attributes_storage.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
@@ -34,6 +34,7 @@
#include "chrome/browser/unified_consent/unified_consent_service_factory.h"
#include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/browser/policy_conversions.h"
#include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
#include "components/prefs/pref_service.h"
#include "components/signin/public/base/signin_metrics.h"
@@ -365,8 +366,9 @@ void DiceTurnSyncOnHelper::OnProviderUpdatePropagated(
if (provider != profile_->GetUserCloudPolicyManager())
return;
VLOG(2) << "Policies after sign in:";
- VLOG(2) << policy::DictionaryPolicyConversions()
- .WithBrowserContext(profile_)
+ VLOG(2) << policy::DictionaryPolicyConversions(
+ std::make_unique<policy::ChromePolicyConversionsClient>(
+ profile_))
.ToJSON();
profile_->GetProfilePolicyConnector()
->policy_service()
@@ -418,7 +420,7 @@ void DiceTurnSyncOnHelper::OnNewProfileCreated(Profile* new_profile,
}
syncer::SyncService* DiceTurnSyncOnHelper::GetSyncService() {
- return profile_->IsSyncAllowed()
+ return ProfileSyncServiceFactory::IsSyncAllowed(profile_)
? ProfileSyncServiceFactory::GetForProfile(profile_)
: nullptr;
}
diff --git a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.cc b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.cc
index ab43eb03cb4..9b652b7adea 100644
--- a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.cc
+++ b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_delegate_impl.cc
@@ -135,7 +135,7 @@ void DiceTurnSyncOnHelperDelegateImpl::ShowSyncConfirmation(
scoped_login_ui_service_observer_.Add(
LoginUIServiceFactory::GetForProfile(profile_));
browser_ = EnsureBrowser(browser_, profile_);
- browser_->signin_view_controller()->ShowModalSyncConfirmationDialog(browser_);
+ browser_->signin_view_controller()->ShowModalSyncConfirmationDialog();
}
void DiceTurnSyncOnHelperDelegateImpl::ShowMergeSyncDataConfirmation(
@@ -143,13 +143,10 @@ void DiceTurnSyncOnHelperDelegateImpl::ShowMergeSyncDataConfirmation(
const std::string& new_email,
DiceTurnSyncOnHelper::SigninChoiceCallback callback) {
DCHECK(callback);
- content::WebContents* web_contents =
- browser_->tab_strip_model()->GetActiveWebContents();
- // TODO(droger): Replace Bind with BindOnce once the
- // SigninEmailConfirmationDialog supports it.
- SigninEmailConfirmationDialog::AskForConfirmation(
- web_contents, profile_, previous_email, new_email,
- base::Bind(&OnEmailConfirmation, base::Passed(std::move(callback))));
+ browser_ = EnsureBrowser(browser_, profile_);
+ browser_->signin_view_controller()->ShowModalSigninEmailConfirmationDialog(
+ previous_email, new_email,
+ base::BindOnce(&OnEmailConfirmation, std::move(callback)));
}
void DiceTurnSyncOnHelperDelegateImpl::ShowSyncSettings() {
diff --git a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
index cb32b231405..6149a51ee80 100644
--- a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
@@ -274,7 +275,7 @@ class DiceTurnSyncOnHelperTest : public testing::Test {
syncer::MockSyncService* mock_sync_service = GetMockSyncService();
EXPECT_CALL(*mock_sync_service, GetSetupInProgressHandle()).Times(1);
ON_CALL(*mock_sync_service, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service, GetTransportState())
.WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE));
}
@@ -283,7 +284,7 @@ class DiceTurnSyncOnHelperTest : public testing::Test {
syncer::MockSyncService* mock_sync_service = GetMockSyncService();
EXPECT_CALL(*mock_sync_service, GetSetupInProgressHandle()).Times(1);
ON_CALL(*mock_sync_service, GetDisableReasons())
- .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE));
+ .WillByDefault(Return(syncer::SyncService::DisableReasonSet()));
ON_CALL(*mock_sync_service, GetTransportState())
.WillByDefault(
Return(syncer::SyncService::TransportState::INITIALIZING));
diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_handler.cc
index f370580c44b..344c6adf263 100644
--- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler.cc
+++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler.cc
@@ -6,6 +6,7 @@
#include <limits.h>
#include <string>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -71,8 +72,7 @@ void InlineLoginHandler::HandleInitializeMessage(const base::ListValue* args) {
AllowJavascript();
content::WebContents* contents = web_ui()->GetWebContents();
content::StoragePartition* partition =
- content::BrowserContext::GetStoragePartitionForSite(
- contents->GetBrowserContext(), signin::GetSigninPartitionURL());
+ signin::GetSigninPartition(contents->GetBrowserContext());
if (partition) {
const GURL& current_url = web_ui()->GetWebContents()->GetURL();
@@ -150,7 +150,7 @@ void InlineLoginHandler::ContinueHandleInitializeMessage() {
params.SetBoolean("readOnlyEmail", !read_only_email.empty());
SetExtraInitParams(params);
- CallJavascriptFunction("inline.login.loadAuthExtension", params);
+ FireWebUIListener("load-auth-extension", params);
}
void InlineLoginHandler::HandleCompleteLoginMessage(
@@ -160,8 +160,7 @@ void InlineLoginHandler::HandleCompleteLoginMessage(
// CookieManager.
content::WebContents* contents = web_ui()->GetWebContents();
content::StoragePartition* partition =
- content::BrowserContext::GetStoragePartitionForSite(
- contents->GetBrowserContext(), signin::GetSigninPartitionURL());
+ signin::GetSigninPartition(contents->GetBrowserContext());
partition->GetCookieManagerForBrowserProcess()->GetCookieList(
GaiaUrls::GetInstance()->gaia_url(),
@@ -175,12 +174,11 @@ void InlineLoginHandler::HandleCompleteLoginMessageWithCookies(
const base::ListValue& args,
const net::CookieStatusList& cookies,
const net::CookieStatusList& excluded_cookies) {
- const base::DictionaryValue* dict = nullptr;
- args.GetDictionary(0, &dict);
+ const base::Value& dict = args.GetList()[0];
- const std::string& email = dict->FindKey("email")->GetString();
- const std::string& password = dict->FindKey("password")->GetString();
- const std::string& gaia_id = dict->FindKey("gaiaId")->GetString();
+ const std::string& email = dict.FindKey("email")->GetString();
+ const std::string& password = dict.FindKey("password")->GetString();
+ const std::string& gaia_id = dict.FindKey("gaiaId")->GetString();
std::string auth_code;
for (const auto& cookie_with_status : cookies) {
@@ -188,16 +186,22 @@ void InlineLoginHandler::HandleCompleteLoginMessageWithCookies(
auth_code = cookie_with_status.cookie.Value();
}
- bool skip_for_now = false;
- dict->GetBoolean("skipForNow", &skip_for_now);
- bool trusted = false;
- bool trusted_found = dict->GetBoolean("trusted", &trusted);
+ bool skip_for_now = dict.FindBoolKey("skipForNow").value_or(false);
+ base::Optional<bool> trusted = dict.FindBoolKey("trusted");
+ bool trusted_value = trusted.value_or(false);
+ bool trusted_found = trusted.has_value();
- bool choose_what_to_sync = false;
- dict->GetBoolean("chooseWhatToSync", &choose_what_to_sync);
+ bool choose_what_to_sync =
+ dict.FindBoolKey("chooseWhatToSync").value_or(false);
- CompleteLogin(email, password, gaia_id, auth_code, skip_for_now, trusted,
- trusted_found, choose_what_to_sync);
+ base::Value edu_login_params;
+ if (args.GetList().size() > 1) {
+ edu_login_params = args.GetList()[1].Clone();
+ }
+
+ CompleteLogin(email, password, gaia_id, auth_code, skip_for_now,
+ trusted_value, trusted_found, choose_what_to_sync,
+ std::move(edu_login_params));
}
void InlineLoginHandler::HandleSwitchToFullTabMessage(
@@ -237,7 +241,7 @@ void InlineLoginHandler::HandleNavigationButtonClicked(
NOTREACHED() << "The inline login handler is no longer used in a browser "
"or tab modal dialog.";
#else
- FireWebUIListener("navigateBackInWebview");
+ FireWebUIListener("navigate-back-in-webview");
#endif
}
@@ -250,5 +254,5 @@ void InlineLoginHandler::HandleDialogClose(const base::ListValue* args) {
void InlineLoginHandler::CloseDialogFromJavascript() {
if (IsJavascriptAllowed())
- CallJavascriptFunction("inline.login.closeDialog");
+ FireWebUIListener("close-dialog");
}
diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler.h b/chromium/chrome/browser/ui/webui/signin/inline_login_handler.h
index ef8ce7823e3..d8e59330c67 100644
--- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler.h
+++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler.h
@@ -14,6 +14,7 @@
#include "net/cookies/canonical_cookie.h"
namespace base {
+class Value;
class DictionaryValue;
}
@@ -86,7 +87,8 @@ class InlineLoginHandler : public content::WebUIMessageHandler {
bool skip_for_now,
bool trusted,
bool trusted_found,
- bool choose_what_to_sync) = 0;
+ bool choose_what_to_sync,
+ base::Value edu_login_params) = 0;
base::WeakPtrFactory<InlineLoginHandler> weak_ptr_factory_{this};
diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
index 1c04bc7f9ab..5033bff5a8d 100644
--- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
+++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc
@@ -4,30 +4,39 @@
#include "chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h"
+#include <memory>
#include <string>
#include "base/base64.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/chrome_device_id_helper.h"
+#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/supervised_user/child_accounts/secondary_account_consent_logger.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/webui/signin/inline_login_handler.h"
#include "chromeos/components/account_manager/account_manager.h"
#include "chromeos/components/account_manager/account_manager_factory.h"
+#include "chromeos/constants/chromeos_features.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "crypto/sha2.h"
+#include "google_apis/gaia/gaia_auth_util.h"
#include "google_apis/gaia/gaia_urls.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace chromeos {
namespace {
+constexpr char kCrosAddAccountFlow[] = "crosAddAccount";
+constexpr char kCrosAddAccountEduFlow[] = "crosAddAccountEdu";
+
// Returns a base64-encoded hash code of "signin_scoped_device_id:gaia_id".
std::string GetAccountDeviceId(const std::string& signin_scoped_device_id,
const std::string& gaia_id) {
@@ -38,6 +47,27 @@ std::string GetAccountDeviceId(const std::string& signin_scoped_device_id,
return account_device_id;
}
+std::string GetInlineLoginFlowName(Profile* profile, const std::string* email) {
+ DCHECK(profile);
+ if (!profile->IsChild()) {
+ return kCrosAddAccountFlow;
+ }
+
+ std::string primary_account_email =
+ IdentityManagerFactory::GetForProfile(profile)
+ ->GetPrimaryAccountInfo(signin::ConsentLevel::kNotRequired)
+ .email;
+ // If provided email is for primary account - it's a reauthentication, use
+ // normal add account flow.
+ if (email && gaia::AreEmailsSame(primary_account_email, *email)) {
+ return kCrosAddAccountFlow;
+ }
+
+ // Child user is adding/reauthenticating a secondary account.
+ CHECK(features::IsEduCoexistenceEnabled());
+ return kCrosAddAccountEduFlow;
+}
+
// A helper class for completing the inline login flow. Primarily, it is
// responsible for exchanging the auth code, obtained after a successful user
// sign in, for OAuth tokens and subsequently populating Chrome OS
@@ -70,6 +100,7 @@ class SigninHelper : public GaiaAuthConsumer {
~SigninHelper() override = default;
+ protected:
// GaiaAuthConsumer overrides.
void OnClientOAuthSuccess(const ClientOAuthResult& result) override {
// Flow of control after this call:
@@ -85,18 +116,29 @@ class SigninHelper : public GaiaAuthConsumer {
// for the account information from Gaia and updates this information into
// |AccountTrackerService|. At this point the account will be fully added to
// the system.
- account_manager_->UpsertAccount(account_key_, email_, result.refresh_token);
+ UpsertAccount(result.refresh_token);
- close_dialog_closure_.Run();
- base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
+ CloseDialogAndExit();
}
void OnClientOAuthFailure(const GoogleServiceAuthError& error) override {
// TODO(sinhak): Display an error.
+ CloseDialogAndExit();
+ }
+
+ void UpsertAccount(const std::string& refresh_token) {
+ account_manager_->UpsertAccount(account_key_, email_, refresh_token);
+ }
+
+ void CloseDialogAndExit() {
close_dialog_closure_.Run();
base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this);
}
+ chromeos::AccountManager* GetAccountManager() { return account_manager_; }
+
+ const std::string GetEmail() { return email_; }
+
private:
// A non-owning pointer to Chrome OS AccountManager.
chromeos::AccountManager* const account_manager_;
@@ -112,6 +154,83 @@ class SigninHelper : public GaiaAuthConsumer {
DISALLOW_COPY_AND_ASSIGN(SigninHelper);
};
+// A version of SigninHelper for child users. After obtaining OAuth token it
+// logs the parental consent with provided parent id and rapt. After successful
+// consent logging populates Chrome OS AccountManager with the token.
+class ChildSigninHelper : public SigninHelper {
+ public:
+ ChildSigninHelper(
+ chromeos::AccountManager* account_manager,
+ const base::RepeatingClosure& close_dialog_closure,
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+ const std::string& gaia_id,
+ const std::string& email,
+ const std::string& auth_code,
+ const std::string& signin_scoped_device_id,
+ signin::IdentityManager* identity_manager,
+ PrefService* pref_service,
+ const std::string& parent_obfuscated_gaia_id,
+ const std::string& re_auth_proof_token)
+ : SigninHelper(account_manager,
+ close_dialog_closure,
+ url_loader_factory,
+ gaia_id,
+ email,
+ auth_code,
+ signin_scoped_device_id),
+ identity_manager_(identity_manager),
+ pref_service_(pref_service),
+ parent_obfuscated_gaia_id_(parent_obfuscated_gaia_id),
+ re_auth_proof_token_(re_auth_proof_token) {}
+ ChildSigninHelper(const ChildSigninHelper&) = delete;
+ ChildSigninHelper& operator=(const ChildSigninHelper&) = delete;
+ ~ChildSigninHelper() override = default;
+
+ protected:
+ // GaiaAuthConsumer overrides.
+ void OnClientOAuthSuccess(const ClientOAuthResult& result) override {
+ // Log parental consent for secondary account addition. In case of success,
+ // refresh token from |result| will be added to Account Manager in
+ // |OnConsentLogged|.
+ DCHECK(!secondary_account_consent_logger_);
+ secondary_account_consent_logger_ =
+ std::make_unique<SecondaryAccountConsentLogger>(
+ identity_manager_, GetAccountManager()->GetUrlLoaderFactory(),
+ pref_service_, GetEmail(), parent_obfuscated_gaia_id_,
+ re_auth_proof_token_,
+ base::BindOnce(&ChildSigninHelper::OnConsentLogged,
+ weak_ptr_factory_.GetWeakPtr(),
+ result.refresh_token));
+ secondary_account_consent_logger_->StartLogging();
+ }
+
+ void OnConsentLogged(const std::string& refresh_token,
+ SecondaryAccountConsentLogger::Result result) {
+ UMA_HISTOGRAM_ENUMERATION("Signin.SecondaryAccountConsentLog", result);
+ secondary_account_consent_logger_.reset();
+ if (result == SecondaryAccountConsentLogger::Result::kSuccess) {
+ UpsertAccount(refresh_token);
+ } else {
+ LOG(ERROR) << "Could not log parent consent, the result was: "
+ << static_cast<int>(result);
+ // TODO(anastasiian): send error to UI?
+ }
+
+ CloseDialogAndExit();
+ }
+
+ private:
+ // Unowned pointer to identity manager.
+ signin::IdentityManager* const identity_manager_;
+ // Unowned pointer to pref service.
+ PrefService* const pref_service_;
+ const std::string parent_obfuscated_gaia_id_;
+ const std::string re_auth_proof_token_;
+ std::unique_ptr<SecondaryAccountConsentLogger>
+ secondary_account_consent_logger_;
+ base::WeakPtrFactory<ChildSigninHelper> weak_ptr_factory_{this};
+};
+
} // namespace
InlineLoginHandlerChromeOS::InlineLoginHandlerChromeOS(
@@ -139,7 +258,9 @@ void InlineLoginHandlerChromeOS::SetExtraInitParams(
params.SetKey("gaiaPath", base::Value(url.path().substr(1)));
params.SetKey("constrained", base::Value("1"));
- params.SetKey("flow", base::Value("crosAddAccount"));
+ params.SetKey("flow", base::Value(GetInlineLoginFlowName(
+ Profile::FromWebUI(web_ui()),
+ params.FindStringKey("email"))));
params.SetBoolean("dontResizeNonEmbeddedPages", true);
// For in-session login flows, request Gaia to ignore third party SAML IdP SSO
@@ -152,7 +273,7 @@ void InlineLoginHandlerChromeOS::SetExtraInitParams(
void InlineLoginHandlerChromeOS::HandleAuthExtensionReadyMessage(
const base::ListValue* args) {
AllowJavascript();
- FireWebUIListener("showBackButton");
+ FireWebUIListener("show-back-button");
}
void InlineLoginHandlerChromeOS::CompleteLogin(const std::string& email,
@@ -162,7 +283,8 @@ void InlineLoginHandlerChromeOS::CompleteLogin(const std::string& email,
bool skip_for_now,
bool trusted,
bool trusted_found,
- bool choose_what_to_sync) {
+ bool choose_what_to_sync,
+ base::Value edu_login_params) {
CHECK(!auth_code.empty());
CHECK(!gaia_id.empty());
CHECK(!email.empty());
@@ -178,6 +300,33 @@ void InlineLoginHandlerChromeOS::CompleteLogin(const std::string& email,
->GetAccountManagerFactory()
->GetAccountManager(profile->GetPath().value());
+ signin::IdentityManager* identity_manager =
+ IdentityManagerFactory::GetForProfile(profile);
+ std::string primary_account_email =
+ identity_manager
+ ->GetPrimaryAccountInfo(signin::ConsentLevel::kNotRequired)
+ .email;
+
+ // Child user added a secondary account.
+ if (profile->IsChild() &&
+ !gaia::AreEmailsSame(primary_account_email, email) &&
+ base::FeatureList::IsEnabled(features::kEduCoexistenceConsentLog)) {
+ CHECK(features::IsEduCoexistenceEnabled());
+ const std::string* rapt =
+ edu_login_params.FindStringKey("reAuthProofToken");
+ CHECK(rapt);
+ const std::string* parentId =
+ edu_login_params.FindStringKey("parentObfuscatedGaiaId");
+ CHECK(parentId);
+ // ChildSigninHelper deletes itself after its work is done.
+ new ChildSigninHelper(
+ account_manager, close_dialog_closure_,
+ account_manager->GetUrlLoaderFactory(), gaia_id, email, auth_code,
+ GetAccountDeviceId(GetSigninScopedDeviceIdForProfile(profile), gaia_id),
+ identity_manager, profile->GetPrefs(), *parentId, *rapt);
+ return;
+ }
+
// SigninHelper deletes itself after its work is done.
new SigninHelper(
account_manager, close_dialog_closure_,
diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h
index 56c511d5973..91cab9a6039 100644
--- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h
+++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h
@@ -31,7 +31,8 @@ class InlineLoginHandlerChromeOS : public InlineLoginHandler {
bool skip_for_now,
bool trusted,
bool trusted_found,
- bool choose_what_to_sync) override;
+ bool choose_what_to_sync,
+ base::Value edu_login_params) override;
void HandleDialogClose(const base::ListValue* args) override;
private:
diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc
index 7e3af1ed57c..f848bc57ffe 100644
--- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc
+++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc
@@ -7,16 +7,21 @@
#include <algorithm>
#include <string>
+#include "ash/public/cpp/window_backdrop.h"
#include "ash/public/cpp/window_properties.h"
+#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/macros.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h"
#include "chrome/common/webui_url_constants.h"
+#include "chromeos/constants/chromeos_features.h"
#include "chromeos/constants/chromeos_pref_names.h"
#include "components/prefs/pref_service.h"
+#include "components/session_manager/core/session_manager.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
+#include "content/public/browser/web_ui.h"
#include "google_apis/gaia/gaia_auth_util.h"
#include "net/base/url_util.h"
#include "ui/aura/window.h"
@@ -33,45 +38,80 @@ InlineLoginHandlerDialogChromeOS* dialog = nullptr;
constexpr int kSigninDialogWidth = 768;
constexpr int kSigninDialogHeight = 640;
+// Keep in sync with resources/chromeos/account_manager_error.js
+enum class AccountManagerErrorType {
+ kSecondaryAccountsDisabled = 0,
+ kChildUserArcDisabled = 1
+};
+
bool IsDeviceAccountEmail(const std::string& email) {
auto* active_user = user_manager::UserManager::Get()->GetActiveUser();
return active_user &&
gaia::AreEmailsSame(active_user->GetDisplayEmail(), email);
}
+GURL GetUrlWithEmailParam(base::StringPiece url_string,
+ const std::string& email) {
+ GURL url = GURL(url_string);
+ if (!email.empty()) {
+ url = net::AppendQueryParameter(url, "email", email);
+ url = net::AppendQueryParameter(url, "readOnlyEmail", "true");
+ }
+ return url;
+}
+
+GURL GetInlineLoginUrl(const std::string& email) {
+ if (IsDeviceAccountEmail(email)) {
+ // It's a device account re-auth.
+ return GetUrlWithEmailParam(chrome::kChromeUIChromeSigninURL, email);
+ }
+ if (!ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
+ chromeos::prefs::kSecondaryGoogleAccountSigninAllowed)) {
+ // Addition of secondary Google Accounts is not allowed.
+ return GURL(chrome::kChromeUIAccountManagerErrorURL);
+ }
+
+ // Addition of secondary Google Accounts is allowed.
+ if (!ProfileManager::GetActiveUserProfile()->IsChild()) {
+ return GetUrlWithEmailParam(chrome::kChromeUIChromeSigninURL, email);
+ }
+ // User type is Child.
+ if (!features::IsEduCoexistenceEnabled()) {
+ return GURL(chrome::kChromeUIAccountManagerErrorURL);
+ }
+ DCHECK_EQ(std::string(chrome::kChromeUIChromeSigninURL).back(), '/');
+ // chrome://chrome-signin/edu
+ const std::string kEduAccountLoginURL =
+ std::string(chrome::kChromeUIChromeSigninURL) + "edu";
+ return GetUrlWithEmailParam(kEduAccountLoginURL, email);
+}
+
} // namespace
// static
-void InlineLoginHandlerDialogChromeOS::Show(const std::string& email) {
+void InlineLoginHandlerDialogChromeOS::Show(const std::string& email,
+ const Source& source) {
+ // If the dialog was triggered as a response to background request, it could
+ // get displayed on the lock screen. In this case it is safe to ignore it,
+ // since in this case user will get it again after a request to Google
+ // properties.
+ if (session_manager::SessionManager::Get()->IsUserSessionBlocked())
+ return;
+
if (dialog) {
dialog->dialog_window()->Focus();
return;
}
- GURL url;
- if (ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
- chromeos::prefs::kSecondaryGoogleAccountSigninAllowed) ||
- IsDeviceAccountEmail(email)) {
- // Addition of secondary Google Accounts is allowed OR it's a primary
- // account re-auth.
- url = GURL(chrome::kChromeUIChromeSigninURL);
- if (!email.empty()) {
- url = net::AppendQueryParameter(url, "email", email);
- url = net::AppendQueryParameter(url, "readOnlyEmail", "true");
- }
- } else {
- // Addition of secondary Google Accounts is not allowed.
- url = GURL(chrome::kChromeUIAccountManagerErrorURL);
- }
-
// Will be deleted by |SystemWebDialogDelegate::OnDialogClosed|.
- dialog = new InlineLoginHandlerDialogChromeOS(url);
+ dialog =
+ new InlineLoginHandlerDialogChromeOS(GetInlineLoginUrl(email), source);
dialog->ShowSystemDialog();
// TODO(crbug.com/1016828): Remove/update this after the dialog behavior on
// Chrome OS is defined.
- dialog->dialog_window()->SetProperty(
- ash::kBackdropWindowMode, ash::BackdropWindowMode::kAutoSemiOpaque);
+ ash::WindowBackdrop::Get(dialog->dialog_window())
+ ->SetBackdropType(ash::WindowBackdrop::BackdropType::kSemiOpaque);
}
void InlineLoginHandlerDialogChromeOS::AdjustWidgetInitParams(
@@ -104,9 +144,12 @@ void InlineLoginHandlerDialogChromeOS::RemoveObserver(
web_modal::ModalDialogHostObserver* observer) {}
InlineLoginHandlerDialogChromeOS::InlineLoginHandlerDialogChromeOS(
- const GURL& url)
+ const GURL& url,
+ const Source& source)
: SystemWebDialogDelegate(url, base::string16() /* title */),
- delegate_(this) {}
+ delegate_(this),
+ source_(source),
+ url_(url) {}
InlineLoginHandlerDialogChromeOS::~InlineLoginHandlerDialogChromeOS() {
DCHECK_EQ(this, dialog);
@@ -121,7 +164,26 @@ void InlineLoginHandlerDialogChromeOS::GetDialogSize(gfx::Size* size) const {
}
std::string InlineLoginHandlerDialogChromeOS::GetDialogArgs() const {
- return std::string();
+ if (url_.GetWithEmptyPath() !=
+ GURL(chrome::kChromeUIAccountManagerErrorURL)) {
+ return std::string();
+ }
+
+ AccountManagerErrorType error =
+ AccountManagerErrorType::kSecondaryAccountsDisabled;
+ if (source_ == Source::kArc &&
+ ProfileManager::GetActiveUserProfile()->IsChild() &&
+ ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
+ chromeos::prefs::kSecondaryGoogleAccountSigninAllowed) &&
+ features::IsEduCoexistenceEnabled()) {
+ error = AccountManagerErrorType::kChildUserArcDisabled;
+ }
+
+ std::string data;
+ base::DictionaryValue dialog_args;
+ dialog_args.SetInteger("errorType", static_cast<int>(error));
+ base::JSONWriter::Write(dialog_args, &data);
+ return data;
}
bool InlineLoginHandlerDialogChromeOS::ShouldShowDialogTitle() const {
diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h
index bc650fdb91c..5d71fa7379d 100644
--- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h
+++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h
@@ -23,10 +23,13 @@ class InlineLoginHandlerDialogChromeOS
: public SystemWebDialogDelegate,
public web_modal::WebContentsModalDialogHost {
public:
+ enum class Source { kChrome = 0, kArc };
+
// Displays the dialog. |email| is an optional parameter that if provided,
// pre-fills the account email field in the sign-in dialog - useful for
// account re-authentication.
- static void Show(const std::string& email = std::string());
+ static void Show(const std::string& email = std::string(),
+ const Source& source = Source::kChrome);
// ui::SystemWebDialogDelegate overrides.
void AdjustWidgetInitParams(views::Widget::InitParams* params) override;
@@ -39,7 +42,7 @@ class InlineLoginHandlerDialogChromeOS
void RemoveObserver(web_modal::ModalDialogHostObserver* observer) override;
protected:
- explicit InlineLoginHandlerDialogChromeOS(const GURL& url);
+ InlineLoginHandlerDialogChromeOS(const GURL& url, const Source& source);
~InlineLoginHandlerDialogChromeOS() override;
// ui::WebDialogDelegate overrides
@@ -50,6 +53,8 @@ class InlineLoginHandlerDialogChromeOS
private:
InlineLoginHandlerModalDelegate delegate_;
+ const Source source_;
+ const GURL url_;
DISALLOW_COPY_AND_ASSIGN(InlineLoginHandlerDialogChromeOS);
};
diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
index fbf48642e0d..c0cf761b098 100644
--- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
+++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -519,6 +519,13 @@ void InlineLoginHandlerImpl::SetExtraInitParams(base::DictionaryValue& params) {
params.SetString("emailDomain", all_email_domains[0]);
}
+ std::string show_tos;
+ if (net::GetValueForKeyInQuery(
+ current_url, credential_provider::kShowTosSwitch, &show_tos)) {
+ if (!show_tos.empty())
+ params.SetString("showTos", show_tos);
+ }
+
// Prevent opening a new window if the embedded page fails to load.
// This will keep the user from being able to access a fully functional
// Chrome window in incognito mode.
@@ -580,7 +587,8 @@ void InlineLoginHandlerImpl::CompleteLogin(const std::string& email,
bool skip_for_now,
bool trusted,
bool trusted_found,
- bool choose_what_to_sync) {
+ bool choose_what_to_sync,
+ base::Value edu_login_params) {
content::WebContents* contents = web_ui()->GetWebContents();
const GURL& current_url = contents->GetURL();
@@ -598,8 +606,7 @@ void InlineLoginHandlerImpl::CompleteLogin(const std::string& email,
DCHECK(!auth_code.empty());
content::StoragePartition* partition =
- content::BrowserContext::GetStoragePartitionForSite(
- contents->GetBrowserContext(), signin::GetSigninPartitionURL());
+ signin::GetSigninPartition(contents->GetBrowserContext());
// If this was called from the user manager to reauthenticate the profile,
// the current profile is the system profile. In this case, use the email to
diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.h b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.h
index e05ee3ae67d..0a278abbf90 100644
--- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.h
+++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.h
@@ -68,9 +68,10 @@ class InlineLoginHandlerImpl : public InlineLoginHandler {
bool skip_for_now,
bool trusted,
bool trusted_found,
- bool choose_what_to_sync) override;
+ bool choose_what_to_sync,
+ base::Value edu_login_params) override;
- // This struct exists to pass paramters to the FinishCompleteLogin() method,
+ // This struct exists to pass parameters to the FinishCompleteLogin() method,
// since the base::Bind() call does not support this many template args.
struct FinishCompleteLoginParams {
public:
diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_ui.cc
index 62f1e70fb49..7669b6ad3ec 100644
--- a/chromium/chrome/browser/ui/webui/signin/inline_login_ui.cc
+++ b/chromium/chrome/browser/ui/webui/signin/inline_login_ui.cc
@@ -8,11 +8,12 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
+#include "chrome/browser/sessions/session_tab_helper_factory.h"
#include "chrome/browser/signin/signin_promo.h"
#include "chrome/browser/ui/webui/metrics_handler.h"
#include "chrome/browser/ui/webui/test_files_request_filter.h"
@@ -26,13 +27,80 @@
#include "content/public/common/content_switches.h"
#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.h"
#include "chrome/browser/ui/webui/signin/inline_login_handler_chromeos.h"
+#include "chrome/browser/ui/webui/webui_util.h"
+#include "chrome/grit/gaia_auth_host_resources.h"
+#include "chrome/grit/gaia_auth_host_resources_map.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/resources/grit/webui_resources.h"
+#include "ui/strings/grit/ui_strings.h"
#else
#include "chrome/browser/ui/webui/signin/inline_login_handler_impl.h"
#endif // defined(OS_CHROMEOS)
namespace {
+#if defined(OS_CHROMEOS)
+constexpr char kResourcesGeneratedPath[] =
+ "@out_folder@/gen/chrome/browser/resources/";
+
+void AddEduStrings(content::WebUIDataSource* source,
+ const base::string16& username) {
+ source->AddLocalizedString("okButton", IDS_APP_OK);
+ source->AddLocalizedString("backButton", IDS_EDU_LOGIN_BACK);
+ source->AddLocalizedString("nextButton", IDS_EDU_LOGIN_NEXT);
+
+ source->AddLocalizedString("welcomeTitle", IDS_EDU_LOGIN_WELCOME_TITLE);
+ source->AddLocalizedString("welcomeBody", IDS_EDU_LOGIN_WELCOME_BODY);
+ source->AddLocalizedString("welcomeReauthTitle",
+ IDS_EDU_LOGIN_WELCOME_REAUTH_TITLE);
+ source->AddLocalizedString("welcomeReauthBody",
+ IDS_EDU_LOGIN_WELCOME_REAUTH_BODY);
+ source->AddLocalizedString("parentsListTitle",
+ IDS_EDU_LOGIN_PARENTS_LIST_TITLE);
+ source->AddLocalizedString("parentsListBody",
+ IDS_EDU_LOGIN_PARENTS_LIST_BODY);
+
+ source->AddLocalizedString("parentSigninTitle",
+ IDS_EDU_LOGIN_PARENT_SIGNIN_TITLE);
+ source->AddString(
+ "parentSigninBody",
+ l10n_util::GetStringFUTF16(IDS_EDU_LOGIN_PARENT_SIGNIN_BODY, username));
+ source->AddLocalizedString("parentSigninPasswordLabel",
+ IDS_EDU_LOGIN_PARENT_SIGNIN_PASSWORD_LABEL);
+ source->AddLocalizedString(
+ "parentSigninPasswordError",
+ IDS_EDU_LOGIN_PARENT_SIGNIN_PASSWORD_ERROR_MESSAGE);
+ source->AddLocalizedString(
+ "parentSigninAccountRecoveryText",
+ IDS_EDU_LOGIN_PARENT_SIGNIN_ACCOUNT_RECOVERY_LINK_TEXT);
+ source->AddLocalizedString("parentSigninPasswordShow",
+ IDS_EDU_LOGIN_PARENT_SIGNIN_PASSWORD_SHOW);
+ source->AddLocalizedString("parentSigninPasswordHide",
+ IDS_EDU_LOGIN_PARENT_SIGNIN_PASSWORD_HIDE);
+ source->AddString("parentSigninAccountRecoveryUrl",
+ chrome::kAccountRecoveryURL);
+
+ source->AddLocalizedString("parentInfoTitle", IDS_EDU_LOGIN_INFO_TITLE);
+ source->AddLocalizedString("parentInfoParentSettingsText",
+ IDS_EDU_LOGIN_INFO_PARENT_SETTINGS);
+ source->AddString(
+ "parentInfoBody",
+ l10n_util::GetStringFUTF16(
+ IDS_EDU_LOGIN_INFO_BODY,
+ base::ASCIIToUTF16(chrome::kGsuiteTermsEducationPrivacyURL)));
+ source->AddString(
+ "parentInfoDataProtectionText",
+ l10n_util::GetStringFUTF16(
+ IDS_EDU_LOGIN_INFO_DATA_PROTECTION,
+ base::ASCIIToUTF16(chrome::kClassroomSigninLearnMoreURL)));
+ source->AddLocalizedString("parentInfoResourcesAvailabilityText",
+ IDS_EDU_LOGIN_INFO_RESOURCES_AVAILABILITY);
+}
+#endif // defined(OS_CHROMEOS)
+
content::WebUIDataSource* CreateWebUIDataSource() {
content::WebUIDataSource* source =
content::WebUIDataSource::Create(chrome::kChromeUIChromeSigninHost);
@@ -54,6 +122,46 @@ content::WebUIDataSource* CreateWebUIDataSource() {
source->AddResourcePath("inline_login.js", IDR_INLINE_LOGIN_JS);
source->AddResourcePath("gaia_auth_host.js", IDR_GAIA_AUTH_AUTHENTICATOR_JS);
+#if defined(OS_CHROMEOS)
+ source->OverrideContentSecurityPolicyScriptSrc(
+ "script-src chrome://resources chrome://test 'self';");
+
+ source->AddResourcePath("edu", IDR_EDU_LOGIN_EDU_LOGIN_HTML);
+ source->AddResourcePath("app.js", IDR_EDU_LOGIN_EDU_LOGIN_JS);
+ source->AddResourcePath("edu_login_button.js",
+ IDR_EDU_LOGIN_EDU_LOGIN_BUTTON_JS);
+ source->AddResourcePath("edu_login_template.js",
+ IDR_EDU_LOGIN_EDU_LOGIN_TEMPLATE_JS);
+ source->AddResourcePath("edu_login_css.js", IDR_EDU_LOGIN_EDU_LOGIN_CSS_JS);
+ source->AddResourcePath("icons.js", IDR_EDU_LOGIN_ICONS_JS);
+ source->AddResourcePath("browser_proxy.js", IDR_EDU_LOGIN_BROWSER_PROXY_JS);
+ source->AddResourcePath("edu_login_util.js", IDR_EDU_LOGIN_EDU_LOGIN_UTIL_JS);
+ source->AddResourcePath("edu_login_welcome.js",
+ IDR_EDU_LOGIN_EDU_LOGIN_WELCOME_JS);
+ source->AddResourcePath("edu_login_parents.js",
+ IDR_EDU_LOGIN_EDU_LOGIN_PARENTS_JS);
+ source->AddResourcePath("edu_login_parent_signin.js",
+ IDR_EDU_LOGIN_EDU_LOGIN_PARENT_SIGNIN_JS);
+ source->AddResourcePath("edu_login_parent_info.js",
+ IDR_EDU_LOGIN_EDU_LOGIN_PARENT_INFO_JS);
+ source->AddResourcePath("edu_login_signin.js",
+ IDR_EDU_LOGIN_EDU_LOGIN_SIGNIN_JS);
+
+ source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER);
+ source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER);
+
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ source->AddResourcePath("googleg.svg",
+ IDR_ACCOUNT_MANAGER_WELCOME_GOOGLE_LOGO_SVG);
+#endif
+ source->AddResourcePath("family_link_logo.svg", IDR_FAMILY_LINK_LOGO_SVG);
+
+ webui::SetupWebUIDataSource(
+ source,
+ base::make_span(kGaiaAuthHostResources, kGaiaAuthHostResourcesSize),
+ kResourcesGeneratedPath, IDR_INLINE_LOGIN_HTML);
+#endif // defined(OS_CHROMEOS)
+
source->AddLocalizedString("title", IDS_CHROME_SIGNIN_TITLE);
source->AddLocalizedString(
"accessibleCloseButtonLabel", IDS_SIGNIN_ACCESSIBLE_CLOSE_BUTTON);
@@ -103,13 +211,22 @@ InlineLoginUI::InlineLoginUI(content::WebUI* web_ui) : WebDialogUI(web_ui) {
return;
Profile* profile = Profile::FromWebUI(web_ui);
- content::WebUIDataSource::Add(profile, CreateWebUIDataSource());
+ content::WebUIDataSource* source = CreateWebUIDataSource();
+#if defined(OS_CHROMEOS)
+ base::string16 username =
+ chromeos::ProfileHelper::Get()->GetUserByProfile(profile)->GetGivenName();
+ AddEduStrings(source, username);
+#endif // defined(OS_CHROMEOS)
+ content::WebUIDataSource::Add(profile, source);
#if defined(OS_CHROMEOS)
web_ui->AddMessageHandler(
std::make_unique<chromeos::InlineLoginHandlerChromeOS>(
base::BindRepeating(&WebDialogUIBase::CloseDialog,
weak_factory_.GetWeakPtr(), nullptr /* args */)));
+ web_ui->AddMessageHandler(std::make_unique<chromeos::EduAccountLoginHandler>(
+ base::BindRepeating(&WebDialogUIBase::CloseDialog,
+ weak_factory_.GetWeakPtr(), nullptr /* args */)));
#else
web_ui->AddMessageHandler(std::make_unique<InlineLoginHandlerImpl>());
#endif // defined(OS_CHROMEOS)
@@ -126,7 +243,7 @@ InlineLoginUI::InlineLoginUI(content::WebUI* web_ui) : WebDialogUI(web_ui) {
// Ensure that the login UI has a tab ID, which will allow the GAIA auth
// extension's background script to tell it apart from iframes injected by
// other extensions.
- SessionTabHelper::CreateForWebContents(contents);
+ CreateSessionServiceTabHelper(contents);
}
InlineLoginUI::~InlineLoginUI() {}
diff --git a/chromium/chrome/browser/ui/webui/signin/login_ui_service.cc b/chromium/chrome/browser/ui/webui/signin/login_ui_service.cc
index e9b169c910f..77f3d7f8f49 100644
--- a/chromium/chrome/browser/ui/webui/signin/login_ui_service.cc
+++ b/chromium/chrome/browser/ui/webui/signin/login_ui_service.cc
@@ -82,13 +82,12 @@ void LoginUIService::ShowExtensionLoginPrompt(bool enable_sync,
if (enable_sync) {
// Set a primary account.
browser->signin_view_controller()->ShowDiceEnableSyncTab(
- browser, signin_metrics::AccessPoint::ACCESS_POINT_EXTENSIONS,
+ signin_metrics::AccessPoint::ACCESS_POINT_EXTENSIONS,
signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO, email_hint);
} else {
// Add an account to the web without setting a primary account.
browser->signin_view_controller()->ShowDiceAddAccountTab(
- browser, signin_metrics::AccessPoint::ACCESS_POINT_EXTENSIONS,
- email_hint);
+ signin_metrics::AccessPoint::ACCESS_POINT_EXTENSIONS, email_hint);
}
#endif
}
@@ -105,7 +104,7 @@ void LoginUIService::DisplayLoginResult(Browser* browser,
last_login_error_email_ = email;
if (!error_message.empty()) {
if (browser)
- browser->signin_view_controller()->ShowModalSigninErrorDialog(browser);
+ browser->signin_view_controller()->ShowModalSigninErrorDialog();
else
UserManagerProfileDialog::DisplayErrorMessage();
} else if (browser) {
diff --git a/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
index 446e1ddc0f7..a434306458f 100644
--- a/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
+++ b/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -6,8 +6,11 @@
#include "base/run_loop.h"
#include "base/scoped_observer.h"
+#include "base/strings/stringprintf.h"
#include "base/test/bind_test_util.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/account_consistency_mode_manager.h"
@@ -59,12 +62,25 @@ class SignInObserver : public signin::IdentityManager::Observer {
if (seen_)
return;
+ base::OneShotTimer timer;
+ timer.Start(FROM_HERE, base::TimeDelta::FromSeconds(30),
+ base::BindRepeating(&SignInObserver::OnTimeout,
+ base::Unretained(this)));
running_ = true;
message_loop_runner_ = new MessageLoopRunner;
message_loop_runner_->Run();
EXPECT_TRUE(seen_);
}
+ void OnTimeout() {
+ seen_ = false;
+ if (!running_)
+ return;
+ message_loop_runner_->Quit();
+ running_ = false;
+ FAIL() << "Sign in observer timed out!";
+ }
+
void OnPrimaryAccountSet(
const CoreAccountInfo& primary_account_info) override {
DVLOG(1) << "Google signin succeeded.";
@@ -187,6 +203,36 @@ std::string GetButtonIdForSyncConfirmationDialogAction(
return "cancelButton";
}
}
+
+std::string GetRadioButtonIdForSigninEmailConfirmationDialogAction(
+ SigninEmailConfirmationDialog::Action action) {
+ switch (action) {
+ case SigninEmailConfirmationDialog::CREATE_NEW_USER:
+ case SigninEmailConfirmationDialog::CLOSE:
+ return "createNewUserRadioButton";
+ case SigninEmailConfirmationDialog::START_SYNC:
+ return "startSyncRadioButton";
+ }
+}
+
+std::string GetButtonIdForSigninEmailConfirmationDialogAction(
+ SigninEmailConfirmationDialog::Action action) {
+ switch (action) {
+ case SigninEmailConfirmationDialog::CREATE_NEW_USER:
+ case SigninEmailConfirmationDialog::START_SYNC:
+ return "confirmButton";
+ case SigninEmailConfirmationDialog::CLOSE:
+ return "closeButton";
+ }
+}
+
+std::string GetButtonSelectorForApp(const std::string& app,
+ const std::string& button_id) {
+ return base::StringPrintf(
+ "(document.querySelector('%s') == null ? null :"
+ "document.querySelector('%s').shadowRoot.querySelector('#%s'))",
+ app.c_str(), app.c_str(), button_id.c_str());
+}
#endif // !defined(OS_CHROMEOS)
} // namespace
@@ -203,29 +249,25 @@ class SigninViewControllerTestUtil {
#else
SigninViewController* signin_view_controller =
browser->signin_view_controller();
- DCHECK_NE(signin_view_controller, nullptr);
+ DCHECK(signin_view_controller);
if (!signin_view_controller->ShowsModalDialog())
return false;
content::WebContents* dialog_web_contents =
signin_view_controller->GetModalDialogWebContentsForTesting();
- DCHECK_NE(dialog_web_contents, nullptr);
- std::string button_id = GetButtonIdForSyncConfirmationDialogAction(action);
- std::string button_selector =
- "(document.querySelector('sync-confirmation-app') == null ? null :"
- "document.querySelector('sync-confirmation-app').shadowRoot."
- "querySelector('#" +
- button_id + "'))";
+ DCHECK(dialog_web_contents);
+ std::string button_selector = GetButtonSelectorForApp(
+ "sync-confirmation-app",
+ GetButtonIdForSyncConfirmationDialogAction(action));
std::string message;
- std::string find_button_js =
+ std::string find_button_js = base::StringPrintf(
"if (document.readyState != 'complete') {"
" window.domAutomationController.send('DocumentNotReady');"
- "} else if (" +
- button_selector +
- " == null) {"
+ "} else if (%s == null) {"
" window.domAutomationController.send('NotFound');"
"} else {"
" window.domAutomationController.send('Ok');"
- "}";
+ "}",
+ button_selector.c_str());
EXPECT_TRUE(content::ExecuteScriptAndExtractString(
dialog_web_contents, find_button_js, &message));
if (message != "Ok")
@@ -238,6 +280,52 @@ class SigninViewControllerTestUtil {
return true;
#endif
}
+
+ static bool TryCompleteSigninEmailConfirmationDialog(
+ Browser* browser,
+ SigninEmailConfirmationDialog::Action action) {
+#if defined(OS_CHROMEOS)
+ NOTREACHED();
+ return false;
+#else
+ SigninViewController* signin_view_controller =
+ browser->signin_view_controller();
+ DCHECK(signin_view_controller);
+ if (!signin_view_controller->ShowsModalDialog())
+ return false;
+ content::WebContents* dialog_web_contents =
+ signin_view_controller->GetModalDialogWebContentsForTesting();
+ DCHECK(dialog_web_contents);
+ std::string radio_button_selector = GetButtonSelectorForApp(
+ "signin-email-confirmation-app",
+ GetRadioButtonIdForSigninEmailConfirmationDialogAction(action));
+ std::string button_selector = GetButtonSelectorForApp(
+ "signin-email-confirmation-app",
+ GetButtonIdForSigninEmailConfirmationDialogAction(action));
+ std::string message;
+ std::string find_button_js = base::StringPrintf(
+ "if (document.readyState != 'complete') {"
+ " window.domAutomationController.send('DocumentNotReady');"
+ "} else if (%s == null || %s == null) {"
+ " window.domAutomationController.send('NotFound');"
+ "} else {"
+ " window.domAutomationController.send('Ok');"
+ "}",
+ radio_button_selector.c_str(), button_selector.c_str());
+ EXPECT_TRUE(content::ExecuteScriptAndExtractString(
+ dialog_web_contents, find_button_js, &message));
+ if (message != "Ok")
+ return false;
+
+ // This cannot be a synchronous call, because it closes the window as a side
+ // effect, which may cause the javascript execution to never finish.
+ content::ExecuteScriptAsync(
+ dialog_web_contents, base::StringPrintf("%s.click(); %s.click();",
+ radio_button_selector.c_str(),
+ button_selector.c_str()));
+ return true;
+#endif
+ }
};
void WaitUntilUIReady(Browser* browser) {
@@ -369,4 +457,19 @@ bool CancelSyncConfirmationDialog(Browser* browser, base::TimeDelta timeout) {
SyncConfirmationDialogAction::kCancel);
}
+bool CompleteSigninEmailConfirmationDialog(
+ Browser* browser,
+ base::TimeDelta timeout,
+ SigninEmailConfirmationDialog::Action action) {
+ const base::Time expire_time = base::Time::Now() + timeout;
+ while (base::Time::Now() <= expire_time) {
+ if (SigninViewControllerTestUtil::TryCompleteSigninEmailConfirmationDialog(
+ browser, action)) {
+ return true;
+ }
+ RunLoopFor(base::TimeDelta::FromMilliseconds(1000));
+ }
+ return false;
+}
+
} // namespace login_ui_test_utils
diff --git a/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.h b/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.h
index 3f68f8f10fa..b9440eabf6f 100644
--- a/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.h
+++ b/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/time/time.h"
+#include "chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h"
#include "components/signin/public/base/signin_metrics.h"
class Browser;
@@ -51,6 +52,14 @@ bool ConfirmSyncConfirmationDialog(Browser* browser, base::TimeDelta timeout);
// |timeout|.
bool CancelSyncConfirmationDialog(Browser* browser, base::TimeDelta timeout);
+// Waits for the signin email confirmation dialog to get displayed, then
+// executes javascript to perform |action|. Returns false if failed to dismiss
+// the dialog before |timeout|.
+bool CompleteSigninEmailConfirmationDialog(
+ Browser* browser,
+ base::TimeDelta timeout,
+ SigninEmailConfirmationDialog::Action action);
+
} // namespace login_ui_test_utils
#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_LOGIN_UI_TEST_UTILS_H_
diff --git a/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc b/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc
index 96ef2616d15..47b62389943 100644
--- a/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc
+++ b/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc
@@ -8,9 +8,11 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/user_metrics.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser_dialogs.h"
+#include "chrome/browser/ui/signin_view_controller.h"
#include "chrome/browser/ui/webui/signin/signin_email_confirmation_ui.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/host_zoom_map.h"
@@ -62,34 +64,37 @@ class SigninEmailConfirmationDialog::DialogWebContentsObserver
};
SigninEmailConfirmationDialog::SigninEmailConfirmationDialog(
+ SigninViewController* signin_view_controller,
content::WebContents* contents,
Profile* profile,
const std::string& last_email,
const std::string& new_email,
- const Callback& callback)
- : web_contents_(contents),
+ Callback callback)
+ : signin_view_controller_(signin_view_controller),
+ web_contents_(contents),
profile_(profile),
last_email_(last_email),
new_email_(new_email),
- callback_(callback) {
- chrome::RecordDialogCreation(
- chrome::DialogIdentifier::SIGN_IN_EMAIL_CONFIRMATION);
-}
+ callback_(std::move(callback)) {}
SigninEmailConfirmationDialog::~SigninEmailConfirmationDialog() {}
// static
-void SigninEmailConfirmationDialog::AskForConfirmation(
+SigninEmailConfirmationDialog*
+SigninEmailConfirmationDialog::AskForConfirmation(
+ SigninViewController* signin_view_controller,
content::WebContents* contents,
Profile* profile,
const std::string& last_email,
const std::string& email,
- const Callback& callback) {
+ Callback callback) {
base::RecordAction(base::UserMetricsAction("Signin_Show_ImportDataPrompt"));
// ShowDialog() will take care of ownership.
SigninEmailConfirmationDialog* dialog = new SigninEmailConfirmationDialog(
- contents, profile, last_email, email, callback);
+ signin_view_controller, contents, profile, last_email, email,
+ std::move(callback));
dialog->ShowDialog();
+ return dialog;
}
void SigninEmailConfirmationDialog::ShowDialog() {
@@ -199,10 +204,13 @@ void SigninEmailConfirmationDialog::OnDialogClosed(
action = CLOSE;
}
- if (!callback_.is_null()) {
- callback_.Run(action);
- callback_.Reset();
+ if (signin_view_controller_) {
+ signin_view_controller_->ResetModalSigninDelegate();
+ signin_view_controller_ = nullptr;
}
+
+ if (callback_)
+ std::move(callback_).Run(action);
}
void SigninEmailConfirmationDialog::OnCloseContents(
@@ -214,3 +222,15 @@ void SigninEmailConfirmationDialog::OnCloseContents(
bool SigninEmailConfirmationDialog::ShouldShowDialogTitle() const {
return false;
}
+
+void SigninEmailConfirmationDialog::CloseModalSignin() {
+ CloseDialog();
+}
+
+void SigninEmailConfirmationDialog::ResizeNativeView(int height) {
+ NOTIMPLEMENTED();
+}
+
+content::WebContents* SigninEmailConfirmationDialog::GetWebContents() {
+ return GetDialogWebContents();
+}
diff --git a/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h b/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h
index 6ea34dd1732..ec51957390e 100644
--- a/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h
+++ b/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h
@@ -11,11 +11,13 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "chrome/browser/ui/signin_view_controller_delegate.h"
#include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
#include "ui/web_dialogs/web_dialog_delegate.h"
#include "ui/web_dialogs/web_dialog_ui.h"
class Profile;
+class SigninViewController;
namespace content {
class WebContents;
@@ -23,7 +25,8 @@ class WebUIMessageHandler;
}
// A tab-modal dialog to ask the user to confirm his email before signing in.
-class SigninEmailConfirmationDialog : public ui::WebDialogDelegate {
+class SigninEmailConfirmationDialog : public ui::WebDialogDelegate,
+ public SigninViewControllerDelegate {
public:
// Actions that can be taken when the user is asked to confirm their account.
enum Action {
@@ -39,26 +42,29 @@ class SigninEmailConfirmationDialog : public ui::WebDialogDelegate {
};
// Callback indicating action performed by the user.
- using Callback = base::Callback<void(Action)>;
+ using Callback = base::OnceCallback<void(Action)>;
// Create and show the dialog, which owns itself.
// Ask the user for confirmation before starting to sync.
- static void AskForConfirmation(content::WebContents* contents,
- Profile* profile,
- const std::string& last_email,
- const std::string& email,
- const Callback& callback);
+ static SigninEmailConfirmationDialog* AskForConfirmation(
+ SigninViewController* signin_view_controller,
+ content::WebContents* contents,
+ Profile* profile,
+ const std::string& last_email,
+ const std::string& email,
+ Callback callback);
~SigninEmailConfirmationDialog() override;
private:
class DialogWebContentsObserver;
- SigninEmailConfirmationDialog(content::WebContents* contents,
+ SigninEmailConfirmationDialog(SigninViewController* signin_view_controller,
+ content::WebContents* contents,
Profile* profile,
const std::string& last_email,
const std::string& new_email,
- const Callback& callback);
+ Callback callback);
// WebDialogDelegate implementation.
ui::ModalType GetDialogModalType() const override;
@@ -73,6 +79,11 @@ class SigninEmailConfirmationDialog : public ui::WebDialogDelegate {
bool* out_close_dialog) override;
bool ShouldShowDialogTitle() const override;
+ // SigninViewControllerDelegate:
+ void CloseModalSignin() override;
+ void ResizeNativeView(int height) override;
+ content::WebContents* GetWebContents() override;
+
// Shows the dialog and releases ownership of this object. Another object will
// take ownership and delete this object.
void ShowDialog();
@@ -87,6 +98,8 @@ class SigninEmailConfirmationDialog : public ui::WebDialogDelegate {
// Returns nullptr if there is no dialog.
content::WebContents* GetDialogWebContents() const;
+ SigninViewController* signin_view_controller_;
+
// Web contents from which the "Learn more" link should be opened.
content::WebContents* const web_contents_;
Profile* const profile_;
diff --git a/chromium/chrome/browser/ui/webui/signin/signin_error_handler.cc b/chromium/chrome/browser/ui/webui/signin/signin_error_handler.cc
index 8bda6fa9869..480a3eecadf 100644
--- a/chromium/chrome/browser/ui/webui/signin/signin_error_handler.cc
+++ b/chromium/chrome/browser/ui/webui/signin/signin_error_handler.cc
@@ -66,8 +66,7 @@ void SigninErrorHandler::HandleSwitchToExistingProfile(
// Switch to the existing duplicate profile. Do not create a new window when
// any existing ones can be reused.
profiles::SwitchToProfile(path_switching_to, false,
- ProfileManager::CreateCallback(),
- ProfileMetrics::SWITCH_PROFILE_DUPLICATE);
+ ProfileManager::CreateCallback());
}
void SigninErrorHandler::HandleConfirm(const base::ListValue* args) {
@@ -87,7 +86,7 @@ void SigninErrorHandler::HandleInitializedWithSize(
const base::ListValue* args) {
AllowJavascript();
if (duplicate_profile_path_.empty())
- CallJavascriptFunction("signin.error.removeSwitchButton");
+ FireWebUIListener("switch-button-unavailable");
signin::SetInitializedModalHeight(browser_, web_ui(), args);
@@ -96,7 +95,7 @@ void SigninErrorHandler::HandleInitializedWithSize(
// TODO(anthonyvd): Figure out why this is needed on Mac and not other
// platforms and if there's a way to start unfocused while avoiding this
// workaround.
- CallJavascriptFunction("signin.error.clearFocus");
+ FireWebUIListener("clear-focus");
}
void SigninErrorHandler::CloseDialog() {
diff --git a/chromium/chrome/browser/ui/webui/signin/signin_error_ui.cc b/chromium/chrome/browser/ui/webui/signin/signin_error_ui.cc
index cef433977bc..39f01b21d74 100644
--- a/chromium/chrome/browser/ui/webui/signin/signin_error_ui.cc
+++ b/chromium/chrome/browser/ui/webui/signin/signin_error_ui.cc
@@ -68,6 +68,8 @@ void SigninErrorUI::Initialize(Browser* browser, bool is_system_profile) {
content::WebUIDataSource::Create(chrome::kChromeUISigninErrorHost);
source->UseStringsJs();
source->SetDefaultResource(IDR_SIGNIN_ERROR_HTML);
+ source->AddResourcePath("signin_error_app.html", IDR_SIGNIN_ERROR_APP_HTML);
+ source->AddResourcePath("signin_error_app.js", IDR_SIGNIN_ERROR_APP_JS);
source->AddResourcePath("signin_error.js", IDR_SIGNIN_ERROR_JS);
source->AddResourcePath("signin_shared_old_css.html",
IDR_SIGNIN_SHARED_OLD_CSS_HTML);
diff --git a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
index f98fd1b70c9..eba97fb4b9f 100644
--- a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
+++ b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_avatar_icon_util.h"
#include "chrome/browser/signin/identity_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/signin_view_controller_delegate.h"
@@ -24,10 +25,13 @@
#include "components/consent_auditor/consent_auditor.h"
#include "components/signin/public/base/avatar_icon_util.h"
#include "components/signin/public/identity_manager/account_info.h"
+#include "components/signin/public/identity_manager/consent_level.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "url/gurl.h"
+using signin::ConsentLevel;
+
namespace {
const int kProfileImageSize = 128;
} // namespace
@@ -89,7 +93,7 @@ void SyncConfirmationHandler::HandleConfirm(const base::ListValue* args) {
}
void SyncConfirmationHandler::HandleGoToSettings(const base::ListValue* args) {
- DCHECK(profile_->IsSyncAllowed());
+ DCHECK(ProfileSyncServiceFactory::IsSyncAllowed(profile_));
did_user_explicitly_interact_ = true;
RecordConsent(args);
CloseModalSigninWindow(LoginUIService::CONFIGURE_SYNC_FIRST);
@@ -102,10 +106,10 @@ void SyncConfirmationHandler::HandleUndo(const base::ListValue* args) {
void SyncConfirmationHandler::HandleAccountImageRequest(
const base::ListValue* args) {
- DCHECK(profile_->IsSyncAllowed());
+ DCHECK(ProfileSyncServiceFactory::IsSyncAllowed(profile_));
base::Optional<AccountInfo> primary_account_info =
identity_manager_->FindExtendedAccountInfoForAccountWithRefreshToken(
- identity_manager_->GetPrimaryAccountInfo());
+ identity_manager_->GetPrimaryAccountInfo(ConsentLevel::kNotRequired));
// Fire the "account-image-changed" listener from |SetUserImageURL()|.
// Note: If the account info is not available yet in the
@@ -147,12 +151,13 @@ void SyncConfirmationHandler::RecordConsent(const base::ListValue* args) {
consent_auditor::ConsentAuditor* consent_auditor =
ConsentAuditorFactory::GetForProfile(profile_);
- consent_auditor->RecordSyncConsent(identity_manager_->GetPrimaryAccountId(),
- sync_consent);
+ consent_auditor->RecordSyncConsent(
+ identity_manager_->GetPrimaryAccountId(ConsentLevel::kNotRequired),
+ sync_consent);
}
void SyncConfirmationHandler::SetUserImageURL(const std::string& picture_url) {
- if (!profile_->IsSyncAllowed()) {
+ if (!ProfileSyncServiceFactory::IsSyncAllowed(profile_)) {
// The sync disabled confirmation handler does not present the user image.
// Avoid updating the image URL in this case.
return;
@@ -180,8 +185,10 @@ void SyncConfirmationHandler::OnExtendedAccountInfoUpdated(
if (!info.IsValid())
return;
- if (info.account_id != identity_manager_->GetPrimaryAccountId())
+ if (info.account_id !=
+ identity_manager_->GetPrimaryAccountId(ConsentLevel::kNotRequired)) {
return;
+ }
identity_manager_->RemoveObserver(this);
SetUserImageURL(info.picture_url);
@@ -217,7 +224,7 @@ void SyncConfirmationHandler::HandleInitializedWithSize(
base::Optional<AccountInfo> primary_account_info =
identity_manager_->FindExtendedAccountInfoForAccountWithRefreshToken(
- identity_manager_->GetPrimaryAccountInfo());
+ identity_manager_->GetPrimaryAccountInfo(ConsentLevel::kNotRequired));
if (!primary_account_info) {
// No account is signed in, so there is nothing to be displayed in the sync
// confirmation dialog.
diff --git a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.h b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
index d3f055814c6..f80bf2e8c6e 100644
--- a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
+++ b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.h
@@ -22,6 +22,9 @@ namespace signin {
class IdentityManager;
}
+// WebUI message handler for the sync confirmation dialog. IdentityManager calls
+// in this class use signin::ConsentLevel::kNotRequired because the user hasn't
+// consented to sync yet.
class SyncConfirmationHandler : public content::WebUIMessageHandler,
public signin::IdentityManager::Observer,
public BrowserListObserver {
diff --git a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
index 51e035b6ac7..3ba5023e3c6 100644
--- a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
+++ b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc
@@ -28,13 +28,19 @@
SyncConfirmationUI::SyncConfirmationUI(content::WebUI* web_ui)
: SigninWebDialogUI(web_ui) {
Profile* profile = Profile::FromWebUI(web_ui);
- bool is_sync_allowed = profile->IsSyncAllowed();
+ const bool is_sync_allowed =
+ ProfileSyncServiceFactory::IsSyncAllowed(profile);
content::WebUIDataSource* source =
content::WebUIDataSource::Create(chrome::kChromeUISyncConfirmationHost);
source->UseStringsJs();
source->EnableReplaceI18nInJS();
+ source->AddResourcePath("signin_shared_css.js", IDR_SIGNIN_SHARED_CSS_JS);
+ source->AddResourcePath("sync_confirmation_browser_proxy.js",
+ IDR_SYNC_CONFIRMATION_BROWSER_PROXY_JS);
+ source->AddResourcePath("sync_confirmation.js", IDR_SYNC_CONFIRMATION_JS);
+
if (is_sync_allowed) {
source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER);
source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER);
@@ -42,12 +48,8 @@ SyncConfirmationUI::SyncConfirmationUI(content::WebUI* web_ui)
"script-src chrome://resources chrome://test 'self';");
source->SetDefaultResource(IDR_SYNC_CONFIRMATION_HTML);
- source->AddResourcePath("signin_shared_css.js", IDR_SIGNIN_SHARED_CSS_JS);
- source->AddResourcePath("sync_confirmation_browser_proxy.js",
- IDR_SYNC_CONFIRMATION_BROWSER_PROXY_JS);
source->AddResourcePath("sync_confirmation_app.js",
IDR_SYNC_CONFIRMATION_APP_JS);
- source->AddResourcePath("sync_confirmation.js", IDR_SYNC_CONFIRMATION_JS);
source->AddResourcePath(
"images/sync_confirmation_illustration.svg",
@@ -89,10 +91,8 @@ SyncConfirmationUI::SyncConfirmationUI(content::WebUI* web_ui)
source->AddString("accountPictureUrl", custom_picture_url);
} else {
source->SetDefaultResource(IDR_SYNC_DISABLED_CONFIRMATION_HTML);
- source->AddResourcePath("signin_shared_old_css.html",
- IDR_SIGNIN_SHARED_OLD_CSS_HTML);
- source->AddResourcePath("sync_disabled_confirmation.js",
- IDR_SYNC_DISABLED_CONFIRMATION_JS);
+ source->AddResourcePath("sync_disabled_confirmation_app.js",
+ IDR_SYNC_DISABLED_CONFIRMATION_APP_JS);
AddStringResource(source, "syncDisabledConfirmationTitle",
IDS_SYNC_DISABLED_CONFIRMATION_CHROME_SYNC_TITLE);
diff --git a/chromium/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chromium/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index faa9222bb43..39ca8f0c887 100644
--- a/chromium/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
+++ b/chromium/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -484,13 +484,11 @@ void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) {
// not needing authentication. If it is, just ignore the "launch" request.
if (entry->IsSigninRequired())
return;
- ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY);
profiles::SwitchToProfile(
profile_path, false, /* reuse any existing windows */
base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
- weak_ptr_factory_.GetWeakPtr()),
- ProfileMetrics::SWITCH_PROFILE_MANAGER);
+ weak_ptr_factory_.GetWeakPtr()));
}
void UserManagerScreenHandler::HandleRemoveUserWarningLoadStats(
@@ -541,11 +539,6 @@ void UserManagerScreenHandler::RemoveUserDialogLoadStatsCallback(
stat->SetKey("count", base::Value(item.count));
return_value.SetWithoutPathExpansion(item.category, std::move(stat));
}
- if (result.size() == profiles::kProfileStatisticsCategories.size()) {
- // All categories are finished.
- UMA_HISTOGRAM_TIMES("Profile.RemoveUserWarningStatsTime",
- base::Time::Now() - start_time);
- }
web_ui()->CallJavascriptFunctionUnsafe("updateRemoveWarningDialog",
base::Value(profile_path.value()),
return_value);
@@ -614,6 +607,7 @@ void UserManagerScreenHandler::RegisterMessages() {
// Unused callbacks from display_manager.js
web_ui()->RegisterMessageCallback("showAddUser", base::DoNothing());
web_ui()->RegisterMessageCallback("updateCurrentScreen", base::DoNothing());
+ web_ui()->RegisterMessageCallback("updateOobeUIState", base::DoNothing());
web_ui()->RegisterMessageCallback("loginVisible", base::DoNothing());
// Unused callbacks from user_pod_row.js
web_ui()->RegisterMessageCallback("focusPod", base::DoNothing());
@@ -838,15 +832,13 @@ void UserManagerScreenHandler::SendUserList() {
void UserManagerScreenHandler::ReportAuthenticationResult(
bool success,
ProfileMetrics::ProfileAuth auth) {
- ProfileMetrics::LogProfileAuthResult(auth);
email_address_.clear();
if (success) {
profiles::SwitchToProfile(
authenticating_profile_path_, true,
base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
- weak_ptr_factory_.GetWeakPtr()),
- ProfileMetrics::SWITCH_PROFILE_UNLOCK);
+ weak_ptr_factory_.GetWeakPtr()));
} else {
web_ui()->CallJavascriptFunctionUnsafe(
"cr.ui.UserManager.showSignInError", base::Value(0),
diff --git a/chromium/chrome/browser/ui/webui/signin_internals_ui.cc b/chromium/chrome/browser/ui/webui/signin_internals_ui.cc
index 8f288996daf..011dc70c605 100644
--- a/chromium/chrome/browser/ui/webui/signin_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/signin_internals_ui.cc
@@ -13,7 +13,7 @@
#include "chrome/browser/signin/about_signin_internals_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/common/url_constants.h"
-#include "components/grit/components_resources.h"
+#include "components/grit/dev_ui_components_resources.h"
#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "content/public/browser/web_ui.h"
diff --git a/chromium/chrome/browser/ui/webui/site_settings_helper.cc b/chromium/chrome/browser/ui/webui/site_settings_helper.cc
index 423b78feabb..9de4ee74b87 100644
--- a/chromium/chrome/browser/ui/webui/site_settings_helper.cc
+++ b/chromium/chrome/browser/ui/webui/site_settings_helper.cc
@@ -11,25 +11,34 @@
#include "base/feature_list.h"
#include "base/stl_util.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
+#include "chrome/browser/bluetooth/bluetooth_chooser_context.h"
+#include "chrome/browser/bluetooth/bluetooth_chooser_context_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/hid/hid_chooser_context.h"
#include "chrome/browser/hid/hid_chooser_context_factory.h"
-#include "chrome/browser/permissions/chooser_context_base.h"
-#include "chrome/browser/permissions/permission_manager.h"
-#include "chrome/browser/permissions/permission_result.h"
+#include "chrome/browser/permissions/permission_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/serial/serial_chooser_context.h"
#include "chrome/browser/serial/serial_chooser_context_factory.h"
#include "chrome/browser/usb/usb_chooser_context.h"
#include "chrome/browser/usb/usb_chooser_context_factory.h"
#include "chrome/common/pref_names.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/content_settings_utils.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/permissions/chooser_context_base.h"
+#include "components/permissions/permission_manager.h"
+#include "components/permissions/permission_result.h"
#include "components/prefs/pref_service.h"
#include "components/subresource_filter/core/browser/subresource_filter_features.h"
+#include "components/url_formatter/url_formatter.h"
+#include "content/public/common/content_features.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/constants.h"
#include "url/origin.h"
@@ -56,6 +65,7 @@ typedef std::map<std::pair<GURL, std::string>, OneOriginObjects>
const char kUsbChooserDataGroupType[] = "usb-devices-data";
const char kSerialChooserDataGroupType[] = "serial-ports-data";
const char kHidChooserDataGroupType[] = "hid-devices-data";
+const char kBluetoothChooserDataGroupType[] = "bluetooth-devices-data";
const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
// The following ContentSettingsTypes have UI in Content Settings
@@ -79,7 +89,7 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
{ContentSettingsType::BACKGROUND_SYNC, "background-sync"},
{ContentSettingsType::ADS, "ads"},
{ContentSettingsType::SOUND, "sound"},
- {ContentSettingsType::CLIPBOARD_READ, "clipboard"},
+ {ContentSettingsType::CLIPBOARD_READ_WRITE, "clipboard"},
{ContentSettingsType::SENSORS, "sensors"},
{ContentSettingsType::PAYMENT_HANDLER, "payment-handler"},
{ContentSettingsType::USB_GUARD, "usb-devices"},
@@ -93,6 +103,11 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
{ContentSettingsType::NATIVE_FILE_SYSTEM_WRITE_GUARD,
"native-file-system-write"},
{ContentSettingsType::MIXEDSCRIPT, "mixed-script"},
+ {ContentSettingsType::VR, "vr"},
+ {ContentSettingsType::AR, "ar"},
+ {ContentSettingsType::BLUETOOTH_GUARD, "bluetooth-devices"},
+ {ContentSettingsType::BLUETOOTH_CHOOSER_DATA,
+ kBluetoothChooserDataGroupType},
// Add new content settings here if a corresponding Javascript string
// representation for it is not required. Note some exceptions do have UI in
@@ -103,7 +118,6 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
{ContentSettingsType::APP_BANNER, nullptr},
{ContentSettingsType::SITE_ENGAGEMENT, nullptr},
{ContentSettingsType::DURABLE_STORAGE, nullptr},
- {ContentSettingsType::BLUETOOTH_GUARD, nullptr},
{ContentSettingsType::AUTOPLAY, nullptr},
{ContentSettingsType::IMPORTANT_SITE_INFO, nullptr},
{ContentSettingsType::PERMISSION_AUTOBLOCKER_DATA, nullptr},
@@ -113,7 +127,7 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
{ContentSettingsType::MEDIA_ENGAGEMENT, nullptr},
{ContentSettingsType::CLIENT_HINTS, nullptr},
{ContentSettingsType::ACCESSIBILITY_EVENTS, nullptr},
- {ContentSettingsType::CLIPBOARD_WRITE, nullptr},
+ {ContentSettingsType::CLIPBOARD_SANITIZED_WRITE, nullptr},
{ContentSettingsType::PLUGINS_DATA, nullptr},
{ContentSettingsType::BACKGROUND_FETCH, nullptr},
{ContentSettingsType::INTENT_PICKER_DISPLAY, nullptr},
@@ -123,7 +137,9 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
{ContentSettingsType::LEGACY_COOKIE_ACCESS, nullptr},
{ContentSettingsType::INSTALLED_WEB_APP_METADATA, nullptr},
{ContentSettingsType::NFC, nullptr},
- {ContentSettingsType::BLUETOOTH_CHOOSER_DATA, nullptr},
+ {ContentSettingsType::SAFE_BROWSING_URL_CHECK_DATA, nullptr},
+ {ContentSettingsType::NATIVE_FILE_SYSTEM_READ_GUARD, nullptr},
+ {ContentSettingsType::STORAGE_ACCESS, nullptr},
};
static_assert(base::size(kContentSettingsTypeGroupNames) ==
// ContentSettingsType starts at -1, so add 1 here.
@@ -152,6 +168,28 @@ static_assert(base::size(kSiteSettingSourceStringMapping) ==
"kSiteSettingSourceStringMapping should have "
"SiteSettingSource::kNumSources elements");
+struct PolicyIndicatorTypeStringMapping {
+ PolicyIndicatorType source;
+ const char* indicator_str;
+};
+
+// Converts a policy indicator type to its JS usable string representation.
+const PolicyIndicatorTypeStringMapping kPolicyIndicatorTypeStringMapping[] = {
+ {PolicyIndicatorType::kDevicePolicy, "devicePolicy"},
+ {PolicyIndicatorType::kExtension, "extension"},
+ {PolicyIndicatorType::kNone, "none"},
+ {PolicyIndicatorType::kOwner, "owner"},
+ {PolicyIndicatorType::kPrimaryUser, "primary_user"},
+ {PolicyIndicatorType::kRecommended, "recommended"},
+ {PolicyIndicatorType::kUserPolicy, "userPolicy"},
+ {PolicyIndicatorType::kParent, "parent"},
+ {PolicyIndicatorType::kChildRestriction, "childRestriction"},
+};
+static_assert(base::size(kPolicyIndicatorTypeStringMapping) ==
+ static_cast<int>(PolicyIndicatorType::kNumIndicators),
+ "kPolicyIndicatorStringMapping should have "
+ "PolicyIndicatorType::kNumIndicators elements");
+
// Retrieves the corresponding string, according to the following precedence
// order from highest to lowest priority:
// 1. Kill-switch.
@@ -170,11 +208,11 @@ SiteSettingSource CalculateSiteSettingSource(
const ContentSettingsType content_type,
const GURL& origin,
const content_settings::SettingInfo& info,
- const PermissionResult result) {
- if (result.source == PermissionStatusSource::KILL_SWITCH)
+ const permissions::PermissionResult result) {
+ if (result.source == permissions::PermissionStatusSource::KILL_SWITCH)
return SiteSettingSource::kKillSwitch; // Source #1.
- if (result.source == PermissionStatusSource::INSECURE_ORIGIN)
+ if (result.source == permissions::PermissionStatusSource::INSECURE_ORIGIN)
return SiteSettingSource::kInsecureOrigin; // Source #2.
if (info.source == content_settings::SETTING_SOURCE_POLICY ||
@@ -205,8 +243,10 @@ SiteSettingSource CalculateSiteSettingSource(
DCHECK_NE(content_settings::SETTING_SOURCE_NONE, info.source);
if (info.source == content_settings::SETTING_SOURCE_USER) {
- if (result.source == PermissionStatusSource::MULTIPLE_DISMISSALS ||
- result.source == PermissionStatusSource::MULTIPLE_IGNORES) {
+ if (result.source ==
+ permissions::PermissionStatusSource::MULTIPLE_DISMISSALS ||
+ result.source ==
+ permissions::PermissionStatusSource::MULTIPLE_IGNORES) {
return SiteSettingSource::kEmbargo; // Source #8.
}
if (info.primary_pattern == ContentSettingsPattern::Wildcard() &&
@@ -226,6 +266,21 @@ SiteSettingSource CalculateSiteSettingSource(
return SiteSettingSource::kPreference;
}
+// Whether |pattern| applies to a single origin.
+bool PatternAppliesToSingleOrigin(const ContentSettingPatternSource& pattern) {
+ const GURL url(pattern.primary_pattern.ToString());
+ // Default settings and other patterns apply to multiple origins.
+ if (url::Origin::Create(url).opaque())
+ return false;
+ // Embedded content settings only when |url| is embedded in another origin, so
+ // ignore non-wildcard secondary patterns that are different to the primary.
+ if (pattern.primary_pattern != pattern.secondary_pattern &&
+ pattern.secondary_pattern != ContentSettingsPattern::Wildcard()) {
+ return false;
+ }
+ return true;
+}
+
// Retrieves the source of a chooser exception as a string. This method uses the
// CalculateSiteSettingSource method above to calculate the correct string to
// use.
@@ -239,8 +294,9 @@ std::string GetSourceStringForChooserException(
// Chooser exceptions do not use a PermissionContextBase for their
// permissions.
- PermissionResult permission_result(CONTENT_SETTING_DEFAULT,
- PermissionStatusSource::UNSPECIFIED);
+ permissions::PermissionResult permission_result(
+ CONTENT_SETTING_DEFAULT,
+ permissions::PermissionStatusSource::UNSPECIFIED);
// The |origin| parameter is only used for |ContentSettingsType::ADS| with
// the |kSafeBrowsingSubresourceFilter| feature flag enabled, so an empty GURL
@@ -253,26 +309,54 @@ std::string GetSourceStringForChooserException(
return SiteSettingSourceToString(calculated_source);
}
-ChooserContextBase* GetUsbChooserContext(Profile* profile) {
+permissions::ChooserContextBase* GetUsbChooserContext(Profile* profile) {
return UsbChooserContextFactory::GetForProfile(profile);
}
-ChooserContextBase* GetSerialChooserContext(Profile* profile) {
+permissions::ChooserContextBase* GetSerialChooserContext(Profile* profile) {
return SerialChooserContextFactory::GetForProfile(profile);
}
-ChooserContextBase* GetHidChooserContext(Profile* profile) {
+permissions::ChooserContextBase* GetHidChooserContext(Profile* profile) {
return HidChooserContextFactory::GetForProfile(profile);
}
+// The BluetoothChooserContext is only available when the
+// WebBluetoothNewPermissionsBackend flag is enabled.
+// TODO(https://crbug.com/589228): Remove the feature check when it is enabled
+// by default.
+permissions::ChooserContextBase* GetBluetoothChooserContext(Profile* profile) {
+ if (base::FeatureList::IsEnabled(
+ features::kWebBluetoothNewPermissionsBackend)) {
+ return BluetoothChooserContextFactory::GetForProfile(profile);
+ }
+ return nullptr;
+}
+
const ChooserTypeNameEntry kChooserTypeGroupNames[] = {
- {&GetUsbChooserContext, &UsbChooserContext::GetObjectName,
- kUsbChooserDataGroupType},
- {&GetSerialChooserContext, &SerialChooserContext::GetObjectName,
- kSerialChooserDataGroupType},
- {&GetHidChooserContext, &HidChooserContext::GetObjectName,
- kHidChooserDataGroupType},
-};
+ {&GetUsbChooserContext, kUsbChooserDataGroupType},
+ {&GetSerialChooserContext, kSerialChooserDataGroupType},
+ {&GetHidChooserContext, kHidChooserDataGroupType},
+ {&GetBluetoothChooserContext, kBluetoothChooserDataGroupType}};
+
+PolicyIndicatorType GetPolicyIndicatorFromSettingSource(
+ content_settings::SettingSource setting_source) {
+ switch (setting_source) {
+ case content_settings::SETTING_SOURCE_POLICY:
+ return PolicyIndicatorType::kDevicePolicy;
+ case content_settings::SETTING_SOURCE_SUPERVISED:
+ return PolicyIndicatorType::kParent;
+ case content_settings::SETTING_SOURCE_EXTENSION:
+ return PolicyIndicatorType::kExtension;
+ case content_settings::SETTING_SOURCE_USER:
+ case content_settings::SETTING_SOURCE_WHITELIST:
+ case content_settings::SETTING_SOURCE_NONE:
+ return PolicyIndicatorType::kNone;
+ case content_settings::SETTING_SOURCE_INSTALLED_WEBAPP:
+ NOTREACHED();
+ return PolicyIndicatorType::kNone;
+ }
+}
} // namespace
@@ -311,10 +395,31 @@ std::string ContentSettingsTypeToGroupName(ContentSettingsType type) {
return std::string();
}
+std::vector<ContentSettingsType> ContentSettingsTypesFromGroupNames(
+ const base::Value::ConstListView types) {
+ std::vector<ContentSettingsType> content_types;
+ content_types.reserve(types.size());
+ for (const auto& value : types) {
+ const auto& type = value.GetString();
+ content_types.push_back(
+ site_settings::ContentSettingsTypeFromGroupName(type));
+ }
+ return content_types;
+}
+
std::string SiteSettingSourceToString(const SiteSettingSource source) {
return kSiteSettingSourceStringMapping[static_cast<int>(source)].source_str;
}
+base::Value GetValueForManagedState(const site_settings::ManagedState& state) {
+ base::Value value(base::Value::Type::DICTIONARY);
+ value.SetKey(site_settings::kDisabled, base::Value(state.disabled));
+ value.SetKey(
+ site_settings::kPolicyIndicator,
+ base::Value(site_settings::PolicyIndicatorTypeToString(state.indicator)));
+ return value;
+}
+
// Add an "Allow"-entry to the list of |exceptions| for a |url_pattern| from
// the web extent of a hosted |app|.
void AddExceptionForHostedApp(const std::string& url_pattern,
@@ -393,9 +498,14 @@ std::string GetDisplayNameForGURL(
if (!display_name.empty())
return display_name;
- // Note that using Serialize() here will chop off default port numbers and
- // percent encode the origin.
- return origin.Serialize();
+ auto url_16 = url_formatter::FormatUrl(
+ url,
+ url_formatter::kFormatUrlOmitDefaults |
+ url_formatter::kFormatUrlOmitHTTPS |
+ url_formatter::kFormatUrlOmitTrailingSlashOnBareHostname,
+ net::UnescapeRule::NONE, nullptr, nullptr, nullptr);
+ auto url_string = base::UTF16ToUTF8(url_16);
+ return url_string;
}
// If the given |pattern| represents an individual origin or extension, retrieve
@@ -541,11 +651,13 @@ ContentSetting GetContentSettingForOrigin(
origin, origin, content_type, std::string(), &info);
// Retrieve the content setting.
- PermissionResult result(CONTENT_SETTING_DEFAULT,
- PermissionStatusSource::UNSPECIFIED);
- if (PermissionUtil::IsPermission(content_type)) {
- result = PermissionManager::Get(profile)->GetPermissionStatus(
- content_type, origin, origin);
+ permissions::PermissionResult result(
+ CONTENT_SETTING_DEFAULT,
+ permissions::PermissionStatusSource::UNSPECIFIED);
+ if (permissions::PermissionUtil::IsPermission(content_type)) {
+ result =
+ PermissionManagerFactory::GetForProfile(profile)->GetPermissionStatus(
+ content_type, origin, origin);
} else {
DCHECK(value.get());
DCHECK_EQ(base::Value::Type::INTEGER, value->type());
@@ -561,6 +673,19 @@ ContentSetting GetContentSettingForOrigin(
return result.content_setting;
}
+std::vector<ContentSettingPatternSource> GetSiteExceptionsForContentType(
+ HostContentSettingsMap* map,
+ ContentSettingsType content_type) {
+ ContentSettingsForOneType entries;
+ map->GetSettingsForOneType(content_type, std::string(), &entries);
+ entries.erase(std::remove_if(entries.begin(), entries.end(),
+ [](const ContentSettingPatternSource& e) {
+ return !PatternAppliesToSingleOrigin(e);
+ }),
+ entries.end());
+ return entries;
+}
+
void GetPolicyAllowedUrls(
ContentSettingsType type,
std::vector<std::unique_ptr<base::DictionaryValue>>* exceptions,
@@ -617,7 +742,7 @@ const ChooserTypeNameEntry* ChooserTypeFromGroupName(const std::string& name) {
// in a chooser permission exceptions table. The chooser permission will contain
// a list of site exceptions that correspond to the exception.
base::Value CreateChooserExceptionObject(
- const std::string& display_name,
+ const base::string16& display_name,
const base::Value& object,
const std::string& chooser_type,
const ChooserExceptionDetails& chooser_exception_details) {
@@ -677,24 +802,36 @@ base::Value GetChooserExceptionListFromProfile(
ContentSettingsType content_type =
ContentSettingsTypeFromGroupName(std::string(chooser_type.name));
- ChooserContextBase* chooser_context = chooser_type.get_context(profile);
- std::vector<std::unique_ptr<ChooserContextBase::Object>> objects =
- chooser_context->GetAllGrantedObjects();
+ // The BluetoothChooserContext is only available when the
+ // WebBluetoothNewPermissionsBackend flag is enabled.
+ // TODO(https://crbug.com/589228): Remove the nullptr check when it is enabled
+ // by default.
+ permissions::ChooserContextBase* chooser_context =
+ chooser_type.get_context(profile);
+ if (!chooser_context)
+ return exceptions;
+
+ std::vector<std::unique_ptr<permissions::ChooserContextBase::Object>>
+ objects = chooser_context->GetAllGrantedObjects();
if (profile->HasOffTheRecordProfile()) {
Profile* incognito_profile = profile->GetOffTheRecordProfile();
- ChooserContextBase* incognito_chooser_context =
+ permissions::ChooserContextBase* incognito_chooser_context =
chooser_type.get_context(incognito_profile);
- std::vector<std::unique_ptr<ChooserContextBase::Object>> incognito_objects =
- incognito_chooser_context->GetAllGrantedObjects();
+ std::vector<std::unique_ptr<permissions::ChooserContextBase::Object>>
+ incognito_objects = incognito_chooser_context->GetAllGrantedObjects();
objects.insert(objects.end(),
std::make_move_iterator(incognito_objects.begin()),
std::make_move_iterator(incognito_objects.end()));
}
- AllChooserObjects all_chooser_objects;
+ // Maps from a chooser exception name/object pair to a
+ // ChooserExceptionDetails. This will group and sort the exceptions by the UI
+ // string and object for display.
+ std::map<std::pair<base::string16, base::Value>, ChooserExceptionDetails>
+ all_chooser_objects;
for (const auto& object : objects) {
- std::string name = chooser_type.get_object_name(object->value);
+ base::string16 name = chooser_context->GetObjectDisplayName(object->value);
auto& chooser_exception_details =
all_chooser_objects[std::make_pair(name, object->value.Clone())];
@@ -712,7 +849,7 @@ base::Value GetChooserExceptionListFromProfile(
}
for (const auto& all_chooser_objects_entry : all_chooser_objects) {
- const std::string& name = all_chooser_objects_entry.first.first;
+ const base::string16& name = all_chooser_objects_entry.first.first;
const base::Value& object = all_chooser_objects_entry.first.second;
const ChooserExceptionDetails& chooser_exception_details =
all_chooser_objects_entry.second;
@@ -723,4 +860,145 @@ base::Value GetChooserExceptionListFromProfile(
return exceptions;
}
+CookieControlsManagedState GetCookieControlsManagedState(Profile* profile) {
+ // Setup a default unmanaged state that is updated based on the actual
+ // managed state.
+ CookieControlsManagedState managed_state;
+
+ HostContentSettingsMap* map =
+ HostContentSettingsMapFactory::GetForProfile(profile);
+ std::string content_setting_provider;
+ auto content_setting = map->GetDefaultContentSetting(
+ ContentSettingsType::COOKIES, &content_setting_provider);
+ auto content_setting_source =
+ HostContentSettingsMap::GetSettingSourceFromProviderName(
+ content_setting_provider);
+ bool content_setting_enforced =
+ content_setting_source !=
+ content_settings::SettingSource::SETTING_SOURCE_USER;
+
+ // Both the content setting and the block_third_party preference can
+ // be controlled via policy.
+ const PrefService::Preference* block_third_party_pref =
+ profile->GetPrefs()->FindPreference(prefs::kBlockThirdPartyCookies);
+ bool block_third_party_on = block_third_party_pref->GetValue()->GetBool();
+ bool block_third_party_enforced = !block_third_party_pref->IsUserModifiable();
+ // IsRecommended() cannot be used as we care if a recommended value exists at
+ // all, even if a user has overwritten it.
+ bool block_third_party_recommended =
+ (block_third_party_pref && block_third_party_pref->GetRecommendedValue());
+ bool block_third_party_recommended_on =
+ block_third_party_recommended &&
+ block_third_party_pref->GetRecommendedValue()->GetBool();
+
+ // kCookieControlsMode == kOn should imply block_third_party is on.
+ auto control_mode = static_cast<content_settings::CookieControlsMode>(
+ profile->GetPrefs()->GetInteger(prefs::kCookieControlsMode));
+ DCHECK(control_mode != content_settings::CookieControlsMode::kOn ||
+ block_third_party_on)
+ << "kCookieControlsMode == kOn should imply "
+ << "kBlockThirdPartyCookies is true";
+
+ // Get indicators representing each settings source. These may or may not
+ // be used depending on the determined managed state.
+ auto content_setting_source_indicator =
+ GetPolicyIndicatorFromSettingSource(content_setting_source);
+ auto block_third_party_source_indicator =
+ GetPolicyIndicatorFromPref(block_third_party_pref);
+
+ if (!content_setting_enforced && !block_third_party_enforced &&
+ !block_third_party_recommended) {
+ // No cookie controls are managed or recommended.
+ return managed_state;
+ }
+
+ if (content_setting_enforced) {
+ // Block and session only managed state only depend on the content setting.
+ managed_state.block_all = {/*disabled*/ true,
+ content_setting_source_indicator};
+ managed_state.session_only = {/*disabled*/ true,
+ content_setting_source_indicator};
+ }
+
+ if (content_setting_enforced && content_setting == CONTENT_SETTING_BLOCK) {
+ // All remaining controls are managed by the content setting source.
+ managed_state.allow_all = {/*disabled*/ true,
+ content_setting_source_indicator};
+ managed_state.block_third_party_incognito = {
+ /*disabled*/ true, content_setting_source_indicator};
+ managed_state.block_third_party = {/*disabled*/ true,
+ content_setting_source_indicator};
+ return managed_state;
+ }
+ if (content_setting_enforced && block_third_party_enforced) {
+ // All remaining controls are managed by the block_third_party source.
+ managed_state.allow_all = {/*disabled*/ true,
+ block_third_party_source_indicator};
+ managed_state.block_third_party_incognito = {
+ /*disabled*/ true, block_third_party_source_indicator};
+ managed_state.block_third_party = {/*disabled*/ true,
+ block_third_party_source_indicator};
+ return managed_state;
+ }
+ DCHECK(!content_setting_enforced ||
+ content_setting == CONTENT_SETTING_ALLOW ||
+ content_setting == CONTENT_SETTING_SESSION_ONLY);
+ DCHECK(!content_setting_enforced || !block_third_party_enforced);
+ // At this stage the content setting is not enforcing a BLOCK state. Given
+ // this, allow and block_third_party are still valid choices that do not
+ // contradict the content setting. They can thus be controlled or recommended
+ // by the block_third_party preference.
+ if (block_third_party_enforced) {
+ DCHECK(!content_setting_enforced);
+ managed_state.block_third_party_incognito = {
+ true, block_third_party_source_indicator};
+ if (block_third_party_on) {
+ managed_state.allow_all = {/*disabled*/ true,
+ block_third_party_source_indicator};
+ } else {
+ managed_state.block_third_party = {/*disabled*/ true,
+ block_third_party_source_indicator};
+ }
+ return managed_state;
+ }
+ if (block_third_party_recommended) {
+ if (block_third_party_recommended_on) {
+ managed_state.block_third_party = {/*disabled*/ false,
+ block_third_party_source_indicator};
+ } else {
+ managed_state.allow_all = {/*disabled*/ false,
+ block_third_party_source_indicator};
+ }
+ return managed_state;
+ }
+ DCHECK(content_setting_enforced && !block_third_party_enforced &&
+ !block_third_party_recommended);
+ return managed_state;
+}
+
+std::string PolicyIndicatorTypeToString(const PolicyIndicatorType type) {
+ return kPolicyIndicatorTypeStringMapping[static_cast<int>(type)]
+ .indicator_str;
+}
+
+PolicyIndicatorType GetPolicyIndicatorFromPref(
+ const PrefService::Preference* pref) {
+ if (!pref) {
+ return PolicyIndicatorType::kNone;
+ }
+ if (pref->IsExtensionControlled()) {
+ return PolicyIndicatorType::kExtension;
+ }
+ if (pref->IsManagedByCustodian()) {
+ return PolicyIndicatorType::kParent;
+ }
+ if (pref->IsManaged()) {
+ return PolicyIndicatorType::kDevicePolicy;
+ }
+ if (pref->GetRecommendedValue()) {
+ return PolicyIndicatorType::kRecommended;
+ }
+ return PolicyIndicatorType::kNone;
+}
+
} // namespace site_settings
diff --git a/chromium/chrome/browser/ui/webui/site_settings_helper.h b/chromium/chrome/browser/ui/webui/site_settings_helper.h
index f952cdbc7e9..07c890235a9 100644
--- a/chromium/chrome/browser/ui/webui/site_settings_helper.h
+++ b/chromium/chrome/browser/ui/webui/site_settings_helper.h
@@ -12,26 +12,29 @@
#include <utility>
#include <vector>
+#include "base/strings/string16.h"
+#include "base/values.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/content_settings/core/common/content_settings_types.h"
-#include "content/public/browser/web_ui.h"
+#include "components/prefs/pref_service.h"
#include "extensions/common/extension.h"
-class ChooserContextBase;
class HostContentSettingsMap;
class Profile;
-namespace base {
-class DictionaryValue;
-class ListValue;
-class Value;
-} // namespace base
+namespace content {
+class WebUI;
+}
namespace extensions {
class ExtensionRegistry;
}
+namespace permissions {
+class ChooserContextBase;
+}
+
namespace site_settings {
// Maps from a secondary pattern to a setting.
@@ -50,22 +53,25 @@ typedef std::map<std::pair<ContentSettingsPattern, std::string>,
using ChooserExceptionDetails =
std::map<std::pair<GURL, std::string>, std::set<std::pair<GURL, bool>>>;
-// Maps from a chooser exception name/object pair to a ChooserExceptionDetails.
-// This will group and sort the exceptions by the UI string and object for
-// display.
-using AllChooserObjects =
- std::map<std::pair<std::string, base::Value>, ChooserExceptionDetails>;
-
+constexpr char kAllowAll[] = "allowAll";
+constexpr char kBlockThirdPartyIncognito[] = "blockThirdPartyIncognito";
+constexpr char kBlockThirdParty[] = "blockThirdParty";
+constexpr char kBlockAll[] = "blockAll";
+constexpr char kSessionOnly[] = "sessionOnly";
constexpr char kChooserType[] = "chooserType";
constexpr char kDisplayName[] = "displayName";
constexpr char kEmbeddingOrigin[] = "embeddingOrigin";
constexpr char kIncognito[] = "incognito";
constexpr char kObject[] = "object";
+constexpr char kDisabled[] = "disabled";
constexpr char kOrigin[] = "origin";
constexpr char kOriginForFavicon[] = "originForFavicon";
+constexpr char kRecentPermissions[] = "recentPermissions";
constexpr char kSetting[] = "setting";
constexpr char kSites[] = "sites";
+constexpr char kPolicyIndicator[] = "indicator";
constexpr char kSource[] = "source";
+constexpr char kType[] = "type";
enum class SiteSettingSource {
kAdsFilterBlacklist,
@@ -80,6 +86,37 @@ enum class SiteSettingSource {
kNumSources,
};
+// Possible policy indicators that can be shown in settings.
+// Must be kept in sync with the CrPolicyIndicatorType enum located in
+// src/ui/webui/resources/cr_elements/policy/cr_policy_indicator_behavior.js
+enum class PolicyIndicatorType {
+ kDevicePolicy,
+ kExtension,
+ kNone,
+ kOwner,
+ kPrimaryUser,
+ kRecommended,
+ kUserPolicy,
+ kParent,
+ kChildRestriction,
+ kNumIndicators,
+};
+
+// Represents the managed state for a single settings control.
+struct ManagedState {
+ bool disabled = false;
+ PolicyIndicatorType indicator = PolicyIndicatorType::kNone;
+};
+
+// Represents the manage states for all of the cookie controls.
+struct CookieControlsManagedState {
+ ManagedState allow_all;
+ ManagedState block_third_party_incognito;
+ ManagedState block_third_party;
+ ManagedState block_all;
+ ManagedState session_only;
+};
+
// Returns whether a group name has been registered for the given type.
bool HasRegisteredGroupName(ContentSettingsType type);
@@ -87,9 +124,16 @@ bool HasRegisteredGroupName(ContentSettingsType type);
ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name);
std::string ContentSettingsTypeToGroupName(ContentSettingsType type);
+// Converts a ListValue of group names to a list of ContentSettingsTypes
+std::vector<ContentSettingsType> ContentSettingsTypesFromGroupNames(
+ const base::Value::ConstListView types);
+
// Converts a SiteSettingSource to its string identifier.
std::string SiteSettingSourceToString(const SiteSettingSource source);
+// Converts a ManagedState to a base::Value suitable for sending to JavaScript.
+base::Value GetValueForManagedState(const ManagedState& state);
+
// Helper function to construct a dictionary for an exception.
std::unique_ptr<base::DictionaryValue> GetExceptionForPage(
const ContentSettingsPattern& pattern,
@@ -145,12 +189,16 @@ void GetPolicyAllowedUrls(
content::WebUI* web_ui,
bool incognito);
+// Returns all site permission exceptions for a given content type
+std::vector<ContentSettingPatternSource> GetSiteExceptionsForContentType(
+ HostContentSettingsMap* map,
+ ContentSettingsType content_type);
+
// This struct facilitates lookup of a chooser context factory function by name
// for a given content settings type and is declared early so that it can used
// by functions below.
struct ChooserTypeNameEntry {
- ChooserContextBase* (*get_context)(Profile*);
- std::string (*get_object_name)(const base::Value&);
+ permissions::ChooserContextBase* (*get_context)(Profile*);
const char* name;
};
@@ -170,7 +218,7 @@ const ChooserTypeNameEntry* ChooserTypeFromGroupName(const std::string& name);
// The structure of the SiteException objects is the same as the objects
// returned by GetExceptionForPage().
base::Value CreateChooserExceptionObject(
- const std::string& display_name,
+ const base::string16& display_name,
const base::Value& object,
const std::string& chooser_type,
const ChooserExceptionDetails& chooser_exception_details);
@@ -180,6 +228,16 @@ base::Value GetChooserExceptionListFromProfile(
Profile* profile,
const ChooserTypeNameEntry& chooser_type);
+// Returns the cookie controls manage state for a given profile.
+CookieControlsManagedState GetCookieControlsManagedState(Profile* profile);
+
+// Concerts a PolicyIndicatorType to its string identifier.
+std::string PolicyIndicatorTypeToString(const PolicyIndicatorType type);
+
+// Returns the appropriate indicator for the source of a preference.
+PolicyIndicatorType GetPolicyIndicatorFromPref(
+ const PrefService::Preference* pref);
+
} // namespace site_settings
#endif // CHROME_BROWSER_UI_WEBUI_SITE_SETTINGS_HELPER_H_
diff --git a/chromium/chrome/browser/ui/webui/site_settings_helper_unittest.cc b/chromium/chrome/browser/ui/webui/site_settings_helper_unittest.cc
index f386d843b8b..c53099d4123 100644
--- a/chromium/chrome/browser/ui/webui/site_settings_helper_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/site_settings_helper_unittest.cc
@@ -7,8 +7,8 @@
#include "base/bind_helpers.h"
#include "base/guid.h"
#include "base/json/json_reader.h"
+#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
-#include "chrome/browser/permissions/chooser_context_base.h"
#include "chrome/browser/usb/usb_chooser_context.h"
#include "chrome/browser/usb/usb_chooser_context_factory.h"
#include "chrome/common/pref_names.h"
@@ -19,7 +19,9 @@
#include "components/content_settings/core/common/pref_names.h"
#include "components/content_settings/core/test/content_settings_mock_provider.h"
#include "components/content_settings/core/test/content_settings_test_utils.h"
+#include "components/permissions/chooser_context_base.h"
#include "components/prefs/pref_service.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/browser/extension_registry.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -236,14 +238,22 @@ TEST_F(SiteSettingsHelperTest, ContentSettingSource) {
namespace {
// Test GURLs
-const GURL kGoogleUrl("https://google.com");
-const GURL kChromiumUrl("https://chromium.org");
-const GURL kAndroidUrl("https://android.com");
+// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter
+// function.
+GURL GoogleUrl() {
+ return GURL("https://google.com");
+}
+GURL ChromiumUrl() {
+ return GURL("https://chromium.org");
+}
+GURL AndroidUrl() {
+ return GURL("https://android.com");
+}
void ExpectValidChooserExceptionObject(
const base::Value& actual_exception_object,
const std::string& chooser_type,
- const std::string& display_name,
+ const base::string16& display_name,
const base::Value& chooser_object) {
const base::Value* chooser_type_value = actual_exception_object.FindKeyOfType(
kChooserType, base::Value::Type::STRING);
@@ -253,7 +263,7 @@ void ExpectValidChooserExceptionObject(
const base::Value* display_name_value = actual_exception_object.FindKeyOfType(
kDisplayName, base::Value::Type::STRING);
ASSERT_TRUE(display_name_value);
- EXPECT_EQ(display_name_value->GetString(), display_name);
+ EXPECT_EQ(base::UTF8ToUTF16(display_name_value->GetString()), display_name);
const base::Value* object_value = actual_exception_object.FindKeyOfType(
kObject, base::Value::Type::DICTIONARY);
@@ -322,7 +332,7 @@ TEST_F(SiteSettingsHelperTest, CreateChooserExceptionObject) {
SiteSettingSourceToString(SiteSettingSource::kPolicy);
const std::string& kPreferenceSource =
SiteSettingSourceToString(SiteSettingSource::kPreference);
- const char kObjectName[] = "Gadget";
+ const base::string16& kObjectName = base::ASCIIToUTF16("Gadget");
ChooserExceptionDetails exception_details;
// Create a chooser object for testing.
@@ -331,8 +341,8 @@ TEST_F(SiteSettingsHelperTest, CreateChooserExceptionObject) {
// Add a user permission for a requesting origin of |kGoogleOrigin| and an
// embedding origin of |kChromiumOrigin|.
- exception_details[std::make_pair(kGoogleUrl.GetOrigin(), kPreferenceSource)]
- .insert(std::make_pair(kChromiumUrl.GetOrigin(), /*incognito=*/false));
+ exception_details[std::make_pair(GoogleUrl().GetOrigin(), kPreferenceSource)]
+ .insert(std::make_pair(ChromiumUrl().GetOrigin(), /*incognito=*/false));
{
auto exception = CreateChooserExceptionObject(
@@ -346,16 +356,16 @@ TEST_F(SiteSettingsHelperTest, CreateChooserExceptionObject) {
const auto& sites_list = exception.FindKey(kSites)->GetList();
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[0],
- /*origin=*/kGoogleUrl,
- /*embedding_origin=*/kChromiumUrl,
+ /*origin=*/GoogleUrl(),
+ /*embedding_origin=*/ChromiumUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/false);
}
// Add a user permissions for a requesting and embedding origin pair of
// |kAndroidOrigin| granted in an off the record profile.
- exception_details[std::make_pair(kAndroidUrl.GetOrigin(), kPreferenceSource)]
- .insert(std::make_pair(kAndroidUrl.GetOrigin(), /*incognito=*/true));
+ exception_details[std::make_pair(AndroidUrl().GetOrigin(), kPreferenceSource)]
+ .insert(std::make_pair(AndroidUrl().GetOrigin(), /*incognito=*/true));
{
auto exception = CreateChooserExceptionObject(
@@ -372,20 +382,20 @@ TEST_F(SiteSettingsHelperTest, CreateChooserExceptionObject) {
// be first, followed by the origin pair (kGoogleOrigin, kChromiumOrigin).
const auto& sites_list = exception.FindKey(kSites)->GetList();
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[0],
- /*origin=*/kAndroidUrl,
- /*embedding_origin=*/kAndroidUrl,
+ /*origin=*/AndroidUrl(),
+ /*embedding_origin=*/AndroidUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/true);
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[1],
- /*origin=*/kGoogleUrl,
- /*embedding_origin=*/kChromiumUrl,
+ /*origin=*/GoogleUrl(),
+ /*embedding_origin=*/ChromiumUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/false);
}
// Add a policy permission for a requesting origin of |kGoogleOrigin| with a
// wildcard embedding origin.
- exception_details[std::make_pair(kGoogleUrl.GetOrigin(), kPolicySource)]
+ exception_details[std::make_pair(GoogleUrl().GetOrigin(), kPolicySource)]
.insert(std::make_pair(GURL::EmptyGURL(), /*incognito=*/false));
{
auto exception = CreateChooserExceptionObject(
@@ -404,18 +414,18 @@ TEST_F(SiteSettingsHelperTest, CreateChooserExceptionObject) {
// sites.
const auto& sites_list = exception.FindKey(kSites)->GetList();
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[0],
- /*origin=*/kGoogleUrl,
+ /*origin=*/GoogleUrl(),
/*embedding_origin=*/GURL::EmptyGURL(),
/*source=*/kPolicySource,
/*incognito=*/false);
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[1],
- /*origin=*/kAndroidUrl,
- /*embedding_origin=*/kAndroidUrl,
+ /*origin=*/AndroidUrl(),
+ /*embedding_origin=*/AndroidUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/true);
ExpectValidSiteExceptionObject(/*actual_site_object=*/sites_list[2],
- /*origin=*/kGoogleUrl,
- /*embedding_origin=*/kChromiumUrl,
+ /*origin=*/GoogleUrl(),
+ /*embedding_origin=*/ChromiumUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/false);
}
@@ -466,9 +476,9 @@ class SiteSettingsHelperChooserExceptionTest : public testing::Test {
base::DoNothing::Once<std::vector<device::mojom::UsbDeviceInfoPtr>>());
base::RunLoop().RunUntilIdle();
- const auto kAndroidOrigin = url::Origin::Create(kAndroidUrl);
- const auto kChromiumOrigin = url::Origin::Create(kChromiumUrl);
- const auto kGoogleOrigin = url::Origin::Create(kGoogleUrl);
+ const auto kAndroidOrigin = url::Origin::Create(AndroidUrl());
+ const auto kChromiumOrigin = url::Origin::Create(ChromiumUrl());
+ const auto kGoogleOrigin = url::Origin::Create(GoogleUrl());
// Add the user granted permissions for testing.
// These two persistent device permissions should be lumped together with
@@ -540,8 +550,8 @@ TEST_F(SiteSettingsHelperChooserExceptionTest,
const auto& sites_list = exception.FindKey(kSites)->GetList();
ASSERT_EQ(sites_list.size(), 1u);
ExpectValidSiteExceptionObject(sites_list[0],
- /*origin=*/kGoogleUrl,
- /*embedding_origin=*/kAndroidUrl,
+ /*origin=*/GoogleUrl(),
+ /*embedding_origin=*/AndroidUrl(),
/*source=*/kPolicySource,
/*incognito=*/false);
}
@@ -558,8 +568,8 @@ TEST_F(SiteSettingsHelperChooserExceptionTest,
const auto& sites_list = exception.FindKey(kSites)->GetList();
ASSERT_EQ(sites_list.size(), 1u);
ExpectValidSiteExceptionObject(sites_list[0],
- /*origin=*/kGoogleUrl,
- /*embedding_origin=*/kGoogleUrl,
+ /*origin=*/GoogleUrl(),
+ /*embedding_origin=*/GoogleUrl(),
/*source=*/kPolicySource,
/*incognito=*/false);
}
@@ -577,7 +587,7 @@ TEST_F(SiteSettingsHelperChooserExceptionTest,
const auto& sites_list = exception.FindKey(kSites)->GetList();
ASSERT_EQ(sites_list.size(), 1u);
ExpectValidSiteExceptionObject(sites_list[0],
- /*origin=*/kAndroidUrl,
+ /*origin=*/AndroidUrl(),
/*source=*/kPolicySource,
/*incognito=*/false);
}
@@ -602,15 +612,313 @@ TEST_F(SiteSettingsHelperChooserExceptionTest,
const auto& sites_list = exception.FindKey(kSites)->GetList();
ASSERT_EQ(sites_list.size(), 2u);
ExpectValidSiteExceptionObject(sites_list[0],
- /*origin=*/kChromiumUrl,
+ /*origin=*/ChromiumUrl(),
/*source=*/kPolicySource,
/*incognito=*/false);
ExpectValidSiteExceptionObject(sites_list[1],
- /*origin=*/kAndroidUrl,
- /*embedding_origin=*/kChromiumUrl,
+ /*origin=*/AndroidUrl(),
+ /*embedding_origin=*/ChromiumUrl(),
/*source=*/kPreferenceSource,
/*incognito=*/false);
}
}
+namespace {
+
+// All of the possible managed states for a boolean preference that can be
+// both enforced and recommended.
+enum class PrefSetting {
+ kEnforcedOff,
+ kEnforcedOn,
+ kRecommendedOff,
+ kRecommendedOn,
+ kNotSet,
+};
+
+// Possible preference sources supported by TestingPrefService.
+// TODO(crbug.com/1063281): Extend TestingPrefService to support prefs set for
+// supervised users.
+enum class PrefSource {
+ kExtension,
+ kDevicePolicy,
+ kRecommended,
+ kNone,
+};
+
+// Represents a set of settings, preferences and the associated expected
+// CookieControlsManagedState.
+struct CookiesManagedStateTestCase {
+ ContentSetting default_content_setting;
+ content_settings::SettingSource default_content_setting_source;
+ PrefSetting block_third_party;
+ PrefSource block_third_party_source;
+ CookieControlsManagedState expected_result;
+};
+
+const std::vector<CookiesManagedStateTestCase> test_cases = {
+ {CONTENT_SETTING_DEFAULT,
+ content_settings::SETTING_SOURCE_NONE,
+ PrefSetting::kEnforcedOff,
+ PrefSource::kExtension,
+ {{false, PolicyIndicatorType::kNone},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone}}},
+ {CONTENT_SETTING_DEFAULT,
+ content_settings::SETTING_SOURCE_NONE,
+ PrefSetting::kEnforcedOn,
+ PrefSource::kDevicePolicy,
+ {{true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone}}},
+ {CONTENT_SETTING_DEFAULT,
+ content_settings::SETTING_SOURCE_NONE,
+ PrefSetting::kRecommendedOff,
+ PrefSource::kRecommended,
+ {{false, PolicyIndicatorType::kRecommended},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone}}},
+ {CONTENT_SETTING_DEFAULT,
+ content_settings::SETTING_SOURCE_NONE,
+ PrefSetting::kRecommendedOn,
+ PrefSource::kRecommended,
+ {{false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kRecommended},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone}}},
+ {CONTENT_SETTING_DEFAULT,
+ content_settings::SETTING_SOURCE_NONE,
+ PrefSetting::kNotSet,
+ PrefSource::kNone,
+ {{false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone}}},
+ {CONTENT_SETTING_ALLOW,
+ content_settings::SETTING_SOURCE_POLICY,
+ PrefSetting::kEnforcedOff,
+ PrefSource::kExtension,
+ {{true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy}}},
+ {CONTENT_SETTING_ALLOW,
+ content_settings::SETTING_SOURCE_EXTENSION,
+ PrefSetting::kEnforcedOn,
+ PrefSource::kDevicePolicy,
+ {{true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension}}},
+ {CONTENT_SETTING_ALLOW,
+ content_settings::SETTING_SOURCE_SUPERVISED,
+ PrefSetting::kRecommendedOff,
+ PrefSource::kRecommended,
+ {{false, PolicyIndicatorType::kRecommended},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent}}},
+ {CONTENT_SETTING_ALLOW,
+ content_settings::SETTING_SOURCE_POLICY,
+ PrefSetting::kRecommendedOn,
+ PrefSource::kRecommended,
+ {{false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kRecommended},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy}}},
+ {CONTENT_SETTING_ALLOW,
+ content_settings::SETTING_SOURCE_EXTENSION,
+ PrefSetting::kNotSet,
+ PrefSource::kNone,
+ {{false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension}}},
+ {CONTENT_SETTING_BLOCK,
+ content_settings::SETTING_SOURCE_SUPERVISED,
+ PrefSetting::kEnforcedOff,
+ PrefSource::kDevicePolicy,
+ {{true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent}}},
+ {CONTENT_SETTING_BLOCK,
+ content_settings::SETTING_SOURCE_POLICY,
+ PrefSetting::kEnforcedOn,
+ PrefSource::kExtension,
+ {{true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy}}},
+ {CONTENT_SETTING_BLOCK,
+ content_settings::SETTING_SOURCE_EXTENSION,
+ PrefSetting::kRecommendedOff,
+ PrefSource::kRecommended,
+ {{true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension}}},
+ {CONTENT_SETTING_BLOCK,
+ content_settings::SETTING_SOURCE_SUPERVISED,
+ PrefSetting::kRecommendedOn,
+ PrefSource::kRecommended,
+ {{true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent}}},
+ {CONTENT_SETTING_BLOCK,
+ content_settings::SETTING_SOURCE_POLICY,
+ PrefSetting::kNotSet,
+ PrefSource::kNone,
+ {{true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy}}},
+ {CONTENT_SETTING_SESSION_ONLY,
+ content_settings::SETTING_SOURCE_EXTENSION,
+ PrefSetting::kEnforcedOff,
+ PrefSource::kDevicePolicy,
+ {{true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension}}},
+ {CONTENT_SETTING_SESSION_ONLY,
+ content_settings::SETTING_SOURCE_SUPERVISED,
+ PrefSetting::kEnforcedOn,
+ PrefSource::kExtension,
+ {{true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent}}},
+ {CONTENT_SETTING_SESSION_ONLY,
+ content_settings::SETTING_SOURCE_POLICY,
+ PrefSetting::kRecommendedOff,
+ PrefSource::kRecommended,
+ {{false, PolicyIndicatorType::kRecommended},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {true, PolicyIndicatorType::kDevicePolicy},
+ {true, PolicyIndicatorType::kDevicePolicy}}},
+ {CONTENT_SETTING_SESSION_ONLY,
+ content_settings::SETTING_SOURCE_EXTENSION,
+ PrefSetting::kRecommendedOn,
+ PrefSource::kRecommended,
+ {{false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kRecommended},
+ {true, PolicyIndicatorType::kExtension},
+ {true, PolicyIndicatorType::kExtension}}},
+ {CONTENT_SETTING_SESSION_ONLY,
+ content_settings::SETTING_SOURCE_SUPERVISED,
+ PrefSetting::kNotSet,
+ PrefSource::kNone,
+ {{false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {false, PolicyIndicatorType::kNone},
+ {true, PolicyIndicatorType::kParent},
+ {true, PolicyIndicatorType::kParent}}}};
+
+void SetupTestConditions(HostContentSettingsMap* map,
+ sync_preferences::TestingPrefServiceSyncable* prefs,
+ const CookiesManagedStateTestCase& test_case) {
+ if (test_case.default_content_setting != CONTENT_SETTING_DEFAULT) {
+ auto provider = std::make_unique<content_settings::MockProvider>();
+ provider->SetWebsiteSetting(
+ ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
+ ContentSettingsType::COOKIES, std::string(),
+ std::make_unique<base::Value>(test_case.default_content_setting));
+ HostContentSettingsMap::ProviderType provider_type;
+ switch (test_case.default_content_setting_source) {
+ case content_settings::SETTING_SOURCE_POLICY:
+ provider_type = HostContentSettingsMap::POLICY_PROVIDER;
+ break;
+ case content_settings::SETTING_SOURCE_EXTENSION:
+ provider_type = HostContentSettingsMap::CUSTOM_EXTENSION_PROVIDER;
+ break;
+ case content_settings::SETTING_SOURCE_SUPERVISED:
+ provider_type = HostContentSettingsMap::SUPERVISED_PROVIDER;
+ break;
+ case content_settings::SETTING_SOURCE_NONE:
+ default:
+ provider_type = HostContentSettingsMap::DEFAULT_PROVIDER;
+ }
+ content_settings::TestUtils::OverrideProvider(map, std::move(provider),
+ provider_type);
+ }
+
+ if (test_case.block_third_party != PrefSetting::kNotSet) {
+ bool third_party_value =
+ test_case.block_third_party == PrefSetting::kRecommendedOn ||
+ test_case.block_third_party == PrefSetting::kEnforcedOn;
+ if (test_case.block_third_party_source == PrefSource::kExtension) {
+ prefs->SetExtensionPref(prefs::kBlockThirdPartyCookies,
+ std::make_unique<base::Value>(third_party_value));
+ } else if (test_case.block_third_party_source ==
+ PrefSource::kDevicePolicy) {
+ prefs->SetManagedPref(prefs::kBlockThirdPartyCookies,
+ std::make_unique<base::Value>(third_party_value));
+ } else if (test_case.block_third_party_source == PrefSource::kRecommended) {
+ prefs->SetRecommendedPref(
+ prefs::kBlockThirdPartyCookies,
+ std::make_unique<base::Value>(third_party_value));
+ }
+ }
+}
+
+void AssertManagedCookieStateEqual(const CookieControlsManagedState& a,
+ const CookieControlsManagedState b) {
+ ASSERT_EQ(a.allow_all.disabled, b.allow_all.disabled);
+ ASSERT_EQ(a.allow_all.indicator, b.allow_all.indicator);
+ ASSERT_EQ(a.block_third_party_incognito.disabled,
+ b.block_third_party_incognito.disabled);
+ ASSERT_EQ(a.block_third_party_incognito.indicator,
+ b.block_third_party_incognito.indicator);
+ ASSERT_EQ(a.block_third_party.disabled, b.block_third_party.disabled);
+ ASSERT_EQ(a.block_third_party.indicator, b.block_third_party.indicator);
+ ASSERT_EQ(a.block_all.disabled, b.block_all.disabled);
+ ASSERT_EQ(a.block_all.indicator, b.block_all.indicator);
+ ASSERT_EQ(a.session_only.disabled, b.session_only.disabled);
+ ASSERT_EQ(a.session_only.indicator, b.session_only.indicator);
+}
+
+TEST_F(SiteSettingsHelperTest, CookiesManagedState) {
+ for (auto test_case : test_cases) {
+ TestingProfile profile;
+ HostContentSettingsMap* map =
+ HostContentSettingsMapFactory::GetForProfile(&profile);
+ sync_preferences::TestingPrefServiceSyncable* prefs =
+ profile.GetTestingPrefService();
+ testing::Message scope_message;
+ scope_message << "Content Setting:" << test_case.default_content_setting
+ << " Block Third Party:"
+ << static_cast<int>(test_case.block_third_party);
+ SCOPED_TRACE(scope_message);
+ SetupTestConditions(map, prefs, test_case);
+ AssertManagedCookieStateEqual(
+ site_settings::GetCookieControlsManagedState(&profile),
+ test_case.expected_result);
+ }
+}
+
+} // namespace
+
} // namespace site_settings
diff --git a/chromium/chrome/browser/ui/webui/snippets_internals/BUILD.gn b/chromium/chrome/browser/ui/webui/snippets_internals/BUILD.gn
index f83f5c25536..8981f58301f 100644
--- a/chromium/chrome/browser/ui/webui/snippets_internals/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/snippets_internals/BUILD.gn
@@ -5,7 +5,5 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "snippets_internals.mojom",
- ]
+ sources = [ "snippets_internals.mojom" ]
}
diff --git a/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc b/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc
index 7df14607805..24cecc6a0dd 100644
--- a/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc
@@ -13,12 +13,12 @@
#include "chrome/browser/ui/webui/snippets_internals/snippets_internals.mojom.h"
#include "chrome/browser/ui/webui/snippets_internals/snippets_internals_page_handler.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "content/public/browser/web_ui_data_source.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#if defined(OS_ANDROID)
-#include "chrome/browser/android/chrome_feature_list.h"
+#include "chrome/browser/flags/android/chrome_feature_list.h"
#endif
SnippetsInternalsUI::SnippetsInternalsUI(content::WebUI* web_ui)
@@ -38,14 +38,13 @@ SnippetsInternalsUI::SnippetsInternalsUI(content::WebUI* web_ui)
ContentSuggestionsServiceFactory::GetInstance()->GetForProfile(profile);
pref_service_ = profile->GetPrefs();
content::WebUIDataSource::Add(profile, source);
- AddHandlerToRegistry(base::BindRepeating(
- &SnippetsInternalsUI::BindSnippetsInternalsPageHandlerFactory,
- base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(SnippetsInternalsUI)
+
SnippetsInternalsUI::~SnippetsInternalsUI() {}
-void SnippetsInternalsUI::BindSnippetsInternalsPageHandlerFactory(
+void SnippetsInternalsUI::BindInterface(
mojo::PendingReceiver<snippets_internals::mojom::PageHandlerFactory>
receiver) {
receiver_.reset();
diff --git a/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.h b/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.h
index 524b74fe032..2852762e68b 100644
--- a/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.h
+++ b/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.h
@@ -29,11 +29,13 @@ class SnippetsInternalsUI
mojo::PendingRemote<snippets_internals::mojom::Page> page,
CreatePageHandlerCallback callback) override;
- private:
- void BindSnippetsInternalsPageHandlerFactory(
+ // Instantiates the implementor of the mojom::PageHandlerFactory mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<snippets_internals::mojom::PageHandlerFactory>
receiver);
+ private:
std::unique_ptr<SnippetsInternalsPageHandler> page_handler_;
ntp_snippets::ContentSuggestionsService* content_suggestions_service_;
PrefService* pref_service_;
@@ -41,6 +43,8 @@ class SnippetsInternalsUI
// Receiver from the mojo interface to concrete impl.
mojo::Receiver<snippets_internals::mojom::PageHandlerFactory> receiver_{this};
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(SnippetsInternalsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/supervised_user_internals_ui.cc b/chromium/chrome/browser/ui/webui/supervised_user_internals_ui.cc
index 4f213ca690c..33484a1287b 100644
--- a/chromium/chrome/browser/ui/webui/supervised_user_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/supervised_user_internals_ui.cc
@@ -9,7 +9,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/supervised_user_internals_message_handler.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
diff --git a/chromium/chrome/browser/ui/webui/sync_internals_browsertest.js b/chromium/chrome/browser/ui/webui/sync_internals_browsertest.js
index b909869b5b9..6bde6774f1a 100644
--- a/chromium/chrome/browser/ui/webui/sync_internals_browsertest.js
+++ b/chromium/chrome/browser/ui/webui/sync_internals_browsertest.js
@@ -42,18 +42,18 @@ SyncInternalsWebUITest.prototype = {
* @protected
*/
hasInDetails: function(isValid, key, value) {
- var details = chrome.sync.aboutInfo.details;
+ const details = chrome.sync.aboutInfo.details;
if (!details) {
return false;
}
- for (var i = 0; i < details.length; ++i) {
+ for (let i = 0; i < details.length; ++i) {
if (!details[i].data) {
continue;
}
- for (var j = 0; j < details[i].data.length; ++j) {
- var obj = details[i].data[j];
- if (obj.stat_name == key) {
- return obj.is_valid == isValid && obj.stat_value == value;
+ for (let j = 0; j < details[i].data.length; ++j) {
+ const obj = details[i].data[j];
+ if (obj.stat_name === key) {
+ return obj.is_valid === isValid && obj.stat_value === value;
}
}
}
@@ -65,98 +65,93 @@ SyncInternalsWebUITest.prototype = {
* Constant hard-coded value to return from mock getAllNodes.
* @const
*/
-var HARD_CODED_ALL_NODES = [{
- 'nodes': [{
- 'ATTACHMENT_METADATA': '',
- 'BASE_SERVER_SPECIFICS': {},
- 'BASE_VERSION': '1396470970810000',
- 'CTIME': 'Wednesday, December 31, 1969 4:00:00 PM',
- 'ID': 'sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf7yXJ1SkJwpp1YL' +
- '6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==',
- 'IS_DEL': false,
- 'IS_DIR': true,
- 'IS_UNAPPLIED_UPDATE': false,
- 'IS_UNSYNCED': false,
- 'LOCAL_EXTERNAL_ID': '0',
- 'META_HANDLE': '387',
- 'MTIME': 'Wednesday, December 31, 1969 4:00:00 PM',
- 'NON_UNIQUE_NAME': 'Autofill',
- 'PARENT_ID': 'r',
- 'SERVER_CTIME': 'Wednesday, December 31, 1969 4:00:00 PM',
- 'SERVER_IS_DEL': false,
- 'SERVER_IS_DIR': true,
- 'SERVER_MTIME': 'Wednesday, December 31, 1969 4:00:00 PM',
- 'SERVER_NON_UNIQUE_NAME': 'Autofill',
- 'SERVER_PARENT_ID': 'r',
- 'SERVER_SPECIFICS': {
- 'autofill': {
- 'usage_timestamp': []
- }
- },
- 'SERVER_UNIQUE_POSITION': 'INVALID[]',
- 'SERVER_VERSION': '1396470970810000',
- 'SPECIFICS': {
- 'autofill': {
- 'usage_timestamp': []
- }
- },
- 'SYNCING': false,
- 'TRANSACTION_VERSION': '1',
- 'UNIQUE_BOOKMARK_TAG': '',
- 'UNIQUE_CLIENT_TAG': '',
- 'UNIQUE_POSITION': 'INVALID[]',
- 'UNIQUE_SERVER_TAG': 'google_chrome_autofill',
- 'isDirty': false,
- 'modelType': 'Autofill'
- }, {
- 'ATTACHMENT_METADATA': '',
- 'BASE_SERVER_SPECIFICS': {},
- 'BASE_VERSION': '1394241139528639',
- 'CTIME': 'Friday, March 7, 2014 5:12:19 PM',
- 'ID': 'sZ:ADqtAZwzc/ol1iaz+yNLjjWak9PBE0o/hATzpqJsyq/HX2xzV2f88' +
- 'FaOrT7HDE4tyn7zx2LWgkAFvZfCA5mOy4p0XFgiY0L+mw==',
- 'IS_DEL': false,
- 'IS_DIR': false,
- 'IS_UNAPPLIED_UPDATE': false,
- 'IS_UNSYNCED': false,
- 'LOCAL_EXTERNAL_ID': '0',
- 'META_HANDLE': '2989',
- 'MTIME': 'Friday, March 7, 2014 5:12:19 PM',
- 'NON_UNIQUE_NAME': 'autofill_entry|Email|rlsynctet2',
- 'PARENT_ID': 'sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf7yXJ1Sk' +
- 'Jwpp1YL6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==',
- 'SERVER_CTIME': 'Friday, March 7, 2014 5:12:19 PM',
- 'SERVER_IS_DEL': false,
- 'SERVER_IS_DIR': false,
- 'SERVER_MTIME': 'Friday, March 7, 2014 5:12:19 PM',
- 'SERVER_NON_UNIQUE_NAME': 'autofill_entry|Email|rlsynctet2',
- 'SERVER_PARENT_ID': 'sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf' +
- '7yXJ1SkJwpp1YL6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==',
- 'SERVER_SPECIFICS': {
- 'autofill': {
- 'name': 'Email',
- 'usage_timestamp': ['13038713887000000', '13038713890000000'],
- 'value': 'rlsynctet2'
- }
- },
- 'SERVER_UNIQUE_POSITION': 'INVALID[]',
- 'SERVER_VERSION': '1394241139528639',
- 'SPECIFICS': {
- 'autofill': {
- 'name': 'Email',
- 'usage_timestamp': ['13038713887000000', '13038713890000000'],
- 'value': 'rlsynctet2'
- }
+const HARD_CODED_ALL_NODES = [{
+ 'nodes': [
+ {
+ 'ATTACHMENT_METADATA': '',
+ 'BASE_SERVER_SPECIFICS': {},
+ 'BASE_VERSION': '1396470970810000',
+ 'CTIME': 'Wednesday, December 31, 1969 4:00:00 PM',
+ 'ID': 'sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf7yXJ1SkJwpp1YL' +
+ '6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==',
+ 'IS_DEL': false,
+ 'IS_DIR': true,
+ 'IS_UNAPPLIED_UPDATE': false,
+ 'IS_UNSYNCED': false,
+ 'LOCAL_EXTERNAL_ID': '0',
+ 'META_HANDLE': '387',
+ 'MTIME': 'Wednesday, December 31, 1969 4:00:00 PM',
+ 'NON_UNIQUE_NAME': 'Autofill',
+ 'PARENT_ID': 'r',
+ 'SERVER_CTIME': 'Wednesday, December 31, 1969 4:00:00 PM',
+ 'SERVER_IS_DEL': false,
+ 'SERVER_IS_DIR': true,
+ 'SERVER_MTIME': 'Wednesday, December 31, 1969 4:00:00 PM',
+ 'SERVER_NON_UNIQUE_NAME': 'Autofill',
+ 'SERVER_PARENT_ID': 'r',
+ 'SERVER_SPECIFICS': {'autofill': {'usage_timestamp': []}},
+ 'SERVER_UNIQUE_POSITION': 'INVALID[]',
+ 'SERVER_VERSION': '1396470970810000',
+ 'SPECIFICS': {'autofill': {'usage_timestamp': []}},
+ 'SYNCING': false,
+ 'TRANSACTION_VERSION': '1',
+ 'UNIQUE_BOOKMARK_TAG': '',
+ 'UNIQUE_CLIENT_TAG': '',
+ 'UNIQUE_POSITION': 'INVALID[]',
+ 'UNIQUE_SERVER_TAG': 'google_chrome_autofill',
+ 'isDirty': false,
+ 'modelType': 'Autofill'
},
- 'SYNCING': false,
- 'TRANSACTION_VERSION': '1',
- 'UNIQUE_BOOKMARK_TAG': '',
- 'UNIQUE_CLIENT_TAG': 'EvliorKUf1rLjT+BGkNZp586Tsk=',
- 'UNIQUE_POSITION': 'INVALID[]',
- 'UNIQUE_SERVER_TAG': '',
- 'isDirty': false,
- 'modelType': 'Autofill'
- }],
+ {
+ 'ATTACHMENT_METADATA': '',
+ 'BASE_SERVER_SPECIFICS': {},
+ 'BASE_VERSION': '1394241139528639',
+ 'CTIME': 'Friday, March 7, 2014 5:12:19 PM',
+ 'ID': 'sZ:ADqtAZwzc/ol1iaz+yNLjjWak9PBE0o/hATzpqJsyq/HX2xzV2f88' +
+ 'FaOrT7HDE4tyn7zx2LWgkAFvZfCA5mOy4p0XFgiY0L+mw==',
+ 'IS_DEL': false,
+ 'IS_DIR': false,
+ 'IS_UNAPPLIED_UPDATE': false,
+ 'IS_UNSYNCED': false,
+ 'LOCAL_EXTERNAL_ID': '0',
+ 'META_HANDLE': '2989',
+ 'MTIME': 'Friday, March 7, 2014 5:12:19 PM',
+ 'NON_UNIQUE_NAME': 'autofill_entry|Email|rlsynctet2',
+ 'PARENT_ID': 'sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf7yXJ1Sk' +
+ 'Jwpp1YL6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==',
+ 'SERVER_CTIME': 'Friday, March 7, 2014 5:12:19 PM',
+ 'SERVER_IS_DEL': false,
+ 'SERVER_IS_DIR': false,
+ 'SERVER_MTIME': 'Friday, March 7, 2014 5:12:19 PM',
+ 'SERVER_NON_UNIQUE_NAME': 'autofill_entry|Email|rlsynctet2',
+ 'SERVER_PARENT_ID': 'sZ:ADqtAZwzF4GOIyvkI2enSI62AU5p/7MNmvuSSyf' +
+ '7yXJ1SkJwpp1YL6bbMkF8inzqW+EO6n2aPJ/uXccW9GHxorBlnKoZAWHVzg==',
+ 'SERVER_SPECIFICS': {
+ 'autofill': {
+ 'name': 'Email',
+ 'usage_timestamp': ['13038713887000000', '13038713890000000'],
+ 'value': 'rlsynctet2'
+ }
+ },
+ 'SERVER_UNIQUE_POSITION': 'INVALID[]',
+ 'SERVER_VERSION': '1394241139528639',
+ 'SPECIFICS': {
+ 'autofill': {
+ 'name': 'Email',
+ 'usage_timestamp': ['13038713887000000', '13038713890000000'],
+ 'value': 'rlsynctet2'
+ }
+ },
+ 'SYNCING': false,
+ 'TRANSACTION_VERSION': '1',
+ 'UNIQUE_BOOKMARK_TAG': '',
+ 'UNIQUE_CLIENT_TAG': 'EvliorKUf1rLjT+BGkNZp586Tsk=',
+ 'UNIQUE_POSITION': 'INVALID[]',
+ 'UNIQUE_SERVER_TAG': '',
+ 'isDirty': false,
+ 'modelType': 'Autofill'
+ }
+ ],
'type': 'Autofill'
}];
@@ -277,21 +272,21 @@ TEST_F('SyncInternalsWebUITest', 'LoadPastedAboutInfo', function() {
});
TEST_F('SyncInternalsWebUITest', 'NetworkEventsTest', function() {
- let networkEvent1 = new Event('onProtocolEvent');
+ const networkEvent1 = new Event('onProtocolEvent');
networkEvent1.details = NETWORK_EVENT_DETAILS_1;
- let networkEvent2 = new Event('onProtocolEvent');
+ const networkEvent2 = new Event('onProtocolEvent');
networkEvent2.details = NETWORK_EVENT_DETAILS_2;
chrome.sync.events.dispatchEvent(networkEvent1);
chrome.sync.events.dispatchEvent(networkEvent2);
// Make sure that both events arrived.
- let eventCount = $('traffic-event-container').children.length;
+ const eventCount = $('traffic-event-container').children.length;
assertGE(eventCount, 2);
// Check that the event details are displayed.
- let displayedEvent1 = $('traffic-event-container').children[eventCount - 2];
- let displayedEvent2 = $('traffic-event-container').children[eventCount - 1];
+ const displayedEvent1 = $('traffic-event-container').children[eventCount - 2];
+ const displayedEvent2 = $('traffic-event-container').children[eventCount - 1];
expectTrue(
displayedEvent1.innerHTML.includes(NETWORK_EVENT_DETAILS_1.details));
expectTrue(displayedEvent1.innerHTML.includes(NETWORK_EVENT_DETAILS_1.type));
@@ -333,7 +328,7 @@ TEST_F('SyncInternalsWebUITest', 'SearchTabDoesntChangeOnItemSelect',
});
TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() {
- var getAllNodesSavedArgs = new SaveMockArguments();
+ const getAllNodesSavedArgs = new SaveMockArguments();
this.mockHandler.expects(once()).
getAllNodes(getAllNodesSavedArgs.match(ANYTHING)).
will(callFunctionWithSavedArgs(getAllNodesSavedArgs,
@@ -350,17 +345,17 @@ TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() {
// hard-coded nodes, specified elsewhere in this file.
// Start with the tree itself.
- var tree = $('sync-node-tree');
+ const tree = $('sync-node-tree');
assertEquals(1, tree.items.length);
// Check the type root and expand it.
- var typeRoot = tree.items[0];
+ const typeRoot = tree.items[0];
expectFalse(typeRoot.expanded);
typeRoot.expanded = true;
assertEquals(1, typeRoot.items.length);
// An actual sync node. The child of the type root.
- var leaf = typeRoot.items[0];
+ const leaf = typeRoot.items[0];
// Verify that selecting it affects the details view.
expectTrue($('node-details').hasAttribute('hidden'));
@@ -369,7 +364,7 @@ TEST_F('SyncInternalsWebUITest', 'NodeBrowserTest', function() {
});
TEST_F('SyncInternalsWebUITest', 'NodeBrowserRefreshOnTabSelect', function() {
- var getAllNodesSavedArgs = new SaveMockArguments();
+ const getAllNodesSavedArgs = new SaveMockArguments();
this.mockHandler.expects(once()).
getAllNodes(getAllNodesSavedArgs.match(ANYTHING)).
will(callFunctionWithSavedArgs(getAllNodesSavedArgs,
@@ -393,21 +388,21 @@ TEST_F('SyncInternalsWebUITest', 'NodeBrowserRefreshOnTabSelect', function() {
// Tests that the events log page correctly receives and displays an event.
TEST_F('SyncInternalsWebUITest', 'EventLogTest', function() {
// Dispatch an event.
- var connectionEvent = new Event('onConnectionStatusChange');
+ const connectionEvent = new Event('onConnectionStatusChange');
connectionEvent.details = {'status': 'CONNECTION_OK'};
chrome.sync.events.dispatchEvent(connectionEvent);
// Verify that it is displayed in the events log.
- var syncEventsTable = $('sync-events');
+ const syncEventsTable = $('sync-events');
assertGE(syncEventsTable.children.length, 1);
- var lastRow = syncEventsTable.children[syncEventsTable.children.length - 1];
+ const lastRow = syncEventsTable.children[syncEventsTable.children.length - 1];
// Makes some assumptions about column ordering. We'll need re-think this if
// it turns out to be a maintenance burden.
assertEquals(4, lastRow.children.length);
- var detailsText = lastRow.children[0].textContent;
- var submoduleName = lastRow.children[1].textContent;
- var eventName = lastRow.children[2].textContent;
+ const detailsText = lastRow.children[0].textContent;
+ const submoduleName = lastRow.children[1].textContent;
+ const eventName = lastRow.children[2].textContent;
expectGE(submoduleName.indexOf('manager'), 0,
'submoduleName=' + submoduleName);
@@ -419,7 +414,7 @@ TEST_F('SyncInternalsWebUITest', 'EventLogTest', function() {
TEST_F('SyncInternalsWebUITest', 'DumpSyncEventsToText', function() {
// Dispatch an event.
- var connectionEvent = new Event('onConnectionStatusChange');
+ const connectionEvent = new Event('onConnectionStatusChange');
connectionEvent.details = {'status': 'CONNECTION_OK'};
chrome.sync.events.dispatchEvent(connectionEvent);
@@ -427,7 +422,7 @@ TEST_F('SyncInternalsWebUITest', 'DumpSyncEventsToText', function() {
$('dump-to-text').click();
// Verify our event is among the results.
- var eventDumpText = $('data-dump').textContent;
+ const eventDumpText = $('data-dump').textContent;
expectGE(eventDumpText.indexOf('onConnectionStatusChange'), 0);
expectGE(eventDumpText.indexOf('CONNECTION_OK'), 0);
diff --git a/chromium/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc b/chromium/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
index b4091b4eab5..e22011f7342 100644
--- a/chromium/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/sync_internals_message_handler_unittest.cc
@@ -66,7 +66,7 @@ class TestSyncService : public syncer::FakeSyncService {
}
void GetAllNodesForDebugging(
- const base::Callback<void(std::unique_ptr<base::ListValue>)>& callback)
+ base::OnceCallback<void(std::unique_ptr<base::ListValue>)> callback)
override {
get_all_nodes_callback_ = std::move(callback);
}
@@ -79,7 +79,7 @@ class TestSyncService : public syncer::FakeSyncService {
int remove_type_debug_info_observer_count() const {
return remove_type_debug_info_observer_count_;
}
- base::Callback<void(std::unique_ptr<base::ListValue>)>
+ base::OnceCallback<void(std::unique_ptr<base::ListValue>)>
get_all_nodes_callback() {
return std::move(get_all_nodes_callback_);
}
@@ -90,7 +90,7 @@ class TestSyncService : public syncer::FakeSyncService {
int add_type_debug_info_observer_count_ = 0;
int remove_type_debug_info_observer_count_ = 0;
syncer::MockJsController js_controller_;
- base::Callback<void(std::unique_ptr<base::ListValue>)>
+ base::OnceCallback<void(std::unique_ptr<base::ListValue>)>
get_all_nodes_callback_;
};
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part.cc b/chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part.cc
new file mode 100644
index 00000000000..08451dad7be
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part.cc
@@ -0,0 +1,39 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part.h"
+
+#include "chrome/common/webui_url_constants.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/web_preferences.h"
+
+ChromeContentBrowserClientTabStripPart::
+ ChromeContentBrowserClientTabStripPart() = default;
+ChromeContentBrowserClientTabStripPart::
+ ~ChromeContentBrowserClientTabStripPart() = default;
+
+void ChromeContentBrowserClientTabStripPart::OverrideWebkitPrefs(
+ content::RenderViewHost* rvh,
+ content::WebPreferences* web_prefs) {
+ content::WebContents* contents =
+ content::WebContents::FromRenderViewHost(rvh);
+
+ if (!contents)
+ return;
+
+ content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
+ GURL url = entry ? entry->GetURL() : GURL();
+
+ if (url.host_piece() != chrome::kChromeUITabStripHost) {
+ return;
+ }
+
+ content::WebPreferences default_prefs;
+ web_prefs->default_font_size = default_prefs.default_font_size;
+ web_prefs->default_fixed_font_size = default_prefs.default_fixed_font_size;
+ web_prefs->minimum_font_size = default_prefs.minimum_font_size;
+ web_prefs->minimum_logical_font_size =
+ default_prefs.minimum_logical_font_size;
+}
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part.h b/chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part.h
new file mode 100644
index 00000000000..63af9321d82
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part.h
@@ -0,0 +1,27 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_TAB_STRIP_CHROME_CONTENT_BROWSER_CLIENT_TAB_STRIP_PART_H_
+#define CHROME_BROWSER_UI_WEBUI_TAB_STRIP_CHROME_CONTENT_BROWSER_CLIENT_TAB_STRIP_PART_H_
+
+#include "base/macros.h"
+#include "chrome/browser/chrome_content_browser_client_parts.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/common/web_preferences.h"
+
+class ChromeContentBrowserClientTabStripPart
+ : public ChromeContentBrowserClientParts {
+ public:
+ ChromeContentBrowserClientTabStripPart();
+ ~ChromeContentBrowserClientTabStripPart() override;
+
+ // ChromeContentBrowserClientParts:
+ void OverrideWebkitPrefs(content::RenderViewHost* rvh,
+ content::WebPreferences* web_prefs) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromeContentBrowserClientTabStripPart);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_TAB_STRIP_CHROME_CONTENT_BROWSER_CLIENT_TAB_STRIP_PART_H_
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part_browsertest.cc b/chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part_browsertest.cc
new file mode 100644
index 00000000000..6b201ef2d24
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/chrome_content_browser_client_tab_strip_part_browsertest.cc
@@ -0,0 +1,73 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/common/web_preferences.h"
+#include "content/public/test/browser_test.h"
+#include "ui/base/ui_base_switches.h"
+
+class ChromeContentBrowserClientTabStripPartTest : public InProcessBrowserTest {
+ public:
+ std::unique_ptr<content::WebContents> CreateTabStripWebContents() {
+ std::unique_ptr<content::WebContents> webui_contents =
+ content::WebContents::Create(
+ content::WebContents::CreateParams(browser()->profile()));
+ webui_contents->GetController().LoadURLWithParams(
+ content::NavigationController::LoadURLParams(
+ GURL(chrome::kChromeUITabStripURL)));
+ return webui_contents;
+ }
+
+ protected:
+ std::unique_ptr<content::WebContents> webui_contents_;
+};
+
+IN_PROC_BROWSER_TEST_F(ChromeContentBrowserClientTabStripPartTest,
+ TabStripHasDefaultFontSizes) {
+ const content::WebPreferences default_prefs;
+ const int kDefaultFontSize = default_prefs.default_font_size;
+ const int kDefaultFixedFontSize = default_prefs.default_fixed_font_size;
+ const int kDefaultMinimumFontSize = default_prefs.minimum_font_size;
+ const int kDefaultMinimumLogicalFontSize =
+ default_prefs.minimum_logical_font_size;
+
+ content::WebPreferences preexisting_tab_strip_prefs =
+ CreateTabStripWebContents()->GetRenderViewHost()->GetWebkitPreferences();
+
+ Profile* profile = browser()->profile();
+ PrefService* profile_prefs = profile->GetPrefs();
+ profile_prefs->SetInteger(prefs::kWebKitDefaultFontSize,
+ kDefaultFontSize + 1);
+ profile_prefs->SetInteger(prefs::kWebKitDefaultFixedFontSize,
+ kDefaultFixedFontSize + 2);
+ profile_prefs->SetInteger(prefs::kWebKitMinimumFontSize,
+ kDefaultMinimumFontSize + 3);
+ profile_prefs->SetInteger(prefs::kWebKitMinimumLogicalFontSize,
+ kDefaultMinimumLogicalFontSize + 4);
+
+ EXPECT_EQ(kDefaultFontSize, preexisting_tab_strip_prefs.default_font_size);
+ EXPECT_EQ(kDefaultFixedFontSize,
+ preexisting_tab_strip_prefs.default_fixed_font_size);
+ EXPECT_EQ(kDefaultMinimumFontSize,
+ preexisting_tab_strip_prefs.minimum_font_size);
+ EXPECT_EQ(kDefaultMinimumLogicalFontSize,
+ preexisting_tab_strip_prefs.minimum_logical_font_size);
+
+ content::WebPreferences new_tab_strip_prefs =
+ CreateTabStripWebContents()->GetRenderViewHost()->GetWebkitPreferences();
+ EXPECT_EQ(kDefaultFontSize, new_tab_strip_prefs.default_font_size);
+ EXPECT_EQ(kDefaultFixedFontSize, new_tab_strip_prefs.default_fixed_font_size);
+ EXPECT_EQ(kDefaultMinimumFontSize, new_tab_strip_prefs.minimum_font_size);
+ EXPECT_EQ(kDefaultMinimumLogicalFontSize,
+ new_tab_strip_prefs.minimum_logical_font_size);
+}
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.cc b/chromium/chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.cc
new file mode 100644
index 00000000000..c0cea3a3f2e
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.cc
@@ -0,0 +1,48 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.h"
+#include <memory>
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace tab_strip_ui {
+
+TabBeforeUnloadTracker::TabBeforeUnloadTracker(
+ TabCloseCancelledCallback cancelled_callback)
+ : cancelled_callback_(std::move(cancelled_callback)) {}
+TabBeforeUnloadTracker::~TabBeforeUnloadTracker() = default;
+
+void TabBeforeUnloadTracker::Observe(content::WebContents* contents) {
+ observers_[contents] = std::make_unique<TabObserver>(contents, this);
+}
+
+void TabBeforeUnloadTracker::Unobserve(content::WebContents* contents) {
+ observers_.erase(contents);
+}
+
+void TabBeforeUnloadTracker::OnBeforeUnloadDialogCancelled(
+ content::WebContents* contents) {
+ cancelled_callback_.Run(contents);
+}
+
+class TabBeforeUnloadTracker::TabObserver
+ : public content::WebContentsObserver {
+ public:
+ TabObserver(content::WebContents* contents, TabBeforeUnloadTracker* tracker)
+ : content::WebContentsObserver(contents), tracker_(tracker) {}
+ ~TabObserver() override = default;
+
+ // content::WebContentsObserver
+ void WebContentsDestroyed() override { tracker_->Unobserve(web_contents()); }
+
+ void BeforeUnloadDialogCancelled() override {
+ tracker_->OnBeforeUnloadDialogCancelled(web_contents());
+ }
+
+ private:
+ TabBeforeUnloadTracker* tracker_;
+};
+
+} // namespace tab_strip_ui
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.h b/chromium/chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.h
new file mode 100644
index 00000000000..7988854159f
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.h
@@ -0,0 +1,38 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_BEFORE_UNLOAD_TRACKER_H_
+#define CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_BEFORE_UNLOAD_TRACKER_H_
+
+#include "base/observer_list.h"
+#include "content/public/browser/web_contents.h"
+
+namespace tab_strip_ui {
+
+// This class keeps track of WebContents observers that listen for when a tab
+// is actually closed or when a user cancels out of a beforeunload confirm
+// dialog. The observers are added once a user has swiped on a tab in the
+// WebUI tab strip and is needed to make the swiped tab in the tab strip
+// visible again if a user cancels out of the close flow.
+class TabBeforeUnloadTracker {
+ public:
+ using TabCloseCancelledCallback =
+ base::RepeatingCallback<void(content::WebContents*)>;
+
+ explicit TabBeforeUnloadTracker(TabCloseCancelledCallback cancelled_callback);
+ ~TabBeforeUnloadTracker();
+
+ void Observe(content::WebContents* contents);
+ void Unobserve(content::WebContents* contents);
+ void OnBeforeUnloadDialogCancelled(content::WebContents* contents);
+
+ private:
+ class TabObserver;
+ std::map<content::WebContents*, std::unique_ptr<TabObserver>> observers_;
+ TabCloseCancelledCallback cancelled_callback_;
+};
+
+} // namespace tab_strip_ui
+
+#endif // CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_BEFORE_UNLOAD_TRACKER_H_
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
index a9bc851b804..c372c0a290e 100644
--- a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.cc
@@ -4,39 +4,17 @@
#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui.h"
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/base64.h"
-#include "base/bind.h"
#include "base/feature_list.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/time/time.h"
-#include "base/values.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/favicon/favicon_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/themes/theme_service_factory.h"
#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/tabs/tab_menu_model.h"
-#include "chrome/browser/ui/tabs/tab_network_state.h"
-#include "chrome/browser/ui/tabs/tab_renderer_data.h"
-#include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
-#include "chrome/browser/ui/tabs/tab_utils.h"
#include "chrome/browser/ui/ui_features.h"
#include "chrome/browser/ui/webui/favicon_source.h"
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h"
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.h"
#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h"
-#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h"
#include "chrome/browser/ui/webui/theme_handler.h"
#include "chrome/browser/ui/webui/webui_util.h"
#include "chrome/common/webui_url_constants.h"
@@ -45,578 +23,20 @@
#include "chrome/grit/tab_strip_resources_map.h"
#include "components/favicon_base/favicon_url_parser.h"
#include "components/strings/grit/components_strings.h"
-#include "content/public/browser/favicon_status.h"
#include "content/public/browser/host_zoom_map.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "content/public/common/url_constants.h"
-#include "third_party/skia/include/core/SkImageEncoder.h"
-#include "third_party/skia/include/core/SkStream.h"
-#include "ui/base/accelerators/accelerator.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/models/simple_menu_model.h"
#include "ui/base/theme_provider.h"
+#include "ui/base/webui/web_ui_util.h"
#include "ui/gfx/color_utils.h"
-#include "ui/gfx/geometry/point_conversions.h"
#include "ui/resources/grit/webui_resources.h"
-namespace {
-
-// Writes bytes to a std::vector that can be fetched. This is used to record the
-// output of skia image encoding.
-class BufferWStream : public SkWStream {
- public:
- BufferWStream() = default;
- ~BufferWStream() override = default;
-
- // Returns the output buffer by moving.
- std::vector<unsigned char> GetBuffer() { return std::move(result_); }
-
- // SkWStream:
- bool write(const void* buffer, size_t size) override {
- const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buffer);
- result_.insert(result_.end(), bytes, bytes + size);
- return true;
- }
-
- size_t bytesWritten() const override { return result_.size(); }
-
- private:
- std::vector<unsigned char> result_;
-};
-
-std::string MakeDataURIForImage(base::span<const uint8_t> image_data,
- base::StringPiece mime_subtype) {
- std::string result = "data:image/";
- result.append(mime_subtype.begin(), mime_subtype.end());
- result += ";base64,";
- result += base::Base64Encode(image_data);
- return result;
-}
-
-std::string EncodePNGAndMakeDataURI(gfx::ImageSkia image, float scale_factor) {
- const SkBitmap& bitmap = image.GetRepresentation(scale_factor).GetBitmap();
- BufferWStream stream;
- const bool encoding_succeeded =
- SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100);
- DCHECK(encoding_succeeded);
- return MakeDataURIForImage(
- base::as_bytes(base::make_span(stream.GetBuffer())), "png");
-}
-
-class WebUIBackgroundMenuModel : public ui::SimpleMenuModel {
- public:
- explicit WebUIBackgroundMenuModel(ui::SimpleMenuModel::Delegate* delegate)
- : ui::SimpleMenuModel(delegate) {
- AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
- AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB);
- AddItemWithStringId(IDC_BOOKMARK_ALL_TABS, IDS_BOOKMARK_ALL_TABS);
- }
-};
-
-class WebUIBackgroundContextMenu : public ui::SimpleMenuModel::Delegate,
- public WebUIBackgroundMenuModel {
- public:
- WebUIBackgroundContextMenu(
- Browser* browser,
- const ui::AcceleratorProvider* accelerator_provider)
- : WebUIBackgroundMenuModel(this),
- browser_(browser),
- accelerator_provider_(accelerator_provider) {}
- ~WebUIBackgroundContextMenu() override = default;
-
- void ExecuteCommand(int command_id, int event_flags) override {
- chrome::ExecuteCommand(browser_, command_id);
- }
-
- bool GetAcceleratorForCommandId(int command_id,
- ui::Accelerator* accelerator) const override {
- return accelerator_provider_->GetAcceleratorForCommandId(command_id,
- accelerator);
- }
-
- private:
- Browser* const browser_;
- const ui::AcceleratorProvider* const accelerator_provider_;
-};
-
-class WebUITabMenuModel : public ui::SimpleMenuModel {
- public:
- WebUITabMenuModel(ui::SimpleMenuModel::Delegate* delegate,
- TabStripModel* tab_strip_model,
- int tab_index)
- : ui::SimpleMenuModel(delegate) {
- AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
- AddSeparator(ui::NORMAL_SEPARATOR);
- AddItemWithStringId(TabStripModel::CommandReload, IDS_TAB_CXMENU_RELOAD);
- AddItemWithStringId(TabStripModel::CommandDuplicate,
- IDS_TAB_CXMENU_DUPLICATE);
- const int pin_str = tab_strip_model->WillContextMenuPin(tab_index)
- ? IDS_TAB_CXMENU_PIN_TAB
- : IDS_TAB_CXMENU_UNPIN_TAB;
- AddItemWithStringId(TabStripModel::CommandTogglePinned, pin_str);
- const int mute_str = chrome::IsSiteMuted(*tab_strip_model, tab_index)
- ? IDS_TAB_CXMENU_SOUND_UNMUTE_SITE
- : IDS_TAB_CXMENU_SOUND_MUTE_SITE;
- AddItem(TabStripModel::CommandToggleSiteMuted,
- l10n_util::GetPluralStringFUTF16(mute_str, 1));
- AddSeparator(ui::NORMAL_SEPARATOR);
- AddItemWithStringId(TabStripModel::CommandCloseTab,
- IDS_TAB_CXMENU_CLOSETAB);
- AddItemWithStringId(TabStripModel::CommandCloseTabsToRight,
- IDS_TAB_CXMENU_CLOSETABSTORIGHT);
- }
-};
-
-class WebUITabContextMenu : public ui::SimpleMenuModel::Delegate,
- public WebUITabMenuModel {
- public:
- WebUITabContextMenu(Browser* browser,
- const ui::AcceleratorProvider* accelerator_provider,
- int tab_index)
- : WebUITabMenuModel(this, browser->tab_strip_model(), tab_index),
- browser_(browser),
- accelerator_provider_(accelerator_provider),
- tab_index_(tab_index) {}
- ~WebUITabContextMenu() override = default;
-
- void ExecuteCommand(int command_id, int event_flags) override {
- DCHECK_LT(tab_index_, browser_->tab_strip_model()->count());
- if (command_id == IDC_NEW_TAB) {
- chrome::NewTab(browser_);
- return;
- }
- browser_->tab_strip_model()->ExecuteContextMenuCommand(
- tab_index_, static_cast<TabStripModel::ContextMenuCommand>(command_id));
- }
-
- bool GetAcceleratorForCommandId(int command_id,
- ui::Accelerator* accelerator) const override {
- int real_command = -1;
- if (command_id == IDC_NEW_TAB) {
- real_command = IDC_NEW_TAB;
- } else {
- TabStripModel::ContextMenuCommandToBrowserCommand(command_id,
- &real_command);
- }
-
- if (real_command != -1) {
- return accelerator_provider_->GetAcceleratorForCommandId(real_command,
- accelerator);
- } else {
- return false;
- }
- }
-
- private:
- Browser* const browser_;
- const ui::AcceleratorProvider* const accelerator_provider_;
- const int tab_index_;
-};
-
-} // namespace
-
-class TabStripUIHandler : public content::WebUIMessageHandler,
- public TabStripModelObserver {
- public:
- explicit TabStripUIHandler(Browser* browser, TabStripUI::Embedder* embedder)
- : browser_(browser),
- embedder_(embedder),
- thumbnail_tracker_(base::Bind(&TabStripUIHandler::HandleThumbnailUpdate,
- base::Unretained(this))) {}
- ~TabStripUIHandler() override = default;
-
- void OnJavascriptAllowed() override {
- browser_->tab_strip_model()->AddObserver(this);
- }
-
- void NotifyLayoutChanged() {
- if (!IsJavascriptAllowed())
- return;
- FireWebUIListener("layout-changed", embedder_->GetLayout().AsDictionary());
- }
-
- void NotifyReceivedKeyboardFocus() {
- if (!IsJavascriptAllowed())
- return;
- FireWebUIListener("received-keyboard-focus");
- }
-
- // TabStripModelObserver:
- void OnTabStripModelChanged(
- TabStripModel* tab_strip_model,
- const TabStripModelChange& change,
- const TabStripSelectionChange& selection) override {
- if (tab_strip_model->empty())
- return;
-
- switch (change.type()) {
- case TabStripModelChange::kInserted: {
- for (const auto& contents : change.GetInsert()->contents) {
- FireWebUIListener("tab-created",
- GetTabData(contents.contents, contents.index));
- }
- break;
- }
- case TabStripModelChange::kRemoved: {
- for (const auto& contents : change.GetRemove()->contents) {
- FireWebUIListener("tab-removed",
- base::Value(extensions::ExtensionTabUtil::GetTabId(
- contents.contents)));
- }
- break;
- }
- case TabStripModelChange::kMoved: {
- auto* move = change.GetMove();
- FireWebUIListener(
- "tab-moved",
- base::Value(extensions::ExtensionTabUtil::GetTabId(move->contents)),
- base::Value(move->to_index));
- break;
- }
- case TabStripModelChange::kReplaced: {
- auto* replace = change.GetReplace();
- FireWebUIListener("tab-replaced",
- base::Value(extensions::ExtensionTabUtil::GetTabId(
- replace->old_contents)),
- base::Value(extensions::ExtensionTabUtil::GetTabId(
- replace->new_contents)));
- break;
- }
- case TabStripModelChange::kSelectionOnly:
- // Multi-selection is not supported for touch.
- break;
- }
-
- if (selection.active_tab_changed()) {
- content::WebContents* new_contents = selection.new_contents;
- int index = selection.new_model.active();
- if (new_contents && index != TabStripModel::kNoTab) {
- FireWebUIListener(
- "tab-active-changed",
- base::Value(extensions::ExtensionTabUtil::GetTabId(new_contents)));
- }
- }
- }
-
- void TabChangedAt(content::WebContents* contents,
- int index,
- TabChangeType change_type) override {
- FireWebUIListener("tab-updated", GetTabData(contents, index));
- }
-
- void TabPinnedStateChanged(TabStripModel* tab_strip_model,
- content::WebContents* contents,
- int index) override {
- FireWebUIListener("tab-updated", GetTabData(contents, index));
- }
-
- void TabBlockedStateChanged(content::WebContents* contents,
- int index) override {
- FireWebUIListener("tab-updated", GetTabData(contents, index));
- }
-
- protected:
- // content::WebUIMessageHandler:
- void RegisterMessages() override {
- web_ui()->RegisterMessageCallback(
- "getTabs",
- base::Bind(&TabStripUIHandler::HandleGetTabs, base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "getThemeColors", base::Bind(&TabStripUIHandler::HandleGetThemeColors,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "setThumbnailTracked",
- base::Bind(&TabStripUIHandler::HandleSetThumbnailTracked,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "closeContainer", base::Bind(&TabStripUIHandler::HandleCloseContainer,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "showBackgroundContextMenu",
- base::Bind(&TabStripUIHandler::HandleShowBackgroundContextMenu,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "showTabContextMenu",
- base::Bind(&TabStripUIHandler::HandleShowTabContextMenu,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "getLayout", base::Bind(&TabStripUIHandler::HandleGetLayout,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "reportTabActivationDuration",
- base::Bind(&TabStripUIHandler::HandleReportTabActivationDuration,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "reportTabDataReceivedDuration",
- base::Bind(&TabStripUIHandler::HandleReportTabDataReceivedDuration,
- base::Unretained(this)));
- web_ui()->RegisterMessageCallback(
- "reportTabCreationDuration",
- base::Bind(&TabStripUIHandler::HandleReportTabCreationDuration,
- base::Unretained(this)));
- }
-
- private:
- base::DictionaryValue GetTabData(content::WebContents* contents, int index) {
- base::DictionaryValue tab_data;
-
- tab_data.SetBoolean("active",
- browser_->tab_strip_model()->active_index() == index);
- tab_data.SetInteger("id", extensions::ExtensionTabUtil::GetTabId(contents));
- tab_data.SetInteger("index", index);
-
- TabRendererData tab_renderer_data =
- TabRendererData::FromTabInModel(browser_->tab_strip_model(), index);
- tab_data.SetBoolean("pinned", tab_renderer_data.pinned);
- tab_data.SetString("title", tab_renderer_data.title);
- tab_data.SetString("url", tab_renderer_data.visible_url.GetContent());
-
- if (!tab_renderer_data.favicon.isNull()) {
- tab_data.SetString("favIconUrl", EncodePNGAndMakeDataURI(
- tab_renderer_data.favicon,
- web_ui()->GetDeviceScaleFactor()));
- tab_data.SetBoolean("isDefaultFavicon",
- tab_renderer_data.favicon.BackedBySameObjectAs(
- favicon::GetDefaultFavicon().AsImageSkia()));
- } else {
- tab_data.SetBoolean("isDefaultFavicon", true);
- }
- tab_data.SetBoolean("showIcon", tab_renderer_data.show_icon);
- tab_data.SetInteger("networkState",
- static_cast<int>(tab_renderer_data.network_state));
- tab_data.SetBoolean("shouldHideThrobber",
- tab_renderer_data.should_hide_throbber);
- tab_data.SetBoolean("blocked", tab_renderer_data.blocked);
- tab_data.SetBoolean("crashed", tab_renderer_data.IsCrashed());
- // TODO(johntlee): Add the rest of TabRendererData
-
- auto alert_states = std::make_unique<base::ListValue>();
- for (const auto alert_state :
- chrome::GetTabAlertStatesForContents(contents)) {
- alert_states->Append(static_cast<int>(alert_state));
- }
- tab_data.SetList("alertStates", std::move(alert_states));
-
- return tab_data;
- }
-
- void HandleGetTabs(const base::ListValue* args) {
- AllowJavascript();
- const base::Value& callback_id = args->GetList()[0];
-
- base::ListValue tabs;
- TabStripModel* tab_strip_model = browser_->tab_strip_model();
- for (int i = 0; i < tab_strip_model->count(); ++i) {
- tabs.Append(GetTabData(tab_strip_model->GetWebContentsAt(i), i));
- }
- ResolveJavascriptCallback(callback_id, tabs);
- }
-
- void HandleGetThemeColors(const base::ListValue* args) {
- AllowJavascript();
- const base::Value& callback_id = args->GetList()[0];
-
- const ui::ThemeProvider& tp =
- ThemeService::GetThemeProviderForProfile(browser_->profile());
-
- // This should return an object of CSS variables to rgba values so that
- // the WebUI can use the CSS variables to color the tab strip
- base::DictionaryValue colors;
- colors.SetString("--tabstrip-background-color",
- color_utils::SkColorToRgbaString(
- tp.GetColor(ThemeProperties::COLOR_FRAME)));
- colors.SetString("--tabstrip-tab-background-color",
- color_utils::SkColorToRgbaString(
- tp.GetColor(ThemeProperties::COLOR_TOOLBAR)));
- colors.SetString("--tabstrip-tab-text-color",
- color_utils::SkColorToRgbaString(
- tp.GetColor(ThemeProperties::COLOR_TAB_TEXT)));
- colors.SetString("--tabstrip-tab-separator-color",
- color_utils::SkColorToRgbaString(SkColorSetA(
- tp.GetColor(ThemeProperties::COLOR_TAB_TEXT),
- /* 16% opacity */ 0.16 * 255)));
-
- colors.SetString("--tabstrip-tab-loading-spinning-color",
- color_utils::SkColorToRgbaString(tp.GetColor(
- ThemeProperties::COLOR_TAB_THROBBER_SPINNING)));
- colors.SetString("--tabstrip-tab-waiting-spinning-color",
- color_utils::SkColorToRgbaString(tp.GetColor(
- ThemeProperties::COLOR_TAB_THROBBER_WAITING)));
- colors.SetString("--tabstrip-indicator-recording-color",
- color_utils::SkColorToRgbaString(tp.GetColor(
- ThemeProperties::COLOR_TAB_ALERT_RECORDING)));
- colors.SetString("--tabstrip-indicator-pip-color",
- color_utils::SkColorToRgbaString(
- tp.GetColor(ThemeProperties::COLOR_TAB_PIP_PLAYING)));
- colors.SetString("--tabstrip-indicator-capturing-color",
- color_utils::SkColorToRgbaString(tp.GetColor(
- ThemeProperties::COLOR_TAB_ALERT_CAPTURING)));
- colors.SetString("--tabstrip-tab-blocked-color",
- color_utils::SkColorToRgbaString(
- ui::NativeTheme::GetInstanceForWeb()->GetSystemColor(
- ui::NativeTheme::kColorId_ProminentButtonColor)));
- colors.SetString("--tabstrip-focus-outline-color",
- color_utils::SkColorToRgbaString(
- ui::NativeTheme::GetInstanceForWeb()->GetSystemColor(
- ui::NativeTheme::kColorId_FocusedBorderColor)));
-
- ResolveJavascriptCallback(callback_id, colors);
- }
-
- void HandleCloseContainer(const base::ListValue* args) {
- // We only autoclose for tab selection.
- RecordTabStripUICloseHistogram(TabStripUICloseAction::kTabSelected);
- DCHECK(embedder_);
- embedder_->CloseContainer();
- }
-
- void HandleShowBackgroundContextMenu(const base::ListValue* args) {
- gfx::PointF point;
- {
- double x = 0;
- args->GetDouble(0, &x);
- double y = 0;
- args->GetDouble(1, &y);
- point = gfx::PointF(x, y);
- }
-
- DCHECK(embedder_);
- embedder_->ShowContextMenuAtPoint(
- gfx::ToRoundedPoint(point),
- std::make_unique<WebUIBackgroundContextMenu>(
- browser_, embedder_->GetAcceleratorProvider()));
- }
-
- void HandleShowTabContextMenu(const base::ListValue* args) {
- int tab_id = 0;
- args->GetInteger(0, &tab_id);
-
- gfx::PointF point;
- {
- double x = 0;
- args->GetDouble(1, &x);
- double y = 0;
- args->GetDouble(2, &y);
- point = gfx::PointF(x, y);
- }
-
- Browser* browser = nullptr;
- int tab_index = -1;
- const bool got_tab = extensions::ExtensionTabUtil::GetTabById(
- tab_id, browser_->profile(), true /* include_incognito */, &browser,
- nullptr, nullptr, &tab_index);
- DCHECK(got_tab);
- DCHECK_EQ(browser, browser_);
-
- DCHECK(embedder_);
- embedder_->ShowContextMenuAtPoint(
- gfx::ToRoundedPoint(point),
- std::make_unique<WebUITabContextMenu>(
- browser, embedder_->GetAcceleratorProvider(), tab_index));
- }
-
- void HandleGetLayout(const base::ListValue* args) {
- AllowJavascript();
- const base::Value& callback_id = args->GetList()[0];
-
- base::Value layout = embedder_->GetLayout().AsDictionary();
- ResolveJavascriptCallback(callback_id, layout);
- }
-
- void HandleSetThumbnailTracked(const base::ListValue* args) {
- AllowJavascript();
-
- int tab_id = 0;
- if (!args->GetInteger(0, &tab_id))
- return;
-
- const bool thumbnail_tracked = args->GetList()[1].GetBool();
-
- content::WebContents* tab = nullptr;
- if (!extensions::ExtensionTabUtil::GetTabById(tab_id, browser_->profile(),
- true, &tab)) {
- // ID didn't refer to a valid tab.
- DVLOG(1) << "Invalid tab ID";
- return;
- }
-
- if (thumbnail_tracked)
- thumbnail_tracker_.AddTab(tab);
- else
- thumbnail_tracker_.RemoveTab(tab);
- }
-
- void HandleReportTabActivationDuration(const base::ListValue* args) {
- int duration_ms = 0;
- args->GetInteger(0, &duration_ms);
- UMA_HISTOGRAM_TIMES("WebUITabStrip.TabActivation",
- base::TimeDelta::FromMilliseconds(duration_ms));
- }
-
- void HandleReportTabDataReceivedDuration(const base::ListValue* args) {
- int tab_count = 0;
- args->GetInteger(0, &tab_count);
- int duration_ms = 0;
- args->GetInteger(1, &duration_ms);
- ReportTabDurationHistogram("TabDataReceived", tab_count,
- base::TimeDelta::FromMilliseconds(duration_ms));
- }
-
- void HandleReportTabCreationDuration(const base::ListValue* args) {
- int tab_count = 0;
- args->GetInteger(0, &tab_count);
- int duration_ms = 0;
- args->GetInteger(1, &duration_ms);
- ReportTabDurationHistogram("TabCreation", tab_count,
- base::TimeDelta::FromMilliseconds(duration_ms));
- }
-
- // Callback passed to |thumbnail_tracker_|. Called when a tab's thumbnail
- // changes, or when we start watching the tab.
- void HandleThumbnailUpdate(content::WebContents* tab,
- ThumbnailTracker::CompressedThumbnailData image) {
- // Send base-64 encoded image to JS side.
- std::string data_uri =
- MakeDataURIForImage(base::make_span(image->data), "jpeg");
-
- const int tab_id = extensions::ExtensionTabUtil::GetTabId(tab);
- FireWebUIListener("tab-thumbnail-updated", base::Value(tab_id),
- base::Value(data_uri));
- }
-
- // Reports a histogram using the format
- // WebUITabStrip.|histogram_fragment|.[tab count bucket].
- void ReportTabDurationHistogram(const char* histogram_fragment,
- int tab_count,
- base::TimeDelta duration) {
- if (tab_count <= 0)
- return;
-
- // It isn't possible to report both a number of tabs and duration datapoint
- // together in a histogram or to correlate two histograms together. As a
- // result the histogram is manually bucketed.
- const char* tab_count_bucket = "01_05";
- if (6 <= tab_count && tab_count <= 20) {
- tab_count_bucket = "06_20";
- } else if (20 < tab_count) {
- tab_count_bucket = "21_";
- }
-
- std::string histogram_name = base::JoinString(
- {"WebUITabStrip", histogram_fragment, tab_count_bucket}, ".");
- base::UmaHistogramTimes(histogram_name, duration);
- }
-
- Browser* const browser_;
- TabStripUI::Embedder* const embedder_;
-
- ThumbnailTracker thumbnail_tracker_;
-
- DISALLOW_COPY_AND_ASSIGN(TabStripUIHandler);
-};
+// These data types must be in all lowercase.
+const char kWebUITabIdDataType[] = "application/vnd.chromium.tab";
+const char kWebUITabGroupIdDataType[] = "application/vnd.chromium.tabgroup";
TabStripUI::TabStripUI(content::WebUI* web_ui)
: content::WebUIController(web_ui) {
@@ -627,24 +47,14 @@ TabStripUI::TabStripUI(content::WebUI* web_ui)
Profile* profile = Profile::FromWebUI(web_ui);
content::WebUIDataSource* html_source =
content::WebUIDataSource::Create(chrome::kChromeUITabStripHost);
-
- html_source->OverrideContentSecurityPolicyScriptSrc(
- "script-src chrome://resources chrome://test 'self';");
-
std::string generated_path =
"@out_folder@/gen/chrome/browser/resources/tab_strip/";
+ webui::SetupWebUIDataSource(
+ html_source, base::make_span(kTabStripResources, kTabStripResourcesSize),
+ generated_path, IDR_TAB_STRIP_HTML);
- for (size_t i = 0; i < kTabStripResourcesSize; ++i) {
- std::string path = kTabStripResources[i].name;
- if (path.rfind(generated_path, 0) == 0) {
- path = path.substr(generated_path.length());
- }
- html_source->AddResourcePath(path, kTabStripResources[i].value);
- }
- html_source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER);
- html_source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER);
-
- html_source->SetDefaultResource(IDR_TAB_STRIP_HTML);
+ html_source->AddString("tabIdDataType", kWebUITabIdDataType);
+ html_source->AddString("tabGroupIdDataType", kWebUITabGroupIdDataType);
// Add a load time string for the frame color to allow the tab strip to paint
// a background color that matches the frame before any content loads
@@ -652,13 +62,14 @@ TabStripUI::TabStripUI(content::WebUI* web_ui)
ThemeService::GetThemeProviderForProfile(profile);
html_source->AddString("frameColor",
color_utils::SkColorToRgbaString(
- tp.GetColor(ThemeProperties::COLOR_FRAME)));
+ tp.GetColor(ThemeProperties::COLOR_FRAME_ACTIVE)));
html_source->AddBoolean(
"showDemoOptions",
base::FeatureList::IsEnabled(features::kWebUITabStripDemoOptions));
static constexpr webui::LocalizedString kStrings[] = {
+ {"newTab", IDS_TOOLTIP_NEW_TAB},
{"tabListTitle", IDS_ACCNAME_TAB_LIST},
{"closeTab", IDS_ACCNAME_CLOSE},
{"defaultTabTitle", IDS_DEFAULT_TAB_TITLE},
@@ -668,6 +79,7 @@ TabStripUI::TabStripUI(content::WebUI* web_ui)
{"audioPlaying", IDS_TAB_AX_LABEL_AUDIO_PLAYING_FORMAT},
{"usbConnected", IDS_TAB_AX_LABEL_USB_CONNECTED_FORMAT},
{"bluetoothConnected", IDS_TAB_AX_LABEL_BLUETOOTH_CONNECTED_FORMAT},
+ {"hidConnected", IDS_TAB_AX_LABEL_HID_CONNECTED_FORMAT},
{"serialConnected", IDS_TAB_AX_LABEL_SERIAL_CONNECTED_FORMAT},
{"mediaRecording", IDS_TAB_AX_LABEL_MEDIA_RECORDING_FORMAT},
{"audioMuting", IDS_TAB_AX_LABEL_AUDIO_MUTING_FORMAT},
@@ -675,10 +87,10 @@ TabStripUI::TabStripUI(content::WebUI* web_ui)
{"pipPlaying", IDS_TAB_AX_LABEL_PIP_PLAYING_FORMAT},
{"desktopCapturing", IDS_TAB_AX_LABEL_DESKTOP_CAPTURING_FORMAT},
{"vrPresenting", IDS_TAB_AX_LABEL_VR_PRESENTING},
+ {"unnamedGroupLabel", IDS_GROUP_AX_LABEL_UNNAMED_GROUP_FORMAT},
+ {"namedGroupLabel", IDS_GROUP_AX_LABEL_NAMED_GROUP_FORMAT},
};
AddLocalizedStringsBulk(html_source, kStrings);
- html_source->UseStringsJs();
-
content::WebUIDataSource::Add(profile, html_source);
content::URLDataSource::Add(
@@ -688,9 +100,9 @@ TabStripUI::TabStripUI(content::WebUI* web_ui)
web_ui->AddMessageHandler(std::make_unique<ThemeHandler>());
}
-TabStripUI::~TabStripUI() {}
+TabStripUI::~TabStripUI() = default;
-void TabStripUI::Initialize(Browser* browser, Embedder* embedder) {
+void TabStripUI::Initialize(Browser* browser, TabStripUIEmbedder* embedder) {
content::WebUI* const web_ui = TabStripUI::web_ui();
DCHECK_EQ(Profile::FromWebUI(web_ui), browser->profile());
auto handler = std::make_unique<TabStripUIHandler>(browser, embedder);
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.h b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.h
index f153e10910f..b30afc1e6d4 100644
--- a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.h
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui.h
@@ -12,47 +12,23 @@
#include "content/public/browser/web_ui_controller.h"
class Browser;
+class TabStripUIEmbedder;
class TabStripUIHandler;
-struct TabStripUILayout;
-namespace gfx {
-class Point;
-} // namespace gfx
-
-namespace ui {
-class AcceleratorProvider;
-class MenuModel;
-}
+extern const char kWebUITabIdDataType[];
+extern const char kWebUITabGroupIdDataType[];
// The WebUI version of the tab strip in the browser. It is currently only
// supported on ChromeOS in tablet mode.
class TabStripUI : public content::WebUIController {
public:
- // Interface to be implemented by the embedder. Provides native UI
- // functionality such as showing context menus.
- class Embedder {
- public:
- Embedder() = default;
- virtual ~Embedder() {}
-
- virtual const ui::AcceleratorProvider* GetAcceleratorProvider() const = 0;
-
- virtual void CloseContainer() = 0;
-
- virtual void ShowContextMenuAtPoint(
- gfx::Point point,
- std::unique_ptr<ui::MenuModel> menu_model) = 0;
-
- virtual TabStripUILayout GetLayout() = 0;
- };
-
explicit TabStripUI(content::WebUI* web_ui);
~TabStripUI() override;
// Initialize TabStripUI with its embedder and the Browser it's
// running in. Must be called exactly once. The WebUI won't work until
// this is called.
- void Initialize(Browser* browser, Embedder* embedder);
+ void Initialize(Browser* browser, TabStripUIEmbedder* embedder);
// The embedder should call this whenever the result of
// Embedder::GetLayout() changes.
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc
index ca503d6debb..0baf2802f93 100644
--- a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc
@@ -14,17 +14,23 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h"
#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h"
#include "chrome/common/chrome_isolated_world_ids.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/test/base/in_process_browser_test.h"
+#include "components/tab_groups/tab_group_id.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "ui/base/accelerators/accelerator.h"
#include "ui/base/models/menu_model.h"
+#include "ui/base/theme_provider.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/point_f.h"
@@ -32,18 +38,16 @@
namespace {
-class MockTabStripUIEmbedder : public TabStripUI::Embedder {
+class MockTabStripUIEmbedder : public TabStripUIEmbedder {
public:
- MOCK_METHOD(const ui::AcceleratorProvider*,
- GetAcceleratorProvider,
- (),
- (const override));
- MOCK_METHOD(void, CloseContainer, (), (override));
- MOCK_METHOD(void,
- ShowContextMenuAtPoint,
- (gfx::Point point, std::unique_ptr<ui::MenuModel> menu_model),
- (override));
- MOCK_METHOD(TabStripUILayout, GetLayout, (), (override));
+ MOCK_CONST_METHOD0(GetAcceleratorProvider, const ui::AcceleratorProvider*());
+ MOCK_METHOD0(CloseContainer, void());
+ MOCK_METHOD2(ShowContextMenuAtPoint,
+ void(gfx::Point, std::unique_ptr<ui::MenuModel>));
+ MOCK_METHOD3(ShowEditDialogForGroupAtPoint,
+ void(gfx::Point, gfx::Rect, tab_groups::TabGroupId));
+ MOCK_METHOD0(GetLayout, TabStripUILayout());
+ MOCK_CONST_METHOD1(GetColor, SkColor(int));
};
} // namespace
@@ -54,8 +58,7 @@ class TabStripUIBrowserTest : public InProcessBrowserTest {
// In this test, we create our own TabStripUI instance with a mock
// Embedder. Disable the production one to avoid conflicting with
// it.
- base::CommandLine::ForCurrentProcess()->RemoveSwitch(
- switches::kWebUITabStrip);
+ feature_override_.InitAndDisableFeature(features::kWebUITabStrip);
InProcessBrowserTest::SetUp();
}
@@ -125,3 +128,44 @@ IN_PROC_BROWSER_TEST_F(TabStripUIBrowserTest,
content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
ISOLATED_WORLD_ID_CHROME_INTERNAL));
}
+
+IN_PROC_BROWSER_TEST_F(TabStripUIBrowserTest, InvokesEditDialogForGroups) {
+ using ::testing::_;
+
+ tab_groups::TabGroupId group_id =
+ browser()->tab_strip_model()->AddToNewGroup({0});
+
+ const std::string get_chip_js =
+ "const chip = document.querySelector('tabstrip-tab-list')"
+ " .shadowRoot.querySelector('tabstrip-tab-group')"
+ " .shadowRoot.querySelector('#chip');"
+ "const chipRect = chip.getBoundingClientRect();";
+ int left =
+ content::EvalJs(webui_contents_.get(), get_chip_js + "chipRect.left",
+ content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+ ISOLATED_WORLD_ID_CHROME_INTERNAL)
+ .ExtractInt();
+ int top = content::EvalJs(webui_contents_.get(), get_chip_js + "chipRect.top",
+ content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+ ISOLATED_WORLD_ID_CHROME_INTERNAL)
+ .ExtractInt();
+ int width =
+ content::EvalJs(webui_contents_.get(), get_chip_js + "chipRect.width",
+ content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+ ISOLATED_WORLD_ID_CHROME_INTERNAL)
+ .ExtractInt();
+ int height =
+ content::EvalJs(webui_contents_.get(), get_chip_js + "chipRect.height",
+ content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+ ISOLATED_WORLD_ID_CHROME_INTERNAL)
+ .ExtractInt();
+
+ EXPECT_CALL(mock_embedder_,
+ ShowEditDialogForGroupAtPoint(gfx::Point(left, top),
+ gfx::Rect(width, height), group_id))
+ .Times(1);
+ ASSERT_TRUE(content::ExecJs(webui_contents_.get(),
+ get_chip_js + "chip.click();",
+ content::EXECUTE_SCRIPT_DEFAULT_OPTIONS,
+ ISOLATED_WORLD_ID_CHROME_INTERNAL));
+}
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h
new file mode 100644
index 00000000000..d798f96a009
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h
@@ -0,0 +1,38 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_EMBEDDER_H_
+#define CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_EMBEDDER_H_
+
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h"
+#include "components/tab_groups/tab_group_id.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/models/menu_model.h"
+#include "ui/gfx/geometry/point.h"
+
+// Interface to be implemented by the embedder. Provides native UI
+// functionality such as showing context menus.
+class TabStripUIEmbedder {
+ public:
+ TabStripUIEmbedder() = default;
+ virtual ~TabStripUIEmbedder() = default;
+
+ virtual const ui::AcceleratorProvider* GetAcceleratorProvider() const = 0;
+
+ virtual void CloseContainer() = 0;
+
+ virtual void ShowContextMenuAtPoint(
+ gfx::Point point,
+ std::unique_ptr<ui::MenuModel> menu_model) = 0;
+
+ virtual void ShowEditDialogForGroupAtPoint(gfx::Point point,
+ gfx::Rect rect,
+ tab_groups::TabGroupId group) = 0;
+
+ virtual TabStripUILayout GetLayout() = 0;
+
+ virtual SkColor GetColor(int id) const = 0;
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_EMBEDDER_H_
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
new file mode 100644
index 00000000000..3a0837ac868
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
@@ -0,0 +1,883 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.h"
+#include <memory>
+
+#include "base/base64.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
+#include "base/values.h"
+#include "chrome/app/chrome_command_ids.h"
+#include "chrome/browser/extensions/extension_tab_util.h"
+#include "chrome/browser/favicon/favicon_utils.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/tabs/tab_group.h"
+#include "chrome/browser/ui/tabs/tab_group_model.h"
+#include "chrome/browser/ui/tabs/tab_group_theme.h"
+#include "chrome/browser/ui/tabs/tab_menu_model.h"
+#include "chrome/browser/ui/tabs/tab_renderer_data.h"
+#include "chrome/browser/ui/tabs/tab_utils.h"
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h"
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h"
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/tab_groups/tab_group_color.h"
+#include "components/tab_groups/tab_group_id.h"
+#include "components/tab_groups/tab_group_visual_data.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/models/simple_menu_model.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace {
+
+// Writes bytes to a std::vector that can be fetched. This is used to record the
+// output of skia image encoding.
+class BufferWStream : public SkWStream {
+ public:
+ BufferWStream() = default;
+ ~BufferWStream() override = default;
+
+ // Returns the output buffer by moving.
+ std::vector<unsigned char> GetBuffer() { return std::move(result_); }
+
+ // SkWStream:
+ bool write(const void* buffer, size_t size) override {
+ const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buffer);
+ result_.insert(result_.end(), bytes, bytes + size);
+ return true;
+ }
+
+ size_t bytesWritten() const override { return result_.size(); }
+
+ private:
+ std::vector<unsigned char> result_;
+};
+
+std::string MakeDataURIForImage(base::span<const uint8_t> image_data,
+ base::StringPiece mime_subtype) {
+ std::string result = "data:image/";
+ result.append(mime_subtype.begin(), mime_subtype.end());
+ result += ";base64,";
+ result += base::Base64Encode(image_data);
+ return result;
+}
+
+std::string EncodePNGAndMakeDataURI(gfx::ImageSkia image, float scale_factor) {
+ const SkBitmap& bitmap = image.GetRepresentation(scale_factor).GetBitmap();
+ BufferWStream stream;
+ const bool encoding_succeeded =
+ SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100);
+ DCHECK(encoding_succeeded);
+ return MakeDataURIForImage(
+ base::as_bytes(base::make_span(stream.GetBuffer())), "png");
+}
+
+class WebUIBackgroundMenuModel : public ui::SimpleMenuModel {
+ public:
+ explicit WebUIBackgroundMenuModel(ui::SimpleMenuModel::Delegate* delegate)
+ : ui::SimpleMenuModel(delegate) {
+ AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
+ AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB);
+ AddItemWithStringId(IDC_BOOKMARK_ALL_TABS, IDS_BOOKMARK_ALL_TABS);
+ }
+};
+
+class WebUIBackgroundContextMenu : public ui::SimpleMenuModel::Delegate,
+ public WebUIBackgroundMenuModel {
+ public:
+ WebUIBackgroundContextMenu(
+ Browser* browser,
+ const ui::AcceleratorProvider* accelerator_provider)
+ : WebUIBackgroundMenuModel(this),
+ browser_(browser),
+ accelerator_provider_(accelerator_provider) {}
+ ~WebUIBackgroundContextMenu() override = default;
+
+ void ExecuteCommand(int command_id, int event_flags) override {
+ chrome::ExecuteCommand(browser_, command_id);
+ }
+
+ bool GetAcceleratorForCommandId(int command_id,
+ ui::Accelerator* accelerator) const override {
+ return accelerator_provider_->GetAcceleratorForCommandId(command_id,
+ accelerator);
+ }
+
+ private:
+ Browser* const browser_;
+ const ui::AcceleratorProvider* const accelerator_provider_;
+};
+
+class WebUITabContextMenu : public ui::SimpleMenuModel::Delegate,
+ public TabMenuModel {
+ public:
+ WebUITabContextMenu(Browser* browser,
+ const ui::AcceleratorProvider* accelerator_provider,
+ int tab_index)
+ : TabMenuModel(this, browser->tab_strip_model(), tab_index),
+ browser_(browser),
+ accelerator_provider_(accelerator_provider),
+ tab_index_(tab_index) {}
+ ~WebUITabContextMenu() override = default;
+
+ void ExecuteCommand(int command_id, int event_flags) override {
+ DCHECK_LT(tab_index_, browser_->tab_strip_model()->count());
+ browser_->tab_strip_model()->ExecuteContextMenuCommand(
+ tab_index_, static_cast<TabStripModel::ContextMenuCommand>(command_id));
+ }
+
+ bool GetAcceleratorForCommandId(int command_id,
+ ui::Accelerator* accelerator) const override {
+ int real_command = -1;
+ TabStripModel::ContextMenuCommandToBrowserCommand(command_id,
+ &real_command);
+
+ if (real_command != -1) {
+ return accelerator_provider_->GetAcceleratorForCommandId(real_command,
+ accelerator);
+ } else {
+ return false;
+ }
+ }
+
+ private:
+ Browser* const browser_;
+ const ui::AcceleratorProvider* const accelerator_provider_;
+ const int tab_index_;
+};
+
+} // namespace
+
+TabStripUIHandler::TabStripUIHandler(Browser* browser,
+ TabStripUIEmbedder* embedder)
+ : browser_(browser),
+ embedder_(embedder),
+ thumbnail_tracker_(base::Bind(&TabStripUIHandler::HandleThumbnailUpdate,
+ base::Unretained(this))),
+ tab_before_unload_tracker_(
+ base::Bind(&TabStripUIHandler::OnTabCloseCancelled,
+ base::Unretained(this))) {}
+TabStripUIHandler::~TabStripUIHandler() = default;
+
+void TabStripUIHandler::NotifyLayoutChanged() {
+ if (!IsJavascriptAllowed())
+ return;
+ FireWebUIListener("layout-changed", embedder_->GetLayout().AsDictionary());
+}
+
+void TabStripUIHandler::NotifyReceivedKeyboardFocus() {
+ if (!IsJavascriptAllowed())
+ return;
+ FireWebUIListener("received-keyboard-focus");
+}
+
+// content::WebUIMessageHandler:
+void TabStripUIHandler::OnJavascriptAllowed() {
+ browser_->tab_strip_model()->AddObserver(this);
+}
+
+// TabStripModelObserver:
+void TabStripUIHandler::OnTabGroupChanged(const TabGroupChange& change) {
+ switch (change.type) {
+ case TabGroupChange::kCreated:
+ case TabGroupChange::kContentsChanged: {
+ // TabGroupChange::kCreated events are unnecessary as the front-end will
+ // assume a group was created if there is a tab-group-state-changed event
+ // with a new group ID. TabGroupChange::kContentsChanged events are
+ // handled by TabGroupStateChanged.
+ break;
+ }
+
+ case TabGroupChange::kVisualsChanged: {
+ FireWebUIListener(
+ "tab-group-visuals-changed", base::Value(change.group.ToString()),
+ GetTabGroupData(
+ browser_->tab_strip_model()->group_model()->GetTabGroup(
+ change.group)));
+ break;
+ }
+
+ case TabGroupChange::kMoved: {
+ FireWebUIListener("tab-group-moved", base::Value(change.group.ToString()),
+ base::Value(browser_->tab_strip_model()
+ ->group_model()
+ ->GetTabGroup(change.group)
+ ->ListTabs()
+ .front()));
+ break;
+ }
+
+ case TabGroupChange::kClosed: {
+ FireWebUIListener("tab-group-closed",
+ base::Value(change.group.ToString()));
+ break;
+ }
+ }
+}
+
+void TabStripUIHandler::TabGroupedStateChanged(
+ base::Optional<tab_groups::TabGroupId> group,
+ int index) {
+ int tab_id = extensions::ExtensionTabUtil::GetTabId(
+ browser_->tab_strip_model()->GetWebContentsAt(index));
+ if (group.has_value()) {
+ FireWebUIListener("tab-group-state-changed", base::Value(tab_id),
+ base::Value(index),
+ base::Value(group.value().ToString()));
+ } else {
+ FireWebUIListener("tab-group-state-changed", base::Value(tab_id),
+ base::Value(index));
+ }
+}
+
+void TabStripUIHandler::OnTabStripModelChanged(
+ TabStripModel* tab_strip_model,
+ const TabStripModelChange& change,
+ const TabStripSelectionChange& selection) {
+ if (tab_strip_model->empty())
+ return;
+
+ switch (change.type()) {
+ case TabStripModelChange::kInserted: {
+ for (const auto& contents : change.GetInsert()->contents) {
+ FireWebUIListener("tab-created",
+ GetTabData(contents.contents, contents.index));
+ }
+ break;
+ }
+ case TabStripModelChange::kRemoved: {
+ for (const auto& contents : change.GetRemove()->contents) {
+ FireWebUIListener("tab-removed",
+ base::Value(extensions::ExtensionTabUtil::GetTabId(
+ contents.contents)));
+ }
+ break;
+ }
+ case TabStripModelChange::kMoved: {
+ auto* move = change.GetMove();
+
+ // TODO(johntlee): Investigate if this is still needed, when
+ // TabGroupChange::kMoved exists.
+ base::Optional<tab_groups::TabGroupId> tab_group_id =
+ tab_strip_model->GetTabGroupForTab(move->to_index);
+ if (tab_group_id.has_value()) {
+ const std::vector<int> tabs_in_group =
+ tab_strip_model->group_model()
+ ->GetTabGroup(tab_group_id.value())
+ ->ListTabs();
+ if (tabs_in_group == selection.new_model.selected_indices()) {
+ // If the selection includes all the tabs within the changed tab's
+ // group, it is an indication that the entire group is being moved.
+ // To prevent sending multiple events for the same batch move, fire a
+ // separate single tab-group-moved event once all tabs have been
+ // moved. All tabs have moved only after all the indices in the group
+ // are in the correct continuous order.
+ if (tabs_in_group.back() - tabs_in_group.front() + 1 ==
+ static_cast<int>(tabs_in_group.size())) {
+ FireWebUIListener("tab-group-moved",
+ base::Value(tab_group_id.value().ToString()),
+ base::Value(tabs_in_group[0]));
+ }
+ break;
+ }
+ }
+
+ FireWebUIListener(
+ "tab-moved",
+ base::Value(extensions::ExtensionTabUtil::GetTabId(move->contents)),
+ base::Value(move->to_index));
+ break;
+ }
+ case TabStripModelChange::kReplaced: {
+ auto* replace = change.GetReplace();
+ FireWebUIListener("tab-replaced",
+ base::Value(extensions::ExtensionTabUtil::GetTabId(
+ replace->old_contents)),
+ base::Value(extensions::ExtensionTabUtil::GetTabId(
+ replace->new_contents)));
+ break;
+ }
+ case TabStripModelChange::kSelectionOnly:
+ // Multi-selection is not supported for touch.
+ break;
+ }
+
+ if (selection.active_tab_changed()) {
+ content::WebContents* new_contents = selection.new_contents;
+ int index = selection.new_model.active();
+ if (new_contents && index != TabStripModel::kNoTab) {
+ FireWebUIListener(
+ "tab-active-changed",
+ base::Value(extensions::ExtensionTabUtil::GetTabId(new_contents)));
+ }
+ }
+}
+
+void TabStripUIHandler::TabChangedAt(content::WebContents* contents,
+ int index,
+ TabChangeType change_type) {
+ FireWebUIListener("tab-updated", GetTabData(contents, index));
+}
+
+void TabStripUIHandler::TabPinnedStateChanged(TabStripModel* tab_strip_model,
+ content::WebContents* contents,
+ int index) {
+ FireWebUIListener("tab-updated", GetTabData(contents, index));
+}
+
+void TabStripUIHandler::TabBlockedStateChanged(content::WebContents* contents,
+ int index) {
+ FireWebUIListener("tab-updated", GetTabData(contents, index));
+}
+
+// content::WebUIMessageHandler:
+void TabStripUIHandler::RegisterMessages() {
+ web_ui()->RegisterMessageCallback(
+ "createNewTab", base::Bind(&TabStripUIHandler::HandleCreateNewTab,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "getTabs",
+ base::Bind(&TabStripUIHandler::HandleGetTabs, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "getGroupVisualData",
+ base::Bind(&TabStripUIHandler::HandleGetGroupVisualData,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "getThemeColors", base::Bind(&TabStripUIHandler::HandleGetThemeColors,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "groupTab",
+ base::Bind(&TabStripUIHandler::HandleGroupTab, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "ungroupTab",
+ base::Bind(&TabStripUIHandler::HandleUngroupTab, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "moveGroup",
+ base::Bind(&TabStripUIHandler::HandleMoveGroup, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "moveTab",
+ base::Bind(&TabStripUIHandler::HandleMoveTab, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "setThumbnailTracked",
+ base::Bind(&TabStripUIHandler::HandleSetThumbnailTracked,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "closeContainer", base::Bind(&TabStripUIHandler::HandleCloseContainer,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "closeTab",
+ base::Bind(&TabStripUIHandler::HandleCloseTab, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "showBackgroundContextMenu",
+ base::Bind(&TabStripUIHandler::HandleShowBackgroundContextMenu,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "showEditDialogForGroup",
+ base::Bind(&TabStripUIHandler::HandleShowEditDialogForGroup,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "showTabContextMenu",
+ base::Bind(&TabStripUIHandler::HandleShowTabContextMenu,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "getLayout",
+ base::Bind(&TabStripUIHandler::HandleGetLayout, base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "reportTabActivationDuration",
+ base::Bind(&TabStripUIHandler::HandleReportTabActivationDuration,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "reportTabDataReceivedDuration",
+ base::Bind(&TabStripUIHandler::HandleReportTabDataReceivedDuration,
+ base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "reportTabCreationDuration",
+ base::Bind(&TabStripUIHandler::HandleReportTabCreationDuration,
+ base::Unretained(this)));
+}
+
+void TabStripUIHandler::HandleCreateNewTab(const base::ListValue* args) {
+ UMA_HISTOGRAM_ENUMERATION("Tab.NewTab",
+ TabStripModel::NEW_TAB_BUTTON_IN_WEBUI_TAB_STRIP,
+ TabStripModel::NEW_TAB_ENUM_COUNT);
+ chrome::ExecuteCommand(browser_, IDC_NEW_TAB);
+}
+
+base::DictionaryValue TabStripUIHandler::GetTabData(
+ content::WebContents* contents,
+ int index) {
+ base::DictionaryValue tab_data;
+
+ tab_data.SetBoolean("active",
+ browser_->tab_strip_model()->active_index() == index);
+ tab_data.SetInteger("id", extensions::ExtensionTabUtil::GetTabId(contents));
+ tab_data.SetInteger("index", index);
+
+ const base::Optional<tab_groups::TabGroupId> group_id =
+ browser_->tab_strip_model()->GetTabGroupForTab(index);
+ if (group_id.has_value()) {
+ tab_data.SetString("groupId", group_id.value().ToString());
+ }
+
+ TabRendererData tab_renderer_data =
+ TabRendererData::FromTabInModel(browser_->tab_strip_model(), index);
+ tab_data.SetBoolean("pinned", tab_renderer_data.pinned);
+ tab_data.SetString("title", tab_renderer_data.title);
+ tab_data.SetString("url", tab_renderer_data.visible_url.GetContent());
+
+ if (!tab_renderer_data.favicon.isNull()) {
+ tab_data.SetString("favIconUrl", EncodePNGAndMakeDataURI(
+ tab_renderer_data.favicon,
+ web_ui()->GetDeviceScaleFactor()));
+ tab_data.SetBoolean("isDefaultFavicon",
+ tab_renderer_data.favicon.BackedBySameObjectAs(
+ favicon::GetDefaultFavicon().AsImageSkia()));
+ } else {
+ tab_data.SetBoolean("isDefaultFavicon", true);
+ }
+ tab_data.SetBoolean("showIcon", tab_renderer_data.show_icon);
+ tab_data.SetInteger("networkState",
+ static_cast<int>(tab_renderer_data.network_state));
+ tab_data.SetBoolean("shouldHideThrobber",
+ tab_renderer_data.should_hide_throbber);
+ tab_data.SetBoolean("blocked", tab_renderer_data.blocked);
+ tab_data.SetBoolean("crashed", tab_renderer_data.IsCrashed());
+ // TODO(johntlee): Add the rest of TabRendererData
+
+ auto alert_states = std::make_unique<base::ListValue>();
+ for (const auto alert_state :
+ chrome::GetTabAlertStatesForContents(contents)) {
+ alert_states->Append(static_cast<int>(alert_state));
+ }
+ tab_data.SetList("alertStates", std::move(alert_states));
+
+ return tab_data;
+}
+
+base::DictionaryValue TabStripUIHandler::GetTabGroupData(TabGroup* group) {
+ const tab_groups::TabGroupVisualData* visual_data = group->visual_data();
+
+ base::DictionaryValue visual_data_dict;
+ visual_data_dict.SetString("title", visual_data->title());
+
+ // TODO the tab strip should support toggles between inactive and active frame
+ // states. Currently the webui tab strip only uses active frame colors
+ // (https://crbug.com/1060398).
+ const int color_id = GetTabGroupTabStripColorId(visual_data->color(), true);
+ const SkColor group_color = embedder_->GetColor(color_id);
+ visual_data_dict.SetString("color",
+ color_utils::SkColorToRgbString(group_color));
+ visual_data_dict.SetString(
+ "textColor", color_utils::SkColorToRgbString(
+ color_utils::GetColorWithMaxContrast(group_color)));
+
+ return visual_data_dict;
+}
+
+void TabStripUIHandler::HandleGetTabs(const base::ListValue* args) {
+ AllowJavascript();
+ const base::Value& callback_id = args->GetList()[0];
+
+ base::ListValue tabs;
+ TabStripModel* tab_strip_model = browser_->tab_strip_model();
+ for (int i = 0; i < tab_strip_model->count(); ++i) {
+ tabs.Append(GetTabData(tab_strip_model->GetWebContentsAt(i), i));
+ }
+ ResolveJavascriptCallback(callback_id, tabs);
+}
+
+void TabStripUIHandler::HandleGetGroupVisualData(const base::ListValue* args) {
+ AllowJavascript();
+ const base::Value& callback_id = args->GetList()[0];
+
+ base::DictionaryValue group_visual_datas;
+ std::vector<tab_groups::TabGroupId> groups =
+ browser_->tab_strip_model()->group_model()->ListTabGroups();
+ for (const tab_groups::TabGroupId& group : groups) {
+ group_visual_datas.SetDictionary(
+ group.ToString(),
+ std::make_unique<base::DictionaryValue>(GetTabGroupData(
+ browser_->tab_strip_model()->group_model()->GetTabGroup(group))));
+ }
+ ResolveJavascriptCallback(callback_id, group_visual_datas);
+}
+
+void TabStripUIHandler::HandleGetThemeColors(const base::ListValue* args) {
+ AllowJavascript();
+ const base::Value& callback_id = args->GetList()[0];
+
+ // This should return an object of CSS variables to rgba values so that
+ // the WebUI can use the CSS variables to color the tab strip
+ base::DictionaryValue colors;
+ colors.SetString("--tabstrip-background-color",
+ color_utils::SkColorToRgbaString(embedder_->GetColor(
+ ThemeProperties::COLOR_FRAME_ACTIVE)));
+ colors.SetString("--tabstrip-tab-background-color",
+ color_utils::SkColorToRgbaString(
+ embedder_->GetColor(ThemeProperties::COLOR_TOOLBAR)));
+ colors.SetString(
+ "--tabstrip-tab-text-color",
+ color_utils::SkColorToRgbaString(embedder_->GetColor(
+ ThemeProperties::COLOR_TAB_FOREGROUND_ACTIVE_FRAME_ACTIVE)));
+ colors.SetString(
+ "--tabstrip-tab-separator-color",
+ color_utils::SkColorToRgbaString(SkColorSetA(
+ embedder_->GetColor(
+ ThemeProperties::COLOR_TAB_FOREGROUND_ACTIVE_FRAME_ACTIVE),
+ /* 16% opacity */ 0.16 * 255)));
+
+ colors.SetString("--tabstrip-tab-loading-spinning-color",
+ color_utils::SkColorToRgbaString(embedder_->GetColor(
+ ThemeProperties::COLOR_TAB_THROBBER_SPINNING)));
+ colors.SetString("--tabstrip-tab-waiting-spinning-color",
+ color_utils::SkColorToRgbaString(embedder_->GetColor(
+ ThemeProperties::COLOR_TAB_THROBBER_WAITING)));
+ colors.SetString("--tabstrip-indicator-recording-color",
+ color_utils::SkColorToRgbaString(embedder_->GetColor(
+ ThemeProperties::COLOR_TAB_ALERT_RECORDING)));
+ colors.SetString("--tabstrip-indicator-pip-color",
+ color_utils::SkColorToRgbaString(embedder_->GetColor(
+ ThemeProperties::COLOR_TAB_PIP_PLAYING)));
+ colors.SetString("--tabstrip-indicator-capturing-color",
+ color_utils::SkColorToRgbaString(embedder_->GetColor(
+ ThemeProperties::COLOR_TAB_ALERT_CAPTURING)));
+ colors.SetString("--tabstrip-tab-blocked-color",
+ color_utils::SkColorToRgbaString(
+ ui::NativeTheme::GetInstanceForWeb()->GetSystemColor(
+ ui::NativeTheme::kColorId_ProminentButtonColor)));
+ colors.SetString("--tabstrip-focus-outline-color",
+ color_utils::SkColorToRgbaString(
+ ui::NativeTheme::GetInstanceForWeb()->GetSystemColor(
+ ui::NativeTheme::kColorId_FocusedBorderColor)));
+
+#if !defined(OS_CHROMEOS)
+ colors.SetString(
+ "--tabstrip-scrollbar-thumb-color-rgb",
+ color_utils::SkColorToRgbString(color_utils::GetColorWithMaxContrast(
+ embedder_->GetColor(ThemeProperties::COLOR_FRAME_ACTIVE))));
+#endif
+
+ ResolveJavascriptCallback(callback_id, colors);
+}
+
+void TabStripUIHandler::HandleGroupTab(const base::ListValue* args) {
+ int tab_id = args->GetList()[0].GetInt();
+
+ int tab_index = -1;
+ bool got_tab = extensions::ExtensionTabUtil::GetTabById(
+ tab_id, browser_->profile(), /*include_incognito=*/true, nullptr, nullptr,
+ nullptr, &tab_index);
+ DCHECK(got_tab);
+
+ const std::string group_id_string = args->GetList()[1].GetString();
+ base::Optional<tab_groups::TabGroupId> group_id =
+ tab_strip_ui::GetTabGroupIdFromString(
+ browser_->tab_strip_model()->group_model(), group_id_string);
+ if (group_id.has_value()) {
+ browser_->tab_strip_model()->AddToExistingGroup({tab_index},
+ group_id.value());
+ }
+}
+
+void TabStripUIHandler::HandleUngroupTab(const base::ListValue* args) {
+ int tab_id = args->GetList()[0].GetInt();
+
+ int tab_index = -1;
+ bool got_tab = extensions::ExtensionTabUtil::GetTabById(
+ tab_id, browser_->profile(), /*include_incognito=*/true, nullptr, nullptr,
+ nullptr, &tab_index);
+ DCHECK(got_tab);
+
+ browser_->tab_strip_model()->RemoveFromGroup({tab_index});
+}
+
+void TabStripUIHandler::HandleMoveGroup(const base::ListValue* args) {
+ const std::string group_id_string = args->GetList()[0].GetString();
+
+ int to_index = args->GetList()[1].GetInt();
+ if (to_index == -1) {
+ to_index = browser_->tab_strip_model()->count();
+ }
+
+ auto* target_browser = browser_;
+ Browser* source_browser =
+ tab_strip_ui::GetBrowserWithGroupId(browser_->profile(), group_id_string);
+ if (!source_browser) {
+ return;
+ }
+
+ base::Optional<tab_groups::TabGroupId> group_id =
+ tab_strip_ui::GetTabGroupIdFromString(
+ source_browser->tab_strip_model()->group_model(), group_id_string);
+ TabGroup* group =
+ source_browser->tab_strip_model()->group_model()->GetTabGroup(
+ group_id.value());
+
+ if (source_browser == target_browser) {
+ if (group->ListTabs().front() == to_index) {
+ // If the group is already in place, don't move it. This may happen
+ // if multiple drag events happen while the tab group is still
+ // being moved.
+ return;
+ }
+
+ // If moving within the same browser, just do a simple move.
+ target_browser->tab_strip_model()->MoveGroupTo(group_id.value(), to_index);
+ return;
+ }
+
+ // Create a new group and copy the visuals to it.
+ tab_groups::TabGroupId new_group_id = tab_groups::TabGroupId::GenerateNew();
+ browser_->tab_strip_model()->group_model()->AddTabGroup(
+ new_group_id,
+ base::Optional<tab_groups::TabGroupVisualData>{*group->visual_data()});
+
+ // The front-end needs to understand that the tab group ID has changed so
+ // that when the tabs are moved into the new group, the new group ID is
+ // updated with the correct value.
+ FireWebUIListener("tab-group-id-replaced",
+ base::Value(group->id().ToString()),
+ base::Value(new_group_id.ToString()));
+
+ std::vector<int> source_tab_indices = group->ListTabs();
+ int tab_count = source_tab_indices.size();
+ for (int i = 0; i < tab_count; i++) {
+ // The index needs to account for the tabs being detached, as they will
+ // cause the indices to shift.
+ int from_index = source_tab_indices[i] - i;
+ tab_strip_ui::MoveTabAcrossWindows(
+ source_browser, from_index, target_browser, to_index + i, new_group_id);
+ }
+}
+
+void TabStripUIHandler::HandleMoveTab(const base::ListValue* args) {
+ int tab_id = args->GetList()[0].GetInt();
+ int to_index = args->GetList()[1].GetInt();
+ if (to_index == -1) {
+ to_index = browser_->tab_strip_model()->count();
+ }
+
+ Browser* source_browser;
+ int from_index = -1;
+ if (!extensions::ExtensionTabUtil::GetTabById(tab_id, browser_->profile(),
+ true, &source_browser, nullptr,
+ nullptr, &from_index)) {
+ return;
+ }
+
+ if (source_browser->profile() != browser_->profile()) {
+ return;
+ }
+
+ if (source_browser == browser_) {
+ browser_->tab_strip_model()->MoveWebContentsAt(from_index, to_index, false);
+ return;
+ }
+
+ tab_strip_ui::MoveTabAcrossWindows(source_browser, from_index, browser_,
+ to_index);
+}
+
+void TabStripUIHandler::HandleCloseContainer(const base::ListValue* args) {
+ // We only autoclose for tab selection.
+ RecordTabStripUICloseHistogram(TabStripUICloseAction::kTabSelected);
+ DCHECK(embedder_);
+ embedder_->CloseContainer();
+}
+
+void TabStripUIHandler::HandleCloseTab(const base::ListValue* args) {
+ AllowJavascript();
+
+ int tab_id = args->GetList()[0].GetInt();
+ content::WebContents* tab = nullptr;
+ if (!extensions::ExtensionTabUtil::GetTabById(tab_id, browser_->profile(),
+ true, &tab)) {
+ // ID didn't refer to a valid tab.
+ DVLOG(1) << "Invalid tab ID";
+ return;
+ }
+
+ bool tab_was_swiped = args->GetList()[1].GetBool();
+ if (tab_was_swiped) {
+ // The unload tracker will automatically unobserve the tab when it
+ // successfully closes.
+ tab_before_unload_tracker_.Observe(tab);
+ }
+ tab->Close();
+}
+
+void TabStripUIHandler::HandleShowBackgroundContextMenu(
+ const base::ListValue* args) {
+ gfx::PointF point;
+ {
+ double x = args->GetList()[0].GetDouble();
+ double y = args->GetList()[1].GetDouble();
+ point = gfx::PointF(x, y);
+ }
+
+ DCHECK(embedder_);
+ embedder_->ShowContextMenuAtPoint(
+ gfx::ToRoundedPoint(point),
+ std::make_unique<WebUIBackgroundContextMenu>(
+ browser_, embedder_->GetAcceleratorProvider()));
+}
+
+void TabStripUIHandler::HandleShowEditDialogForGroup(
+ const base::ListValue* args) {
+ const std::string group_id_string = args->GetList()[0].GetString();
+ base::Optional<tab_groups::TabGroupId> group_id =
+ tab_strip_ui::GetTabGroupIdFromString(
+ browser_->tab_strip_model()->group_model(), group_id_string);
+ if (!group_id.has_value()) {
+ return;
+ }
+
+ gfx::Point point;
+ {
+ double x = args->GetList()[1].GetDouble();
+ double y = args->GetList()[2].GetDouble();
+ point = gfx::Point(x, y);
+ }
+
+ gfx::Rect rect;
+ {
+ double width = args->GetList()[3].GetDouble();
+ double height = args->GetList()[4].GetDouble();
+ rect = gfx::Rect(width, height);
+ }
+
+ DCHECK(embedder_);
+ embedder_->ShowEditDialogForGroupAtPoint(point, rect, group_id.value());
+}
+
+void TabStripUIHandler::HandleShowTabContextMenu(const base::ListValue* args) {
+ int tab_id = args->GetList()[0].GetInt();
+
+ gfx::PointF point;
+ {
+ double x = args->GetList()[1].GetDouble();
+ double y = args->GetList()[2].GetDouble();
+ point = gfx::PointF(x, y);
+ }
+
+ Browser* browser = nullptr;
+ int tab_index = -1;
+ const bool got_tab = extensions::ExtensionTabUtil::GetTabById(
+ tab_id, browser_->profile(), true /* include_incognito */, &browser,
+ nullptr, nullptr, &tab_index);
+ DCHECK(got_tab);
+ DCHECK_EQ(browser, browser_);
+
+ DCHECK(embedder_);
+ embedder_->ShowContextMenuAtPoint(
+ gfx::ToRoundedPoint(point),
+ std::make_unique<WebUITabContextMenu>(
+ browser, embedder_->GetAcceleratorProvider(), tab_index));
+}
+
+void TabStripUIHandler::HandleGetLayout(const base::ListValue* args) {
+ AllowJavascript();
+ const base::Value& callback_id = args->GetList()[0];
+
+ base::Value layout = embedder_->GetLayout().AsDictionary();
+ ResolveJavascriptCallback(callback_id, layout);
+}
+
+void TabStripUIHandler::HandleSetThumbnailTracked(const base::ListValue* args) {
+ AllowJavascript();
+
+ int tab_id = args->GetList()[0].GetInt();
+ const bool thumbnail_tracked = args->GetList()[1].GetBool();
+
+ content::WebContents* tab = nullptr;
+ if (!extensions::ExtensionTabUtil::GetTabById(tab_id, browser_->profile(),
+ true, &tab)) {
+ // ID didn't refer to a valid tab.
+ DVLOG(1) << "Invalid tab ID";
+ return;
+ }
+
+ if (thumbnail_tracked)
+ thumbnail_tracker_.AddTab(tab);
+ else
+ thumbnail_tracker_.RemoveTab(tab);
+}
+
+void TabStripUIHandler::HandleReportTabActivationDuration(
+ const base::ListValue* args) {
+ int duration_ms = args->GetList()[0].GetInt();
+ UMA_HISTOGRAM_TIMES("WebUITabStrip.TabActivation",
+ base::TimeDelta::FromMilliseconds(duration_ms));
+}
+
+void TabStripUIHandler::HandleReportTabDataReceivedDuration(
+ const base::ListValue* args) {
+ int tab_count = args->GetList()[0].GetInt();
+ int duration_ms = args->GetList()[1].GetInt();
+ ReportTabDurationHistogram("TabDataReceived", tab_count,
+ base::TimeDelta::FromMilliseconds(duration_ms));
+}
+
+void TabStripUIHandler::HandleReportTabCreationDuration(
+ const base::ListValue* args) {
+ int tab_count = args->GetList()[0].GetInt();
+ int duration_ms = args->GetList()[1].GetInt();
+ ReportTabDurationHistogram("TabCreation", tab_count,
+ base::TimeDelta::FromMilliseconds(duration_ms));
+}
+
+// Callback passed to |thumbnail_tracker_|. Called when a tab's thumbnail
+// changes, or when we start watching the tab.
+void TabStripUIHandler::HandleThumbnailUpdate(
+ content::WebContents* tab,
+ ThumbnailTracker::CompressedThumbnailData image) {
+ // Send base-64 encoded image to JS side.
+ std::string data_uri =
+ MakeDataURIForImage(base::make_span(image->data), "jpeg");
+
+ const int tab_id = extensions::ExtensionTabUtil::GetTabId(tab);
+ FireWebUIListener("tab-thumbnail-updated", base::Value(tab_id),
+ base::Value(data_uri));
+}
+
+void TabStripUIHandler::OnTabCloseCancelled(content::WebContents* tab) {
+ tab_before_unload_tracker_.Unobserve(tab);
+ const int tab_id = extensions::ExtensionTabUtil::GetTabId(tab);
+ FireWebUIListener("tab-close-cancelled", base::Value(tab_id));
+}
+
+// Reports a histogram using the format
+// WebUITabStrip.|histogram_fragment|.[tab count bucket].
+void TabStripUIHandler::ReportTabDurationHistogram(
+ const char* histogram_fragment,
+ int tab_count,
+ base::TimeDelta duration) {
+ if (tab_count <= 0)
+ return;
+
+ // It isn't possible to report both a number of tabs and duration datapoint
+ // together in a histogram or to correlate two histograms together. As a
+ // result the histogram is manually bucketed.
+ const char* tab_count_bucket = "01_05";
+ if (6 <= tab_count && tab_count <= 20) {
+ tab_count_bucket = "06_20";
+ } else if (20 < tab_count) {
+ tab_count_bucket = "21_";
+ }
+
+ std::string histogram_name = base::JoinString(
+ {"WebUITabStrip", histogram_fragment, tab_count_bucket}, ".");
+ base::UmaHistogramTimes(histogram_name, duration);
+}
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.h b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.h
new file mode 100644
index 00000000000..3221e4c3a8f
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.h
@@ -0,0 +1,99 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_HANDLER_H_
+#define CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_HANDLER_H_
+
+#include "base/macros.h"
+#include "base/values.h"
+#include "chrome/browser/ui/tabs/tab_change_type.h"
+#include "chrome/browser/ui/tabs/tab_group.h"
+#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
+#include "chrome/browser/ui/webui/tab_strip/tab_before_unload_tracker.h"
+#include "chrome/browser/ui/webui/tab_strip/thumbnail_tracker.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui_message_handler.h"
+
+class Browser;
+class TabStripUIEmbedder;
+
+class TabStripUIHandler : public content::WebUIMessageHandler,
+ public TabStripModelObserver {
+ public:
+ explicit TabStripUIHandler(Browser* browser, TabStripUIEmbedder* embedder);
+ ~TabStripUIHandler() override;
+
+ void NotifyLayoutChanged();
+ void NotifyReceivedKeyboardFocus();
+
+ // TabStripModelObserver:
+ void OnTabGroupChanged(const TabGroupChange& change) override;
+ void TabGroupedStateChanged(base::Optional<tab_groups::TabGroupId> group,
+ int index) override;
+ void OnTabStripModelChanged(
+ TabStripModel* tab_strip_model,
+ const TabStripModelChange& change,
+ const TabStripSelectionChange& selection) override;
+ void TabChangedAt(content::WebContents* contents,
+ int index,
+ TabChangeType change_type) override;
+ void TabPinnedStateChanged(TabStripModel* tab_strip_model,
+ content::WebContents* contents,
+ int index) override;
+ void TabBlockedStateChanged(content::WebContents* contents,
+ int index) override;
+
+ protected:
+ // content::WebUIMessageHandler:
+ void OnJavascriptAllowed() override;
+ void RegisterMessages() override;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, CloseTab);
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, GetGroupVisualData);
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, GroupTab);
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, MoveGroup);
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, MoveGroupAcrossProfiles);
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, MoveGroupAcrossWindows);
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, MoveTab);
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, MoveTabAcrossProfiles);
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, MoveTabAcrossWindows);
+ FRIEND_TEST_ALL_PREFIXES(TabStripUIHandlerTest, UngroupTab);
+
+ void HandleCreateNewTab(const base::ListValue* args);
+ base::DictionaryValue GetTabData(content::WebContents* contents, int index);
+ base::DictionaryValue GetTabGroupData(TabGroup* group);
+ void HandleGetTabs(const base::ListValue* args);
+ void HandleGetGroupVisualData(const base::ListValue* args);
+ void HandleGetThemeColors(const base::ListValue* args);
+ void HandleCloseContainer(const base::ListValue* args);
+ void HandleCloseTab(const base::ListValue* args);
+ void HandleShowBackgroundContextMenu(const base::ListValue* args);
+ void HandleShowEditDialogForGroup(const base::ListValue* args);
+ void HandleShowTabContextMenu(const base::ListValue* args);
+ void HandleGetLayout(const base::ListValue* args);
+ void HandleGroupTab(const base::ListValue* args);
+ void HandleUngroupTab(const base::ListValue* args);
+ void HandleMoveGroup(const base::ListValue* args);
+ void HandleMoveTab(const base::ListValue* args);
+ void HandleSetThumbnailTracked(const base::ListValue* args);
+ void HandleReportTabActivationDuration(const base::ListValue* args);
+ void HandleReportTabDataReceivedDuration(const base::ListValue* args);
+ void HandleReportTabCreationDuration(const base::ListValue* args);
+ void HandleThumbnailUpdate(content::WebContents* tab,
+ ThumbnailTracker::CompressedThumbnailData image);
+ void OnTabCloseCancelled(content::WebContents* tab);
+ void ReportTabDurationHistogram(const char* histogram_fragment,
+ int tab_count,
+ base::TimeDelta duration);
+
+ Browser* const browser_;
+ TabStripUIEmbedder* const embedder_;
+ ThumbnailTracker thumbnail_tracker_;
+ tab_strip_ui::TabBeforeUnloadTracker tab_before_unload_tracker_;
+
+ DISALLOW_COPY_AND_ASSIGN(TabStripUIHandler);
+};
+
+#endif // CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_HANDLER_H_
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc
new file mode 100644
index 00000000000..1e37827a132
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc
@@ -0,0 +1,568 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.h"
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_tab_util.h"
+#include "chrome/browser/ui/tabs/tab_group_model.h"
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h"
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h"
+#include "chrome/test/base/browser_with_test_window_test.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "components/tab_groups/tab_group_color.h"
+#include "components/tab_groups/tab_group_id.h"
+#include "components/tab_groups/tab_group_visual_data.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/test/test_web_ui.h"
+#include "content/public/test/web_contents_tester.h"
+#include "ui/base/accelerators/accelerator.h"
+#include "ui/base/theme_provider.h"
+#include "ui/gfx/color_utils.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace {
+
+class TestTabStripUIHandler : public TabStripUIHandler {
+ public:
+ explicit TestTabStripUIHandler(content::WebUI* web_ui,
+ Browser* browser,
+ TabStripUIEmbedder* embedder)
+ : TabStripUIHandler(browser, embedder) {
+ set_web_ui(web_ui);
+ }
+};
+
+class StubTabStripUIEmbedder : public TabStripUIEmbedder {
+ public:
+ const ui::AcceleratorProvider* GetAcceleratorProvider() const override {
+ return nullptr;
+ }
+ void CloseContainer() override {}
+ void ShowContextMenuAtPoint(
+ gfx::Point point,
+ std::unique_ptr<ui::MenuModel> menu_model) override {}
+ void ShowEditDialogForGroupAtPoint(gfx::Point point,
+ gfx::Rect rect,
+ tab_groups::TabGroupId group_id) override {
+ }
+ TabStripUILayout GetLayout() override { return TabStripUILayout(); }
+ SkColor GetColor(int id) const override { return SK_ColorWHITE; }
+};
+
+} // namespace
+
+class TabStripUIHandlerTest : public BrowserWithTestWindowTest {
+ public:
+ TabStripUIHandlerTest() = default;
+
+ void SetUp() override {
+ BrowserWithTestWindowTest::SetUp();
+ handler_ = std::make_unique<TestTabStripUIHandler>(web_ui(), browser(),
+ &stub_embedder_);
+ handler()->AllowJavascriptForTesting();
+ web_ui()->ClearTrackedCalls();
+ }
+
+ TabStripUIHandler* handler() { return handler_.get(); }
+ content::TestWebUI* web_ui() { return &web_ui_; }
+
+ void ExpectVisualDataDictionary(
+ const tab_groups::TabGroupVisualData visual_data,
+ const base::DictionaryValue* visual_data_dict) {
+ std::string group_title;
+ ASSERT_TRUE(visual_data_dict->GetString("title", &group_title));
+ EXPECT_EQ(base::UTF16ToASCII(visual_data.title()), group_title);
+
+ std::string group_color;
+ ASSERT_TRUE(visual_data_dict->GetString("color", &group_color));
+ EXPECT_EQ(color_utils::SkColorToRgbString(SK_ColorWHITE), group_color);
+ }
+
+ private:
+ StubTabStripUIEmbedder stub_embedder_;
+ content::TestWebUI web_ui_;
+ std::unique_ptr<TestTabStripUIHandler> handler_;
+};
+
+TEST_F(TabStripUIHandlerTest, GroupClosedEvent) {
+ AddTab(browser(), GURL("http://foo"));
+ tab_groups::TabGroupId expected_group_id =
+ browser()->tab_strip_model()->AddToNewGroup({0});
+ browser()->tab_strip_model()->RemoveFromGroup({0});
+
+ const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
+ EXPECT_EQ("tab-group-closed", call_data.arg1()->GetString());
+ EXPECT_EQ(expected_group_id.ToString(), call_data.arg2()->GetString());
+}
+
+TEST_F(TabStripUIHandlerTest, GroupStateChangedEvents) {
+ AddTab(browser(), GURL("http://foo/1"));
+ AddTab(browser(), GURL("http://foo/2"));
+
+ // Add one of the tabs to a group to test for a tab-group-state-changed event.
+ tab_groups::TabGroupId expected_group_id =
+ browser()->tab_strip_model()->AddToNewGroup({0, 1});
+ int expected_tab_id = extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(1));
+
+ const content::TestWebUI::CallData& grouped_call_data =
+ *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIListenerCallback", grouped_call_data.function_name());
+ EXPECT_EQ("tab-group-state-changed", grouped_call_data.arg1()->GetString());
+ EXPECT_EQ(expected_tab_id, grouped_call_data.arg2()->GetInt());
+ EXPECT_EQ(1, grouped_call_data.arg3()->GetInt());
+ EXPECT_EQ(expected_group_id.ToString(),
+ grouped_call_data.arg4()->GetString());
+
+ // Remove the tab from the group to test for a tab-group-state-changed event.
+ browser()->tab_strip_model()->RemoveFromGroup({1});
+ const content::TestWebUI::CallData& ungrouped_call_data =
+ *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIListenerCallback", ungrouped_call_data.function_name());
+ EXPECT_EQ("tab-group-state-changed", ungrouped_call_data.arg1()->GetString());
+ EXPECT_EQ(expected_tab_id, ungrouped_call_data.arg2()->GetInt());
+ EXPECT_EQ(1, ungrouped_call_data.arg3()->GetInt());
+ EXPECT_EQ(nullptr, ungrouped_call_data.arg4());
+}
+
+TEST_F(TabStripUIHandlerTest, GroupMovedEvents) {
+ // Create a tab group and a few other tabs to allow the group to move.
+ AddTab(browser(), GURL("http://foo/1"));
+ AddTab(browser(), GURL("http://foo/2"));
+ AddTab(browser(), GURL("http://foo/3"));
+ AddTab(browser(), GURL("http://foo/4"));
+ tab_groups::TabGroupId expected_group_id =
+ browser()->tab_strip_model()->AddToNewGroup({0, 1});
+
+ // Select all the tabs in the group.
+ ui::ListSelectionModel selection;
+ selection.AddIndexToSelection(0);
+ selection.AddIndexToSelection(1);
+ selection.set_active(0);
+ browser()->tab_strip_model()->SetSelectionFromModel(selection);
+
+ web_ui()->ClearTrackedCalls();
+
+ // Move the selected tabs to later in the tab strip. This should result in
+ // a single event that is fired to indicate the entire group has moved.
+ int expected_index = 2;
+ browser()->tab_strip_model()->MoveSelectedTabsTo(expected_index);
+
+ EXPECT_EQ(1U, web_ui()->call_data().size());
+
+ const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
+ EXPECT_EQ("tab-group-moved", call_data.arg1()->GetString());
+ EXPECT_EQ(expected_group_id.ToString(), call_data.arg2()->GetString());
+ EXPECT_EQ(expected_index, call_data.arg3()->GetInt());
+
+ web_ui()->ClearTrackedCalls();
+
+ // Move the selected tabs to earlier in the tab strip. This should also
+ // result in a single event that is fired to indicate the entire group has
+ // moved.
+ expected_index = 1;
+ browser()->tab_strip_model()->MoveSelectedTabsTo(expected_index);
+
+ EXPECT_EQ(1U, web_ui()->call_data().size());
+
+ const content::TestWebUI::CallData& call_data2 =
+ *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data2.function_name());
+ EXPECT_EQ("tab-group-moved", call_data2.arg1()->GetString());
+ EXPECT_EQ(expected_group_id.ToString(), call_data2.arg2()->GetString());
+ EXPECT_EQ(expected_index, call_data2.arg3()->GetInt());
+}
+
+TEST_F(TabStripUIHandlerTest, GetGroupVisualData) {
+ AddTab(browser(), GURL("http://foo/1"));
+ AddTab(browser(), GURL("http://foo/2"));
+ tab_groups::TabGroupId group1 =
+ browser()->tab_strip_model()->AddToNewGroup({0});
+ const tab_groups::TabGroupVisualData group1_visuals(
+ base::ASCIIToUTF16("Group 1"), tab_groups::TabGroupColorId::kGreen);
+ browser()
+ ->tab_strip_model()
+ ->group_model()
+ ->GetTabGroup(group1)
+ ->SetVisualData(group1_visuals);
+ tab_groups::TabGroupId group2 =
+ browser()->tab_strip_model()->AddToNewGroup({1});
+ const tab_groups::TabGroupVisualData group2_visuals(
+ base::ASCIIToUTF16("Group 2"), tab_groups::TabGroupColorId::kCyan);
+ browser()
+ ->tab_strip_model()
+ ->group_model()
+ ->GetTabGroup(group2)
+ ->SetVisualData(group2_visuals);
+
+ base::ListValue args;
+ args.AppendString("callback-id");
+ handler()->HandleGetGroupVisualData(&args);
+
+ const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIResponse", call_data.function_name());
+ EXPECT_EQ("callback-id", call_data.arg1()->GetString());
+ EXPECT_TRUE(call_data.arg2()->GetBool());
+
+ const base::DictionaryValue* returned_data;
+ ASSERT_TRUE(call_data.arg3()->GetAsDictionary(&returned_data));
+
+ const base::DictionaryValue* group1_dict;
+ ASSERT_TRUE(returned_data->GetDictionary(group1.ToString(), &group1_dict));
+ ExpectVisualDataDictionary(group1_visuals, group1_dict);
+
+ const base::DictionaryValue* group2_dict;
+ ASSERT_TRUE(returned_data->GetDictionary(group2.ToString(), &group2_dict));
+ ExpectVisualDataDictionary(group2_visuals, group2_dict);
+}
+
+TEST_F(TabStripUIHandlerTest, GroupVisualDataChangedEvent) {
+ AddTab(browser(), GURL("http://foo"));
+ tab_groups::TabGroupId expected_group_id =
+ browser()->tab_strip_model()->AddToNewGroup({0});
+ const tab_groups::TabGroupVisualData new_visual_data(
+ base::ASCIIToUTF16("My new title"), tab_groups::TabGroupColorId::kGreen);
+ browser()
+ ->tab_strip_model()
+ ->group_model()
+ ->GetTabGroup(expected_group_id)
+ ->SetVisualData(new_visual_data);
+
+ const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
+ EXPECT_EQ("tab-group-visuals-changed", call_data.arg1()->GetString());
+ EXPECT_EQ(expected_group_id.ToString(), call_data.arg2()->GetString());
+
+ const base::DictionaryValue* visual_data;
+ ASSERT_TRUE(call_data.arg3()->GetAsDictionary(&visual_data));
+ ExpectVisualDataDictionary(new_visual_data, visual_data);
+}
+
+TEST_F(TabStripUIHandlerTest, GroupTab) {
+ // Add a tab inside of a group.
+ AddTab(browser(), GURL("http://foo"));
+ tab_groups::TabGroupId group_id =
+ browser()->tab_strip_model()->AddToNewGroup({0});
+
+ // Add another tab, and try to group it.
+ AddTab(browser(), GURL("http://foo"));
+ base::ListValue args;
+ args.AppendInteger(extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(0)));
+ args.AppendString(group_id.ToString());
+ handler()->HandleGroupTab(&args);
+
+ ASSERT_EQ(group_id, browser()->tab_strip_model()->GetTabGroupForTab(0));
+}
+
+TEST_F(TabStripUIHandlerTest, MoveGroup) {
+ AddTab(browser(), GURL("http://foo/1"));
+ AddTab(browser(), GURL("http://foo/2"));
+ tab_groups::TabGroupId group_id =
+ browser()->tab_strip_model()->AddToNewGroup({0});
+
+ // Move the group to index 1.
+ int new_index = 1;
+ base::ListValue args;
+ args.AppendString(group_id.ToString());
+ args.AppendInteger(new_index);
+ handler()->HandleMoveGroup(&args);
+
+ std::vector<int> tabs_in_group = browser()
+ ->tab_strip_model()
+ ->group_model()
+ ->GetTabGroup(group_id)
+ ->ListTabs();
+ ASSERT_EQ(new_index, tabs_in_group.front());
+ ASSERT_EQ(new_index, tabs_in_group.back());
+}
+
+TEST_F(TabStripUIHandlerTest, MoveGroupAcrossWindows) {
+ AddTab(browser(), GURL("http://foo"));
+
+ // Create a new window with the same profile, and add a group to it.
+ std::unique_ptr<BrowserWindow> new_window(CreateBrowserWindow());
+ std::unique_ptr<Browser> new_browser =
+ CreateBrowser(profile(), browser()->type(), false, new_window.get());
+ AddTab(new_browser.get(), GURL("http://foo"));
+ AddTab(new_browser.get(), GURL("http://foo"));
+ tab_groups::TabGroupId group_id =
+ new_browser.get()->tab_strip_model()->AddToNewGroup({0, 1});
+
+ // Create some visual data to make sure it gets transferred.
+ const tab_groups::TabGroupVisualData visual_data(
+ base::ASCIIToUTF16("My group"), tab_groups::TabGroupColorId::kGreen);
+ new_browser.get()
+ ->tab_strip_model()
+ ->group_model()
+ ->GetTabGroup(group_id)
+ ->SetVisualData(visual_data);
+
+ content::WebContents* moved_contents1 =
+ new_browser.get()->tab_strip_model()->GetWebContentsAt(0);
+ content::WebContents* moved_contents2 =
+ new_browser.get()->tab_strip_model()->GetWebContentsAt(1);
+ web_ui()->ClearTrackedCalls();
+
+ int new_index = -1;
+ base::ListValue args;
+ args.AppendString(group_id.ToString());
+ args.AppendInteger(new_index);
+ handler()->HandleMoveGroup(&args);
+
+ ASSERT_EQ(0U, new_browser.get()
+ ->tab_strip_model()
+ ->group_model()
+ ->ListTabGroups()
+ .size());
+ ASSERT_EQ(moved_contents1, browser()->tab_strip_model()->GetWebContentsAt(1));
+ ASSERT_EQ(moved_contents2, browser()->tab_strip_model()->GetWebContentsAt(2));
+
+ base::Optional<tab_groups::TabGroupId> new_group_id =
+ browser()->tab_strip_model()->GetTabGroupForTab(1);
+ ASSERT_TRUE(new_group_id.has_value());
+ ASSERT_EQ(browser()->tab_strip_model()->GetTabGroupForTab(1),
+ browser()->tab_strip_model()->GetTabGroupForTab(2));
+
+ const tab_groups::TabGroupVisualData* new_visual_data =
+ browser()
+ ->tab_strip_model()
+ ->group_model()
+ ->GetTabGroup(new_group_id.value())
+ ->visual_data();
+ ASSERT_EQ(visual_data.title(), new_visual_data->title());
+ ASSERT_EQ(visual_data.color(), new_visual_data->color());
+
+ // Test that a WebUI event for the ID change was sent first.
+ const content::TestWebUI::CallData& call_data =
+ *web_ui()->call_data().front();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
+ EXPECT_EQ("tab-group-id-replaced", call_data.arg1()->GetString());
+ EXPECT_EQ(group_id.ToString(), call_data.arg2()->GetString());
+ EXPECT_EQ(new_group_id.value().ToString(), call_data.arg3()->GetString());
+}
+
+TEST_F(TabStripUIHandlerTest, MoveGroupAcrossProfiles) {
+ AddTab(browser(), GURL("http://foo"));
+
+ TestingProfile* different_profile =
+ profile_manager()->CreateTestingProfile("different_profile");
+ std::unique_ptr<BrowserWindow> new_window(CreateBrowserWindow());
+ std::unique_ptr<Browser> new_browser = CreateBrowser(
+ different_profile, browser()->type(), false, new_window.get());
+ AddTab(new_browser.get(), GURL("http://foo"));
+ tab_groups::TabGroupId group_id =
+ new_browser.get()->tab_strip_model()->AddToNewGroup({0});
+
+ int new_index = -1;
+ base::ListValue args;
+ args.AppendString(group_id.ToString());
+ args.AppendInteger(new_index);
+ handler()->HandleMoveGroup(&args);
+
+ ASSERT_TRUE(
+ new_browser.get()->tab_strip_model()->group_model()->ContainsTabGroup(
+ group_id));
+
+ // Close all tabs before destructing.
+ new_browser.get()->tab_strip_model()->CloseAllTabs();
+}
+
+TEST_F(TabStripUIHandlerTest, MoveTab) {
+ AddTab(browser(), GURL("http://foo"));
+ AddTab(browser(), GURL("http://foo"));
+
+ content::WebContents* contents_prev_at_0 =
+ browser()->tab_strip_model()->GetWebContentsAt(0);
+ content::WebContents* contents_prev_at_1 =
+ browser()->tab_strip_model()->GetWebContentsAt(1);
+
+ // Move tab at index 0 to index 1.
+ base::ListValue args;
+ args.AppendInteger(
+ extensions::ExtensionTabUtil::GetTabId(contents_prev_at_0));
+ args.AppendInteger(1);
+ handler()->HandleMoveTab(&args);
+
+ ASSERT_EQ(1, browser()->tab_strip_model()->GetIndexOfWebContents(
+ contents_prev_at_0));
+ ASSERT_EQ(0, browser()->tab_strip_model()->GetIndexOfWebContents(
+ contents_prev_at_1));
+}
+
+TEST_F(TabStripUIHandlerTest, MoveTabAcrossProfiles) {
+ AddTab(browser(), GURL("http://foo"));
+
+ TestingProfile* different_profile =
+ profile_manager()->CreateTestingProfile("different_profile");
+ std::unique_ptr<BrowserWindow> new_window(CreateBrowserWindow());
+ std::unique_ptr<Browser> new_browser = CreateBrowser(
+ different_profile, browser()->type(), false, new_window.get());
+ AddTab(new_browser.get(), GURL("http://foo"));
+
+ base::ListValue args;
+ args.AppendInteger(extensions::ExtensionTabUtil::GetTabId(
+ new_browser->tab_strip_model()->GetWebContentsAt(0)));
+ args.AppendInteger(1);
+ handler()->HandleMoveTab(&args);
+
+ ASSERT_FALSE(browser()->tab_strip_model()->ContainsIndex(1));
+
+ // Close all tabs before destructing.
+ new_browser.get()->tab_strip_model()->CloseAllTabs();
+}
+
+TEST_F(TabStripUIHandlerTest, MoveTabAcrossWindows) {
+ AddTab(browser(), GURL("http://foo"));
+
+ std::unique_ptr<BrowserWindow> new_window(CreateBrowserWindow());
+ std::unique_ptr<Browser> new_browser =
+ CreateBrowser(profile(), browser()->type(), false, new_window.get());
+ AddTab(new_browser.get(), GURL("http://foo"));
+ content::WebContents* moved_contents =
+ new_browser.get()->tab_strip_model()->GetWebContentsAt(0);
+
+ base::ListValue args;
+ args.AppendInteger(extensions::ExtensionTabUtil::GetTabId(
+ new_browser->tab_strip_model()->GetWebContentsAt(0)));
+ args.AppendInteger(1);
+ handler()->HandleMoveTab(&args);
+
+ ASSERT_EQ(moved_contents, browser()->tab_strip_model()->GetWebContentsAt(1));
+
+ // Close all tabs before destructing.
+ new_browser.get()->tab_strip_model()->CloseAllTabs();
+}
+
+TEST_F(TabStripUIHandlerTest, TabCreated) {
+ AddTab(browser(), GURL("http://foo"));
+
+ const content::TestWebUI::CallData& call_data =
+ *web_ui()->call_data().front();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
+ EXPECT_EQ("tab-created", call_data.arg1()->GetString());
+
+ const base::DictionaryValue* tab_data;
+ ASSERT_TRUE(call_data.arg2()->GetAsDictionary(&tab_data));
+
+ int tab_id;
+ ASSERT_TRUE(tab_data->GetInteger("id", &tab_id));
+ ASSERT_EQ(extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(0)),
+ tab_id);
+
+ bool is_active;
+ ASSERT_TRUE(tab_data->GetBoolean("active", &is_active));
+ ASSERT_TRUE(is_active);
+
+ int tab_index;
+ ASSERT_TRUE(tab_data->GetInteger("index", &tab_index));
+ ASSERT_EQ(0, tab_index);
+}
+
+TEST_F(TabStripUIHandlerTest, TabRemoved) {
+ // Two tabs so the browser does not close when a tab is closed.
+ AddTab(browser(), GURL("http://foo"));
+ AddTab(browser(), GURL("http://foo"));
+ int expected_tab_id = extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(0));
+
+ web_ui()->ClearTrackedCalls();
+ browser()->tab_strip_model()->GetWebContentsAt(0)->Close();
+
+ const content::TestWebUI::CallData& call_data =
+ *web_ui()->call_data().front();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
+ EXPECT_EQ("tab-removed", call_data.arg1()->GetString());
+ EXPECT_EQ(expected_tab_id, call_data.arg2()->GetInt());
+}
+
+TEST_F(TabStripUIHandlerTest, TabMoved) {
+ AddTab(browser(), GURL("http://foo"));
+ AddTab(browser(), GURL("http://foo"));
+
+ int from_index = 0;
+ int expected_to_index = 1;
+ int expected_tab_id = extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(from_index));
+
+ browser()->tab_strip_model()->MoveWebContentsAt(from_index, expected_to_index,
+ false);
+
+ const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
+ EXPECT_EQ("tab-moved", call_data.arg1()->GetString());
+ EXPECT_EQ(expected_tab_id, call_data.arg2()->GetInt());
+ EXPECT_EQ(expected_to_index, call_data.arg3()->GetInt());
+}
+
+TEST_F(TabStripUIHandlerTest, TabReplaced) {
+ AddTab(browser(), GURL("http://foo"));
+ int expected_previous_id = extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(0));
+
+ web_ui()->ClearTrackedCalls();
+ browser()->tab_strip_model()->ReplaceWebContentsAt(
+ 0, content::WebContentsTester::CreateTestWebContents(profile(), nullptr));
+ int expected_new_id = extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(0));
+
+ const content::TestWebUI::CallData& call_data =
+ *web_ui()->call_data().front();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
+ EXPECT_EQ("tab-replaced", call_data.arg1()->GetString());
+ ASSERT_EQ(expected_previous_id, call_data.arg2()->GetInt());
+ ASSERT_EQ(expected_new_id, call_data.arg3()->GetInt());
+}
+
+TEST_F(TabStripUIHandlerTest, TabActivated) {
+ AddTab(browser(), GURL("http://foo"));
+ AddTab(browser(), GURL("http://foo"));
+ AddTab(browser(), GURL("http://foo"));
+
+ web_ui()->ClearTrackedCalls();
+ browser()->tab_strip_model()->ActivateTabAt(1);
+
+ const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back();
+ EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name());
+ EXPECT_EQ("tab-active-changed", call_data.arg1()->GetString());
+ EXPECT_EQ(extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(1)),
+ call_data.arg2()->GetInt());
+}
+
+TEST_F(TabStripUIHandlerTest, UngroupTab) {
+ // Add a tab inside of a group.
+ AddTab(browser(), GURL("http://foo"));
+ browser()->tab_strip_model()->AddToNewGroup({0});
+
+ // Add another tab at index 1, and try to group it.
+ base::ListValue args;
+ args.AppendInteger(extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(0)));
+ handler()->HandleUngroupTab(&args);
+
+ ASSERT_FALSE(browser()->tab_strip_model()->GetTabGroupForTab(0).has_value());
+}
+
+TEST_F(TabStripUIHandlerTest, CloseTab) {
+ AddTab(browser(), GURL("http://foo"));
+ AddTab(browser(), GURL("http://bar"));
+
+ base::ListValue args;
+ args.AppendInteger(extensions::ExtensionTabUtil::GetTabId(
+ browser()->tab_strip_model()->GetWebContentsAt(0)));
+ args.AppendBoolean(false); // If the tab is closed by swipe.
+ handler()->HandleCloseTab(&args);
+
+ ASSERT_EQ(1, browser()->tab_strip_model()->GetTabCount());
+}
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.cc b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.cc
index a60fc107571..17bf13136be 100644
--- a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.cc
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.cc
@@ -42,12 +42,16 @@ TabStripUILayout TabStripUILayout::CalculateForWebViewportSize(
layout.tab_title_height);
}
+ layout.tab_thumbnail_aspect_ratio =
+ layout.tab_thumbnail_size.width() /
+ static_cast<double>(layout.tab_thumbnail_size.height());
+
return layout;
}
base::Value TabStripUILayout::AsDictionary() const {
base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetStringKey("--tabstrip-tab-list-padding",
+ dict.SetStringKey("--tabstrip-tab-list-vertical-padding",
base::NumberToString(padding_around_tab_list) + "px");
dict.SetStringKey("--tabstrip-tab-title-height",
base::NumberToString(tab_title_height) + "px");
@@ -55,6 +59,8 @@ base::Value TabStripUILayout::AsDictionary() const {
base::NumberToString(tab_thumbnail_size.width()) + "px");
dict.SetStringKey("--tabstrip-tab-thumbnail-height",
base::NumberToString(tab_thumbnail_size.height()) + "px");
+ dict.SetStringKey("--tabstrip-tab-thumbnail-aspect-ratio",
+ base::NumberToString(tab_thumbnail_aspect_ratio));
dict.SetStringKey("--tabstrip-viewport-width",
base::NumberToString(viewport_width) + "px");
return dict;
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h
index 549932daf19..261adedbc31 100644
--- a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h
@@ -26,6 +26,7 @@ struct TabStripUILayout {
int tab_title_height;
int viewport_width;
gfx::Size tab_thumbnail_size;
+ double tab_thumbnail_aspect_ratio;
};
#endif // CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_LAYOUT_H_
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h
index a45fcafb307..356c7162646 100644
--- a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h
@@ -11,7 +11,9 @@ class TimeDelta;
enum class TabStripUIOpenAction {
kTapOnTabCounter = 0,
- kMaxValue = kTapOnTabCounter,
+ kToolbarDrag = 1,
+ kTabDraggedIntoWindow = 2,
+ kMaxValue = kTabDraggedIntoWindow,
};
enum class TabStripUICloseAction {
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc
new file mode 100644
index 00000000000..ed5f54ce4f2
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.cc
@@ -0,0 +1,68 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/tabs/tab_group_model.h"
+#include "components/tab_groups/tab_group_id.h"
+#include "content/public/browser/web_contents.h"
+
+namespace tab_strip_ui {
+
+base::Optional<tab_groups::TabGroupId> GetTabGroupIdFromString(
+ TabGroupModel* tab_group_model,
+ std::string group_id_string) {
+ for (tab_groups::TabGroupId candidate : tab_group_model->ListTabGroups()) {
+ if (candidate.ToString() == group_id_string) {
+ return base::Optional<tab_groups::TabGroupId>{candidate};
+ }
+ }
+
+ return base::nullopt;
+}
+
+Browser* GetBrowserWithGroupId(Profile* profile, std::string group_id_string) {
+ for (auto* browser : *BrowserList::GetInstance()) {
+ if (browser->profile() != profile) {
+ continue;
+ }
+
+ base::Optional<tab_groups::TabGroupId> group_id = GetTabGroupIdFromString(
+ browser->tab_strip_model()->group_model(), group_id_string);
+ if (group_id.has_value()) {
+ return browser;
+ }
+ }
+
+ return nullptr;
+}
+
+void MoveTabAcrossWindows(Browser* source_browser,
+ int from_index,
+ Browser* target_browser,
+ int to_index,
+ base::Optional<tab_groups::TabGroupId> to_group_id) {
+ bool was_active =
+ source_browser->tab_strip_model()->active_index() == from_index;
+ bool was_pinned = source_browser->tab_strip_model()->IsTabPinned(from_index);
+
+ std::unique_ptr<content::WebContents> detached_contents =
+ source_browser->tab_strip_model()->DetachWebContentsAt(from_index);
+
+ int add_types = TabStripModel::ADD_NONE;
+ if (was_active) {
+ add_types |= TabStripModel::ADD_ACTIVE;
+ }
+ if (was_pinned) {
+ add_types |= TabStripModel::ADD_PINNED;
+ }
+
+ target_browser->tab_strip_model()->InsertWebContentsAt(
+ to_index, std::move(detached_contents), add_types, to_group_id);
+}
+
+} // namespace tab_strip_ui
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.h b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.h
new file mode 100644
index 00000000000..5d5c67fd6b9
--- /dev/null
+++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_UTIL_H_
+#define CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_UTIL_H_
+
+#include "base/optional.h"
+#include "components/tab_groups/tab_group_id.h"
+
+class Browser;
+class Profile;
+class TabGroupModel;
+
+namespace tab_strip_ui {
+
+base::Optional<tab_groups::TabGroupId> GetTabGroupIdFromString(
+ TabGroupModel* tab_group_model,
+ std::string group_id_string);
+
+Browser* GetBrowserWithGroupId(Profile* profile, std::string group_id_string);
+
+void MoveTabAcrossWindows(
+ Browser* source_browser,
+ int from_index,
+ Browser* target_browser,
+ int to_index,
+ base::Optional<tab_groups::TabGroupId> to_group_id = base::nullopt);
+
+} // namespace tab_strip_ui
+
+#endif // CHROME_BROWSER_UI_WEBUI_TAB_STRIP_TAB_STRIP_UI_UTIL_H_
diff --git a/chromium/chrome/browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc b/chromium/chrome/browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc
index 4f77238713e..a604c2f7980 100644
--- a/chromium/chrome/browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc
+++ b/chromium/chrome/browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc
@@ -11,7 +11,7 @@
#include "base/run_loop.h"
#include "base/test/mock_callback.h"
#include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/sessions/session_tab_helper.h"
+#include "chrome/browser/sessions/session_tab_helper_factory.h"
#include "chrome/browser/ui/thumbnails/thumbnail_image.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
@@ -57,7 +57,7 @@ class ThumbnailTrackerTest : public ::testing::Test,
std::unique_ptr<content::WebContents> CreateWebContents() {
auto contents =
content::WebContentsTester::CreateTestWebContents(&profile_, nullptr);
- SessionTabHelper::CreateForWebContents(contents.get());
+ CreateSessionServiceTabHelper(contents.get());
return contents;
}
diff --git a/chromium/chrome/browser/ui/webui/test_data_source.cc b/chromium/chrome/browser/ui/webui/test_data_source.cc
index aa03e09612c..43d7f409c50 100644
--- a/chromium/chrome/browser/ui/webui/test_data_source.cc
+++ b/chromium/chrome/browser/ui/webui/test_data_source.cc
@@ -14,6 +14,7 @@
#include "base/strings/string_util.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/url_constants.h"
@@ -47,9 +48,8 @@ void TestDataSource::StartDataRequest(
const content::WebContents::Getter& wc_getter,
content::URLDataSource::GotDataCallback callback) {
const std::string path = content::URLDataSource::URLToRequestPath(url);
- base::PostTask(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING},
+ base::ThreadPool::PostTask(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING},
base::BindOnce(&TestDataSource::ReadFile, base::Unretained(this), path,
std::move(callback)));
}
diff --git a/chromium/chrome/browser/ui/webui/theme_source.cc b/chromium/chrome/browser/ui/webui/theme_source.cc
index 536f075a835..2ace3bf2c47 100644
--- a/chromium/chrome/browser/ui/webui/theme_source.cc
+++ b/chromium/chrome/browser/ui/webui/theme_source.cc
@@ -44,10 +44,9 @@ GURL GetThemeUrl(const std::string& path) {
}
bool IsNewTabCssPath(const std::string& path) {
- static const char kNewTabCSSPath[] = "css/new_tab_theme.css";
- static const char kIncognitoNewTabCSSPath[] =
- "css/incognito_new_tab_theme.css";
- return (path == kNewTabCSSPath) || (path == kIncognitoNewTabCSSPath);
+ static const char kNewTabThemeCssPath[] = "css/new_tab_theme.css";
+ static const char kIncognitoTabThemeCssPath[] = "css/incognito_tab_theme.css";
+ return path == kNewTabThemeCssPath || path == kIncognitoTabThemeCssPath;
}
void ProcessImageOnUiThread(const gfx::ImageSkia& image,
diff --git a/chromium/chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc b/chromium/chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc
index 42d192b77dd..74131bfe53c 100644
--- a/chromium/chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/translate_internals/translate_internals_ui.cc
@@ -15,7 +15,7 @@
#include "chrome/browser/ui/webui/translate_internals/chrome_translate_internals_handler.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "components/translate/translate_internals/translate_internals_handler.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
diff --git a/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc b/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc
index 378c7e350b9..1eba436b9a3 100644
--- a/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc
@@ -13,7 +13,7 @@
#include "base/bind.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/url_constants.h"
-#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/dev_ui_browser_resources.h"
#include "components/metrics_services_manager/metrics_services_manager.h"
#include "components/ukm/debug/ukm_debug_data_extractor.h"
#include "components/ukm/ukm_service.h"
diff --git a/chromium/chrome/browser/ui/webui/usb_internals/BUILD.gn b/chromium/chrome/browser/ui/webui/usb_internals/BUILD.gn
index d193360fcec..b4b71e7a3f3 100644
--- a/chromium/chrome/browser/ui/webui/usb_internals/BUILD.gn
+++ b/chromium/chrome/browser/ui/webui/usb_internals/BUILD.gn
@@ -5,9 +5,7 @@
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo_bindings") {
- sources = [
- "usb_internals.mojom",
- ]
+ sources = [ "usb_internals.mojom" ]
deps = [
"//services/device/public/mojom:usb",
diff --git a/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc b/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc
index 1b4796bba02..821d61308e0 100644
--- a/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc
+++ b/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.cc
@@ -6,9 +6,7 @@
#include <utility>
-#include "content/public/browser/system_connector.h"
-#include "services/device/public/mojom/constants.mojom.h"
-#include "services/service_manager/public/cpp/connector.h"
+#include "content/public/browser/device_service.h"
UsbInternalsPageHandler::UsbInternalsPageHandler(
mojo::PendingReceiver<mojom::UsbInternalsPageHandler> receiver)
@@ -19,13 +17,11 @@ UsbInternalsPageHandler::~UsbInternalsPageHandler() {}
void UsbInternalsPageHandler::BindTestInterface(
mojo::PendingReceiver<device::mojom::UsbDeviceManagerTest> receiver) {
// Forward the request to the DeviceService.
- content::GetSystemConnector()->Connect(device::mojom::kServiceName,
- std::move(receiver));
+ content::GetDeviceService().BindUsbDeviceManagerTest(std::move(receiver));
}
void UsbInternalsPageHandler::BindUsbDeviceManagerInterface(
mojo::PendingReceiver<device::mojom::UsbDeviceManager> receiver) {
// Forward the request to the DeviceService.
- content::GetSystemConnector()->Connect(device::mojom::kServiceName,
- std::move(receiver));
+ content::GetDeviceService().BindUsbDeviceManager(std::move(receiver));
}
diff --git a/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.h b/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.h
index 01f967c9ce1..11532cca97a 100644
--- a/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.h
+++ b/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_page_handler.h
@@ -10,7 +10,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "services/device/public/mojom/usb_manager.mojom.h"
-#include "services/device/public/mojom/usb_manager_test.mojom.h"
+#include "services/device/public/mojom/usb_manager_test.mojom-forward.h"
class UsbInternalsPageHandler : public mojom::UsbInternalsPageHandler {
public:
diff --git a/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc b/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
index 39656343313..582e633e890 100644
--- a/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
+++ b/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.cc
@@ -39,13 +39,13 @@ UsbInternalsUI::UsbInternalsUI(content::WebUI* web_ui)
source->SetDefaultResource(IDR_USB_INTERNALS_HTML);
content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source);
- AddHandlerToRegistry(base::BindRepeating(
- &UsbInternalsUI::BindUsbInternalsPageHandler, base::Unretained(this)));
}
+WEB_UI_CONTROLLER_TYPE_IMPL(UsbInternalsUI)
+
UsbInternalsUI::~UsbInternalsUI() {}
-void UsbInternalsUI::BindUsbInternalsPageHandler(
+void UsbInternalsUI::BindInterface(
mojo::PendingReceiver<mojom::UsbInternalsPageHandler> receiver) {
page_handler_ =
std::make_unique<UsbInternalsPageHandler>(std::move(receiver));
diff --git a/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.h b/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.h
index 249d376248e..968d9beade7 100644
--- a/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.h
+++ b/chromium/chrome/browser/ui/webui/usb_internals/usb_internals_ui.h
@@ -6,7 +6,7 @@
#define CHROME_BROWSER_UI_WEBUI_USB_INTERNALS_USB_INTERNALS_UI_H_
#include "base/macros.h"
-#include "chrome/browser/ui/webui/usb_internals/usb_internals.mojom.h"
+#include "chrome/browser/ui/webui/usb_internals/usb_internals.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "ui/webui/mojo_web_ui_controller.h"
@@ -18,12 +18,16 @@ class UsbInternalsUI : public ui::MojoWebUIController {
explicit UsbInternalsUI(content::WebUI* web_ui);
~UsbInternalsUI() override;
- private:
- void BindUsbInternalsPageHandler(
+ // Instantiates the implementor of the mojom::UsbInternalsPageHandler mojo
+ // interface passing the pending receiver that will be internally bound.
+ void BindInterface(
mojo::PendingReceiver<mojom::UsbInternalsPageHandler> receiver);
+ private:
std::unique_ptr<UsbInternalsPageHandler> page_handler_;
+ WEB_UI_CONTROLLER_TYPE_DECL();
+
DISALLOW_COPY_AND_ASSIGN(UsbInternalsUI);
};
diff --git a/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui.cc b/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui.cc
index 82cd9fcf3c7..b350bd7e4f7 100644
--- a/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui.cc
+++ b/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui.cc
@@ -9,7 +9,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/user_actions/user_actions_ui_handler.h"
#include "chrome/common/url_constants.h"
-#include "components/grit/components_resources.h"
+#include "components/grit/dev_ui_components_resources.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
diff --git a/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.cc b/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.cc
index ef6ea8f008e..776a57fae60 100644
--- a/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.cc
+++ b/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.cc
@@ -21,9 +21,9 @@ UserActionsUIHandler::~UserActionsUIHandler() {
void UserActionsUIHandler::RegisterMessages() {}
-void UserActionsUIHandler::OnUserAction(const std::string& action) {
+void UserActionsUIHandler::OnUserAction(const std::string& action,
+ base::TimeTicks action_time) {
base::Value user_action_name(action);
web_ui()->CallJavascriptFunctionUnsafe("userActions.observeUserAction",
user_action_name);
}
-
diff --git a/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.h b/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.h
index 9423ff27910..40fb4f5ca72 100644
--- a/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.h
+++ b/chromium/chrome/browser/ui/webui/user_actions/user_actions_ui_handler.h
@@ -9,6 +9,10 @@
#include "base/metrics/user_metrics.h"
#include "content/public/browser/web_ui_message_handler.h"
+namespace base {
+class TimeTicks;
+} // namespace base
+
// UI Handler for chrome://user-actions/
// It listens to user action notifications and passes those notifications
// into the Javascript to update the page.
@@ -22,7 +26,7 @@ class UserActionsUIHandler : public content::WebUIMessageHandler {
void RegisterMessages() override;
private:
- void OnUserAction(const std::string& action);
+ void OnUserAction(const std::string& action, base::TimeTicks action_time);
base::ActionCallback action_callback_;
diff --git a/chromium/chrome/browser/ui/webui/version_handler.cc b/chromium/chrome/browser/ui/webui/version_handler.cc
index 4fe2552d0e4..70058412fa0 100644
--- a/chromium/chrome/browser/ui/webui/version_handler.cc
+++ b/chromium/chrome/browser/ui/webui/version_handler.cc
@@ -14,6 +14,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/grit/generated_resources.h"
@@ -142,9 +143,8 @@ void VersionHandler::HandleRequestPathInfo(const base::ListValue* args) {
// OnGotFilePaths.
base::string16* exec_path_buffer = new base::string16;
base::string16* profile_path_buffer = new base::string16;
- base::PostTaskAndReply(
- FROM_HERE,
- {base::ThreadPool(), base::TaskPriority::USER_VISIBLE, base::MayBlock()},
+ base::ThreadPool::PostTaskAndReply(
+ FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()},
base::BindOnce(&GetFilePaths, Profile::FromWebUI(web_ui())->GetPath(),
base::Unretained(exec_path_buffer),
base::Unretained(profile_path_buffer)),
diff --git a/chromium/chrome/browser/ui/webui/version_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/version_handler_chromeos.cc
index a2ed0a779c2..869f34ae0b5 100644
--- a/chromium/chrome/browser/ui/webui/version_handler_chromeos.cc
+++ b/chromium/chrome/browser/ui/webui/version_handler_chromeos.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "chrome/common/channel_info.h"
#include "components/version_info/channel.h"
#include "content/public/browser/web_ui.h"
@@ -19,25 +20,22 @@ void VersionHandlerChromeOS::HandleRequestVersionInfo(
VersionHandler::HandleRequestVersionInfo(args);
// Start the asynchronous load of the versions.
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
- base::Bind(&chromeos::version_loader::GetVersion,
- chromeos::version_loader::VERSION_FULL),
- base::Bind(&VersionHandlerChromeOS::OnVersion,
- weak_factory_.GetWeakPtr()));
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
- base::Bind(&chromeos::version_loader::GetFirmware),
- base::Bind(&VersionHandlerChromeOS::OnOSFirmware,
- weak_factory_.GetWeakPtr()));
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT},
- base::Bind(&chromeos::version_loader::GetARCVersion),
- base::Bind(&VersionHandlerChromeOS::OnARCVersion,
- weak_factory_.GetWeakPtr()));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&chromeos::version_loader::GetVersion,
+ chromeos::version_loader::VERSION_FULL),
+ base::BindOnce(&VersionHandlerChromeOS::OnVersion,
+ weak_factory_.GetWeakPtr()));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&chromeos::version_loader::GetFirmware),
+ base::BindOnce(&VersionHandlerChromeOS::OnOSFirmware,
+ weak_factory_.GetWeakPtr()));
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
+ base::BindOnce(&chromeos::version_loader::GetARCVersion),
+ base::BindOnce(&VersionHandlerChromeOS::OnARCVersion,
+ weak_factory_.GetWeakPtr()));
}
void VersionHandlerChromeOS::OnVersion(const std::string& version) {
diff --git a/chromium/chrome/browser/ui/webui/version_handler_win.cc b/chromium/chrome/browser/ui/webui/version_handler_win.cc
index 315ce149694..7ce031e4fed 100644
--- a/chromium/chrome/browser/ui/webui/version_handler_win.cc
+++ b/chromium/chrome/browser/ui/webui/version_handler_win.cc
@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/win/windows_version.h"
#include "chrome/browser/ui/webui/version_util_win.h"
#include "content/public/browser/web_ui.h"
@@ -20,9 +21,8 @@ void VersionHandlerWindows::HandleRequestVersionInfo(
VersionHandler::HandleRequestVersionInfo(args);
// Start the asynchronous load of the versions.
- base::PostTaskAndReplyWithResult(
- FROM_HERE,
- {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
base::BindOnce(&version_utils::win::GetFullWindowsVersion),
base::BindOnce(&VersionHandlerWindows::OnVersion,
weak_factory_.GetWeakPtr()));
diff --git a/chromium/chrome/browser/ui/webui/version_ui.cc b/chromium/chrome/browser/ui/webui/version_ui.cc
index e69859cd954..65b02f8ed04 100644
--- a/chromium/chrome/browser/ui/webui/version_ui.cc
+++ b/chromium/chrome/browser/ui/webui/version_ui.cc
@@ -28,6 +28,7 @@
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/common/user_agent.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/webui/web_ui_util.h"
#include "v8/include/v8-version-string.h"
#if defined(OS_ANDROID)
diff --git a/chromium/chrome/browser/ui/webui/web_ui_test_handler.h b/chromium/chrome/browser/ui/webui/web_ui_test_handler.h
index c91a2e6a456..90c461d8f08 100644
--- a/chromium/chrome/browser/ui/webui/web_ui_test_handler.h
+++ b/chromium/chrome/browser/ui/webui/web_ui_test_handler.h
@@ -8,9 +8,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/strings/string16.h"
-#include "chrome/test/data/webui/web_ui_test.mojom.h"
+#include "chrome/test/data/webui/web_ui_test.mojom-forward.h"
#include "content/public/browser/web_ui_message_handler.h"
-#include "mojo/public/cpp/bindings/binding.h"
namespace base {
class Value;
diff --git a/chromium/chrome/browser/ui/webui/webui_util.cc b/chromium/chrome/browser/ui/webui/webui_util.cc
index fa4038374f7..26c0fe8748c 100644
--- a/chromium/chrome/browser/ui/webui/webui_util.cc
+++ b/chromium/chrome/browser/ui/webui/webui_util.cc
@@ -6,6 +6,7 @@
#include "chrome/common/buildflags.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/webui/web_ui_util.h"
#include "ui/resources/grit/webui_resources.h"
#include "ui/resources/grit/webui_resources_map.h"
diff --git a/chromium/chrome/browser/ui/webui/webui_util.h b/chromium/chrome/browser/ui/webui/webui_util.h
index 2eeef6884f5..728da9d8642 100644
--- a/chromium/chrome/browser/ui/webui/webui_util.h
+++ b/chromium/chrome/browser/ui/webui/webui_util.h
@@ -18,11 +18,7 @@ class WebUIDataSource;
struct GritResourceMap;
namespace webui {
-
-struct LocalizedString {
- const char* name;
- int id;
-};
+struct LocalizedString;
struct ResourcePath {
const char* path;
diff --git a/chromium/chrome/browser/ui/webui/webui_webview_browsertest.cc b/chromium/chrome/browser/ui/webui/webui_webview_browsertest.cc
index 3dadde42221..1d6c0e12f3c 100644
--- a/chromium/chrome/browser/ui/webui/webui_webview_browsertest.cc
+++ b/chromium/chrome/browser/ui/webui/webui_webview_browsertest.cc
@@ -16,10 +16,10 @@
#include "chrome/common/url_constants.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chrome/test/base/web_ui_browser_test.h"
+#include "content/public/browser/context_menu_params.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
-#include "content/public/common/context_menu_params.h"
#include "content/public/common/drop_data.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/test/extension_test_message_listener.h"
diff --git a/chromium/chrome/browser/ui/webui/welcome/OWNERS b/chromium/chrome/browser/ui/webui/welcome/OWNERS
index a0bd3ec218b..7f0fbc064f0 100644
--- a/chromium/chrome/browser/ui/webui/welcome/OWNERS
+++ b/chromium/chrome/browser/ui/webui/welcome/OWNERS
@@ -1,3 +1,3 @@
-hcarmona@chromium.org
+johntlee@chromium.org
# COMPONENT: UI>Browser>FirstRun
diff --git a/chromium/chrome/browser/ui/webui/welcome/welcome_handler.cc b/chromium/chrome/browser/ui/webui/welcome/welcome_handler.cc
index 17d4764ec78..e27ea67e305 100644
--- a/chromium/chrome/browser/ui/webui/welcome/welcome_handler.cc
+++ b/chromium/chrome/browser/ui/webui/welcome/welcome_handler.cc
@@ -92,7 +92,7 @@ void WelcomeHandler::HandleActivateSignIn(const base::ListValue* args) {
Browser* browser = GetBrowser();
browser->signin_view_controller()->ShowSignin(
- profiles::BubbleViewMode::BUBBLE_VIEW_MODE_GAIA_SIGNIN, browser,
+ profiles::BubbleViewMode::BUBBLE_VIEW_MODE_GAIA_SIGNIN,
signin_metrics::AccessPoint::ACCESS_POINT_START_PAGE, redirect_url);
}
}
diff --git a/chromium/chrome/browser/ui/webui/welcome/welcome_ui.cc b/chromium/chrome/browser/ui/webui/welcome/welcome_ui.cc
index a6209d2e715..659d9d617da 100644
--- a/chromium/chrome/browser/ui/webui/welcome/welcome_ui.cc
+++ b/chromium/chrome/browser/ui/webui/welcome/welcome_ui.cc
@@ -25,6 +25,7 @@
#include "components/signin/public/base/signin_pref_names.h"
#include "components/strings/grit/components_strings.h"
#include "net/base/url_util.h"
+#include "ui/base/webui/web_ui_util.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
diff --git a/chromium/chrome/browser/upboarding/BUILD.gn b/chromium/chrome/browser/upboarding/BUILD.gn
new file mode 100644
index 00000000000..e6d975a350a
--- /dev/null
+++ b/chromium/chrome/browser/upboarding/BUILD.gn
@@ -0,0 +1,23 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+ import("//build/config/android/config.gni")
+ import("//build/config/android/rules.gni")
+}
+
+group("upboarding") {
+ deps = [ "//chrome/browser/upboarding/query_tiles" ]
+}
+
+group("unit_tests") {
+ testonly = true
+ deps = [ "//chrome/browser/upboarding/query_tiles:unit_tests" ]
+}
+
+if (is_android) {
+ java_group("java") {
+ deps = [ "query_tiles:query_tiles_java" ]
+ }
+}
diff --git a/chromium/chrome/browser/upboarding/query_tiles/BUILD.gn b/chromium/chrome/browser/upboarding/query_tiles/BUILD.gn
new file mode 100644
index 00000000000..26d7d6f6f40
--- /dev/null
+++ b/chromium/chrome/browser/upboarding/query_tiles/BUILD.gn
@@ -0,0 +1,129 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+ import("//build/config/android/config.gni")
+ import("//build/config/android/rules.gni")
+}
+
+if (is_android) {
+ java_group("query_tiles_java") {
+ deps = [ ":public_java" ]
+ }
+}
+
+group("query_tiles") {
+ public_deps = [
+ ":factory",
+ ":public",
+ ]
+
+ deps = [ "internal" ]
+}
+
+source_set("public") {
+ sources = [
+ "query_tile_entry.cc",
+ "query_tile_entry.h",
+ "tile_service.h",
+ ]
+
+ deps = [ "//ui/gfx" ]
+
+ public_deps = [
+ "//base",
+ "//components/keyed_service/core",
+ ]
+
+ if (is_android) {
+ sources += [
+ "android/tile_provider_bridge.cc",
+ "android/tile_provider_bridge.h",
+ ]
+
+ deps += [ ":jni_headers" ]
+ }
+}
+
+source_set("factory") {
+ sources = [
+ "tile_service_factory_helper.cc",
+ "tile_service_factory_helper.h",
+ ]
+
+ deps = [
+ ":public",
+ "internal:internal",
+ ]
+}
+
+if (is_android) {
+ android_library("public_java") {
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileCoordinator.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileCoordinatorFactory.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/Tile.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/TileProvider.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/bridges/TileProviderBridge.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/list/QueryTileCoordinatorImpl.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/list/TileListModel.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/list/TileListProperties.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/list/TileListPropertyViewBinder.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/list/TileListView.java",
+ "android/java/src/org/chromium/chrome/browser/query_tiles/list/TileViewHolder.java",
+ ]
+
+ deps = [
+ ":chrome_upboarding_query_tiles_java_resources",
+ "//base:base_java",
+ "//base:jni_java",
+ "//third_party/android_deps:androidx_recyclerview_recyclerview_java",
+ "//ui/android:ui_java",
+ ]
+
+ annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+ }
+
+ generate_jni("jni_headers") {
+ visibility = [ ":*" ]
+
+ sources = [ "android/java/src/org/chromium/chrome/browser/query_tiles/bridges/TileProviderBridge.java" ]
+ }
+
+ android_resources("chrome_upboarding_query_tiles_java_resources") {
+ sources = [ "android/java/res/layout/query_tile_view.xml" ]
+ custom_package = "org.chromium.chrome.query_tiles"
+ }
+
+ android_library("query_tiles_javatests") {
+ testonly = true
+
+ sources = [ "android/javatests/src/org/chromium/chrome/browser/query_tiles/QueryTileSectionTest.java" ]
+
+ deps = [
+ ":public_java",
+ "//base:base_java",
+ "//base:base_java_test_support",
+ "//chrome/android:chrome_java",
+ "//chrome/android:chrome_test_util_java",
+ "//chrome/test/android:chrome_java_test_support",
+ "//third_party/espresso:espresso_all_java",
+ "//third_party/hamcrest:hamcrest_java",
+ "//third_party/junit",
+ "//third_party/mockito:mockito_java",
+ ]
+ }
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [ "query_tile_entry_unittest.cc" ]
+ visibility = [ "//chrome/browser/upboarding:unit_tests" ]
+ deps = [
+ ":public",
+ "//chrome/browser/upboarding/query_tiles/internal:unit_tests",
+ "//testing/gtest",
+ "//url",
+ ]
+}
diff --git a/chromium/chrome/browser/upboarding/query_tiles/internal/BUILD.gn b/chromium/chrome/browser/upboarding/query_tiles/internal/BUILD.gn
new file mode 100644
index 00000000000..d71ae15c155
--- /dev/null
+++ b/chromium/chrome/browser/upboarding/query_tiles/internal/BUILD.gn
@@ -0,0 +1,78 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+if (is_android) {
+ import("//build/config/android/config.gni")
+ import("//build/config/android/rules.gni")
+}
+
+source_set("internal") {
+ sources = [
+ "cached_image_loader.cc",
+ "cached_image_loader.h",
+ "config.cc",
+ "config.h",
+ "image_data_store.cc",
+ "image_data_store.h",
+ "image_decoder.cc",
+ "image_decoder.h",
+ "image_info_store.cc",
+ "image_info_store.h",
+ "image_loader.h",
+ "proto_conversion.cc",
+ "proto_conversion.h",
+ "query_tile_store.cc",
+ "query_tile_store.h",
+ "query_tile_types.h",
+ "store.h",
+ "tile_info_fetcher.cc",
+ "tile_info_fetcher.h",
+ "tile_service_impl.cc",
+ "tile_service_impl.h",
+ ]
+
+ deps = [
+ "//base",
+ "//chrome/browser/upboarding/query_tiles:public",
+ "//chrome/browser/upboarding/query_tiles/proto",
+ "//components/image_fetcher/core",
+ "//components/leveldb_proto",
+ "//net",
+ "//services/data_decoder/public/cpp",
+ "//services/network/public/cpp",
+ "//skia",
+ "//url",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ visibility = [ "//chrome/browser/upboarding/query_tiles:unit_tests" ]
+
+ sources = [
+ "cached_image_loader_unittest.cc",
+ "image_decoder_unittest.cc",
+ "proto_conversion_unittest.cc",
+ "query_tile_store_unittest.cc",
+ "tile_info_fetcher_unittest.cc",
+ ]
+
+ deps = [
+ ":internal",
+ "//base",
+ "//base/test:test_support",
+ "//chrome/browser/upboarding/query_tiles:public",
+ "//chrome/browser/upboarding/query_tiles/internal",
+ "//chrome/browser/upboarding/query_tiles/proto",
+ "//chrome/browser/upboarding/query_tiles/test:test_lib",
+ "//components/image_fetcher/core:test_support",
+ "//components/leveldb_proto",
+ "//components/leveldb_proto:test_support",
+ "//services/data_decoder/public/cpp:test_support",
+ "//skia",
+ "//testing/gmock",
+ "//testing/gtest",
+ "//url",
+ ]
+}
diff --git a/chromium/chrome/browser/ssl/BUILD.gn b/chromium/chrome/browser/upboarding/query_tiles/proto/BUILD.gn
index 43e523b27c4..822c8fb8915 100644
--- a/chromium/chrome/browser/ssl/BUILD.gn
+++ b/chromium/chrome/browser/upboarding/query_tiles/proto/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright 2017 The Chromium Authors. All rights reserved.
+# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -6,7 +6,7 @@ import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
sources = [
- "ssl_error_assistant.proto",
- "tls_deprecation_config.proto",
+ "image.proto",
+ "query_tile_entry.proto",
]
}
diff --git a/chromium/chrome/browser/upboarding/query_tiles/test/BUILD.gn b/chromium/chrome/browser/upboarding/query_tiles/test/BUILD.gn
new file mode 100644
index 00000000000..c18e50ce33c
--- /dev/null
+++ b/chromium/chrome/browser/upboarding/query_tiles/test/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("test_lib") {
+ testonly = true
+
+ visibility = [
+ "//chrome/browser/upboarding/query_tiles/internal:unit_tests",
+ "//chrome/browser/upboarding/query_tiles:unit_tests",
+ ]
+
+ sources = [
+ "test_utils.cc",
+ "test_utils.h",
+ ]
+
+ deps = [
+ "//chrome/browser/upboarding/query_tiles:public",
+ "//chrome/browser/upboarding/query_tiles/internal",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/chrome/browser/updates/BUILD.gn b/chromium/chrome/browser/updates/BUILD.gn
new file mode 100644
index 00000000000..5d6a1138d06
--- /dev/null
+++ b/chromium/chrome/browser/updates/BUILD.gn
@@ -0,0 +1,49 @@
+# Copyright 2020 The Chromium Authors.All rights reserved.
+# Use of this source code is governed by a BSD - style license that can be
+# found in the LICENSE file.
+
+source_set("updates") {
+ sources = [
+ "update_notification_config.cc",
+ "update_notification_config.h",
+ "update_notification_info.cc",
+ "update_notification_info.h",
+ "update_notification_service.h",
+ "update_notification_service_bridge.h",
+ ]
+
+ deps = [ ":factory" ]
+}
+
+source_set("factory") {
+ sources = [
+ "update_notification_service_factory.cc",
+ "update_notification_service_factory.h",
+ ]
+
+ deps = [
+ "//base",
+ "//chrome/browser/notifications/proto",
+ "//chrome/browser/notifications/scheduler/public",
+ "//chrome/browser/updates/internal:lib",
+ "//components/keyed_service/core",
+ "//components/leveldb_proto",
+ "//skia",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [
+ "internal/update_notification_service_impl_unittest.cc",
+ "test/mock_update_notification_service_bridge.cc",
+ "test/mock_update_notification_service_bridge.h",
+ "update_notification_config_unittest.cc",
+ ]
+ deps = [
+ "//chrome/test:test_support",
+ "//skia",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/chrome/browser/updates/announcement_notification/BUILD.gn b/chromium/chrome/browser/updates/announcement_notification/BUILD.gn
index fe6f065a756..40d7bf1c2cd 100644
--- a/chromium/chrome/browser/updates/announcement_notification/BUILD.gn
+++ b/chromium/chrome/browser/updates/announcement_notification/BUILD.gn
@@ -18,10 +18,15 @@ source_set("announcement_notification") {
"empty_announcement_notification_service.h",
]
+ # TODO(xingliu): Move code depends on //chrome/browser out of this module.
deps = [
"//base",
+ "//chrome/app:generated_resources",
"//components/keyed_service/content",
+ "//components/prefs:prefs",
"//skia",
+ "//ui/base",
+ "//url",
]
if (is_android) {
@@ -29,6 +34,7 @@ source_set("announcement_notification") {
"announcement_notification_delegate_android.cc",
"announcement_notification_delegate_android.h",
]
+ deps += [ "//chrome/android:chrome_jni_headers" ]
} else {
sources += [
"announcement_notification_delegate.cc",
diff --git a/chromium/chrome/browser/updates/internal/BUILD.gn b/chromium/chrome/browser/updates/internal/BUILD.gn
new file mode 100644
index 00000000000..f6c046fb81a
--- /dev/null
+++ b/chromium/chrome/browser/updates/internal/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2020 The Chromium Authors.All rights reserved.
+# Use of this source code is governed by a BSD - style license that can be
+# found in the LICENSE file.
+
+source_set("lib") {
+ visibility = [ "//chrome/browser/updates:factory" ]
+
+ sources = [
+ "update_notification_service_impl.cc",
+ "update_notification_service_impl.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/keyed_service/core",
+ "//skia",
+ ]
+}
diff --git a/chromium/chrome/browser/util/BUILD.gn b/chromium/chrome/browser/util/BUILD.gn
index edc597de0de..5c406d1c5c2 100644
--- a/chromium/chrome/browser/util/BUILD.gn
+++ b/chromium/chrome/browser/util/BUILD.gn
@@ -5,31 +5,28 @@
import("//build/config/android/rules.gni")
android_library("java") {
- java_files = [
+ sources = [
"android/java/src/org/chromium/chrome/browser/util/AccessibilityUtil.java",
"android/java/src/org/chromium/chrome/browser/util/AndroidTaskUtils.java",
"android/java/src/org/chromium/chrome/browser/util/BitmapCache.java",
"android/java/src/org/chromium/chrome/browser/util/ChromeContextUtil.java",
"android/java/src/org/chromium/chrome/browser/util/ChromeFileProvider.java",
- "android/java/src/org/chromium/chrome/browser/util/ColorUtils.java",
"android/java/src/org/chromium/chrome/browser/util/ConversionUtils.java",
"android/java/src/org/chromium/chrome/browser/util/FileSizeUtil.java",
"android/java/src/org/chromium/chrome/browser/util/HashUtil.java",
- "android/java/src/org/chromium/chrome/browser/util/IntentUtils.java",
"android/java/src/org/chromium/chrome/browser/util/KeyNavigationUtil.java",
- "android/java/src/org/chromium/chrome/browser/util/MathUtils.java",
"android/java/src/org/chromium/chrome/browser/util/PlatformUtil.java",
- "android/java/src/org/chromium/chrome/browser/util/UrlConstants.java",
- "android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java",
- "android/java/src/org/chromium/chrome/browser/util/ViewUtils.java",
+ "android/java/src/org/chromium/chrome/browser/util/VoiceRecognitionUtil.java",
]
deps = [
"//base:base_java",
"//base:jni_java",
+ "//components/embedder_support/android:util_java",
"//content/public/android:content_java",
- "//third_party/android_deps:com_android_support_collections_java",
- "//third_party/android_deps:com_android_support_support_compat_java",
- "//third_party/android_deps:com_android_support_support_core_utils_java",
+ "//third_party/android_deps:androidx_collection_collection_java",
+ "//third_party/android_deps:androidx_core_core_java",
+ "//third_party/android_deps:androidx_legacy_legacy_support_core_utils_java",
+ "//url:gurl_java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
@@ -38,23 +35,26 @@ generate_jni("jni_headers") {
sources = [
"android/java/src/org/chromium/chrome/browser/util/ChromeContextUtil.java",
"android/java/src/org/chromium/chrome/browser/util/PlatformUtil.java",
- "android/java/src/org/chromium/chrome/browser/util/UrlUtilities.java",
]
}
android_library("javatests") {
testonly = true
- java_files = [
+ sources = [
"android/java/src/org/chromium/chrome/browser/util/ChromeFileProviderTest.java",
"android/java/src/org/chromium/chrome/browser/util/HashUtilTest.java",
- "android/java/src/org/chromium/chrome/browser/util/UrlUtilitiesTest.java",
+ "android/java/src/org/chromium/chrome/browser/util/VoiceRecognitionUtilTest.java",
]
deps = [
":java",
"//base:base_java",
+ "//base:base_java_test_support",
"//base/test:test_support_java",
"//chrome/test/android:chrome_java_test_support",
+ "//components/signin/core/browser/android:java",
"//content/public/test/android:content_java_test_support",
+ "//third_party/android_sdk:android_test_mock_java",
+ "//third_party/android_support_test_runner:runner_java",
"//third_party/junit",
"//third_party/mockito:mockito_java",
]
diff --git a/chromium/chrome/browser/vr/BUILD.gn b/chromium/chrome/browser/vr/BUILD.gn
index a4fbd9d1b9b..e3ef3aaeff5 100644
--- a/chromium/chrome/browser/vr/BUILD.gn
+++ b/chromium/chrome/browser/vr/BUILD.gn
@@ -189,6 +189,7 @@ component("vr_ui") {
"//components/omnibox/browser:vector_icons",
"//components/url_formatter",
"//components/vector_icons",
+ "//device/base",
"//device/vr/buildflags:buildflags",
"//media",
"//net",
@@ -234,6 +235,8 @@ component("vr_common") {
"browser_renderer.cc",
"browser_renderer.h",
"browser_renderer_browser_interface.h",
+ "consent/xr_session_request_consent_manager.cc",
+ "consent/xr_session_request_consent_manager.h",
"frame_type.h",
"gesture_detector.cc",
"gesture_detector.h",
@@ -244,24 +247,14 @@ component("vr_common") {
"platform_controller.h",
"scheduler_browser_renderer_interface.h",
"scheduler_delegate.h",
- "service/browser_xr_runtime.cc",
- "service/browser_xr_runtime.h",
- "service/gvr_consent_helper.cc",
- "service/gvr_consent_helper.h",
- "service/vr_service_impl.cc",
- "service/vr_service_impl.h",
"service/xr_device_service.cc",
"service/xr_device_service.h",
- "service/xr_runtime_manager.cc",
- "service/xr_runtime_manager.h",
- "service/xr_runtime_manager_observer.h",
- "service/xr_session_request_consent_manager.cc",
- "service/xr_session_request_consent_manager.h",
"sounds_manager_audio_delegate.cc",
"sounds_manager_audio_delegate.h",
"vr_export.h",
"vr_web_contents_observer.cc",
"vr_web_contents_observer.h",
+ "xr_test_utils.h",
]
sources += [
@@ -271,13 +264,6 @@ component("vr_common") {
"platform_controller_for_testing.h",
]
- if (enable_arcore) {
- sources += [
- "service/arcore_consent_prompt_interface.cc",
- "service/arcore_consent_prompt_interface.h",
- ]
- }
-
public_deps = [
":vr_base",
"//device/vr/public/mojom",
@@ -293,6 +279,7 @@ component("vr_common") {
"//components/rappor/public:public",
"//components/ukm/content",
"//content/public/browser",
+ "//device/base",
"//device/vr",
"//device/vr/buildflags:buildflags",
"//device/vr/public/mojom",
@@ -323,15 +310,6 @@ component("vr_common") {
deps += [ ":vr_ui" ]
}
- if (!is_android) {
- sources += [
- "service/isolated_device_provider.cc",
- "service/isolated_device_provider.h",
- "service/vr_ui_host.cc",
- "service/vr_ui_host.h",
- ]
- }
-
defines = [ "VR_IMPLEMENTATION" ]
if (!use_command_buffer) {
@@ -370,6 +348,11 @@ component("vr_base") {
"metrics/metrics_helper.h",
"metrics/session_metrics_helper.cc",
"metrics/session_metrics_helper.h",
+ "metrics/session_timer.cc",
+ "metrics/session_timer.h",
+ "metrics/session_tracker.h",
+ "metrics/webxr_session_tracker.cc",
+ "metrics/webxr_session_tracker.h",
"mode.h",
"model/assets.cc",
"model/assets.h",
@@ -395,7 +378,6 @@ component("vr_base") {
"pose_util.h",
"render_info.h",
"scheduler_ui_interface.h",
- "service/xr_consent_prompt_level.h",
"speech_recognizer.cc",
"speech_recognizer.h",
"text_edit_action.cc",
@@ -454,18 +436,12 @@ component("vr_base") {
}
source_set("vr_gl_bindings") {
- sources = [
- "gl_bindings.h",
- ]
+ sources = [ "gl_bindings.h" ]
public_configs = [ ":vr_gl_mode" ]
if (use_command_buffer) {
- public_deps = [
- "//gpu/command_buffer/client:gles2_c_lib",
- ]
+ public_deps = [ "//gpu/command_buffer/client:gles2_c_lib" ]
} else {
- public_deps = [
- "//ui/gl",
- ]
+ public_deps = [ "//ui/gl" ]
}
}
@@ -514,22 +490,26 @@ test("vr_common_unittests") {
"vr_geometry_util_unittest.cc",
]
- # TODO(mthiesse, crbug.com/769373): The dependency on device/vr:fakes requires
- # some workarounds for tests, since we are static-linking to the fakes instead
- # of loading them from a dll on Windows.
- defines = [ "DEVICE_VR_IMPLEMENTATION" ]
-
deps = [
":vr_test_support",
+ "//chrome/browser",
+ "//chrome/test:test_support",
"//components/url_formatter",
"//components/vector_icons",
+ "//content/test:test_support",
"//mojo/public/cpp/bindings",
"//services/network:test_support",
"//testing/gmock",
"//ui/gfx/geometry",
]
if (is_android) {
- deps += [ "//ui/android:ui_java" ]
+ deps += [
+ "//chrome:chrome_android_core",
+ "//ui/android:ui_java",
+ ]
+ }
+ if (is_win) {
+ configs += [ "//build/config/win:delayloads" ]
}
}
@@ -567,9 +547,7 @@ test("vr_common_perftests") {
}
# Needed for isolate script to execute
- data_deps = [
- "//testing:run_perf_test",
- ]
+ data_deps = [ "//testing:run_perf_test" ]
}
source_set("vr_test_support") {
@@ -598,7 +576,6 @@ source_set("vr_test_support") {
public_deps = [
":vr_common",
- ":vr_test_pak",
":vr_ui",
"//base/test:test_support",
"//cc:test_support",
@@ -613,15 +590,13 @@ source_set("vr_test_support") {
"//ui/gfx:test_support",
# TODO(mthiesse, crbug.com/769373): Remove dependency on device/vr:fakes.
- "//device/vr:fakes",
+ "//device/vr:vr_fakes",
# TODO(cjgrant): Figure out why including //ui/android:ui_java here
# doesn't propagate to individual test executable targets.
]
- data = [
- "$root_out_dir/vr_test.pak",
- ]
+ data_deps = [ ":vr_test_pak" ]
}
source_set("vr_gl_test_support") {
@@ -746,9 +721,7 @@ if (!is_android) {
}
fuzzer_test("vr_omnibox_formatting_fuzzer") {
- sources = [
- "elements/omnibox_formatting_fuzzer.cc",
- ]
+ sources = [ "elements/omnibox_formatting_fuzzer.cc" ]
deps = [
":vr_common",
":vr_ui",
diff --git a/chromium/chrome/browser/vr/testapp/BUILD.gn b/chromium/chrome/browser/vr/testapp/BUILD.gn
index 83b7b2128b4..9034b01477d 100644
--- a/chromium/chrome/browser/vr/testapp/BUILD.gn
+++ b/chromium/chrome/browser/vr/testapp/BUILD.gn
@@ -23,7 +23,6 @@ executable("vr_testapp") {
deps = [
":assets_component_version_header",
- ":vr_testapp_pak",
":vr_testapp_resources",
"//chrome/browser/vr:vr_common",
"//chrome/browser/vr:vr_test_support",
@@ -41,12 +40,11 @@ executable("vr_testapp") {
"//ui/ozone",
"//ui/platform_window",
]
+ data_deps = [ ":vr_testapp_pak" ]
}
process_version("assets_component_version_header") {
- sources = [
- "../../resources/vr/assets/VERSION",
- ]
+ sources = [ "../../resources/vr/assets/VERSION" ]
template_file = "assets_component_version.h.in"
output = "$target_gen_dir/assets_component_version.h"
}
diff --git a/chromium/chrome/browser/web_applications/BUILD.gn b/chromium/chrome/browser/web_applications/BUILD.gn
index 767ce88329c..fcfdc3d5883 100644
--- a/chromium/chrome/browser/web_applications/BUILD.gn
+++ b/chromium/chrome/browser/web_applications/BUILD.gn
@@ -9,6 +9,46 @@ group("web_app_group") {
group("web_app_test_group") {
}
+# Implementations that are common to both BMO/Extensions backends.
+# TODO(alancutter): Migrate sources from :web_applications into here where
+# possible.
+# TODO(https://crbug.com/877898): Merge this into :web_applications once all
+# Extension codepaths have been removed.
+source_set("common") {
+ sources = [
+ "manifest_update_manager.cc",
+ "manifest_update_manager.h",
+ "manifest_update_task.cc",
+ "manifest_update_task.h",
+ "system_web_app_manager.cc",
+ "system_web_app_manager.h",
+ "web_app_tab_helper.cc",
+ "web_app_tab_helper.h",
+ ]
+
+ deps = [
+ ":web_app_group",
+ "//base/util/values:values_util",
+ "//chrome/browser/web_applications/components",
+ "//chrome/common",
+ "//components/content_settings/core/browser",
+ "//components/pref_registry",
+ "//content/public/browser",
+ "//skia",
+ ]
+
+ if (is_chromeos) {
+ deps += [
+ "//ash/public/cpp",
+ "//chromeos/components/help_app_ui",
+ "//chromeos/components/media_app_ui",
+ "//chromeos/components/print_management",
+ "//chromeos/constants",
+ "//chromeos/strings",
+ ]
+ }
+}
+
source_set("web_applications") {
sources = [
"external_web_app_manager.cc",
@@ -21,8 +61,6 @@ source_set("web_applications") {
"pending_app_manager_impl.h",
"pending_app_registration_task.cc",
"pending_app_registration_task.h",
- "system_web_app_manager.cc",
- "system_web_app_manager.h",
"web_app.cc",
"web_app.h",
"web_app_database.cc",
@@ -51,10 +89,11 @@ source_set("web_applications") {
]
deps = [
+ ":common",
":web_app_group",
"//chrome/browser/web_applications/components",
"//chrome/common",
- "//components/pref_registry",
+ "//components/performance_manager",
"//components/sync",
"//content/public/browser",
"//skia",
@@ -62,18 +101,16 @@ source_set("web_applications") {
if (is_chromeos) {
deps += [
- "//ash/public/cpp:cpp",
- "//chromeos/components/help_app_ui",
- "//chromeos/components/media_app_ui",
- "//chromeos/constants",
"//components/arc:arc_base",
"//components/arc/mojom",
]
+
+ if (!is_official_build) {
+ deps += [ "//chromeos/components/sample_system_web_app_ui" ]
+ }
}
- public_deps = [
- "//chrome/browser/web_applications/proto",
- ]
+ public_deps = [ "//chrome/browser/web_applications/proto" ]
}
# This test_support library doesn't use extensions.
@@ -99,6 +136,10 @@ source_set("web_applications_test_support") {
"test/test_pending_app_manager.h",
"test/test_system_web_app_manager.cc",
"test/test_system_web_app_manager.h",
+ "test/test_system_web_app_url_data_source.cc",
+ "test/test_system_web_app_url_data_source.h",
+ "test/test_system_web_app_web_ui_controller_factory.cc",
+ "test/test_system_web_app_web_ui_controller_factory.h",
"test/test_web_app_database_factory.cc",
"test/test_web_app_database_factory.h",
"test/test_web_app_registry_controller.cc",
@@ -113,13 +154,16 @@ source_set("web_applications_test_support") {
"test/web_app_install_observer.h",
"test/web_app_registration_waiter.cc",
"test/web_app_registration_waiter.h",
+ "test/web_app_test.cc",
"test/web_app_test.h",
]
deps = [
+ ":common",
":web_app_test_group",
":web_applications",
"//base/test:test_support",
+ "//chrome/app/theme:chrome_unscaled_resources_grit",
"//chrome/browser",
"//chrome/browser/web_applications/components",
"//components/crx_file:crx_file",
@@ -145,6 +189,7 @@ source_set("web_applications_unit_tests") {
]
deps = [
+ ":common",
":web_app_test_group",
":web_applications",
":web_applications_on_extensions_test_support",
@@ -168,31 +213,53 @@ source_set("web_applications_unit_tests") {
"//components/arc/mojom",
]
}
+
+ if (is_win) {
+ deps +=
+ [ "//chrome/browser/web_applications/chrome_pwa_launcher:unit_tests" ]
+ }
}
source_set("web_applications_browser_tests") {
testonly = true
sources = [
+ "manifest_update_manager_browsertest.cc",
"pending_app_manager_impl_browsertest.cc",
+ "system_web_app_manager_browsertest.cc",
+ "system_web_app_manager_browsertest.h",
+ "web_app_audio_focus_browsertest.cc",
"web_app_icon_manager_browsertest.cc",
+ "web_app_migration_manager_browsertest.cc",
]
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
deps = [
+ ":common",
":web_applications",
+ ":web_applications_on_extensions",
+ ":web_applications_on_extensions_test_support",
":web_applications_test_support",
+ "//chrome/app:command_ids",
"//chrome/browser/web_applications/components",
+ "//chrome/services/app_service/public/cpp:app_update",
"//chrome/test:test_support",
"//chrome/test:test_support_ui",
+ "//components/permissions:permissions",
]
+
+ if (is_chromeos) {
+ deps += [ "//chrome/browser/ui" ]
+ }
}
# TODO(crbug.com/877898): Erase this and move WebAppProvider into
# web_applications set.
source_set("web_applications_on_extensions") {
sources = [
+ "web_app_migration_manager.cc",
+ "web_app_migration_manager.h",
"web_app_provider.cc",
"web_app_provider.h",
"web_app_provider_factory.cc",
@@ -200,6 +267,7 @@ source_set("web_applications_on_extensions") {
]
deps = [
+ ":common",
":web_app_group",
":web_applications",
"//chrome/browser/web_applications/components",
@@ -207,6 +275,7 @@ source_set("web_applications_on_extensions") {
"//chrome/common",
"//components/keyed_service/content",
"//components/pref_registry:pref_registry",
+ "//components/sync",
"//extensions/browser",
]
}
@@ -217,16 +286,20 @@ source_set("web_applications_on_extensions_test_support") {
testonly = true
sources = [
+ "test/test_system_web_app_installation.cc",
+ "test/test_system_web_app_installation.h",
"test/test_web_app_provider.cc",
"test/test_web_app_provider.h",
]
deps = [
+ ":common",
":web_app_test_group",
":web_applications",
":web_applications_on_extensions",
":web_applications_test_support",
"//base",
+ "//base/test:test_support",
"//chrome/browser",
"//chrome/browser/web_applications/components",
"//components/keyed_service/content",
@@ -237,6 +310,7 @@ group("unit_tests") {
testonly = true
deps = [
+ ":common",
":web_app_test_group",
":web_applications_unit_tests",
"//chrome/browser/web_applications/components:unit_tests",
@@ -251,6 +325,5 @@ group("browser_tests") {
":web_app_test_group",
":web_applications_browser_tests",
"//chrome/browser/web_applications/components:browser_tests",
- "//chrome/browser/web_applications/extensions:browser_tests",
]
}
diff --git a/chromium/chrome/browser/web_applications/chrome_pwa_launcher/BUILD.gn b/chromium/chrome/browser/web_applications/chrome_pwa_launcher/BUILD.gn
new file mode 100644
index 00000000000..84503d8b700
--- /dev/null
+++ b/chromium/chrome/browser/web_applications/chrome_pwa_launcher/BUILD.gn
@@ -0,0 +1,81 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+assert(is_win)
+
+import("//chrome/process_version_rc_template.gni")
+
+process_version_rc_template("chrome_pwa_launcher_version") {
+ sources = [ "chrome_pwa_launcher.ver" ]
+ output = "$target_gen_dir/chrome_pwa_launcher_version.rc"
+}
+
+executable("chrome_pwa_launcher") {
+ sources = [
+ "chrome_pwa_launcher_exe.rc",
+ "chrome_pwa_launcher_main.cc",
+ ]
+
+ deps = [
+ ":chrome_pwa_launcher_version",
+ ":util",
+ "//base",
+ "//chrome/common:non_code_constants",
+ "//chrome/install_static:install_static_util",
+ "//components/version_info:generate_version_info",
+ ]
+
+ configs -= [ "//build/config/win:console" ]
+ configs += [ "//build/config/win:windowed" ]
+}
+
+source_set("util") {
+ friend = [
+ ":chrome_pwa_launcher",
+ ":unit_tests",
+ ]
+
+ public = [
+ "chrome_pwa_launcher_util.h",
+ "last_browser_file_util.h",
+ "launcher_update.h",
+ ]
+
+ sources = [
+ "chrome_pwa_launcher_util.cc",
+ "last_browser_file_util.cc",
+ "launcher_log.cc",
+ "launcher_log.h",
+ "launcher_update.cc",
+ ]
+
+ public_deps = [ "//base" ]
+
+ deps = [
+ "//chrome/common:non_code_constants",
+ "//chrome/install_static:install_static_util",
+ "//chrome/installer/util:with_no_strings",
+ "//components/version_info:generate_version_info",
+ ]
+}
+
+source_set("unit_tests") {
+ testonly = true
+
+ sources = [
+ "last_browser_file_util_unittest.cc",
+ "launcher_log_unittest.cc",
+ "launcher_update_unittest.cc",
+ ]
+
+ deps = [
+ ":util",
+ "//base/test:test_support",
+ "//chrome/browser/web_applications/components",
+ "//chrome/test:test_support",
+ "//components/version_info:generate_version_info",
+ "//content/test:test_support",
+ "//testing/gtest",
+ ]
+}
diff --git a/chromium/chrome/browser/web_applications/components/BUILD.gn b/chromium/chrome/browser/web_applications/components/BUILD.gn
index 9dd348c9ffd..30b26f88b3b 100644
--- a/chromium/chrome/browser/web_applications/components/BUILD.gn
+++ b/chromium/chrome/browser/web_applications/components/BUILD.gn
@@ -4,7 +4,6 @@
source_set("components") {
sources = [
- "app_icon_manager.cc",
"app_icon_manager.h",
"app_registrar.cc",
"app_registrar.h",
@@ -26,10 +25,6 @@ source_set("components") {
"install_finalizer.h",
"install_manager.cc",
"install_manager.h",
- "manifest_update_manager.cc",
- "manifest_update_manager.h",
- "manifest_update_task.cc",
- "manifest_update_task.h",
"pending_app_manager.cc",
"pending_app_manager.h",
"policy/web_app_policy_constants.cc",
@@ -48,6 +43,7 @@ source_set("components") {
"web_app_helpers.h",
"web_app_icon_generator.cc",
"web_app_icon_generator.h",
+ "web_app_id.h",
"web_app_install_utils.cc",
"web_app_install_utils.h",
"web_app_prefs_utils.cc",
@@ -58,8 +54,8 @@ source_set("components") {
"web_app_provider_base_factory.h",
"web_app_shortcut.cc",
"web_app_shortcut.h",
- "web_app_tab_helper.cc",
- "web_app_tab_helper.h",
+ "web_app_tab_helper_base.cc",
+ "web_app_tab_helper_base.h",
"web_app_ui_manager.h",
"web_app_url_loader.cc",
"web_app_url_loader.h",
@@ -70,9 +66,9 @@ source_set("components") {
# //chrome/browser/web_applications/components to a stand-alone
# //components/web_app_icon_downloader?
#
- # There's also //components/favicon, //components/image_fetcher as well as
- # code split between //content/public/browser/manifest_icon_downloader.h
- # and //content/browser/manfest/manifest_icon_downloader.cc. Some or all of
+ # There's //components/image_fetcher as well as code split between
+ # //content/public/browser/manifest_icon_downloader.h and
+ # //content/browser/manfest/manifest_icon_downloader.cc. Some or all of
# those might be similar enough to merge.
"web_app_icon_downloader.cc",
"web_app_icon_downloader.h",
@@ -93,6 +89,9 @@ source_set("components") {
if (is_mac) {
sources += [
+ "app_shim_registry_mac.cc",
+ "app_shim_registry_mac.h",
+ "web_app_file_handler_registration_mac.cc",
"web_app_shortcut_mac.h",
"web_app_shortcut_mac.mm",
]
@@ -108,22 +107,36 @@ source_set("components") {
}
deps = [
- "//base/util/values:values_util",
"//chrome/app/resources:platform_locale_settings",
"//chrome/app/theme:chrome_unscaled_resources",
+
+ # web_applications:components uses header files from chrome/browser/banners/
+ # via |allow_circular_includes_from| mechanism enabled for the whole
+ # chrome/browser/ directory. In turn, chrome/browser/banners/ uses header
+ # files from chrome/browser/engagement/. This two-way circular dependency
+ # isn't automatically verified by |gn check| tool and it breaks incremental
+ # distributed build occasionally. For now, we should explicitly depend on
+ # chrome/browser/engagement: gn parts (like mojo_bindings) to fix this.
+ #
+ # TODO(crbug.com/1039736): Refactor AppBannerManager to remove this dep.
+ "//chrome/browser/engagement:mojo_bindings",
"//chrome/browser/web_applications:web_app_group",
"//chrome/common",
- "//components/content_settings/core/browser",
"//components/crx_file",
- "//components/favicon/content",
"//components/keyed_service/content",
"//components/pref_registry",
+ "//components/services/app_service/public/mojom",
"//components/user_manager:user_manager",
"//content/public/browser",
"//extensions/common:common_constants",
+ "//net",
"//services/preferences/public/cpp",
"//skia",
]
+
+ if (is_win) {
+ deps += [ "//chrome/browser/web_applications/chrome_pwa_launcher:util" ]
+ }
}
source_set("unit_tests") {
@@ -148,12 +161,18 @@ source_set("unit_tests") {
}
if (is_mac) {
- sources += [ "web_app_shortcut_mac_unittest.mm" ]
+ sources += [
+ "app_shim_registry_mac_unittest.cc",
+ "web_app_shortcut_mac_unittest.mm",
+ ]
}
if (is_desktop_linux) {
# Desktop linux, doesn't count ChromeOS.
- sources += [ "web_app_shortcut_linux_unittest.cc" ]
+ sources += [
+ "web_app_file_handler_registration_linux_unittest.cc",
+ "web_app_shortcut_linux_unittest.cc",
+ ]
}
deps = [
@@ -172,21 +191,25 @@ source_set("unit_tests") {
if (is_chromeos) {
deps += [ "//chrome/browser/chromeos" ]
}
+
+ if (is_win) {
+ deps += [ "//chrome/browser/web_applications/chrome_pwa_launcher:util" ]
+ }
}
source_set("browser_tests") {
testonly = true
- sources = [
- "manifest_update_manager_browsertest.cc",
- "web_app_url_loader_browsertest.cc",
- ]
+ sources = [ "web_app_url_loader_browsertest.cc" ]
+
+ if (is_desktop_linux) {
+ sources += [ "web_app_file_handler_registration_linux_browsertest.cc" ]
+ }
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
deps = [
":components",
- "//chrome/app:command_ids",
"//chrome/browser/web_applications:web_applications_test_support",
"//chrome/test:test_support",
"//chrome/test:test_support_ui",
diff --git a/chromium/chrome/browser/web_applications/extensions/BUILD.gn b/chromium/chrome/browser/web_applications/extensions/BUILD.gn
index bcebc316730..94870e81e1e 100644
--- a/chromium/chrome/browser/web_applications/extensions/BUILD.gn
+++ b/chromium/chrome/browser/web_applications/extensions/BUILD.gn
@@ -59,6 +59,7 @@ source_set("unit_tests") {
deps = [
":extensions",
"//chrome/browser",
+ "//chrome/browser/web_applications:common",
"//chrome/browser/web_applications:web_app_test_group",
"//chrome/browser/web_applications:web_applications",
"//chrome/browser/web_applications:web_applications_on_extensions",
@@ -76,36 +77,3 @@ source_set("unit_tests") {
"//testing/gtest",
]
}
-
-source_set("browser_tests") {
- testonly = true
-
- sources = [
- "bookmark_app_registrar_browsertest.cc",
- "system_web_app_manager_browsertest.cc",
- "system_web_app_manager_browsertest.h",
- "web_app_audio_focus_browsertest.cc",
- ]
-
- defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
-
- deps = [
- ":extensions",
- "//base/test:test_support",
- "//chrome/app/theme:chrome_unscaled_resources_grit",
- "//chrome/browser",
- "//chrome/browser/ui",
- "//chrome/browser/web_applications",
- "//chrome/browser/web_applications:web_app_test_group",
- "//chrome/browser/web_applications:web_applications_on_extensions",
- "//chrome/browser/web_applications:web_applications_on_extensions_test_support",
- "//chrome/browser/web_applications:web_applications_test_support",
- "//chrome/browser/web_applications/components",
- "//chrome/test:test_support",
- "//chrome/test:test_support_ui",
- "//extensions:test_support",
- "//extensions/browser",
- "//extensions/common",
- "//net:test_support",
- ]
-}
diff --git a/chromium/chrome/browser/web_applications/proto/BUILD.gn b/chromium/chrome/browser/web_applications/proto/BUILD.gn
index 1a555417347..66abe886bf9 100644
--- a/chromium/chrome/browser/web_applications/proto/BUILD.gn
+++ b/chromium/chrome/browser/web_applications/proto/BUILD.gn
@@ -5,9 +5,7 @@
import("//third_party/protobuf/proto_library.gni")
proto_library("proto") {
- import_dirs = [ "//components/sync/protocol" ]
- sources = [
- "web_app.proto",
- ]
+ proto_in_dir = "//"
+ sources = [ "web_app.proto" ]
link_deps = [ "//components/sync/protocol" ]
}
diff --git a/chromium/chrome/browser/win/conflicts/BUILD.gn b/chromium/chrome/browser/win/conflicts/BUILD.gn
index f453df05a0b..b09240ddb6f 100644
--- a/chromium/chrome/browser/win/conflicts/BUILD.gn
+++ b/chromium/chrome/browser/win/conflicts/BUILD.gn
@@ -11,9 +11,7 @@ assert(is_win)
# to the //chrome/browser target (chrome/browser/BUILD.gn).
proto_library("module_list_proto") {
- sources = [
- "proto/module_list.proto",
- ]
+ sources = [ "proto/module_list.proto" ]
}
source_set("module_info") {
@@ -39,9 +37,7 @@ source_set("module_info") {
loadable_module("conflicts_dll") {
testonly = true
- sources = [
- "test/conflicts_dll.cc",
- ]
+ sources = [ "test/conflicts_dll.cc" ]
}
source_set("unit_tests") {
@@ -103,6 +99,7 @@ if (is_chrome_branded) {
"//chrome/browser",
"//chrome/chrome_elf:third_party_shared_defines",
"//chrome/test:test_support_ui",
+ "//components/services/quarantine/public/cpp:features",
"//testing/gtest",
]
}
diff --git a/chromium/chrome/browser/xsurface/BUILD.gn b/chromium/chrome/browser/xsurface/BUILD.gn
new file mode 100644
index 00000000000..ee438487823
--- /dev/null
+++ b/chromium/chrome/browser/xsurface/BUILD.gn
@@ -0,0 +1,18 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+ sources = [
+ "android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java",
+ "android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java",
+ "android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java",
+ "android/java/src/org/chromium/chrome/browser/xsurface/ListContentManagerObserver.java",
+ "android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java",
+ "android/java/src/org/chromium/chrome/browser/xsurface/SurfaceDependencyProvider.java",
+ "android/java/src/org/chromium/chrome/browser/xsurface/SurfaceRenderer.java",
+ ]
+ deps = []
+}